Revert "[sfi] Remove SFI function literal id field"
This reverts commit 1d4a1172f5
.
Reason for revert: https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8%20Linux%20-%20arm64%20-%20sim%20-%20MSAN/21989
Original change's description:
> [sfi] Remove SFI function literal id field
>
> SharedFunctionInfos store their original function literal's id. This is
> also their index in the Script's SFI list.
>
> The function literal id is only needed for lazy compilation and live edit,
> and access only has to be fast in the former. So, we can move the SFI
> function literal id field to UncompiledData, and if patching with live
> edit, or discarding compiled code, we can perform a slower linear search
> through the Script's SFI list.
>
> This is a reland of
> https://chromium-review.googlesource.com/c/v8/v8/+/1082480
> but caching the literal id on UncompiledData rather than always linearly
> searching the SFI list. Also, removes the unused runtime-liveedit.cc file
> instead of fixing it to support this change.
>
> Bug: chromium:818642
> Change-Id: I977bcca0dc72903ca476a7079d156cc8bbe88fde
> Reviewed-on: https://chromium-review.googlesource.com/1128854
> Reviewed-by: Yang Guo <yangguo@chromium.org>
> Reviewed-by: Marja Hölttä <marja@chromium.org>
> Reviewed-by: Camillo Bruni <cbruni@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Commit-Queue: Leszek Swirski <leszeks@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#54464}
TBR=ulan@chromium.org,marja@chromium.org,yangguo@chromium.org,kozyatinskiy@chromium.org,cbruni@chromium.org,leszeks@chromium.org,verwaest@chromium.org
Change-Id: Icee5ee3ab7688b93e2963f91debed65a58164534
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:818642
Reviewed-on: https://chromium-review.googlesource.com/1138276
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54466}
This commit is contained in:
parent
e3b4ffa9ba
commit
58578584d6
@ -623,9 +623,10 @@ Handle<JSFunction> Genesis::CreateEmptyFunction() {
|
||||
Handle<WeakFixedArray> infos = factory()->NewWeakFixedArray(2);
|
||||
script->set_shared_function_infos(*infos);
|
||||
empty_function->shared()->set_scope_info(*scope_info);
|
||||
empty_function->shared()->set_function_literal_id(1);
|
||||
empty_function->shared()->DontAdaptArguments();
|
||||
SharedFunctionInfo::SetScript(handle(empty_function->shared(), isolate()),
|
||||
script, 1);
|
||||
script);
|
||||
|
||||
return empty_function;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ void UnoptimizedCompileJob::PrepareOnMainThread(Isolate* isolate) {
|
||||
|
||||
unicode_cache_.reset(new UnicodeCache());
|
||||
parse_info_->set_unicode_cache(unicode_cache_.get());
|
||||
parse_info_->set_function_literal_id(shared_->FunctionLiteralId(isolate));
|
||||
parse_info_->set_function_literal_id(shared_->function_literal_id());
|
||||
if (V8_UNLIKELY(FLAG_runtime_stats)) {
|
||||
parse_info_->set_runtime_call_stats(new (parse_info_->zone())
|
||||
RuntimeCallStats());
|
||||
@ -196,7 +196,6 @@ void UnoptimizedCompileJob::PrepareOnMainThread(Isolate* isolate) {
|
||||
shared_->EndPosition() - offset));
|
||||
parse_info_->set_character_stream(std::move(stream));
|
||||
}
|
||||
|
||||
parser_.reset(new Parser(parse_info_.get()));
|
||||
parser_->DeserializeScopeChain(isolate, parse_info_.get(),
|
||||
parse_info_->maybe_outer_scope_info());
|
||||
|
@ -779,13 +779,12 @@ class FunctionDataMap : public ThreadVisitor {
|
||||
FunctionData{literal, should_restart});
|
||||
}
|
||||
|
||||
bool Lookup(Isolate* isolate, SharedFunctionInfo* sfi, FunctionData** data) {
|
||||
int function_literal_id = sfi->FunctionLiteralId(isolate);
|
||||
if (!sfi->script()->IsScript() || function_literal_id == -1) {
|
||||
bool Lookup(SharedFunctionInfo* sfi, FunctionData** data) {
|
||||
if (!sfi->script()->IsScript() || sfi->function_literal_id() == -1) {
|
||||
return false;
|
||||
}
|
||||
Script* script = Script::cast(sfi->script());
|
||||
return Lookup(script->id(), function_literal_id, data);
|
||||
return Lookup(script->id(), sfi->function_literal_id(), data);
|
||||
}
|
||||
|
||||
bool Lookup(Handle<Script> script, FunctionLiteral* literal,
|
||||
@ -800,20 +799,20 @@ class FunctionDataMap : public ThreadVisitor {
|
||||
if (obj->IsSharedFunctionInfo()) {
|
||||
SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
|
||||
FunctionData* data = nullptr;
|
||||
if (!Lookup(isolate, sfi, &data)) continue;
|
||||
if (!Lookup(sfi, &data)) continue;
|
||||
data->shared = handle(sfi, isolate);
|
||||
} else if (obj->IsJSFunction()) {
|
||||
JSFunction* js_function = JSFunction::cast(obj);
|
||||
SharedFunctionInfo* sfi = js_function->shared();
|
||||
FunctionData* data = nullptr;
|
||||
if (!Lookup(isolate, sfi, &data)) continue;
|
||||
if (!Lookup(sfi, &data)) continue;
|
||||
data->js_functions.emplace_back(js_function, isolate);
|
||||
} else if (obj->IsJSGeneratorObject()) {
|
||||
JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
|
||||
if (gen->is_closed()) continue;
|
||||
SharedFunctionInfo* sfi = gen->function()->shared();
|
||||
FunctionData* data = nullptr;
|
||||
if (!Lookup(isolate, sfi, &data)) continue;
|
||||
if (!Lookup(sfi, &data)) continue;
|
||||
data->running_generators.emplace_back(gen, isolate);
|
||||
}
|
||||
}
|
||||
@ -843,7 +842,7 @@ class FunctionDataMap : public ThreadVisitor {
|
||||
stack_position = FunctionData::BELOW_NON_DROPPABLE_FRAME;
|
||||
}
|
||||
FunctionData* data = nullptr;
|
||||
if (!Lookup(isolate, *sfi, &data)) continue;
|
||||
if (!Lookup(*sfi, &data)) continue;
|
||||
if (!data->should_restart) continue;
|
||||
data->stack_position = stack_position;
|
||||
*restart_frame_fp = frame->fp();
|
||||
@ -867,7 +866,7 @@ class FunctionDataMap : public ThreadVisitor {
|
||||
it.frame()->GetFunctions(&sfis);
|
||||
for (auto& sfi : sfis) {
|
||||
FunctionData* data = nullptr;
|
||||
if (!Lookup(isolate, *sfi, &data)) continue;
|
||||
if (!Lookup(*sfi, &data)) continue;
|
||||
data->stack_position = FunctionData::ARCHIVED_THREAD;
|
||||
}
|
||||
}
|
||||
@ -932,7 +931,7 @@ bool CanRestartFrame(Isolate* isolate, Address fp,
|
||||
JavaScriptFrame::cast(restart_frame)->GetFunctions(&sfis);
|
||||
for (auto& sfi : sfis) {
|
||||
FunctionData* data = nullptr;
|
||||
if (!function_data_map.Lookup(isolate, *sfi, &data)) continue;
|
||||
if (!function_data_map.Lookup(*sfi, &data)) continue;
|
||||
auto new_literal_it = changed.find(data->literal);
|
||||
if (new_literal_it == changed.end()) continue;
|
||||
if (new_literal_it->second->scope()->new_target_var()) {
|
||||
@ -1061,14 +1060,11 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
|
||||
new_script->shared_function_infos()->Get(
|
||||
mapping.second->function_literal_id());
|
||||
|
||||
sfi->set_function_literal_id(mapping.second->function_literal_id());
|
||||
sfi->set_script(*new_script);
|
||||
if (sfi->HasUncompiledData()) {
|
||||
sfi->uncompiled_data()->set_function_literal_id(
|
||||
mapping.second->function_literal_id());
|
||||
}
|
||||
new_script->shared_function_infos()->Set(
|
||||
mapping.second->function_literal_id(), HeapObjectReference::Weak(*sfi));
|
||||
DCHECK_EQ(sfi->FunctionLiteralId(isolate),
|
||||
DCHECK_EQ(sfi->function_literal_id(),
|
||||
mapping.second->function_literal_id());
|
||||
|
||||
// Swap the now-redundant, newly compiled SFI into the old script, so that
|
||||
@ -1080,16 +1076,12 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
|
||||
SharedFunctionInfo* redundant_new_sfi =
|
||||
SharedFunctionInfo::cast(redundant_new_sfi_obj);
|
||||
|
||||
redundant_new_sfi->set_function_literal_id(
|
||||
mapping.first->function_literal_id());
|
||||
redundant_new_sfi->set_script(*script);
|
||||
if (redundant_new_sfi->HasUncompiledData()) {
|
||||
redundant_new_sfi->uncompiled_data()->set_function_literal_id(
|
||||
mapping.first->function_literal_id());
|
||||
}
|
||||
script->shared_function_infos()->Set(
|
||||
mapping.first->function_literal_id(),
|
||||
HeapObjectReference::Weak(redundant_new_sfi));
|
||||
DCHECK_EQ(redundant_new_sfi->FunctionLiteralId(isolate),
|
||||
mapping.first->function_literal_id());
|
||||
}
|
||||
|
||||
if (sfi->HasUncompiledDataWithPreParsedScope()) {
|
||||
@ -1103,12 +1095,13 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
|
||||
}
|
||||
|
||||
if (!sfi->HasBytecodeArray()) continue;
|
||||
FixedArray* constants = sfi->GetBytecodeArray()->constant_pool();
|
||||
Handle<BytecodeArray> bytecode(sfi->GetBytecodeArray(), isolate);
|
||||
Handle<FixedArray> constants(bytecode->constant_pool(), isolate);
|
||||
for (int i = 0; i < constants->length(); ++i) {
|
||||
if (!constants->get(i)->IsSharedFunctionInfo()) continue;
|
||||
FunctionData* data = nullptr;
|
||||
if (!function_data_map.Lookup(
|
||||
isolate, SharedFunctionInfo::cast(constants->get(i)), &data)) {
|
||||
if (!function_data_map.Lookup(SharedFunctionInfo::cast(constants->get(i)),
|
||||
&data)) {
|
||||
continue;
|
||||
}
|
||||
auto change_it = changed.find(data->literal);
|
||||
@ -1160,7 +1153,7 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
|
||||
// inner_sfi, but the resulting FunctionData will still be referring to
|
||||
// the old, unchanged SFI.
|
||||
FunctionData* data = nullptr;
|
||||
if (!function_data_map.Lookup(isolate, inner_sfi, &data)) continue;
|
||||
if (!function_data_map.Lookup(inner_sfi, &data)) continue;
|
||||
Handle<SharedFunctionInfo> old_unchanged_inner_sfi =
|
||||
data->shared.ToHandleChecked();
|
||||
// Now some sanity checks. Make sure that this inner_sfi is not the
|
||||
@ -1171,21 +1164,17 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
|
||||
DCHECK_EQ(old_unchanged_inner_sfi->script(), *new_script);
|
||||
// ... and that the id of the unchanged SFI matches the unchanged target
|
||||
// literal's id.
|
||||
DCHECK_EQ(old_unchanged_inner_sfi->FunctionLiteralId(isolate),
|
||||
DCHECK_EQ(old_unchanged_inner_sfi->function_literal_id(),
|
||||
unchanged[data->literal]->function_literal_id());
|
||||
constants->set(i, *old_unchanged_inner_sfi);
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
{
|
||||
// Check that all the functions in the new script are valid and that their
|
||||
// function literals match what is expected.
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
// Check that all the functions in the new script are valid.
|
||||
SharedFunctionInfo::ScriptIterator it(isolate, *new_script);
|
||||
while (SharedFunctionInfo* sfi = it.Next()) {
|
||||
DCHECK_EQ(sfi->script(), *new_script);
|
||||
DCHECK_EQ(sfi->FunctionLiteralId(isolate), it.CurrentIndex());
|
||||
|
||||
if (!sfi->HasBytecodeArray()) continue;
|
||||
// Check that all the functions in this function's constant pool are also
|
||||
@ -1198,7 +1187,7 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
|
||||
SharedFunctionInfo::cast(constants->get(i));
|
||||
DCHECK_EQ(inner_sfi->script(), *new_script);
|
||||
DCHECK_EQ(inner_sfi, new_script->shared_function_infos()
|
||||
->Get(inner_sfi->FunctionLiteralId(isolate))
|
||||
->Get(inner_sfi->function_literal_id())
|
||||
->GetHeapObject());
|
||||
}
|
||||
}
|
||||
|
@ -2514,21 +2514,19 @@ Handle<PreParsedScopeData> Factory::NewPreParsedScopeData(int length) {
|
||||
|
||||
Handle<UncompiledDataWithoutPreParsedScope>
|
||||
Factory::NewUncompiledDataWithoutPreParsedScope(int32_t start_position,
|
||||
int32_t end_position,
|
||||
int32_t function_literal_id) {
|
||||
int32_t end_position) {
|
||||
Handle<UncompiledDataWithoutPreParsedScope> result(
|
||||
UncompiledDataWithoutPreParsedScope::cast(
|
||||
New(uncompiled_data_without_pre_parsed_scope_map(), TENURED)),
|
||||
isolate());
|
||||
result->set_start_position(start_position);
|
||||
result->set_end_position(end_position);
|
||||
result->set_function_literal_id(function_literal_id);
|
||||
return result;
|
||||
}
|
||||
|
||||
Handle<UncompiledDataWithPreParsedScope>
|
||||
Factory::NewUncompiledDataWithPreParsedScope(
|
||||
int32_t start_position, int32_t end_position, int32_t function_literal_id,
|
||||
int32_t start_position, int32_t end_position,
|
||||
Handle<PreParsedScopeData> pre_parsed_scope_data) {
|
||||
Handle<UncompiledDataWithPreParsedScope> result(
|
||||
UncompiledDataWithPreParsedScope::cast(
|
||||
@ -2536,7 +2534,6 @@ Factory::NewUncompiledDataWithPreParsedScope(
|
||||
isolate());
|
||||
result->set_start_position(start_position);
|
||||
result->set_end_position(end_position);
|
||||
result->set_function_literal_id(function_literal_id);
|
||||
result->set_pre_parsed_scope_data(*pre_parsed_scope_data);
|
||||
return result;
|
||||
}
|
||||
@ -3419,8 +3416,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForLiteral(
|
||||
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfoForBuiltin(
|
||||
literal->name(), Builtins::kCompileLazy, kind);
|
||||
SharedFunctionInfo::InitFromFunctionLiteral(shared, literal, is_toplevel);
|
||||
SharedFunctionInfo::SetScript(shared, script, literal->function_literal_id(),
|
||||
false);
|
||||
SharedFunctionInfo::SetScript(shared, script, false);
|
||||
return shared;
|
||||
}
|
||||
|
||||
@ -3508,6 +3504,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
||||
share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
|
||||
share->set_function_identifier_or_debug_info(*undefined_value(),
|
||||
SKIP_WRITE_BARRIER);
|
||||
share->set_function_literal_id(FunctionLiteral::kIdTypeInvalid);
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
|
||||
#endif
|
||||
|
@ -728,12 +728,10 @@ class V8_EXPORT_PRIVATE Factory {
|
||||
|
||||
Handle<UncompiledDataWithoutPreParsedScope>
|
||||
NewUncompiledDataWithoutPreParsedScope(int32_t start_position,
|
||||
int32_t end_position,
|
||||
int32_t function_literal_id);
|
||||
int32_t end_position);
|
||||
|
||||
Handle<UncompiledDataWithPreParsedScope> NewUncompiledDataWithPreParsedScope(
|
||||
int32_t start_position, int32_t end_position, int32_t function_literal_id,
|
||||
Handle<PreParsedScopeData>);
|
||||
int32_t start_position, int32_t end_position, Handle<PreParsedScopeData>);
|
||||
|
||||
// Create an External object for V8's external API.
|
||||
Handle<JSObject> NewExternal(void* value);
|
||||
|
@ -12895,8 +12895,9 @@ void Map::SetPrototype(Isolate* isolate, Handle<Map> map,
|
||||
map->set_prototype(*prototype, wb_mode);
|
||||
}
|
||||
|
||||
Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
|
||||
Handle<Map> initial_map) {
|
||||
|
||||
Handle<Object> CacheInitialJSArrayMaps(
|
||||
Handle<Context> native_context, Handle<Map> initial_map) {
|
||||
// Replace all of the cached initial array maps in the native context with
|
||||
// the appropriate transitioned elements kind maps.
|
||||
Handle<Map> current_map = initial_map;
|
||||
@ -13017,6 +13018,7 @@ void JSFunction::SetPrototype(Handle<JSFunction> function,
|
||||
SetInstancePrototype(isolate, function, construct_prototype);
|
||||
}
|
||||
|
||||
|
||||
void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
|
||||
Handle<Object> prototype) {
|
||||
if (map->prototype() != *prototype)
|
||||
@ -13734,8 +13736,8 @@ SharedFunctionInfo* SharedFunctionInfo::GlobalIterator::Next() {
|
||||
|
||||
void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
|
||||
Handle<Object> script_object,
|
||||
int function_literal_id,
|
||||
bool reset_preparsed_scope_data) {
|
||||
DCHECK_NE(shared->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
|
||||
if (shared->script() == *script_object) return;
|
||||
Isolate* isolate = shared->GetIsolate();
|
||||
|
||||
@ -13753,14 +13755,15 @@ void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
|
||||
Handle<WeakFixedArray> list =
|
||||
handle(script->shared_function_infos(), isolate);
|
||||
#ifdef DEBUG
|
||||
DCHECK_LT(function_literal_id, list->length());
|
||||
MaybeObject* maybe_object = list->Get(function_literal_id);
|
||||
DCHECK_LT(shared->function_literal_id(), list->length());
|
||||
MaybeObject* maybe_object = list->Get(shared->function_literal_id());
|
||||
HeapObject* heap_object;
|
||||
if (maybe_object->ToWeakHeapObject(&heap_object)) {
|
||||
DCHECK_EQ(heap_object, *shared);
|
||||
}
|
||||
#endif
|
||||
list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
|
||||
list->Set(shared->function_literal_id(),
|
||||
HeapObjectReference::Weak(*shared));
|
||||
} else {
|
||||
Handle<Object> list = isolate->factory()->noscript_shared_function_infos();
|
||||
|
||||
@ -13786,14 +13789,15 @@ void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
|
||||
// Due to liveedit, it might happen that the old_script doesn't know
|
||||
// about the SharedFunctionInfo, so we have to guard against that.
|
||||
Handle<WeakFixedArray> infos(old_script->shared_function_infos(), isolate);
|
||||
if (function_literal_id < infos->length()) {
|
||||
MaybeObject* raw =
|
||||
old_script->shared_function_infos()->Get(function_literal_id);
|
||||
if (shared->function_literal_id() < infos->length()) {
|
||||
MaybeObject* raw = old_script->shared_function_infos()->Get(
|
||||
shared->function_literal_id());
|
||||
HeapObject* heap_object;
|
||||
if (raw->ToWeakHeapObject(&heap_object) && heap_object == *shared) {
|
||||
old_script->shared_function_infos()->Set(
|
||||
function_literal_id, HeapObjectReference::Strong(
|
||||
ReadOnlyRoots(isolate).undefined_value()));
|
||||
shared->function_literal_id(),
|
||||
HeapObjectReference::Strong(
|
||||
ReadOnlyRoots(isolate).undefined_value()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -13906,27 +13910,6 @@ bool SharedFunctionInfo::IsInlineable() {
|
||||
|
||||
int SharedFunctionInfo::SourceSize() { return EndPosition() - StartPosition(); }
|
||||
|
||||
int SharedFunctionInfo::FindIndexInScript(Isolate* isolate) const {
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
Object* script_obj = script();
|
||||
if (!script_obj->IsScript()) return FunctionLiteral::kIdTypeInvalid;
|
||||
|
||||
WeakFixedArray* shared_info_list =
|
||||
Script::cast(script_obj)->shared_function_infos();
|
||||
SharedFunctionInfo::ScriptIterator iterator(
|
||||
isolate, Handle<WeakFixedArray>(&shared_info_list));
|
||||
|
||||
for (SharedFunctionInfo* shared = iterator.Next(); shared != nullptr;
|
||||
shared = iterator.Next()) {
|
||||
if (shared == this) {
|
||||
return iterator.CurrentIndex();
|
||||
}
|
||||
}
|
||||
|
||||
return FunctionLiteral::kIdTypeInvalid;
|
||||
}
|
||||
|
||||
void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
|
||||
bool has_prototype_slot,
|
||||
int requested_embedder_fields,
|
||||
@ -14069,6 +14052,7 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
|
||||
// FunctionKind must have already been set.
|
||||
DCHECK(lit->kind() == shared_info->kind());
|
||||
shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
|
||||
shared_info->set_function_literal_id(lit->function_literal_id());
|
||||
DCHECK_IMPLIES(lit->requires_instance_fields_initializer(),
|
||||
IsClassConstructor(lit->kind()));
|
||||
shared_info->set_requires_instance_fields_initializer(
|
||||
@ -14115,7 +14099,7 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
|
||||
Handle<UncompiledData> data =
|
||||
isolate->factory()->NewUncompiledDataWithPreParsedScope(
|
||||
lit->start_position(), lit->end_position(),
|
||||
lit->function_literal_id(), pre_parsed_scope_data);
|
||||
pre_parsed_scope_data);
|
||||
shared_info->set_uncompiled_data(*data);
|
||||
needs_position_info = false;
|
||||
}
|
||||
@ -14125,8 +14109,7 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
|
||||
if (needs_position_info) {
|
||||
Handle<UncompiledData> data =
|
||||
isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
|
||||
lit->start_position(), lit->end_position(),
|
||||
lit->function_literal_id());
|
||||
lit->start_position(), lit->end_position());
|
||||
shared_info->set_uncompiled_data(*data);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ void PreParsedScopeData::clear_padding() {
|
||||
CAST_ACCESSOR(UncompiledData)
|
||||
INT32_ACCESSORS(UncompiledData, start_position, kStartPositionOffset)
|
||||
INT32_ACCESSORS(UncompiledData, end_position, kEndPositionOffset)
|
||||
INT32_ACCESSORS(UncompiledData, function_literal_id, kFunctionLiteralIdOffset)
|
||||
|
||||
CAST_ACCESSOR(UncompiledDataWithoutPreParsedScope)
|
||||
|
||||
@ -78,6 +77,7 @@ ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
|
||||
ACCESSORS(SharedFunctionInfo, function_identifier_or_debug_info, Object,
|
||||
kFunctionIdentifierOrDebugInfoOffset)
|
||||
|
||||
INT_ACCESSORS(SharedFunctionInfo, function_literal_id, kFunctionLiteralIdOffset)
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
|
||||
#endif
|
||||
@ -650,21 +650,6 @@ WasmExportedFunctionData* SharedFunctionInfo::wasm_exported_function_data()
|
||||
return WasmExportedFunctionData::cast(function_data());
|
||||
}
|
||||
|
||||
int SharedFunctionInfo::FunctionLiteralId(Isolate* isolate) const {
|
||||
// Fast path for the common case when the SFI is uncompiled and so the
|
||||
// function literal id is already in the uncompiled data.
|
||||
if (HasUncompiledData()) {
|
||||
int id = uncompiled_data()->function_literal_id();
|
||||
// Make sure the id is what we should have found with the slow path.
|
||||
DCHECK_EQ(id, FindIndexInScript(isolate));
|
||||
return id;
|
||||
}
|
||||
|
||||
// Otherwise, search for the function in the SFI's script's function list,
|
||||
// and return its index in that list.
|
||||
return FindIndexInScript(isolate);
|
||||
}
|
||||
|
||||
bool SharedFunctionInfo::HasDebugInfo() const {
|
||||
return function_identifier_or_debug_info()->IsDebugInfo();
|
||||
}
|
||||
@ -752,11 +737,8 @@ void SharedFunctionInfo::DiscardCompiled(
|
||||
|
||||
int start_position = shared_info->StartPosition();
|
||||
int end_position = shared_info->EndPosition();
|
||||
int function_literal_id = shared_info->FunctionLiteralId(isolate);
|
||||
|
||||
if (shared_info->is_compiled()) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
HeapObject* outer_scope_info;
|
||||
if (shared_info->scope_info()->HasOuterScopeInfo()) {
|
||||
outer_scope_info = shared_info->scope_info()->OuterScopeInfo();
|
||||
@ -782,7 +764,7 @@ void SharedFunctionInfo::DiscardCompiled(
|
||||
// validity checks, since we're performing the unusual task of decompiling.
|
||||
Handle<UncompiledData> data =
|
||||
isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
|
||||
start_position, end_position, function_literal_id);
|
||||
start_position, end_position);
|
||||
shared_info->set_function_data(*data);
|
||||
}
|
||||
}
|
||||
|
@ -70,15 +70,13 @@ class UncompiledData : public HeapObject {
|
||||
public:
|
||||
DECL_INT32_ACCESSORS(start_position)
|
||||
DECL_INT32_ACCESSORS(end_position)
|
||||
DECL_INT32_ACCESSORS(function_literal_id)
|
||||
|
||||
DECL_CAST(UncompiledData)
|
||||
|
||||
#define UNCOMPILED_DATA_FIELDS(V) \
|
||||
V(kStartPositionOffset, kInt32Size) \
|
||||
V(kEndPositionOffset, kInt32Size) \
|
||||
V(kFunctionLiteralIdOffset, kInt32Size) \
|
||||
/* Total size. */ \
|
||||
#define UNCOMPILED_DATA_FIELDS(V) \
|
||||
V(kStartPositionOffset, kInt32Size) \
|
||||
V(kEndPositionOffset, kInt32Size) \
|
||||
/* Total size. */ \
|
||||
V(kUnalignedSize, 0)
|
||||
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, UNCOMPILED_DATA_FIELDS)
|
||||
@ -187,7 +185,7 @@ class SharedFunctionInfo : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
// function info is added to the list on the script.
|
||||
V8_EXPORT_PRIVATE static void SetScript(
|
||||
Handle<SharedFunctionInfo> shared, Handle<Object> script_object,
|
||||
int function_literal_id, bool reset_preparsed_scope_data = true);
|
||||
bool reset_preparsed_scope_data = true);
|
||||
|
||||
// Layout description of the optimized code map.
|
||||
static const int kEntriesStart = 0;
|
||||
@ -257,6 +255,11 @@ class SharedFunctionInfo : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
// function. The value is only reliable when the function has been compiled.
|
||||
DECL_UINT16_ACCESSORS(expected_nof_properties)
|
||||
|
||||
// [function_literal_id] - uniquely identifies the FunctionLiteral this
|
||||
// SharedFunctionInfo represents within its script, or -1 if this
|
||||
// SharedFunctionInfo object doesn't correspond to a parsed FunctionLiteral.
|
||||
DECL_INT_ACCESSORS(function_literal_id)
|
||||
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
// [unique_id] - For --trace-maps purposes, an identifier that's persistent
|
||||
// even if the GC moves this SharedFunctionInfo.
|
||||
@ -338,9 +341,6 @@ class SharedFunctionInfo : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
inline String* inferred_name();
|
||||
inline void set_inferred_name(String* inferred_name);
|
||||
|
||||
// Get the function literal id associated with this function, for parsing.
|
||||
inline int FunctionLiteralId(Isolate* isolate) const;
|
||||
|
||||
// The function is subject to debugging if a debug info is attached.
|
||||
inline bool HasDebugInfo() const;
|
||||
inline DebugInfo* GetDebugInfo() const;
|
||||
@ -530,7 +530,6 @@ class SharedFunctionInfo : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
ScriptIterator(Isolate* isolate,
|
||||
Handle<WeakFixedArray> shared_function_infos);
|
||||
SharedFunctionInfo* Next();
|
||||
int CurrentIndex() const { return index_ - 1; }
|
||||
|
||||
// Reset the iterator to run on |script|.
|
||||
void Reset(Script* script);
|
||||
@ -583,6 +582,7 @@ class SharedFunctionInfo : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
V(kFunctionIdentifierOrDebugInfoOffset, kPointerSize) \
|
||||
V(kEndOfPointerFieldsOffset, 0) \
|
||||
/* Raw data fields. */ \
|
||||
V(kFunctionLiteralIdOffset, kInt32Size) \
|
||||
V(kUniqueIdOffset, kUniqueIdFieldSize) \
|
||||
V(kLengthOffset, kUInt16Size) \
|
||||
V(kFormalParameterCountOffset, kUInt16Size) \
|
||||
@ -662,10 +662,6 @@ class SharedFunctionInfo : public HeapObject, public NeverReadOnlySpaceObject {
|
||||
|
||||
inline uint16_t length() const;
|
||||
|
||||
// Find the index of this function in the parent script. Slow path of
|
||||
// FunctionLiteralId.
|
||||
int FindIndexInScript(Isolate* isolate) const;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
|
||||
};
|
||||
|
||||
|
@ -68,7 +68,7 @@ ParseInfo::ParseInfo(Isolate* isolate, Handle<SharedFunctionInfo> shared)
|
||||
set_function_flags(shared->flags());
|
||||
set_start_position(shared->StartPosition());
|
||||
set_end_position(shared->EndPosition());
|
||||
function_literal_id_ = shared->FunctionLiteralId(isolate);
|
||||
function_literal_id_ = shared->function_literal_id();
|
||||
set_language_mode(shared->language_mode());
|
||||
set_asm_wasm_broken(shared->is_asm_wasm_broken());
|
||||
|
||||
|
@ -114,17 +114,16 @@ RUNTIME_FUNCTION(Runtime_SetCode) {
|
||||
bool was_native = target_shared->native();
|
||||
target_shared->set_flags(source_shared->flags());
|
||||
target_shared->set_native(was_native);
|
||||
target_shared->set_function_literal_id(source_shared->function_literal_id());
|
||||
|
||||
target_shared->set_scope_info(source_shared->scope_info());
|
||||
|
||||
Handle<Object> source_script(source_shared->script(), isolate);
|
||||
int function_literal_id = source_shared->FunctionLiteralId(isolate);
|
||||
if (source_script->IsScript()) {
|
||||
SharedFunctionInfo::SetScript(source_shared,
|
||||
isolate->factory()->undefined_value(),
|
||||
function_literal_id);
|
||||
isolate->factory()->undefined_value());
|
||||
}
|
||||
SharedFunctionInfo::SetScript(target_shared, source_script,
|
||||
function_literal_id);
|
||||
SharedFunctionInfo::SetScript(target_shared, source_script);
|
||||
|
||||
// Set the code of the target function.
|
||||
target->set_code(source_shared->GetCode());
|
||||
|
260
src/runtime/runtime-liveedit.cc
Normal file
260
src/runtime/runtime-liveedit.cc
Normal file
@ -0,0 +1,260 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/runtime/runtime-utils.h"
|
||||
|
||||
#include "src/arguments.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/debug/debug-frames.h"
|
||||
#include "src/debug/liveedit.h"
|
||||
#include "src/frames-inl.h"
|
||||
#include "src/isolate-inl.h"
|
||||
#include "src/runtime/runtime.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// For a script finds all SharedFunctionInfo's in the heap that points
|
||||
// to this script. Returns JSArray of SharedFunctionInfo wrapped
|
||||
// in OpaqueReferences.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditFindSharedFunctionInfosForScript) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(1, args.length());
|
||||
CONVERT_ARG_CHECKED(JSValue, script_value, 0);
|
||||
|
||||
CHECK(script_value->value()->IsScript());
|
||||
Handle<Script> script(Script::cast(script_value->value()), isolate);
|
||||
|
||||
std::vector<Handle<SharedFunctionInfo>> found;
|
||||
Heap* heap = isolate->heap();
|
||||
{
|
||||
HeapIterator iterator(heap);
|
||||
HeapObject* heap_obj;
|
||||
while ((heap_obj = iterator.next()) != nullptr) {
|
||||
if (!heap_obj->IsSharedFunctionInfo()) continue;
|
||||
SharedFunctionInfo* shared = SharedFunctionInfo::cast(heap_obj);
|
||||
if (shared->script() != *script) continue;
|
||||
found.push_back(Handle<SharedFunctionInfo>(shared, isolate));
|
||||
}
|
||||
}
|
||||
|
||||
int found_size = static_cast<int>(found.size());
|
||||
Handle<FixedArray> result = isolate->factory()->NewFixedArray(found_size);
|
||||
for (int i = 0; i < found_size; ++i) {
|
||||
Handle<SharedFunctionInfo> shared = found[i];
|
||||
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
|
||||
Handle<String> name(shared->Name(), isolate);
|
||||
info_wrapper.SetProperties(name, shared->StartPosition(),
|
||||
shared->EndPosition(), shared);
|
||||
result->set(i, *info_wrapper.GetJSArray());
|
||||
}
|
||||
return *isolate->factory()->NewJSArrayWithElements(result);
|
||||
}
|
||||
|
||||
|
||||
// For a script calculates compilation information about all its functions.
|
||||
// The script source is explicitly specified by the second argument.
|
||||
// The source of the actual script is not used, however it is important that
|
||||
// all generated code keeps references to this particular instance of script.
|
||||
// Returns a JSArray of compilation infos. The array is ordered so that
|
||||
// each function with all its descendant is always stored in a continues range
|
||||
// with the function itself going first. The root function is a script function.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditGatherCompileInfo) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_CHECKED(JSValue, script, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
|
||||
|
||||
CHECK(script->value()->IsScript());
|
||||
Handle<Script> script_handle(Script::cast(script->value()), isolate);
|
||||
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, LiveEdit::GatherCompileInfo(isolate, script_handle, source));
|
||||
}
|
||||
|
||||
|
||||
// Changes the source of the script to a new_source.
|
||||
// If old_script_name is provided (i.e. is a String), also creates a copy of
|
||||
// the script with its original source and sends notification to debugger.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditReplaceScript) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, old_script_name, 2);
|
||||
|
||||
CHECK(original_script_value->value()->IsScript());
|
||||
Handle<Script> original_script(Script::cast(original_script_value->value()),
|
||||
isolate);
|
||||
|
||||
Handle<Object> old_script = LiveEdit::ChangeScriptSource(
|
||||
isolate, original_script, new_source, old_script_name);
|
||||
|
||||
if (old_script->IsScript()) {
|
||||
Handle<Script> script_handle = Handle<Script>::cast(old_script);
|
||||
return *Script::GetWrapper(script_handle);
|
||||
} else {
|
||||
return ReadOnlyRoots(isolate).null_value();
|
||||
}
|
||||
}
|
||||
|
||||
// Recreate the shared function infos array after changing the IDs of all
|
||||
// SharedFunctionInfos.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditFixupScript) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 2);
|
||||
CONVERT_ARG_CHECKED(JSValue, script_value, 0);
|
||||
CONVERT_INT32_ARG_CHECKED(max_function_literal_id, 1);
|
||||
|
||||
CHECK(script_value->value()->IsScript());
|
||||
Handle<Script> script(Script::cast(script_value->value()), isolate);
|
||||
|
||||
LiveEdit::FixupScript(isolate, script, max_function_literal_id);
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSourceUpdated) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(args.length(), 2);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
|
||||
CONVERT_INT32_ARG_CHECKED(new_function_literal_id, 1);
|
||||
CHECK(SharedInfoWrapper::IsInstance(shared_info));
|
||||
|
||||
LiveEdit::FunctionSourceUpdated(shared_info, new_function_literal_id);
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Replaces code of SharedFunctionInfo with a new one.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditReplaceFunctionCode) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
|
||||
CHECK(SharedInfoWrapper::IsInstance(shared_info));
|
||||
|
||||
LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Connects SharedFunctionInfo to another script.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditFunctionSetScript) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, function_object, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, script_object, 1);
|
||||
|
||||
if (function_object->IsJSValue()) {
|
||||
Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
|
||||
if (script_object->IsJSValue()) {
|
||||
CHECK(JSValue::cast(*script_object)->value()->IsScript());
|
||||
Script* script = Script::cast(JSValue::cast(*script_object)->value());
|
||||
script_object = Handle<Object>(script, isolate);
|
||||
}
|
||||
CHECK(function_wrapper->value()->IsSharedFunctionInfo());
|
||||
LiveEdit::SetFunctionScript(function_wrapper, script_object);
|
||||
} else {
|
||||
// Just ignore this. We may not have a SharedFunctionInfo for some functions
|
||||
// and we check it in this function.
|
||||
}
|
||||
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// In a code of a parent function replaces original function as embedded object
|
||||
// with a substitution one.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditReplaceRefToNestedFunction) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
|
||||
CHECK(parent_wrapper->value()->IsSharedFunctionInfo());
|
||||
CHECK(orig_wrapper->value()->IsSharedFunctionInfo());
|
||||
CHECK(subst_wrapper->value()->IsSharedFunctionInfo());
|
||||
|
||||
LiveEdit::ReplaceRefToNestedFunction(isolate->heap(), parent_wrapper,
|
||||
orig_wrapper, subst_wrapper);
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// Updates positions of a shared function info (first parameter) according
|
||||
// to script source change. Text change is described in second parameter as
|
||||
// array of groups of 3 numbers:
|
||||
// (change_begin, change_end, change_end_new_position).
|
||||
// Each group describes a change in text; groups are sorted by change_begin.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditPatchFunctionPositions) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
|
||||
CHECK(SharedInfoWrapper::IsInstance(shared_array));
|
||||
|
||||
LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
|
||||
// For array of SharedFunctionInfo's (each wrapped in JSValue)
|
||||
// checks that none of them have activations on stacks (of any thread).
|
||||
// Returns array of the same length with corresponding results of
|
||||
// LiveEdit::FunctionPatchabilityStatus type.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditCheckAndDropActivations) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(3, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, old_shared_array, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, new_shared_array, 1);
|
||||
CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 2);
|
||||
USE(new_shared_array);
|
||||
CHECK(old_shared_array->length()->IsSmi());
|
||||
CHECK(new_shared_array->length() == old_shared_array->length());
|
||||
CHECK(old_shared_array->HasFastElements());
|
||||
CHECK(new_shared_array->HasFastElements());
|
||||
int array_length = Smi::ToInt(old_shared_array->length());
|
||||
for (int i = 0; i < array_length; i++) {
|
||||
Handle<Object> old_element;
|
||||
Handle<Object> new_element;
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, old_element,
|
||||
JSReceiver::GetElement(isolate, old_shared_array, i));
|
||||
CHECK(old_element->IsJSValue() &&
|
||||
Handle<JSValue>::cast(old_element)->value()->IsSharedFunctionInfo());
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, new_element,
|
||||
JSReceiver::GetElement(isolate, new_shared_array, i));
|
||||
CHECK(
|
||||
new_element->IsUndefined(isolate) ||
|
||||
(new_element->IsJSValue() &&
|
||||
Handle<JSValue>::cast(new_element)->value()->IsSharedFunctionInfo()));
|
||||
}
|
||||
|
||||
return *LiveEdit::CheckAndDropActivations(old_shared_array, new_shared_array,
|
||||
do_drop);
|
||||
}
|
||||
|
||||
|
||||
// Compares 2 strings line-by-line, then token-wise and returns diff in form
|
||||
// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
|
||||
// of diff chunks.
|
||||
RUNTIME_FUNCTION(Runtime_LiveEditCompareStrings) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
|
||||
|
||||
Handle<JSArray> result = LiveEdit::CompareStrings(isolate, s1, s2);
|
||||
uint32_t array_length = 0;
|
||||
CHECK(result->length()->ToArrayLength(&array_length));
|
||||
if (array_length > 0) {
|
||||
isolate->debug()->feature_tracker()->Track(DebugFeatureTracker::kLiveEdit);
|
||||
}
|
||||
|
||||
return *result;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -38,15 +38,15 @@ Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
|
||||
isolate->factory()->NewSharedFunctionInfoForBuiltin(
|
||||
isolate->factory()->NewStringFromAsciiChecked("f"),
|
||||
Builtins::kCompileLazy);
|
||||
int function_literal_id = 1;
|
||||
// Ensure that the function can be compiled lazily.
|
||||
shared->set_uncompiled_data(
|
||||
*isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
|
||||
0, source->length(), function_literal_id));
|
||||
0, source->length()));
|
||||
// Make sure we have an outer scope info, even though it's empty
|
||||
shared->set_raw_outer_scope_info_or_feedback_metadata(
|
||||
ScopeInfo::Empty(isolate));
|
||||
SharedFunctionInfo::SetScript(shared, script, function_literal_id);
|
||||
shared->set_function_literal_id(1);
|
||||
SharedFunctionInfo::SetScript(shared, script);
|
||||
return scope.CloseAndEscape(shared);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user