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