11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/codegen/pending-optimization-table.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/base/flags.h"
81cb0ef41Sopenharmony_ci#include "src/execution/isolate-inl.h"
91cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"
101cb0ef41Sopenharmony_ci#include "src/objects/hash-table.h"
111cb0ef41Sopenharmony_ci#include "src/objects/js-objects.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cienum class FunctionStatus : int {
171cb0ef41Sopenharmony_ci  kPrepareForOptimize = 1 << 0,
181cb0ef41Sopenharmony_ci  kMarkForOptimize = 1 << 1,
191cb0ef41Sopenharmony_ci  kAllowHeuristicOptimization = 1 << 2,
201cb0ef41Sopenharmony_ci};
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ciusing FunctionStatusFlags = base::Flags<FunctionStatus>;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_civoid PendingOptimizationTable::PreparedForOptimization(
251cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<JSFunction> function,
261cb0ef41Sopenharmony_ci    bool allow_heuristic_optimization) {
271cb0ef41Sopenharmony_ci  DCHECK(FLAG_testing_d8_test_runner);
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci  FunctionStatusFlags status = FunctionStatus::kPrepareForOptimize;
301cb0ef41Sopenharmony_ci  if (allow_heuristic_optimization) {
311cb0ef41Sopenharmony_ci    status |= FunctionStatus::kAllowHeuristicOptimization;
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci  Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  IsCompiledScope is_compiled_scope;
361cb0ef41Sopenharmony_ci  SharedFunctionInfo::EnsureBytecodeArrayAvailable(isolate, shared_info,
371cb0ef41Sopenharmony_ci                                                   &is_compiled_scope);
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci  Handle<ObjectHashTable> table =
401cb0ef41Sopenharmony_ci      isolate->heap()->pending_optimize_for_test_bytecode().IsUndefined()
411cb0ef41Sopenharmony_ci          ? ObjectHashTable::New(isolate, 1)
421cb0ef41Sopenharmony_ci          : handle(ObjectHashTable::cast(
431cb0ef41Sopenharmony_ci                       isolate->heap()->pending_optimize_for_test_bytecode()),
441cb0ef41Sopenharmony_ci                   isolate);
451cb0ef41Sopenharmony_ci  Handle<Tuple2> tuple = isolate->factory()->NewTuple2(
461cb0ef41Sopenharmony_ci      handle(shared_info->GetBytecodeArray(isolate), isolate),
471cb0ef41Sopenharmony_ci      handle(Smi::FromInt(status), isolate), AllocationType::kYoung);
481cb0ef41Sopenharmony_ci  table =
491cb0ef41Sopenharmony_ci      ObjectHashTable::Put(table, handle(function->shared(), isolate), tuple);
501cb0ef41Sopenharmony_ci  isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_cibool PendingOptimizationTable::IsHeuristicOptimizationAllowed(
541cb0ef41Sopenharmony_ci    Isolate* isolate, JSFunction function) {
551cb0ef41Sopenharmony_ci  DCHECK(FLAG_testing_d8_test_runner);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  Handle<Object> table =
581cb0ef41Sopenharmony_ci      handle(isolate->heap()->pending_optimize_for_test_bytecode(), isolate);
591cb0ef41Sopenharmony_ci  Handle<Object> entry =
601cb0ef41Sopenharmony_ci      table->IsUndefined()
611cb0ef41Sopenharmony_ci          ? handle(ReadOnlyRoots(isolate).the_hole_value(), isolate)
621cb0ef41Sopenharmony_ci          : handle(Handle<ObjectHashTable>::cast(table)->Lookup(
631cb0ef41Sopenharmony_ci                       handle(function.shared(), isolate)),
641cb0ef41Sopenharmony_ci                   isolate);
651cb0ef41Sopenharmony_ci  if (entry->IsTheHole()) {
661cb0ef41Sopenharmony_ci    return true;
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci  DCHECK(entry->IsTuple2());
691cb0ef41Sopenharmony_ci  DCHECK(Handle<Tuple2>::cast(entry)->value2().IsSmi());
701cb0ef41Sopenharmony_ci  FunctionStatusFlags status(Smi::ToInt(Handle<Tuple2>::cast(entry)->value2()));
711cb0ef41Sopenharmony_ci  return status & FunctionStatus::kAllowHeuristicOptimization;
721cb0ef41Sopenharmony_ci}
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_civoid PendingOptimizationTable::MarkedForOptimization(
751cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<JSFunction> function) {
761cb0ef41Sopenharmony_ci  DCHECK(FLAG_testing_d8_test_runner);
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  Handle<Object> table =
791cb0ef41Sopenharmony_ci      handle(isolate->heap()->pending_optimize_for_test_bytecode(), isolate);
801cb0ef41Sopenharmony_ci  Handle<Object> entry =
811cb0ef41Sopenharmony_ci      table->IsUndefined()
821cb0ef41Sopenharmony_ci          ? handle(ReadOnlyRoots(isolate).the_hole_value(), isolate)
831cb0ef41Sopenharmony_ci          : handle(Handle<ObjectHashTable>::cast(table)->Lookup(
841cb0ef41Sopenharmony_ci                       handle(function->shared(), isolate)),
851cb0ef41Sopenharmony_ci                   isolate);
861cb0ef41Sopenharmony_ci  if (entry->IsTheHole()) {
871cb0ef41Sopenharmony_ci    PrintF("Error: Function ");
881cb0ef41Sopenharmony_ci    function->ShortPrint();
891cb0ef41Sopenharmony_ci    PrintF(
901cb0ef41Sopenharmony_ci        " should be prepared for optimization with "
911cb0ef41Sopenharmony_ci        "%%PrepareFunctionForOptimization before  "
921cb0ef41Sopenharmony_ci        "%%OptimizeFunctionOnNextCall / %%OptimizeOSR ");
931cb0ef41Sopenharmony_ci    UNREACHABLE();
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  DCHECK(entry->IsTuple2());
971cb0ef41Sopenharmony_ci  DCHECK(Handle<Tuple2>::cast(entry)->value2().IsSmi());
981cb0ef41Sopenharmony_ci  FunctionStatusFlags status(Smi::ToInt(Handle<Tuple2>::cast(entry)->value2()));
991cb0ef41Sopenharmony_ci  status = status.without(FunctionStatus::kPrepareForOptimize) |
1001cb0ef41Sopenharmony_ci           FunctionStatus::kMarkForOptimize;
1011cb0ef41Sopenharmony_ci  Handle<Tuple2>::cast(entry)->set_value2(Smi::FromInt(status));
1021cb0ef41Sopenharmony_ci  table = ObjectHashTable::Put(Handle<ObjectHashTable>::cast(table),
1031cb0ef41Sopenharmony_ci                               handle(function->shared(), isolate), entry);
1041cb0ef41Sopenharmony_ci  isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_civoid PendingOptimizationTable::FunctionWasOptimized(
1081cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<JSFunction> function) {
1091cb0ef41Sopenharmony_ci  DCHECK(FLAG_testing_d8_test_runner);
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  if (isolate->heap()->pending_optimize_for_test_bytecode().IsUndefined()) {
1121cb0ef41Sopenharmony_ci    return;
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  Handle<ObjectHashTable> table =
1161cb0ef41Sopenharmony_ci      handle(ObjectHashTable::cast(
1171cb0ef41Sopenharmony_ci                 isolate->heap()->pending_optimize_for_test_bytecode()),
1181cb0ef41Sopenharmony_ci             isolate);
1191cb0ef41Sopenharmony_ci  Handle<Object> value(table->Lookup(handle(function->shared(), isolate)),
1201cb0ef41Sopenharmony_ci                       isolate);
1211cb0ef41Sopenharmony_ci  // Remove only if we have already seen %OptimizeFunctionOnNextCall. If it is
1221cb0ef41Sopenharmony_ci  // optimized for other reasons, still keep holding the bytecode since we may
1231cb0ef41Sopenharmony_ci  // optimize it later.
1241cb0ef41Sopenharmony_ci  if (!value->IsTheHole() &&
1251cb0ef41Sopenharmony_ci      Smi::cast(Handle<Tuple2>::cast(value)->value2()).value() ==
1261cb0ef41Sopenharmony_ci          static_cast<int>(FunctionStatus::kMarkForOptimize)) {
1271cb0ef41Sopenharmony_ci    bool was_present;
1281cb0ef41Sopenharmony_ci    table = table->Remove(isolate, table, handle(function->shared(), isolate),
1291cb0ef41Sopenharmony_ci                          &was_present);
1301cb0ef41Sopenharmony_ci    DCHECK(was_present);
1311cb0ef41Sopenharmony_ci    isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci}  // namespace internal
1361cb0ef41Sopenharmony_ci}  // namespace v8
137