Commit d21b37d3 authored by Seth Brenith's avatar Seth Brenith Committed by V8 LUCI CQ

Revert several changes that caused performance regressions

This change reverts the following:

400b2cc2 Don't rescue old top-level SharedFunctionInfos
Reviewed on https://chromium-review.googlesource.com/c/v8/v8/+/3657472

16a7150b Reland "Disable recompilation of existing Scripts from
           Isolate compilation cache"
Reviewed on https://chromium-review.googlesource.com/c/v8/v8/+/3655011

2df4d58a Fix rehashing of script compilation cache
Reviewed on https://chromium-review.googlesource.com/c/v8/v8/+/3654413

c8848cf4 Refactor CompilationSubCache
Reviewed on https://chromium-review.googlesource.com/c/v8/v8/+/3629603

25072178 Improve Script reuse in isolate compilation cache, part 1
Reviewed on https://chromium-review.googlesource.com/c/v8/v8/+/3597106

Bug: v8:12808, chromium:1325566, chromium:1325567, chromium:1325601, chromium:1328671, chromium:1328672, chromium:1328678, chromium:1328811, chromium:1328810
Change-Id: I1d318dc172e5214166d3b15f19903186f4fe6024
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3664023Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80744}
parent a6cdc3a3
This diff is collapsed.
...@@ -18,49 +18,78 @@ class Handle; ...@@ -18,49 +18,78 @@ class Handle;
class RootVisitor; class RootVisitor;
struct ScriptDetails; struct ScriptDetails;
// The compilation cache consists of several sub-caches: one each for evals and // The compilation cache consists of several generational sub-caches which uses
// scripts, which use this class as a base class, and a separate generational // this class as a base class. A sub-cache contains a compilation cache tables
// sub-cache for RegExps. Since the same source code string has different // for each generation of the sub-cache. Since the same source code string has
// compiled code for scripts and evals, we use separate sub-caches for different // different compiled code for scripts and evals, we use separate sub-caches
// compilation modes, to avoid retrieving the wrong result. // for different compilation modes, to avoid retrieving the wrong result.
class CompilationCacheEvalOrScript { class CompilationSubCache {
public: public:
explicit CompilationCacheEvalOrScript(Isolate* isolate) : isolate_(isolate) {} CompilationSubCache(Isolate* isolate, int generations)
: isolate_(isolate), generations_(generations) {
DCHECK_LE(generations, kMaxGenerations);
}
static constexpr int kFirstGeneration = 0;
static constexpr int kMaxGenerations = 2;
// Get the compilation cache tables for a specific generation.
Handle<CompilationCacheTable> GetTable(int generation);
// Accessors for first generation.
Handle<CompilationCacheTable> GetFirstTable() {
return GetTable(kFirstGeneration);
}
void SetFirstTable(Handle<CompilationCacheTable> value) {
DCHECK_LT(kFirstGeneration, generations_);
tables_[kFirstGeneration] = *value;
}
// Allocates the table if it didn't yet exist. // Age the sub-cache by evicting the oldest generation and creating a new
Handle<CompilationCacheTable> GetTable(); // young generation.
virtual void Age() = 0;
// GC support. // GC support.
void Iterate(RootVisitor* v); void Iterate(RootVisitor* v);
// Clears this sub-cache evicting all its content. // Clear this sub-cache evicting all its content.
void Clear(); void Clear();
// Removes given shared function info from sub-cache. // Remove given shared function info from sub-cache.
void Remove(Handle<SharedFunctionInfo> function_info); void Remove(Handle<SharedFunctionInfo> function_info);
// Number of generations in this sub-cache.
int generations() const { return generations_; }
protected: protected:
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
// Ageing occurs either by removing the oldest generation, or with
// custom logic implemented in CompilationCacheTable::Age.
static void AgeByGeneration(CompilationSubCache* c);
static void AgeCustom(CompilationSubCache* c);
private:
Isolate* const isolate_; Isolate* const isolate_;
Object table_; const int generations_;
Object tables_[kMaxGenerations]; // One for each generation.
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEvalOrScript); DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache);
}; };
// Sub-cache for scripts. // Sub-cache for scripts.
class CompilationCacheScript : public CompilationCacheEvalOrScript { class CompilationCacheScript : public CompilationSubCache {
public: public:
explicit CompilationCacheScript(Isolate* isolate) explicit CompilationCacheScript(Isolate* isolate);
: CompilationCacheEvalOrScript(isolate) {}
using LookupResult = CompilationCacheScriptLookupResult; MaybeHandle<SharedFunctionInfo> Lookup(Handle<String> source,
LookupResult Lookup(Handle<String> source, const ScriptDetails& script_details,
const ScriptDetails& script_details); LanguageMode language_mode);
void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info); void Put(Handle<String> source, LanguageMode language_mode,
Handle<SharedFunctionInfo> function_info);
void Age(); void Age() override;
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript);
...@@ -78,10 +107,10 @@ class CompilationCacheScript : public CompilationCacheEvalOrScript { ...@@ -78,10 +107,10 @@ class CompilationCacheScript : public CompilationCacheEvalOrScript {
// More specifically these are the CompileString, DebugEvaluate and // More specifically these are the CompileString, DebugEvaluate and
// DebugEvaluateGlobal runtime functions. // DebugEvaluateGlobal runtime functions.
// 4. The start position of the calling scope. // 4. The start position of the calling scope.
class CompilationCacheEval : public CompilationCacheEvalOrScript { class CompilationCacheEval : public CompilationSubCache {
public: public:
explicit CompilationCacheEval(Isolate* isolate) explicit CompilationCacheEval(Isolate* isolate)
: CompilationCacheEvalOrScript(isolate) {} : CompilationSubCache(isolate, 1) {}
InfoCellPair Lookup(Handle<String> source, InfoCellPair Lookup(Handle<String> source,
Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> outer_info,
...@@ -93,45 +122,26 @@ class CompilationCacheEval : public CompilationCacheEvalOrScript { ...@@ -93,45 +122,26 @@ class CompilationCacheEval : public CompilationCacheEvalOrScript {
Handle<Context> native_context, Handle<FeedbackCell> feedback_cell, Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
int position); int position);
void Age(); void Age() override;
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
}; };
// Sub-cache for regular expressions. // Sub-cache for regular expressions.
class CompilationCacheRegExp { class CompilationCacheRegExp : public CompilationSubCache {
public: public:
CompilationCacheRegExp(Isolate* isolate) : isolate_(isolate) {} CompilationCacheRegExp(Isolate* isolate, int generations)
: CompilationSubCache(isolate, generations) {}
MaybeHandle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags); MaybeHandle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags);
void Put(Handle<String> source, JSRegExp::Flags flags, void Put(Handle<String> source, JSRegExp::Flags flags,
Handle<FixedArray> data); Handle<FixedArray> data);
// The number of generations for the RegExp sub cache. void Age() override;
static const int kGenerations = 2;
// Gets the compilation cache tables for a specific generation. Allocates the
// table if it does not yet exist.
Handle<CompilationCacheTable> GetTable(int generation);
// Ages the sub-cache by evicting the oldest generation and creating a new
// young generation.
void Age();
// GC support.
void Iterate(RootVisitor* v);
// Clears this sub-cache evicting all its content.
void Clear();
private: private:
Isolate* isolate() const { return isolate_; }
Isolate* const isolate_;
Object tables_[kGenerations]; // One for each generation.
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp); DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp);
}; };
...@@ -144,10 +154,10 @@ class V8_EXPORT_PRIVATE CompilationCache { ...@@ -144,10 +154,10 @@ class V8_EXPORT_PRIVATE CompilationCache {
CompilationCache(const CompilationCache&) = delete; CompilationCache(const CompilationCache&) = delete;
CompilationCache& operator=(const CompilationCache&) = delete; CompilationCache& operator=(const CompilationCache&) = delete;
// Finds the Script and root SharedFunctionInfo for a script source string. // Finds the script shared function info for a source
// Returns empty handles if the cache doesn't contain a script for the given // string. Returns an empty handle if the cache doesn't contain a
// source string with the right origin. // script for the given source string with the right origin.
CompilationCacheScript::LookupResult LookupScript( MaybeHandle<SharedFunctionInfo> LookupScript(
Handle<String> source, const ScriptDetails& script_details, Handle<String> source, const ScriptDetails& script_details,
LanguageMode language_mode); LanguageMode language_mode);
...@@ -164,7 +174,7 @@ class V8_EXPORT_PRIVATE CompilationCache { ...@@ -164,7 +174,7 @@ class V8_EXPORT_PRIVATE CompilationCache {
MaybeHandle<FixedArray> LookupRegExp(Handle<String> source, MaybeHandle<FixedArray> LookupRegExp(Handle<String> source,
JSRegExp::Flags flags); JSRegExp::Flags flags);
// Associate the source string to the shared function // Associate the (source, kind) pair to the shared function
// info. This may overwrite an existing mapping. // info. This may overwrite an existing mapping.
void PutScript(Handle<String> source, LanguageMode language_mode, void PutScript(Handle<String> source, LanguageMode language_mode,
Handle<SharedFunctionInfo> function_info); Handle<SharedFunctionInfo> function_info);
...@@ -214,11 +224,6 @@ class V8_EXPORT_PRIVATE CompilationCache { ...@@ -214,11 +224,6 @@ class V8_EXPORT_PRIVATE CompilationCache {
bool IsEnabledScriptAndEval() const { bool IsEnabledScriptAndEval() const {
return FLAG_compilation_cache && enabled_script_and_eval_; return FLAG_compilation_cache && enabled_script_and_eval_;
} }
bool IsEnabledScript(LanguageMode language_mode) {
// Tests can change FLAG_use_strict at runtime. The compilation cache only
// contains scripts which were compiled with the default language mode.
return IsEnabledScriptAndEval() && language_mode == LanguageMode::kSloppy;
}
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
...@@ -229,6 +234,9 @@ class V8_EXPORT_PRIVATE CompilationCache { ...@@ -229,6 +234,9 @@ class V8_EXPORT_PRIVATE CompilationCache {
CompilationCacheEval eval_contextual_; CompilationCacheEval eval_contextual_;
CompilationCacheRegExp reg_exp_; CompilationCacheRegExp reg_exp_;
static constexpr int kSubCacheCount = 4;
CompilationSubCache* subcaches_[kSubCacheCount];
// Current enable state of the compilation cache for scripts and eval. // Current enable state of the compilation cache for scripts and eval.
bool enabled_script_and_eval_; bool enabled_script_and_eval_;
......
...@@ -1430,19 +1430,6 @@ Handle<SharedFunctionInfo> CreateTopLevelSharedFunctionInfo( ...@@ -1430,19 +1430,6 @@ Handle<SharedFunctionInfo> CreateTopLevelSharedFunctionInfo(
parse_info->literal(), script, true); parse_info->literal(), script, true);
} }
Handle<SharedFunctionInfo> GetOrCreateTopLevelSharedFunctionInfo(
ParseInfo* parse_info, Handle<Script> script, Isolate* isolate) {
EnsureSharedFunctionInfosArrayOnScript(script, parse_info, isolate);
MaybeHandle<SharedFunctionInfo> maybe_shared =
Script::FindSharedFunctionInfo(script, isolate, parse_info->literal());
if (Handle<SharedFunctionInfo> shared; maybe_shared.ToHandle(&shared)) {
DCHECK_EQ(shared->function_literal_id(),
parse_info->literal()->function_literal_id());
return shared;
}
return CreateTopLevelSharedFunctionInfo(parse_info, script, isolate);
}
MaybeHandle<SharedFunctionInfo> CompileToplevel( MaybeHandle<SharedFunctionInfo> CompileToplevel(
ParseInfo* parse_info, Handle<Script> script, ParseInfo* parse_info, Handle<Script> script,
MaybeHandle<ScopeInfo> maybe_outer_scope_info, Isolate* isolate, MaybeHandle<ScopeInfo> maybe_outer_scope_info, Isolate* isolate,
...@@ -1476,7 +1463,7 @@ MaybeHandle<SharedFunctionInfo> CompileToplevel( ...@@ -1476,7 +1463,7 @@ MaybeHandle<SharedFunctionInfo> CompileToplevel(
// Create the SharedFunctionInfo and add it to the script's list. // Create the SharedFunctionInfo and add it to the script's list.
Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo> shared_info =
GetOrCreateTopLevelSharedFunctionInfo(parse_info, script, isolate); CreateTopLevelSharedFunctionInfo(parse_info, script, isolate);
FinalizeUnoptimizedCompilationDataList FinalizeUnoptimizedCompilationDataList
finalize_unoptimized_compilation_data_list; finalize_unoptimized_compilation_data_list;
...@@ -2819,22 +2806,17 @@ Handle<Script> NewScript( ...@@ -2819,22 +2806,17 @@ Handle<Script> NewScript(
} }
MaybeHandle<SharedFunctionInfo> CompileScriptOnMainThread( MaybeHandle<SharedFunctionInfo> CompileScriptOnMainThread(
UnoptimizedCompileFlags flags, Handle<String> source, const UnoptimizedCompileFlags flags, Handle<String> source,
const ScriptDetails& script_details, NativesFlag natives, const ScriptDetails& script_details, NativesFlag natives,
v8::Extension* extension, Isolate* isolate, v8::Extension* extension, Isolate* isolate,
MaybeHandle<Script> maybe_script, IsCompiledScope* is_compiled_scope) { IsCompiledScope* is_compiled_scope) {
Handle<Script> script;
if (maybe_script.ToHandle(&script)) {
flags.set_script_id(script->id());
}
UnoptimizedCompileState compile_state; UnoptimizedCompileState compile_state;
ReusableUnoptimizedCompileState reusable_state(isolate); ReusableUnoptimizedCompileState reusable_state(isolate);
ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state); ParseInfo parse_info(isolate, flags, &compile_state, &reusable_state);
parse_info.set_extension(extension); parse_info.set_extension(extension);
if (script.is_null()) { Handle<Script> script =
script = NewScript(isolate, &parse_info, source, script_details, natives); NewScript(isolate, &parse_info, source, script_details, natives);
}
DCHECK_IMPLIES(parse_info.flags().collect_type_profile(), DCHECK_IMPLIES(parse_info.flags().collect_type_profile(),
script->IsUserJavaScript()); script->IsUserJavaScript());
DCHECK_EQ(parse_info.flags().is_repl_mode(), script->is_repl_mode()); DCHECK_EQ(parse_info.flags().is_repl_mode(), script->is_repl_mode());
...@@ -2914,10 +2896,8 @@ bool CompilationExceptionIsRangeError(Isolate* isolate, Handle<Object> obj) { ...@@ -2914,10 +2896,8 @@ bool CompilationExceptionIsRangeError(Isolate* isolate, Handle<Object> obj) {
MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread( MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread(
Handle<String> source, const ScriptDetails& script_details, Handle<String> source, const ScriptDetails& script_details,
MaybeHandle<Script> maybe_script, Isolate* isolate, Isolate* isolate, IsCompiledScope* is_compiled_scope) {
IsCompiledScope* is_compiled_scope) {
// Start a background thread compiling the script. // Start a background thread compiling the script.
// TODO(v8:12808): Use maybe_script for the background compilation.
StressBackgroundCompileThread background_compile_thread( StressBackgroundCompileThread background_compile_thread(
isolate, source, isolate, source,
script_details.origin_options.IsModule() ? ScriptType::kModule script_details.origin_options.IsModule() ? ScriptType::kModule
...@@ -2940,7 +2920,7 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread( ...@@ -2940,7 +2920,7 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread(
flags_copy.set_script_id(Script::kTemporaryScriptId); flags_copy.set_script_id(Script::kTemporaryScriptId);
main_thread_maybe_result = CompileScriptOnMainThread( main_thread_maybe_result = CompileScriptOnMainThread(
flags_copy, source, script_details, NOT_NATIVES_CODE, nullptr, isolate, flags_copy, source, script_details, NOT_NATIVES_CODE, nullptr, isolate,
MaybeHandle<Script>(), &inner_is_compiled_scope); &inner_is_compiled_scope);
if (main_thread_maybe_result.is_null()) { if (main_thread_maybe_result.is_null()) {
// Assume all range errors are stack overflows. // Assume all range errors are stack overflows.
main_thread_had_stack_overflow = CompilationExceptionIsRangeError( main_thread_had_stack_overflow = CompilationExceptionIsRangeError(
...@@ -3031,7 +3011,6 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl( ...@@ -3031,7 +3011,6 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
const bool use_compilation_cache = const bool use_compilation_cache =
extension == nullptr && script_details.repl_mode == REPLMode::kNo; extension == nullptr && script_details.repl_mode == REPLMode::kNo;
MaybeHandle<SharedFunctionInfo> maybe_result; MaybeHandle<SharedFunctionInfo> maybe_result;
MaybeHandle<Script> maybe_script;
IsCompiledScope is_compiled_scope; IsCompiledScope is_compiled_scope;
if (use_compilation_cache) { if (use_compilation_cache) {
bool can_consume_code_cache = bool can_consume_code_cache =
...@@ -3041,13 +3020,8 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl( ...@@ -3041,13 +3020,8 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
} }
// First check per-isolate compilation cache. // First check per-isolate compilation cache.
CompilationCacheScript::LookupResult lookup_result = maybe_result =
compilation_cache->LookupScript(source, script_details, language_mode); compilation_cache->LookupScript(source, script_details, language_mode);
if (FLAG_isolate_script_cache_recompilation) {
maybe_script = lookup_result.script();
}
maybe_result = lookup_result.toplevel_sfi();
is_compiled_scope = lookup_result.is_compiled_scope();
if (!maybe_result.is_null()) { if (!maybe_result.is_null()) {
compile_timer.set_hit_isolate_cache(); compile_timer.set_hit_isolate_cache();
} else if (can_consume_code_cache) { } else if (can_consume_code_cache) {
...@@ -3058,10 +3032,6 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl( ...@@ -3058,10 +3032,6 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileDeserialize); RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileDeserialize);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileDeserialize"); "V8.CompileDeserialize");
// TODO(v8:12808): If a Script was found in the compilation cache, then
// both of the code paths below (Finish and Deserialize) should make use
// of that Script to avoid duplicating the Script itself or any
// preexisting SharedFunctionInfos.
if (deserialize_task) { if (deserialize_task) {
// If there's a cache consume task, finish it. // If there's a cache consume task, finish it.
maybe_result = deserialize_task->Finish(isolate, source, maybe_result = deserialize_task->Finish(isolate, source,
...@@ -3096,7 +3066,7 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl( ...@@ -3096,7 +3066,7 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
// If the --stress-background-compile flag is set, do the actual // If the --stress-background-compile flag is set, do the actual
// compilation on a background thread, and wait for its result. // compilation on a background thread, and wait for its result.
maybe_result = CompileScriptOnBothBackgroundAndMainThread( maybe_result = CompileScriptOnBothBackgroundAndMainThread(
source, script_details, maybe_script, isolate, &is_compiled_scope); source, script_details, isolate, &is_compiled_scope);
} else { } else {
UnoptimizedCompileFlags flags = UnoptimizedCompileFlags flags =
UnoptimizedCompileFlags::ForToplevelCompile( UnoptimizedCompileFlags::ForToplevelCompile(
...@@ -3108,9 +3078,9 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl( ...@@ -3108,9 +3078,9 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
flags.set_is_eager(compile_options == ScriptCompiler::kEagerCompile); flags.set_is_eager(compile_options == ScriptCompiler::kEagerCompile);
maybe_result = CompileScriptOnMainThread( maybe_result =
flags, source, script_details, natives, extension, isolate, CompileScriptOnMainThread(flags, source, script_details, natives,
maybe_script, &is_compiled_scope); extension, isolate, &is_compiled_scope);
} }
// Add the result to the isolate cache. // Add the result to the isolate cache.
...@@ -3283,18 +3253,8 @@ Compiler::GetSharedFunctionInfoForStreamedScript( ...@@ -3283,18 +3253,8 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
{ {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.StreamingFinalization.CheckCache"); "V8.StreamingFinalization.CheckCache");
CompilationCacheScript::LookupResult lookup_result = maybe_result = compilation_cache->LookupScript(
compilation_cache->LookupScript(source, script_details, source, script_details, task->flags().outer_language_mode());
task->flags().outer_language_mode());
// TODO(v8:12808): Determine what to do if we finish streaming and find that
// another copy of the Script already exists but has no root
// SharedFunctionInfo or has an uncompiled SharedFunctionInfo. For now, we
// just ignore it and create a new Script.
if (!lookup_result.toplevel_sfi().is_null()) {
maybe_result = lookup_result.toplevel_sfi();
}
if (!maybe_result.is_null()) { if (!maybe_result.is_null()) {
compile_timer.set_hit_isolate_cache(); compile_timer.set_hit_isolate_cache();
} }
...@@ -3315,8 +3275,6 @@ Compiler::GetSharedFunctionInfoForStreamedScript( ...@@ -3315,8 +3275,6 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
// Add compiled code to the isolate cache. // Add compiled code to the isolate cache.
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.StreamingFinalization.AddToCache"); "V8.StreamingFinalization.AddToCache");
DCHECK_EQ(task->flags().outer_language_mode(),
construct_language_mode(FLAG_use_strict));
compilation_cache->PutScript(source, task->flags().outer_language_mode(), compilation_cache->PutScript(source, task->flags().outer_language_mode(),
result); result);
} }
......
...@@ -3887,12 +3887,6 @@ class BigIntPlatform : public bigint::Platform { ...@@ -3887,12 +3887,6 @@ class BigIntPlatform : public bigint::Platform {
private: private:
Isolate* isolate_; Isolate* isolate_;
}; };
void MarkCompactPrologue(v8::Isolate* v8_isolate, v8::GCType gc_type,
v8::GCCallbackFlags flags, void* data) {
Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
isolate->compilation_cache()->MarkCompactPrologue();
}
} // namespace } // namespace
VirtualMemoryCage* Isolate::GetPtrComprCodeCageForTesting() { VirtualMemoryCage* Isolate::GetPtrComprCodeCageForTesting() {
...@@ -4250,9 +4244,6 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data, ...@@ -4250,9 +4244,6 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
} }
#endif #endif
heap()->AddGCPrologueCallback(MarkCompactPrologue, kGCTypeMarkSweepCompact,
nullptr);
initialized_ = true; initialized_ = true;
return true; return true;
......
...@@ -2055,6 +2055,11 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { ...@@ -2055,6 +2055,11 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
static void SetIsolateThreadLocals(Isolate* isolate, static void SetIsolateThreadLocals(Isolate* isolate,
PerIsolateThreadData* data); PerIsolateThreadData* data);
void MarkCompactPrologue(bool is_compacting,
ThreadLocalTop* archived_thread_data);
void MarkCompactEpilogue(bool is_compacting,
ThreadLocalTop* archived_thread_data);
void FillCache(); void FillCache();
// Propagate pending exception message to the v8::TryCatch. // Propagate pending exception message to the v8::TryCatch.
......
...@@ -965,9 +965,6 @@ DEFINE_BOOL(turbo_collect_feedback_in_generic_lowering, true, ...@@ -965,9 +965,6 @@ DEFINE_BOOL(turbo_collect_feedback_in_generic_lowering, true,
"enable experimental feedback collection in generic lowering.") "enable experimental feedback collection in generic lowering.")
DEFINE_BOOL(isolate_script_cache_ageing, true, DEFINE_BOOL(isolate_script_cache_ageing, true,
"enable ageing of the isolate script cache.") "enable ageing of the isolate script cache.")
DEFINE_BOOL(isolate_script_cache_recompilation, false,
"enable recompiling an existing Script from the Isolate cache when "
"there is not a compiled top-level SharedFunctionInfo")
DEFINE_FLOAT(script_delay, 0, "busy wait [ms] on every Script::Run") DEFINE_FLOAT(script_delay, 0, "busy wait [ms] on every Script::Run")
DEFINE_FLOAT(script_delay_once, 0, "busy wait [ms] on the first Script::Run") DEFINE_FLOAT(script_delay_once, 0, "busy wait [ms] on the first Script::Run")
......
...@@ -2673,6 +2673,8 @@ void Heap::MarkCompactPrologue() { ...@@ -2673,6 +2673,8 @@ void Heap::MarkCompactPrologue() {
RegExpResultsCache::Clear(string_split_cache()); RegExpResultsCache::Clear(string_split_cache());
RegExpResultsCache::Clear(regexp_multiple_cache()); RegExpResultsCache::Clear(regexp_multiple_cache());
isolate_->compilation_cache()->MarkCompactPrologue();
FlushNumberStringCache(); FlushNumberStringCache();
} }
......
...@@ -287,9 +287,6 @@ namespace internal { ...@@ -287,9 +287,6 @@ namespace internal {
SC(alive_after_last_gc, V8.AliveAfterLastGC) \ SC(alive_after_last_gc, V8.AliveAfterLastGC) \
SC(compilation_cache_hits, V8.CompilationCacheHits) \ SC(compilation_cache_hits, V8.CompilationCacheHits) \
SC(compilation_cache_misses, V8.CompilationCacheMisses) \ SC(compilation_cache_misses, V8.CompilationCacheMisses) \
/* Number of times the cache contained a reusable Script but not \
the root SharedFunctionInfo */ \
SC(compilation_cache_partial_hits, V8.CompilationCachePartialHits) \
SC(objs_since_last_young, V8.ObjsSinceLastYoung) \ SC(objs_since_last_young, V8.ObjsSinceLastYoung) \
SC(objs_since_last_full, V8.ObjsSinceLastFull) SC(objs_since_last_full, V8.ObjsSinceLastFull)
......
...@@ -26,74 +26,11 @@ CompilationCacheTable::CompilationCacheTable(Address ptr) ...@@ -26,74 +26,11 @@ CompilationCacheTable::CompilationCacheTable(Address ptr)
NEVER_READ_ONLY_SPACE_IMPL(CompilationCacheTable) NEVER_READ_ONLY_SPACE_IMPL(CompilationCacheTable)
CAST_ACCESSOR(CompilationCacheTable) CAST_ACCESSOR(CompilationCacheTable)
Object CompilationCacheTable::PrimaryValueAt(InternalIndex entry) {
return get(EntryToIndex(entry) + 1);
}
void CompilationCacheTable::SetPrimaryValueAt(InternalIndex entry, Object value,
WriteBarrierMode mode) {
set(EntryToIndex(entry) + 1, value, mode);
}
Object CompilationCacheTable::EvalFeedbackValueAt(InternalIndex entry) {
static_assert(CompilationCacheShape::kEntrySize == 3);
return get(EntryToIndex(entry) + 2);
}
void CompilationCacheTable::SetEvalFeedbackValueAt(InternalIndex entry,
Object value,
WriteBarrierMode mode) {
set(EntryToIndex(entry) + 2, value, mode);
}
// The key in a script cache is a WeakFixedArray containing a weak pointer to
// the Script. The corresponding value can be either the root SharedFunctionInfo
// or undefined. The purpose of storing the root SharedFunctionInfo as the value
// is to keep it alive, not to save a lookup on the Script. A newly added entry
// always contains the root SharedFunctionInfo. After the root
// SharedFunctionInfo has aged sufficiently, it is replaced with undefined. In
// this way, all strong references to large objects are dropped, but there is
// still a way to get the Script if it happens to still be alive.
class ScriptCacheKey : public HashTableKey {
public:
enum Index {
kHash,
kWeakScript,
kEnd,
};
explicit ScriptCacheKey(Handle<String> source);
bool IsMatch(Object other) override;
Handle<Object> AsHandle(Isolate* isolate, Handle<SharedFunctionInfo> shared);
static base::Optional<String> SourceFromObject(Object obj) {
DisallowGarbageCollection no_gc;
DCHECK(obj.IsWeakFixedArray());
WeakFixedArray array = WeakFixedArray::cast(obj);
DCHECK_EQ(array.length(), kEnd);
MaybeObject maybe_script = array.Get(kWeakScript);
if (HeapObject script; maybe_script.GetHeapObjectIfWeak(&script)) {
PrimitiveHeapObject source_or_undefined = Script::cast(script).source();
// Scripts stored in the script cache should always have a source string.
return String::cast(source_or_undefined);
}
DCHECK(maybe_script.IsCleared());
return {};
}
private:
Handle<String> source_;
};
uint32_t CompilationCacheShape::RegExpHash(String string, Smi flags) { uint32_t CompilationCacheShape::RegExpHash(String string, Smi flags) {
return string.EnsureHash() + flags.value(); return string.EnsureHash() + flags.value();
} }
uint32_t CompilationCacheShape::EvalHash(String source, uint32_t CompilationCacheShape::StringSharedHash(String source,
SharedFunctionInfo shared, SharedFunctionInfo shared,
LanguageMode language_mode, LanguageMode language_mode,
int position) { int position) {
...@@ -113,6 +50,14 @@ uint32_t CompilationCacheShape::EvalHash(String source, ...@@ -113,6 +50,14 @@ uint32_t CompilationCacheShape::EvalHash(String source,
return hash; return hash;
} }
uint32_t CompilationCacheShape::StringSharedHash(String source,
LanguageMode language_mode) {
uint32_t hash = source.EnsureHash();
static_assert(LanguageModeSize == 2);
if (is_strict(language_mode)) hash ^= 0x8000;
return hash;
}
uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots, uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots,
Object object) { Object object) {
// Eval: The key field contains the hash as a Number. // Eval: The key field contains the hash as a Number.
...@@ -123,24 +68,7 @@ uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots, ...@@ -123,24 +68,7 @@ uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots,
return SharedFunctionInfo::cast(object).Hash(); return SharedFunctionInfo::cast(object).Hash();
} }
// Script. // Script: See StringSharedKey::ToHandle for the encoding.
if (object.IsWeakFixedArray()) {
uint32_t result = static_cast<uint32_t>(Smi::ToInt(
WeakFixedArray::cast(object).Get(ScriptCacheKey::kHash).ToSmi()));
#ifdef DEBUG
base::Optional<String> script_key =
ScriptCacheKey::SourceFromObject(object);
if (script_key) {
uint32_t source_hash;
if (script_key->TryGetHash(&source_hash)) {
DCHECK_EQ(result, source_hash);
}
}
#endif
return result;
}
// Eval: See EvalCacheKey::ToHandle for the encoding.
FixedArray val = FixedArray::cast(object); FixedArray val = FixedArray::cast(object);
if (val.map() == roots.fixed_cow_array_map()) { if (val.map() == roots.fixed_cow_array_map()) {
DCHECK_EQ(4, val.length()); DCHECK_EQ(4, val.length());
...@@ -149,10 +77,14 @@ uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots, ...@@ -149,10 +77,14 @@ uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots,
DCHECK(is_valid_language_mode(language_unchecked)); DCHECK(is_valid_language_mode(language_unchecked));
LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked); LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
int position = Smi::ToInt(val.get(3)); int position = Smi::ToInt(val.get(3));
Object shared = val.get(0); Object shared_or_smi = val.get(0);
DCHECK(shared.IsSharedFunctionInfo()); if (shared_or_smi.IsSmi()) {
return EvalHash(source, SharedFunctionInfo::cast(shared), language_mode, DCHECK_EQ(position, kNoSourcePosition);
position); return StringSharedHash(source, language_mode);
} else {
return StringSharedHash(source, SharedFunctionInfo::cast(shared_or_smi),
language_mode, position);
}
} }
// RegExp: The key field (and the value field) contains the // RegExp: The key field (and the value field) contains the
......
This diff is collapsed.
...@@ -29,8 +29,13 @@ class CompilationCacheShape : public BaseShape<HashTableKey*> { ...@@ -29,8 +29,13 @@ class CompilationCacheShape : public BaseShape<HashTableKey*> {
static inline uint32_t RegExpHash(String string, Smi flags); static inline uint32_t RegExpHash(String string, Smi flags);
static inline uint32_t EvalHash(String source, SharedFunctionInfo shared, static inline uint32_t StringSharedHash(String source,
LanguageMode language_mode, int position); SharedFunctionInfo shared,
LanguageMode language_mode,
int position);
static inline uint32_t StringSharedHash(String source,
LanguageMode language_mode);
static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object); static inline uint32_t HashForObject(ReadOnlyRoots roots, Object object);
...@@ -74,34 +79,6 @@ class InfoCellPair { ...@@ -74,34 +79,6 @@ class InfoCellPair {
FeedbackCell feedback_cell_; FeedbackCell feedback_cell_;
}; };
// A lookup result from the compilation cache for scripts. There are three
// possible states:
//
// 1. Cache miss: script and toplevel_sfi are both null.
// 2. Cache hit: script and toplevel_sfi are both non-null. toplevel_sfi is
// guaranteed to be compiled, and to stay compiled while this lookup result
// instance is alive.
// 3. Partial cache hit: script is non-null, but toplevel_sfi is null. The
// script may contain an uncompiled toplevel SharedFunctionInfo.
class CompilationCacheScriptLookupResult {
public:
MaybeHandle<Script> script() const { return script_; }
MaybeHandle<SharedFunctionInfo> toplevel_sfi() const { return toplevel_sfi_; }
IsCompiledScope is_compiled_scope() const { return is_compiled_scope_; }
using RawObjects = std::pair<Script, SharedFunctionInfo>;
RawObjects GetRawObjects() const;
static CompilationCacheScriptLookupResult FromRawObjects(RawObjects raw,
Isolate* isolate);
private:
MaybeHandle<Script> script_;
MaybeHandle<SharedFunctionInfo> toplevel_sfi_;
IsCompiledScope is_compiled_scope_;
};
EXTERN_DECLARE_HASH_TABLE(CompilationCacheTable, CompilationCacheShape) EXTERN_DECLARE_HASH_TABLE(CompilationCacheTable, CompilationCacheShape)
class CompilationCacheTable class CompilationCacheTable
...@@ -109,18 +86,14 @@ class CompilationCacheTable ...@@ -109,18 +86,14 @@ class CompilationCacheTable
public: public:
NEVER_READ_ONLY_SPACE NEVER_READ_ONLY_SPACE
// The 'script' cache contains SharedFunctionInfos. Once a root // The 'script' cache contains SharedFunctionInfos.
// SharedFunctionInfo has become old enough that its bytecode is flushed, the static MaybeHandle<SharedFunctionInfo> LookupScript(
// entry is still present and can be used to get the Script. For consistency,
// this function always returns the Script. Callers should check whether there
// is a root SharedFunctionInfo in the script and whether it is already
// compiled, and choose what to do accordingly.
static CompilationCacheScriptLookupResult LookupScript(
Handle<CompilationCacheTable> table, Handle<String> src, Handle<CompilationCacheTable> table, Handle<String> src,
Isolate* isolate); LanguageMode language_mode, Isolate* isolate);
static Handle<CompilationCacheTable> PutScript( static Handle<CompilationCacheTable> PutScript(
Handle<CompilationCacheTable> cache, Handle<String> src, Handle<CompilationCacheTable> cache, Handle<String> src,
Handle<SharedFunctionInfo> value, Isolate* isolate); LanguageMode language_mode, Handle<SharedFunctionInfo> value,
Isolate* isolate);
// Eval code only gets cached after a second probe for the // Eval code only gets cached after a second probe for the
// code object. To do so, on first "put" only a hash identifying the // code object. To do so, on first "put" only a hash identifying the
...@@ -151,24 +124,12 @@ class CompilationCacheTable ...@@ -151,24 +124,12 @@ class CompilationCacheTable
JSRegExp::Flags flags, Handle<FixedArray> value); JSRegExp::Flags flags, Handle<FixedArray> value);
void Remove(Object value); void Remove(Object value);
void RemoveEntry(InternalIndex entry); void Age(Isolate* isolate);
inline Object PrimaryValueAt(InternalIndex entry);
inline void SetPrimaryValueAt(InternalIndex entry, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline Object EvalFeedbackValueAt(InternalIndex entry);
inline void SetEvalFeedbackValueAt(
InternalIndex entry, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// The initial placeholder insertion of the eval cache survives this many GCs.
static constexpr int kHashGenerations = 10;
DECL_CAST(CompilationCacheTable) DECL_CAST(CompilationCacheTable)
private: private:
static Handle<CompilationCacheTable> EnsureScriptTableCapacity( void RemoveEntry(int entry_index);
Isolate* isolate, Handle<CompilationCacheTable> cache);
OBJECT_CONSTRUCTORS(CompilationCacheTable, OBJECT_CONSTRUCTORS(CompilationCacheTable,
HashTable<CompilationCacheTable, CompilationCacheShape>); HashTable<CompilationCacheTable, CompilationCacheShape>);
......
...@@ -238,12 +238,6 @@ Object HashTable<Derived, Shape>::KeyAt(PtrComprCageBase cage_base, ...@@ -238,12 +238,6 @@ Object HashTable<Derived, Shape>::KeyAt(PtrComprCageBase cage_base,
return get(cage_base, EntryToIndex(entry) + kEntryKeyIndex, tag); return get(cage_base, EntryToIndex(entry) + kEntryKeyIndex, tag);
} }
template <typename Derived, typename Shape>
void HashTable<Derived, Shape>::SetKeyAt(InternalIndex entry, Object value,
WriteBarrierMode mode) {
set_key(EntryToIndex(entry), value, mode);
}
template <typename Derived, typename Shape> template <typename Derived, typename Shape>
void HashTable<Derived, Shape>::set_key(int index, Object value) { void HashTable<Derived, Shape>::set_key(int index, Object value) {
DCHECK(!IsEphemeronHashTable()); DCHECK(!IsEphemeronHashTable());
......
...@@ -165,9 +165,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable ...@@ -165,9 +165,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
inline Object KeyAt(PtrComprCageBase cage_base, InternalIndex entry, inline Object KeyAt(PtrComprCageBase cage_base, InternalIndex entry,
RelaxedLoadTag tag); RelaxedLoadTag tag);
inline void SetKeyAt(InternalIndex entry, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize; static const int kElementsStartIndex = kPrefixStartIndex + Shape::kPrefixSize;
static const int kEntrySize = Shape::kEntrySize; static const int kEntrySize = Shape::kEntrySize;
static_assert(kEntrySize > 0); static_assert(kEntrySize > 0);
......
This diff is collapsed.
...@@ -23855,25 +23855,23 @@ TEST(StreamingWithHarmonyScopes) { ...@@ -23855,25 +23855,23 @@ TEST(StreamingWithHarmonyScopes) {
delete[] full_source; delete[] full_source;
} }
namespace { // Regression test for crbug.com/v8/12668. Verifies that after a streamed script
void StreamingWithIsolateScriptCache(bool run_gc) { // is inserted into the isolate script cache, a non-streamed script with
i::FLAG_expose_gc = true; // identical origin can reuse that data.
TEST(StreamingWithIsolateScriptCache) {
const char* chunks[] = {"'use strict'; (function test() { return 13; })", const char* chunks[] = {"'use strict'; (function test() { return 13; })",
nullptr}; nullptr};
const char* full_source = chunks[0]; const char* full_source = chunks[0];
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
auto i_isolate = reinterpret_cast<i::Isolate*>(isolate);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
v8::ScriptOrigin origin(isolate, v8_str("http://foo.com"), 0, 0, false, -1, v8::ScriptOrigin origin(isolate, v8_str("http://foo.com"), 0, 0, false, -1,
v8::Local<v8::Value>(), false, false, false); v8::Local<v8::Value>(), false, false, false);
v8::Local<Value> first_function_untyped;
i::Handle<i::JSFunction> first_function; i::Handle<i::JSFunction> first_function;
i::Handle<i::JSFunction> second_function; i::Handle<i::JSFunction> second_function;
// Run the script using streaming. // Run the script using streaming.
{ {
LocalContext env; LocalContext env;
v8::EscapableHandleScope inner_scope(isolate);
v8::ScriptCompiler::StreamedSource source( v8::ScriptCompiler::StreamedSource source(
std::make_unique<TestSourceStream>(chunks), std::make_unique<TestSourceStream>(chunks),
...@@ -23888,38 +23886,13 @@ void StreamingWithIsolateScriptCache(bool run_gc) { ...@@ -23888,38 +23886,13 @@ void StreamingWithIsolateScriptCache(bool run_gc) {
origin) origin)
.ToLocalChecked(); .ToLocalChecked();
v8::Local<Value> result(script->Run(env.local()).ToLocalChecked()); v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
first_function_untyped = inner_scope.Escape(result); first_function =
i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*result));
if (run_gc) {
// Age the top-level bytecode for the script to encourage the Isolate
// script cache to evict it. However, there are still active Handles
// referring to functions in that script, so the script itself should stay
// alive and reachable via the Isolate script cache.
i::Handle<i::JSFunction> script_function =
i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*script));
i::Handle<i::BytecodeArray> script_bytecode(
script_function->shared().GetBytecodeArray(i_isolate), i_isolate);
for (int i = 0; i < 5; ++i) {
script_bytecode->MakeOlder();
}
}
} }
first_function = i::Handle<i::JSFunction>::cast(
v8::Utils::OpenHandle(*first_function_untyped));
// Run the same script in another Context without streaming. // Run the same script in another Context without streaming.
{ {
LocalContext env; LocalContext env;
if (run_gc) {
// Perform garbage collection, which should remove the top-level
// SharedFunctionInfo from the Isolate script cache. However, the
// corresponding Script is still reachable and therefore still present in
// the Isolate script cache.
CompileRun("gc();");
}
v8::ScriptCompiler::Source script_source(v8_str(full_source), origin); v8::ScriptCompiler::Source script_source(v8_str(full_source), origin);
Local<Script> script = Local<Script> script =
v8::ScriptCompiler::Compile(env.local(), &script_source) v8::ScriptCompiler::Compile(env.local(), &script_source)
...@@ -23933,32 +23906,6 @@ void StreamingWithIsolateScriptCache(bool run_gc) { ...@@ -23933,32 +23906,6 @@ void StreamingWithIsolateScriptCache(bool run_gc) {
// SharedFunctionInfo instance due to the isolate script cache. // SharedFunctionInfo instance due to the isolate script cache.
CHECK_EQ(first_function->shared(), second_function->shared()); CHECK_EQ(first_function->shared(), second_function->shared());
} }
} // namespace
// Regression test for crbug.com/v8/12668. Verifies that after a streamed script
// is inserted into the isolate script cache, a non-streamed script with
// identical origin can reuse that data.
TEST(StreamingWithIsolateScriptCache) {
StreamingWithIsolateScriptCache(false);
}
// Variant of the above test which evicts the root SharedFunctionInfo from the
// Isolate script cache but still reuses the same Script.
TEST(StreamingWithIsolateScriptCacheClearingRootSFI) {
// TODO(v8:12808): Remove this check once background compilation is capable of
// reusing an existing Script.
if (v8::internal::FLAG_stress_background_compile) {
return;
}
// If the compiler is configured to not recompile a flushed root SFI, then
// this test is invalid.
if (!v8::internal::FLAG_isolate_script_cache_recompilation) {
return;
}
StreamingWithIsolateScriptCache(true);
}
TEST(CodeCache) { TEST(CodeCache) {
v8::Isolate::CreateParams create_params; v8::Isolate::CreateParams create_params;
...@@ -1820,9 +1820,10 @@ TEST(CodeSerializerPromotedToCompilationCache) { ...@@ -1820,9 +1820,10 @@ TEST(CodeSerializerPromotedToCompilationCache) {
ScriptDetails script_details(src); ScriptDetails script_details(src);
script_details.host_defined_options = script_details.host_defined_options =
default_script_details.host_defined_options; default_script_details.host_defined_options;
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK_EQ(*lookup_result.toplevel_sfi().ToHandleChecked(), *copy); LanguageMode::kSloppy);
CHECK_EQ(*shared.ToHandleChecked(), *copy);
} }
{ {
...@@ -1836,9 +1837,10 @@ TEST(CodeSerializerPromotedToCompilationCache) { ...@@ -1836,9 +1837,10 @@ TEST(CodeSerializerPromotedToCompilationCache) {
default_host_defined_option_1_string); default_host_defined_option_1_string);
host_defined_options->set(1, *host_defined_option_1); host_defined_options->set(1, *host_defined_option_1);
script_details.host_defined_options = host_defined_options; script_details.host_defined_options = host_defined_options;
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK_EQ(*lookup_result.toplevel_sfi().ToHandleChecked(), *copy); LanguageMode::kSloppy);
CHECK_EQ(*shared.ToHandleChecked(), *copy);
} }
{ {
...@@ -1847,48 +1849,49 @@ TEST(CodeSerializerPromotedToCompilationCache) { ...@@ -1847,48 +1849,49 @@ TEST(CodeSerializerPromotedToCompilationCache) {
isolate->factory()->NewStringFromAsciiChecked(source)); isolate->factory()->NewStringFromAsciiChecked(source));
script_details.host_defined_options = script_details.host_defined_options =
default_script_details.host_defined_options; default_script_details.host_defined_options;
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK_EQ(*lookup_result.toplevel_sfi().ToHandleChecked(), *copy); LanguageMode::kSloppy);
CHECK_EQ(*shared.ToHandleChecked(), *copy);
} }
{ {
// Lookup with different name string should fail: // Lookup with different name string should fail:
ScriptDetails script_details( ScriptDetails script_details(
isolate->factory()->NewStringFromAsciiChecked("other")); isolate->factory()->NewStringFromAsciiChecked("other"));
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK(lookup_result.script().is_null() && LanguageMode::kSloppy);
lookup_result.toplevel_sfi().is_null()); CHECK(shared.is_null());
} }
{ {
// Lookup with different position should fail: // Lookup with different position should fail:
ScriptDetails script_details(src); ScriptDetails script_details(src);
script_details.line_offset = 0xFF; script_details.line_offset = 0xFF;
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK(lookup_result.script().is_null() && LanguageMode::kSloppy);
lookup_result.toplevel_sfi().is_null()); CHECK(shared.is_null());
} }
{ {
// Lookup with different position should fail: // Lookup with different position should fail:
ScriptDetails script_details(src); ScriptDetails script_details(src);
script_details.column_offset = 0xFF; script_details.column_offset = 0xFF;
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK(lookup_result.script().is_null() && LanguageMode::kSloppy);
lookup_result.toplevel_sfi().is_null()); CHECK(shared.is_null());
} }
{ {
// Lookup with different language mode should fail: // Lookup with different language mode should fail:
ScriptDetails script_details(src); ScriptDetails script_details(src);
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kStrict); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK(lookup_result.script().is_null() && LanguageMode::kStrict);
lookup_result.toplevel_sfi().is_null()); CHECK(shared.is_null());
} }
{ {
...@@ -1896,20 +1899,20 @@ TEST(CodeSerializerPromotedToCompilationCache) { ...@@ -1896,20 +1899,20 @@ TEST(CodeSerializerPromotedToCompilationCache) {
ScriptOriginOptions origin_options(false, true); ScriptOriginOptions origin_options(false, true);
CHECK_NE(ScriptOriginOptions().Flags(), origin_options.Flags()); CHECK_NE(ScriptOriginOptions().Flags(), origin_options.Flags());
ScriptDetails script_details(src, origin_options); ScriptDetails script_details(src, origin_options);
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK(lookup_result.script().is_null() && LanguageMode::kSloppy);
lookup_result.toplevel_sfi().is_null()); CHECK(shared.is_null());
} }
{ {
// Lookup with different host_defined_options should fail: // Lookup with different host_defined_options should fail:
ScriptDetails script_details(src); ScriptDetails script_details(src);
script_details.host_defined_options = isolate->factory()->NewFixedArray(5); script_details.host_defined_options = isolate->factory()->NewFixedArray(5);
auto lookup_result = isolate->compilation_cache()->LookupScript( MaybeHandle<SharedFunctionInfo> shared =
src, script_details, LanguageMode::kSloppy); isolate->compilation_cache()->LookupScript(src, script_details,
CHECK(lookup_result.script().is_null() && LanguageMode::kSloppy);
lookup_result.toplevel_sfi().is_null()); CHECK(shared.is_null());
} }
delete cache; delete cache;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment