Commit f0696b4c authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[cache] Remove native context params from script cache

Remove the requirement to pass the native context into the script cache,
simple to be able to access the empty function. Instead, for script
cache keys, use Smi::zero() in the 'owner function' slot.

This allows CompileUnboundScript to be called outside of a Context
scope.

Change-Id: I9b4fe6dd43f14944728664f7203b748ced750e76
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2794440
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73737}
parent 3a1730f3
......@@ -145,7 +145,7 @@ bool CompilationCacheScript::HasOrigin(Handle<SharedFunctionInfo> function_info,
MaybeHandle<SharedFunctionInfo> CompilationCacheScript::Lookup(
Handle<String> source, MaybeHandle<Object> name, int line_offset,
int column_offset, ScriptOriginOptions resource_options,
Handle<Context> native_context, LanguageMode language_mode) {
LanguageMode language_mode) {
MaybeHandle<SharedFunctionInfo> result;
// Probe the script generation tables. Make sure not to leak handles
......@@ -156,7 +156,7 @@ MaybeHandle<SharedFunctionInfo> CompilationCacheScript::Lookup(
DCHECK_EQ(generations(), 1);
Handle<CompilationCacheTable> table = GetTable(generation);
MaybeHandle<SharedFunctionInfo> probe = CompilationCacheTable::LookupScript(
table, source, native_context, language_mode);
table, source, language_mode, isolate());
Handle<SharedFunctionInfo> function_info;
if (probe.ToHandle(&function_info)) {
// Break when we've found a suitable shared function info that
......@@ -188,13 +188,12 @@ MaybeHandle<SharedFunctionInfo> CompilationCacheScript::Lookup(
}
void CompilationCacheScript::Put(Handle<String> source,
Handle<Context> native_context,
LanguageMode language_mode,
Handle<SharedFunctionInfo> function_info) {
HandleScope scope(isolate());
Handle<CompilationCacheTable> table = GetFirstTable();
SetFirstTable(CompilationCacheTable::PutScript(table, source, native_context,
language_mode, function_info));
SetFirstTable(CompilationCacheTable::PutScript(table, source, language_mode,
function_info, isolate()));
}
InfoCellPair CompilationCacheEval::Lookup(Handle<String> source,
......@@ -331,11 +330,11 @@ void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) {
MaybeHandle<SharedFunctionInfo> CompilationCache::LookupScript(
Handle<String> source, MaybeHandle<Object> name, int line_offset,
int column_offset, ScriptOriginOptions resource_options,
Handle<Context> native_context, LanguageMode language_mode) {
LanguageMode language_mode) {
if (!IsEnabledScriptAndEval()) return MaybeHandle<SharedFunctionInfo>();
return script_.Lookup(source, name, line_offset, column_offset,
resource_options, native_context, language_mode);
resource_options, language_mode);
}
InfoCellPair CompilationCache::LookupEval(Handle<String> source,
......@@ -378,13 +377,12 @@ MaybeHandle<Code> CompilationCache::LookupCode(Handle<SharedFunctionInfo> sfi) {
}
void CompilationCache::PutScript(Handle<String> source,
Handle<Context> native_context,
LanguageMode language_mode,
Handle<SharedFunctionInfo> function_info) {
if (!IsEnabledScriptAndEval()) return;
LOG(isolate(), CompilationCacheEvent("put", "script", *function_info));
script_.Put(source, native_context, language_mode, function_info);
script_.Put(source, language_mode, function_info);
}
void CompilationCache::PutEval(Handle<String> source,
......
......@@ -85,11 +85,9 @@ class CompilationCacheScript : public CompilationSubCache {
MaybeHandle<Object> name,
int line_offset, int column_offset,
ScriptOriginOptions resource_options,
Handle<Context> native_context,
LanguageMode language_mode);
void Put(Handle<String> source, Handle<Context> context,
LanguageMode language_mode,
void Put(Handle<String> source, LanguageMode language_mode,
Handle<SharedFunctionInfo> function_info);
void Age() override;
......@@ -193,7 +191,7 @@ class V8_EXPORT_PRIVATE CompilationCache {
MaybeHandle<SharedFunctionInfo> LookupScript(
Handle<String> source, MaybeHandle<Object> name, int line_offset,
int column_offset, ScriptOriginOptions resource_options,
Handle<Context> native_context, LanguageMode language_mode);
LanguageMode language_mode);
// Finds the shared function info for a source string for eval in a
// given context. Returns an empty handle if the cache doesn't
......@@ -212,8 +210,7 @@ class V8_EXPORT_PRIVATE CompilationCache {
// Associate the (source, kind) pair to the shared function
// info. This may overwrite an existing mapping.
void PutScript(Handle<String> source, Handle<Context> native_context,
LanguageMode language_mode,
void PutScript(Handle<String> source, LanguageMode language_mode,
Handle<SharedFunctionInfo> function_info);
// Associate the (source, context->closure()->shared(), kind) triple
......
......@@ -2874,8 +2874,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
// First check per-isolate compilation cache.
maybe_result = compilation_cache->LookupScript(
source, script_details.name_obj, script_details.line_offset,
script_details.column_offset, origin_options, isolate->native_context(),
language_mode);
script_details.column_offset, origin_options, language_mode);
if (!maybe_result.is_null()) {
compile_timer.set_hit_isolate_cache();
} else if (can_consume_code_cache) {
......@@ -2894,8 +2893,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
// Promote to per-isolate compilation cache.
is_compiled_scope = inner_result->is_compiled_scope(isolate);
DCHECK(is_compiled_scope.is_compiled());
compilation_cache->PutScript(source, isolate->native_context(),
language_mode, inner_result);
compilation_cache->PutScript(source, language_mode, inner_result);
Handle<Script> script(Script::cast(inner_result->script()), isolate);
maybe_result = inner_result;
} else {
......@@ -2933,8 +2931,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
Handle<SharedFunctionInfo> result;
if (use_compilation_cache && maybe_result.ToHandle(&result)) {
DCHECK(is_compiled_scope.is_compiled());
compilation_cache->PutScript(source, isolate->native_context(),
language_mode, result);
compilation_cache->PutScript(source, language_mode, result);
} else if (maybe_result.is_null() && natives != EXTENSION_CODE) {
isolate->ReportPendingMessages();
}
......@@ -3064,8 +3061,7 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
"V8.StreamingFinalization.CheckCache");
maybe_result = compilation_cache->LookupScript(
source, script_details.name_obj, script_details.line_offset,
script_details.column_offset, origin_options, isolate->native_context(),
task->language_mode());
script_details.column_offset, origin_options, task->language_mode());
if (!maybe_result.is_null()) {
compile_timer.set_hit_isolate_cache();
}
......@@ -3156,8 +3152,7 @@ Compiler::GetSharedFunctionInfoForStreamedScript(
// Add compiled code to the isolate cache.
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.StreamingFinalization.AddToCache");
compilation_cache->PutScript(source, isolate->native_context(),
task->language_mode(), result);
compilation_cache->PutScript(source, task->language_mode(), result);
}
}
......
......@@ -43,10 +43,18 @@ uint32_t CompilationCacheShape::StringSharedHash(String source,
// collection.
Script script(Script::cast(shared.script()));
hash ^= String::cast(script.source()).EnsureHash();
STATIC_ASSERT(LanguageModeSize == 2);
if (is_strict(language_mode)) hash ^= 0x8000;
hash += position;
}
STATIC_ASSERT(LanguageModeSize == 2);
if (is_strict(language_mode)) hash ^= 0x8000;
hash += position;
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;
}
......@@ -64,13 +72,19 @@ uint32_t CompilationCacheShape::HashForObject(ReadOnlyRoots roots,
FixedArray val = FixedArray::cast(object);
if (val.map() == roots.fixed_cow_array_map()) {
DCHECK_EQ(4, val.length());
SharedFunctionInfo shared = SharedFunctionInfo::cast(val.get(0));
String source = String::cast(val.get(1));
int language_unchecked = Smi::ToInt(val.get(2));
DCHECK(is_valid_language_mode(language_unchecked));
LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
int position = Smi::ToInt(val.get(3));
return StringSharedHash(source, shared, language_mode, position);
Object shared_or_smi = val.get(0);
if (shared_or_smi.IsSmi()) {
DCHECK_EQ(position, kNoSourcePosition);
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
......
......@@ -151,6 +151,14 @@ class StringSharedKey : public HashTableKey {
language_mode_(language_mode),
position_(position) {}
// This tuple unambiguously identifies script compilation.
StringSharedKey(Handle<String> source, LanguageMode language_mode)
: HashTableKey(
CompilationCacheShape::StringSharedHash(*source, language_mode)),
source_(source),
language_mode_(language_mode),
position_(kNoSourcePosition) {}
bool IsMatch(Object other) override {
DisallowGarbageCollection no_gc;
if (!other.IsFixedArray()) {
......@@ -159,8 +167,14 @@ class StringSharedKey : public HashTableKey {
return Hash() == other_hash;
}
FixedArray other_array = FixedArray::cast(other);
SharedFunctionInfo shared = SharedFunctionInfo::cast(other_array.get(0));
if (shared != *shared_) return false;
DCHECK(other_array.get(0).IsSharedFunctionInfo() ||
other_array.get(0) == Smi::zero());
Handle<SharedFunctionInfo> shared;
if (shared_.ToHandle(&shared)) {
if (*shared != other_array.get(0)) return false;
} else {
if (Smi::zero() != other_array.get(0)) return false;
}
int language_unchecked = Smi::ToInt(other_array.get(2));
DCHECK(is_valid_language_mode(language_unchecked));
LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
......@@ -173,7 +187,12 @@ class StringSharedKey : public HashTableKey {
Handle<Object> AsHandle(Isolate* isolate) {
Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
array->set(0, *shared_);
Handle<SharedFunctionInfo> shared;
if (shared_.ToHandle(&shared)) {
array->set(0, *shared);
} else {
array->set(0, Smi::zero());
}
array->set(1, *source_);
array->set(2, Smi::FromEnum(language_mode_));
array->set(3, Smi::FromInt(position_));
......@@ -183,7 +202,7 @@ class StringSharedKey : public HashTableKey {
private:
Handle<String> source_;
Handle<SharedFunctionInfo> shared_;
MaybeHandle<SharedFunctionInfo> shared_;
LanguageMode language_mode_;
int position_;
};
......@@ -227,16 +246,9 @@ class CodeKey : public HashTableKey {
MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
Handle<CompilationCacheTable> table, Handle<String> src,
Handle<Context> native_context, LanguageMode language_mode) {
// We use the empty function SFI as part of the key. Although the
// empty_function is native context dependent, the SFI is de-duped on
// snapshot builds by the StartupObjectCache, and so this does not prevent
// reuse of scripts in the compilation cache across native contexts.
Handle<SharedFunctionInfo> shared(native_context->empty_function().shared(),
native_context->GetIsolate());
Isolate* isolate = native_context->GetIsolate();
LanguageMode language_mode, Isolate* isolate) {
src = String::Flatten(isolate, src);
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
StringSharedKey key(src, language_mode);
InternalIndex entry = table->FindEntry(isolate, &key);
if (entry.is_not_found()) return MaybeHandle<SharedFunctionInfo>();
int index = EntryToIndex(entry);
......@@ -245,7 +257,7 @@ MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
}
Object obj = table->get(index + 1);
if (obj.IsSharedFunctionInfo()) {
return handle(SharedFunctionInfo::cast(obj), native_context->GetIsolate());
return handle(SharedFunctionInfo::cast(obj), isolate);
}
return MaybeHandle<SharedFunctionInfo>();
}
......@@ -295,17 +307,10 @@ MaybeHandle<Code> CompilationCacheTable::LookupCode(
Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
Handle<CompilationCacheTable> cache, Handle<String> src,
Handle<Context> native_context, LanguageMode language_mode,
Handle<SharedFunctionInfo> value) {
Isolate* isolate = native_context->GetIsolate();
// We use the empty function SFI as part of the key. Although the
// empty_function is native context dependent, the SFI is de-duped on
// snapshot builds by the StartupObjectCache, and so this does not prevent
// reuse of scripts in the compilation cache across native contexts.
Handle<SharedFunctionInfo> shared(native_context->empty_function().shared(),
isolate);
LanguageMode language_mode, Handle<SharedFunctionInfo> value,
Isolate* isolate) {
src = String::Flatten(isolate, src);
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
StringSharedKey key(src, language_mode);
Handle<Object> k = key.AsHandle(isolate);
cache = EnsureCapacity(isolate, cache);
InternalIndex entry = cache->FindInsertionEntry(isolate, key.Hash());
......
......@@ -34,6 +34,9 @@ class CompilationCacheShape : public BaseShape<HashTableKey*> {
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 const int kPrefixSize = 0;
......@@ -86,11 +89,11 @@ class CompilationCacheTable
// The 'script' cache contains SharedFunctionInfos.
static MaybeHandle<SharedFunctionInfo> LookupScript(
Handle<CompilationCacheTable> table, Handle<String> src,
Handle<Context> native_context, LanguageMode language_mode);
LanguageMode language_mode, Isolate* isolate);
static Handle<CompilationCacheTable> PutScript(
Handle<CompilationCacheTable> cache, Handle<String> src,
Handle<Context> native_context, LanguageMode language_mode,
Handle<SharedFunctionInfo> value);
LanguageMode language_mode, Handle<SharedFunctionInfo> value,
Isolate* isolate);
// Eval code only gets cached after a second probe for the
// code object. To do so, on first "put" only a hash identifying the
......
......@@ -1473,7 +1473,6 @@ TEST(CompilationCacheCachingBehavior) {
"};"
"foo();";
Handle<String> source = factory->InternalizeUtf8String(raw_source);
Handle<Context> native_context = isolate->native_context();
{
v8::HandleScope scope(CcTest::isolate());
......@@ -1486,7 +1485,7 @@ TEST(CompilationCacheCachingBehavior) {
MaybeHandle<SharedFunctionInfo> cached_script =
compilation_cache->LookupScript(source, Handle<Object>(), 0, 0,
v8::ScriptOriginOptions(true, false),
native_context, language_mode);
language_mode);
CHECK(!cached_script.is_null());
}
......@@ -1497,7 +1496,7 @@ TEST(CompilationCacheCachingBehavior) {
MaybeHandle<SharedFunctionInfo> cached_script =
compilation_cache->LookupScript(source, Handle<Object>(), 0, 0,
v8::ScriptOriginOptions(true, false),
native_context, language_mode);
language_mode);
CHECK(!cached_script.is_null());
// Progress code age until it's old and ready for GC.
......@@ -1517,7 +1516,7 @@ TEST(CompilationCacheCachingBehavior) {
MaybeHandle<SharedFunctionInfo> cached_script =
compilation_cache->LookupScript(source, Handle<Object>(), 0, 0,
v8::ScriptOriginOptions(true, false),
native_context, language_mode);
language_mode);
CHECK(cached_script.is_null());
}
}
......
......@@ -1730,8 +1730,7 @@ TEST(CodeSerializerPromotedToCompilationCache) {
MaybeHandle<SharedFunctionInfo> shared =
isolate->compilation_cache()->LookupScript(
src, src, 0, 0, v8::ScriptOriginOptions(), isolate->native_context(),
LanguageMode::kSloppy);
src, src, 0, 0, v8::ScriptOriginOptions(), LanguageMode::kSloppy);
CHECK(*shared.ToHandleChecked() == *copy);
......
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