11cb0ef41Sopenharmony_ci// Copyright 2011 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/compilation-cache.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/codegen/script-details.h" 81cb0ef41Sopenharmony_ci#include "src/common/globals.h" 91cb0ef41Sopenharmony_ci#include "src/heap/factory.h" 101cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 111cb0ef41Sopenharmony_ci#include "src/logging/log.h" 121cb0ef41Sopenharmony_ci#include "src/objects/compilation-cache-table-inl.h" 131cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 141cb0ef41Sopenharmony_ci#include "src/objects/slots.h" 151cb0ef41Sopenharmony_ci#include "src/objects/visitors.h" 161cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace v8 { 191cb0ef41Sopenharmony_cinamespace internal { 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// The number of generations for each sub cache. 221cb0ef41Sopenharmony_cistatic const int kRegExpGenerations = 2; 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// Initial size of each compilation cache table allocated. 251cb0ef41Sopenharmony_cistatic const int kInitialCacheSize = 64; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciCompilationCache::CompilationCache(Isolate* isolate) 281cb0ef41Sopenharmony_ci : isolate_(isolate), 291cb0ef41Sopenharmony_ci script_(isolate), 301cb0ef41Sopenharmony_ci eval_global_(isolate), 311cb0ef41Sopenharmony_ci eval_contextual_(isolate), 321cb0ef41Sopenharmony_ci reg_exp_(isolate, kRegExpGenerations), 331cb0ef41Sopenharmony_ci enabled_script_and_eval_(true) { 341cb0ef41Sopenharmony_ci CompilationSubCache* subcaches[kSubCacheCount] = { 351cb0ef41Sopenharmony_ci &script_, &eval_global_, &eval_contextual_, ®_exp_}; 361cb0ef41Sopenharmony_ci for (int i = 0; i < kSubCacheCount; ++i) { 371cb0ef41Sopenharmony_ci subcaches_[i] = subcaches[i]; 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci} 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciHandle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { 421cb0ef41Sopenharmony_ci DCHECK_LT(generation, generations()); 431cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> result; 441cb0ef41Sopenharmony_ci if (tables_[generation].IsUndefined(isolate())) { 451cb0ef41Sopenharmony_ci result = CompilationCacheTable::New(isolate(), kInitialCacheSize); 461cb0ef41Sopenharmony_ci tables_[generation] = *result; 471cb0ef41Sopenharmony_ci } else { 481cb0ef41Sopenharmony_ci CompilationCacheTable table = 491cb0ef41Sopenharmony_ci CompilationCacheTable::cast(tables_[generation]); 501cb0ef41Sopenharmony_ci result = Handle<CompilationCacheTable>(table, isolate()); 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci return result; 531cb0ef41Sopenharmony_ci} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci// static 561cb0ef41Sopenharmony_civoid CompilationSubCache::AgeByGeneration(CompilationSubCache* c) { 571cb0ef41Sopenharmony_ci DCHECK_GT(c->generations(), 1); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci // Age the generations implicitly killing off the oldest. 601cb0ef41Sopenharmony_ci for (int i = c->generations() - 1; i > 0; i--) { 611cb0ef41Sopenharmony_ci c->tables_[i] = c->tables_[i - 1]; 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // Set the first generation as unborn. 651cb0ef41Sopenharmony_ci c->tables_[0] = ReadOnlyRoots(c->isolate()).undefined_value(); 661cb0ef41Sopenharmony_ci} 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci// static 691cb0ef41Sopenharmony_civoid CompilationSubCache::AgeCustom(CompilationSubCache* c) { 701cb0ef41Sopenharmony_ci DCHECK_EQ(c->generations(), 1); 711cb0ef41Sopenharmony_ci if (c->tables_[0].IsUndefined(c->isolate())) return; 721cb0ef41Sopenharmony_ci CompilationCacheTable::cast(c->tables_[0]).Age(c->isolate()); 731cb0ef41Sopenharmony_ci} 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_civoid CompilationCacheScript::Age() { 761cb0ef41Sopenharmony_ci if (FLAG_isolate_script_cache_ageing) AgeCustom(this); 771cb0ef41Sopenharmony_ci} 781cb0ef41Sopenharmony_civoid CompilationCacheEval::Age() { AgeCustom(this); } 791cb0ef41Sopenharmony_civoid CompilationCacheRegExp::Age() { AgeByGeneration(this); } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_civoid CompilationSubCache::Iterate(RootVisitor* v) { 821cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kCompilationCache, nullptr, 831cb0ef41Sopenharmony_ci FullObjectSlot(&tables_[0]), 841cb0ef41Sopenharmony_ci FullObjectSlot(&tables_[generations()])); 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_civoid CompilationSubCache::Clear() { 881cb0ef41Sopenharmony_ci MemsetPointer(reinterpret_cast<Address*>(tables_), 891cb0ef41Sopenharmony_ci ReadOnlyRoots(isolate()).undefined_value().ptr(), 901cb0ef41Sopenharmony_ci generations()); 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_civoid CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) { 941cb0ef41Sopenharmony_ci // Probe the script generation tables. Make sure not to leak handles 951cb0ef41Sopenharmony_ci // into the caller's handle scope. 961cb0ef41Sopenharmony_ci { 971cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 981cb0ef41Sopenharmony_ci for (int generation = 0; generation < generations(); generation++) { 991cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetTable(generation); 1001cb0ef41Sopenharmony_ci table->Remove(*function_info); 1011cb0ef41Sopenharmony_ci } 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci} 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ciCompilationCacheScript::CompilationCacheScript(Isolate* isolate) 1061cb0ef41Sopenharmony_ci : CompilationSubCache(isolate, 1) {} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_cinamespace { 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci// We only re-use a cached function for some script source code if the 1111cb0ef41Sopenharmony_ci// script originates from the same place. This is to avoid issues 1121cb0ef41Sopenharmony_ci// when reporting errors, etc. 1131cb0ef41Sopenharmony_cibool HasOrigin(Isolate* isolate, Handle<SharedFunctionInfo> function_info, 1141cb0ef41Sopenharmony_ci const ScriptDetails& script_details) { 1151cb0ef41Sopenharmony_ci Handle<Script> script = 1161cb0ef41Sopenharmony_ci Handle<Script>(Script::cast(function_info->script()), isolate); 1171cb0ef41Sopenharmony_ci // If the script name isn't set, the boilerplate script should have 1181cb0ef41Sopenharmony_ci // an undefined name to have the same origin. 1191cb0ef41Sopenharmony_ci Handle<Object> name; 1201cb0ef41Sopenharmony_ci if (!script_details.name_obj.ToHandle(&name)) { 1211cb0ef41Sopenharmony_ci return script->name().IsUndefined(isolate); 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci // Do the fast bailout checks first. 1241cb0ef41Sopenharmony_ci if (script_details.line_offset != script->line_offset()) return false; 1251cb0ef41Sopenharmony_ci if (script_details.column_offset != script->column_offset()) return false; 1261cb0ef41Sopenharmony_ci // Check that both names are strings. If not, no match. 1271cb0ef41Sopenharmony_ci if (!name->IsString() || !script->name().IsString()) return false; 1281cb0ef41Sopenharmony_ci // Are the origin_options same? 1291cb0ef41Sopenharmony_ci if (script_details.origin_options.Flags() != 1301cb0ef41Sopenharmony_ci script->origin_options().Flags()) { 1311cb0ef41Sopenharmony_ci return false; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci // Compare the two name strings for equality. 1341cb0ef41Sopenharmony_ci if (!String::Equals(isolate, Handle<String>::cast(name), 1351cb0ef41Sopenharmony_ci Handle<String>(String::cast(script->name()), isolate))) { 1361cb0ef41Sopenharmony_ci return false; 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci // TODO(cbruni, chromium:1244145): Remove once migrated to the context 1401cb0ef41Sopenharmony_ci Handle<Object> maybe_host_defined_options; 1411cb0ef41Sopenharmony_ci if (!script_details.host_defined_options.ToHandle( 1421cb0ef41Sopenharmony_ci &maybe_host_defined_options)) { 1431cb0ef41Sopenharmony_ci maybe_host_defined_options = isolate->factory()->empty_fixed_array(); 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci Handle<FixedArray> host_defined_options = 1461cb0ef41Sopenharmony_ci Handle<FixedArray>::cast(maybe_host_defined_options); 1471cb0ef41Sopenharmony_ci Handle<FixedArray> script_options( 1481cb0ef41Sopenharmony_ci FixedArray::cast(script->host_defined_options()), isolate); 1491cb0ef41Sopenharmony_ci int length = host_defined_options->length(); 1501cb0ef41Sopenharmony_ci if (length != script_options->length()) return false; 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci for (int i = 0; i < length; i++) { 1531cb0ef41Sopenharmony_ci // host-defined options is a v8::PrimitiveArray. 1541cb0ef41Sopenharmony_ci DCHECK(host_defined_options->get(i).IsPrimitive()); 1551cb0ef41Sopenharmony_ci DCHECK(script_options->get(i).IsPrimitive()); 1561cb0ef41Sopenharmony_ci if (!host_defined_options->get(i).StrictEquals(script_options->get(i))) { 1571cb0ef41Sopenharmony_ci return false; 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci return true; 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci} // namespace 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci// TODO(245): Need to allow identical code from different contexts to 1651cb0ef41Sopenharmony_ci// be cached in the same script generation. Currently the first use 1661cb0ef41Sopenharmony_ci// will be cached, but subsequent code from different source / line 1671cb0ef41Sopenharmony_ci// won't. 1681cb0ef41Sopenharmony_ciMaybeHandle<SharedFunctionInfo> CompilationCacheScript::Lookup( 1691cb0ef41Sopenharmony_ci Handle<String> source, const ScriptDetails& script_details, 1701cb0ef41Sopenharmony_ci LanguageMode language_mode) { 1711cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> result; 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci // Probe the script generation tables. Make sure not to leak handles 1741cb0ef41Sopenharmony_ci // into the caller's handle scope. 1751cb0ef41Sopenharmony_ci { 1761cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 1771cb0ef41Sopenharmony_ci const int generation = 0; 1781cb0ef41Sopenharmony_ci DCHECK_EQ(generations(), 1); 1791cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetTable(generation); 1801cb0ef41Sopenharmony_ci MaybeHandle<SharedFunctionInfo> probe = CompilationCacheTable::LookupScript( 1811cb0ef41Sopenharmony_ci table, source, language_mode, isolate()); 1821cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> function_info; 1831cb0ef41Sopenharmony_ci if (probe.ToHandle(&function_info)) { 1841cb0ef41Sopenharmony_ci // Break when we've found a suitable shared function info that 1851cb0ef41Sopenharmony_ci // matches the origin. 1861cb0ef41Sopenharmony_ci if (HasOrigin(isolate(), function_info, script_details)) { 1871cb0ef41Sopenharmony_ci result = scope.CloseAndEscape(function_info); 1881cb0ef41Sopenharmony_ci } 1891cb0ef41Sopenharmony_ci } 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // Once outside the manacles of the handle scope, we need to recheck 1931cb0ef41Sopenharmony_ci // to see if we actually found a cached script. If so, we return a 1941cb0ef41Sopenharmony_ci // handle created in the caller's handle scope. 1951cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> function_info; 1961cb0ef41Sopenharmony_ci if (result.ToHandle(&function_info)) { 1971cb0ef41Sopenharmony_ci // Since HasOrigin can allocate, we need to protect the SharedFunctionInfo 1981cb0ef41Sopenharmony_ci // with handles during the call. 1991cb0ef41Sopenharmony_ci DCHECK(HasOrigin(isolate(), function_info, script_details)); 2001cb0ef41Sopenharmony_ci isolate()->counters()->compilation_cache_hits()->Increment(); 2011cb0ef41Sopenharmony_ci LOG(isolate(), CompilationCacheEvent("hit", "script", *function_info)); 2021cb0ef41Sopenharmony_ci } else { 2031cb0ef41Sopenharmony_ci isolate()->counters()->compilation_cache_misses()->Increment(); 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci return result; 2061cb0ef41Sopenharmony_ci} 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_civoid CompilationCacheScript::Put(Handle<String> source, 2091cb0ef41Sopenharmony_ci LanguageMode language_mode, 2101cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> function_info) { 2111cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 2121cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetFirstTable(); 2131cb0ef41Sopenharmony_ci SetFirstTable(CompilationCacheTable::PutScript(table, source, language_mode, 2141cb0ef41Sopenharmony_ci function_info, isolate())); 2151cb0ef41Sopenharmony_ci} 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ciInfoCellPair CompilationCacheEval::Lookup(Handle<String> source, 2181cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> outer_info, 2191cb0ef41Sopenharmony_ci Handle<Context> native_context, 2201cb0ef41Sopenharmony_ci LanguageMode language_mode, 2211cb0ef41Sopenharmony_ci int position) { 2221cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 2231cb0ef41Sopenharmony_ci // Make sure not to leak the table into the surrounding handle 2241cb0ef41Sopenharmony_ci // scope. Otherwise, we risk keeping old tables around even after 2251cb0ef41Sopenharmony_ci // having cleared the cache. 2261cb0ef41Sopenharmony_ci InfoCellPair result; 2271cb0ef41Sopenharmony_ci const int generation = 0; 2281cb0ef41Sopenharmony_ci DCHECK_EQ(generations(), 1); 2291cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetTable(generation); 2301cb0ef41Sopenharmony_ci result = CompilationCacheTable::LookupEval( 2311cb0ef41Sopenharmony_ci table, source, outer_info, native_context, language_mode, position); 2321cb0ef41Sopenharmony_ci if (result.has_shared()) { 2331cb0ef41Sopenharmony_ci isolate()->counters()->compilation_cache_hits()->Increment(); 2341cb0ef41Sopenharmony_ci } else { 2351cb0ef41Sopenharmony_ci isolate()->counters()->compilation_cache_misses()->Increment(); 2361cb0ef41Sopenharmony_ci } 2371cb0ef41Sopenharmony_ci return result; 2381cb0ef41Sopenharmony_ci} 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_civoid CompilationCacheEval::Put(Handle<String> source, 2411cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> outer_info, 2421cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> function_info, 2431cb0ef41Sopenharmony_ci Handle<Context> native_context, 2441cb0ef41Sopenharmony_ci Handle<FeedbackCell> feedback_cell, 2451cb0ef41Sopenharmony_ci int position) { 2461cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 2471cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetFirstTable(); 2481cb0ef41Sopenharmony_ci table = 2491cb0ef41Sopenharmony_ci CompilationCacheTable::PutEval(table, source, outer_info, function_info, 2501cb0ef41Sopenharmony_ci native_context, feedback_cell, position); 2511cb0ef41Sopenharmony_ci SetFirstTable(table); 2521cb0ef41Sopenharmony_ci} 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ciMaybeHandle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source, 2551cb0ef41Sopenharmony_ci JSRegExp::Flags flags) { 2561cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 2571cb0ef41Sopenharmony_ci // Make sure not to leak the table into the surrounding handle 2581cb0ef41Sopenharmony_ci // scope. Otherwise, we risk keeping old tables around even after 2591cb0ef41Sopenharmony_ci // having cleared the cache. 2601cb0ef41Sopenharmony_ci Handle<Object> result = isolate()->factory()->undefined_value(); 2611cb0ef41Sopenharmony_ci int generation; 2621cb0ef41Sopenharmony_ci for (generation = 0; generation < generations(); generation++) { 2631cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetTable(generation); 2641cb0ef41Sopenharmony_ci result = table->LookupRegExp(source, flags); 2651cb0ef41Sopenharmony_ci if (result->IsFixedArray()) break; 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci if (result->IsFixedArray()) { 2681cb0ef41Sopenharmony_ci Handle<FixedArray> data = Handle<FixedArray>::cast(result); 2691cb0ef41Sopenharmony_ci if (generation != 0) { 2701cb0ef41Sopenharmony_ci Put(source, flags, data); 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci isolate()->counters()->compilation_cache_hits()->Increment(); 2731cb0ef41Sopenharmony_ci return scope.CloseAndEscape(data); 2741cb0ef41Sopenharmony_ci } else { 2751cb0ef41Sopenharmony_ci isolate()->counters()->compilation_cache_misses()->Increment(); 2761cb0ef41Sopenharmony_ci return MaybeHandle<FixedArray>(); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci} 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_civoid CompilationCacheRegExp::Put(Handle<String> source, JSRegExp::Flags flags, 2811cb0ef41Sopenharmony_ci Handle<FixedArray> data) { 2821cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 2831cb0ef41Sopenharmony_ci Handle<CompilationCacheTable> table = GetFirstTable(); 2841cb0ef41Sopenharmony_ci SetFirstTable( 2851cb0ef41Sopenharmony_ci CompilationCacheTable::PutRegExp(isolate(), table, source, flags, data)); 2861cb0ef41Sopenharmony_ci} 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_civoid CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { 2891cb0ef41Sopenharmony_ci if (!IsEnabledScriptAndEval()) return; 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci eval_global_.Remove(function_info); 2921cb0ef41Sopenharmony_ci eval_contextual_.Remove(function_info); 2931cb0ef41Sopenharmony_ci script_.Remove(function_info); 2941cb0ef41Sopenharmony_ci} 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ciMaybeHandle<SharedFunctionInfo> CompilationCache::LookupScript( 2971cb0ef41Sopenharmony_ci Handle<String> source, const ScriptDetails& script_details, 2981cb0ef41Sopenharmony_ci LanguageMode language_mode) { 2991cb0ef41Sopenharmony_ci if (!IsEnabledScriptAndEval()) return MaybeHandle<SharedFunctionInfo>(); 3001cb0ef41Sopenharmony_ci return script_.Lookup(source, script_details, language_mode); 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_ciInfoCellPair CompilationCache::LookupEval(Handle<String> source, 3041cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> outer_info, 3051cb0ef41Sopenharmony_ci Handle<Context> context, 3061cb0ef41Sopenharmony_ci LanguageMode language_mode, 3071cb0ef41Sopenharmony_ci int position) { 3081cb0ef41Sopenharmony_ci InfoCellPair result; 3091cb0ef41Sopenharmony_ci if (!IsEnabledScriptAndEval()) return result; 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci const char* cache_type; 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci if (context->IsNativeContext()) { 3141cb0ef41Sopenharmony_ci result = eval_global_.Lookup(source, outer_info, context, language_mode, 3151cb0ef41Sopenharmony_ci position); 3161cb0ef41Sopenharmony_ci cache_type = "eval-global"; 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci } else { 3191cb0ef41Sopenharmony_ci DCHECK_NE(position, kNoSourcePosition); 3201cb0ef41Sopenharmony_ci Handle<Context> native_context(context->native_context(), isolate()); 3211cb0ef41Sopenharmony_ci result = eval_contextual_.Lookup(source, outer_info, native_context, 3221cb0ef41Sopenharmony_ci language_mode, position); 3231cb0ef41Sopenharmony_ci cache_type = "eval-contextual"; 3241cb0ef41Sopenharmony_ci } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci if (result.has_shared()) { 3271cb0ef41Sopenharmony_ci LOG(isolate(), CompilationCacheEvent("hit", cache_type, result.shared())); 3281cb0ef41Sopenharmony_ci } 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci return result; 3311cb0ef41Sopenharmony_ci} 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ciMaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, 3341cb0ef41Sopenharmony_ci JSRegExp::Flags flags) { 3351cb0ef41Sopenharmony_ci return reg_exp_.Lookup(source, flags); 3361cb0ef41Sopenharmony_ci} 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_civoid CompilationCache::PutScript(Handle<String> source, 3391cb0ef41Sopenharmony_ci LanguageMode language_mode, 3401cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> function_info) { 3411cb0ef41Sopenharmony_ci if (!IsEnabledScriptAndEval()) return; 3421cb0ef41Sopenharmony_ci LOG(isolate(), CompilationCacheEvent("put", "script", *function_info)); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci script_.Put(source, language_mode, function_info); 3451cb0ef41Sopenharmony_ci} 3461cb0ef41Sopenharmony_ci 3471cb0ef41Sopenharmony_civoid CompilationCache::PutEval(Handle<String> source, 3481cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> outer_info, 3491cb0ef41Sopenharmony_ci Handle<Context> context, 3501cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> function_info, 3511cb0ef41Sopenharmony_ci Handle<FeedbackCell> feedback_cell, 3521cb0ef41Sopenharmony_ci int position) { 3531cb0ef41Sopenharmony_ci if (!IsEnabledScriptAndEval()) return; 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci const char* cache_type; 3561cb0ef41Sopenharmony_ci HandleScope scope(isolate()); 3571cb0ef41Sopenharmony_ci if (context->IsNativeContext()) { 3581cb0ef41Sopenharmony_ci eval_global_.Put(source, outer_info, function_info, context, feedback_cell, 3591cb0ef41Sopenharmony_ci position); 3601cb0ef41Sopenharmony_ci cache_type = "eval-global"; 3611cb0ef41Sopenharmony_ci } else { 3621cb0ef41Sopenharmony_ci DCHECK_NE(position, kNoSourcePosition); 3631cb0ef41Sopenharmony_ci Handle<Context> native_context(context->native_context(), isolate()); 3641cb0ef41Sopenharmony_ci eval_contextual_.Put(source, outer_info, function_info, native_context, 3651cb0ef41Sopenharmony_ci feedback_cell, position); 3661cb0ef41Sopenharmony_ci cache_type = "eval-contextual"; 3671cb0ef41Sopenharmony_ci } 3681cb0ef41Sopenharmony_ci LOG(isolate(), CompilationCacheEvent("put", cache_type, *function_info)); 3691cb0ef41Sopenharmony_ci} 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_civoid CompilationCache::PutRegExp(Handle<String> source, JSRegExp::Flags flags, 3721cb0ef41Sopenharmony_ci Handle<FixedArray> data) { 3731cb0ef41Sopenharmony_ci reg_exp_.Put(source, flags, data); 3741cb0ef41Sopenharmony_ci} 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_civoid CompilationCache::Clear() { 3771cb0ef41Sopenharmony_ci for (int i = 0; i < kSubCacheCount; i++) { 3781cb0ef41Sopenharmony_ci subcaches_[i]->Clear(); 3791cb0ef41Sopenharmony_ci } 3801cb0ef41Sopenharmony_ci} 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_civoid CompilationCache::Iterate(RootVisitor* v) { 3831cb0ef41Sopenharmony_ci for (int i = 0; i < kSubCacheCount; i++) { 3841cb0ef41Sopenharmony_ci subcaches_[i]->Iterate(v); 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci} 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_civoid CompilationCache::MarkCompactPrologue() { 3891cb0ef41Sopenharmony_ci for (int i = 0; i < kSubCacheCount; i++) { 3901cb0ef41Sopenharmony_ci subcaches_[i]->Age(); 3911cb0ef41Sopenharmony_ci } 3921cb0ef41Sopenharmony_ci} 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_civoid CompilationCache::EnableScriptAndEval() { 3951cb0ef41Sopenharmony_ci enabled_script_and_eval_ = true; 3961cb0ef41Sopenharmony_ci} 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_civoid CompilationCache::DisableScriptAndEval() { 3991cb0ef41Sopenharmony_ci enabled_script_and_eval_ = false; 4001cb0ef41Sopenharmony_ci Clear(); 4011cb0ef41Sopenharmony_ci} 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci} // namespace internal 4041cb0ef41Sopenharmony_ci} // namespace v8 405