Use outer language mode when storing streamed script in isolate cache

Currently, a streamed script which specifies 'use strict' is stored in
the isolate script cache with a key indicating that it is strict mode.
However, the keys should be based on the context executing the script,
not the content of the script, so that the next lookup can find the
entry without having to parse the script first.

Bug: v8:12668
Change-Id: Iaa76c00c431ad54a86ffd18b61cb4f67dc457b03
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3498220
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#79331}
This commit is contained in:
Seth Brenith 2022-03-01 09:28:38 -08:00 committed by V8 LUCI CQ
parent 6c3d4ddd3e
commit c2fa5fccb1
3 changed files with 57 additions and 16 deletions

View File

@ -1430,8 +1430,7 @@ BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
timer_(isolate->counters()->compile_script_on_background()),
start_position_(0),
end_position_(0),
function_literal_id_(kFunctionLiteralIdTopLevel),
language_mode_(flags_.outer_language_mode()) {
function_literal_id_(kFunctionLiteralIdTopLevel) {
VMState<PARSER> state(isolate);
LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile,
@ -1455,8 +1454,7 @@ BackgroundCompileTask::BackgroundCompileTask(
input_shared_info_(shared_info),
start_position_(shared_info->StartPosition()),
end_position_(shared_info->EndPosition()),
function_literal_id_(shared_info->function_literal_id()),
language_mode_(flags_.outer_language_mode()) {
function_literal_id_(shared_info->function_literal_id()) {
DCHECK(!shared_info->is_toplevel());
character_stream_->Seek(start_position_);
@ -1594,9 +1592,6 @@ void BackgroundCompileTask::Run(
function_literal_id_);
parser.UpdateStatistics(script_, &use_counts_, &total_preparse_skipped_);
// Save the language mode.
language_mode_ = info.language_mode();
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.CompileCodeBackground");
RCS_SCOPE(isolate, RuntimeCallCounterIdForCompile(&info),
@ -1628,9 +1623,6 @@ void BackgroundCompileTask::Run(
outer_function_sfi_ = isolate->heap()->NewPersistentMaybeHandle(maybe_result);
DCHECK(isolate->heap()->ContainsPersistentHandle(script_.location()));
persistent_handles_ = isolate->heap()->DetachPersistentHandles();
// Make sure the language mode didn't change.
DCHECK_EQ(language_mode_, info.language_mode());
}
MaybeHandle<SharedFunctionInfo> BackgroundCompileTask::FinalizeScript(
@ -3182,8 +3174,8 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.StreamingFinalization.CheckCache");
maybe_result = compilation_cache->LookupScript(source, script_details,
task->language_mode());
maybe_result = compilation_cache->LookupScript(
source, script_details, task->flags().outer_language_mode());
if (!maybe_result.is_null()) {
compile_timer.set_hit_isolate_cache();
}
@ -3204,7 +3196,8 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
// Add compiled code to the isolate cache.
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.StreamingFinalization.AddToCache");
compilation_cache->PutScript(source, task->language_mode(), result);
compilation_cache->PutScript(source, task->flags().outer_language_mode(),
result);
}
}

View File

@ -529,7 +529,6 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
void AbortFunction();
UnoptimizedCompileFlags flags() const { return flags_; }
LanguageMode language_mode() const { return language_mode_; }
private:
void ReportStatistics(Isolate* isolate);
@ -561,8 +560,6 @@ class V8_EXPORT_PRIVATE BackgroundCompileTask {
int start_position_;
int end_position_;
int function_literal_id_;
LanguageMode language_mode_;
};
// Contains all data which needs to be transmitted between threads for

View File

@ -24255,6 +24255,57 @@ TEST(StreamingWithHarmonyScopes) {
delete[] full_source;
}
// 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) {
const char* chunks[] = {"'use strict'; (function test() { return 13; })",
nullptr};
const char* full_source = chunks[0];
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
v8::ScriptOrigin origin(isolate, v8_str("http://foo.com"), 0, 0, false, -1,
v8::Local<v8::Value>(), false, false, false);
i::Handle<i::JSFunction> first_function;
i::Handle<i::JSFunction> second_function;
// Run the script using streaming.
{
LocalContext env;
v8::ScriptCompiler::StreamedSource source(
std::make_unique<TestSourceStream>(chunks),
v8::ScriptCompiler::StreamedSource::ONE_BYTE);
v8::ScriptCompiler::ScriptStreamingTask* task =
v8::ScriptCompiler::StartStreaming(isolate, &source,
v8::ScriptType::kClassic);
StreamerThread::StartThreadForTaskAndJoin(task);
delete task;
v8::Local<Script> script =
v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
origin)
.ToLocalChecked();
v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
first_function =
i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*result));
}
// Run the same script in another Context without streaming.
{
LocalContext env;
v8::ScriptCompiler::Source script_source(v8_str(full_source), origin);
Local<Script> script =
v8::ScriptCompiler::Compile(env.local(), &script_source)
.ToLocalChecked();
v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
second_function =
i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*result));
}
// The functions created by both copies of the script should refer to the same
// SharedFunctionInfo instance due to the isolate script cache.
CHECK_EQ(first_function->shared(), second_function->shared());
}
TEST(CodeCache) {
v8::Isolate::CreateParams create_params;