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_, &reg_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