Commit 5dee5ade authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[sfi] Remove SFI function literal id field (reland^2)

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
 1) https://chromium-review.googlesource.com/1082480 and
 2) https://chromium-review.googlesource.com/1128854
the differences being:
 1) caching the literal id on UncompiledData rather than always linearly
    searching the SFI list, and removing the unused runtime-liveedit.cc
    file instead of fixing it to support this change.
 2) clearing padding on UncompiledData now that it has 3 int32 fields,
    making its end unaligned on x64.

TBR=yangguo@chromium.org,marja@chromium.org,ulan@chromium.org,cbruni@chromium.org

Bug: chromium:818642
Change-Id: I58dcb12a2a60a680f662568da428e01189c62638
Reviewed-on: https://chromium-review.googlesource.com/1138325Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54473}
parent 414b841b
......@@ -623,10 +623,9 @@ 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);
script, 1);
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_->function_literal_id());
parse_info_->set_function_literal_id(shared_->FunctionLiteralId(isolate));
if (V8_UNLIKELY(FLAG_runtime_stats)) {
parse_info_->set_runtime_call_stats(new (parse_info_->zone())
RuntimeCallStats());
......@@ -196,6 +196,7 @@ 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,12 +779,13 @@ class FunctionDataMap : public ThreadVisitor {
FunctionData{literal, should_restart});
}
bool Lookup(SharedFunctionInfo* sfi, FunctionData** data) {
if (!sfi->script()->IsScript() || sfi->function_literal_id() == -1) {
bool Lookup(Isolate* isolate, SharedFunctionInfo* sfi, FunctionData** data) {
int function_literal_id = sfi->FunctionLiteralId(isolate);
if (!sfi->script()->IsScript() || function_literal_id == -1) {
return false;
}
Script* script = Script::cast(sfi->script());
return Lookup(script->id(), sfi->function_literal_id(), data);
return Lookup(script->id(), function_literal_id, data);
}
bool Lookup(Handle<Script> script, FunctionLiteral* literal,
......@@ -799,20 +800,20 @@ class FunctionDataMap : public ThreadVisitor {
if (obj->IsSharedFunctionInfo()) {
SharedFunctionInfo* sfi = SharedFunctionInfo::cast(obj);
FunctionData* data = nullptr;
if (!Lookup(sfi, &data)) continue;
if (!Lookup(isolate, 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(sfi, &data)) continue;
if (!Lookup(isolate, 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(sfi, &data)) continue;
if (!Lookup(isolate, sfi, &data)) continue;
data->running_generators.emplace_back(gen, isolate);
}
}
......@@ -842,7 +843,7 @@ class FunctionDataMap : public ThreadVisitor {
stack_position = FunctionData::BELOW_NON_DROPPABLE_FRAME;
}
FunctionData* data = nullptr;
if (!Lookup(*sfi, &data)) continue;
if (!Lookup(isolate, *sfi, &data)) continue;
if (!data->should_restart) continue;
data->stack_position = stack_position;
*restart_frame_fp = frame->fp();
......@@ -866,7 +867,7 @@ class FunctionDataMap : public ThreadVisitor {
it.frame()->GetFunctions(&sfis);
for (auto& sfi : sfis) {
FunctionData* data = nullptr;
if (!Lookup(*sfi, &data)) continue;
if (!Lookup(isolate, *sfi, &data)) continue;
data->stack_position = FunctionData::ARCHIVED_THREAD;
}
}
......@@ -931,7 +932,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(*sfi, &data)) continue;
if (!function_data_map.Lookup(isolate, *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()) {
......@@ -1060,11 +1061,14 @@ 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->function_literal_id(),
DCHECK_EQ(sfi->FunctionLiteralId(isolate),
mapping.second->function_literal_id());
// Swap the now-redundant, newly compiled SFI into the old script, so that
......@@ -1076,12 +1080,16 @@ 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()) {
......@@ -1095,13 +1103,12 @@ void LiveEdit::PatchScript(Isolate* isolate, Handle<Script> script,
}
if (!sfi->HasBytecodeArray()) continue;
Handle<BytecodeArray> bytecode(sfi->GetBytecodeArray(), isolate);
Handle<FixedArray> constants(bytecode->constant_pool(), isolate);
FixedArray* constants = sfi->GetBytecodeArray()->constant_pool();
for (int i = 0; i < constants->length(); ++i) {
if (!constants->get(i)->IsSharedFunctionInfo()) continue;
FunctionData* data = nullptr;
if (!function_data_map.Lookup(SharedFunctionInfo::cast(constants->get(i)),
&data)) {
if (!function_data_map.Lookup(
isolate, SharedFunctionInfo::cast(constants->get(i)), &data)) {
continue;
}
auto change_it = changed.find(data->literal);
......@@ -1153,7 +1160,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(inner_sfi, &data)) continue;
if (!function_data_map.Lookup(isolate, 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
......@@ -1164,17 +1171,21 @@ 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->function_literal_id(),
DCHECK_EQ(old_unchanged_inner_sfi->FunctionLiteralId(isolate),
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.
// Check that all the functions in the new script are valid and that their
// function literals match what is expected.
DisallowHeapAllocation no_gc;
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
......@@ -1187,7 +1198,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->function_literal_id())
->Get(inner_sfi->FunctionLiteralId(isolate))
->GetHeapObject());
}
}
......
......@@ -2514,19 +2514,23 @@ Handle<PreParsedScopeData> Factory::NewPreParsedScopeData(int length) {
Handle<UncompiledDataWithoutPreParsedScope>
Factory::NewUncompiledDataWithoutPreParsedScope(int32_t start_position,
int32_t end_position) {
int32_t end_position,
int32_t function_literal_id) {
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);
result->clear_padding();
return result;
}
Handle<UncompiledDataWithPreParsedScope>
Factory::NewUncompiledDataWithPreParsedScope(
int32_t start_position, int32_t end_position,
int32_t start_position, int32_t end_position, int32_t function_literal_id,
Handle<PreParsedScopeData> pre_parsed_scope_data) {
Handle<UncompiledDataWithPreParsedScope> result(
UncompiledDataWithPreParsedScope::cast(
......@@ -2534,7 +2538,10 @@ 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);
result->clear_padding();
return result;
}
......@@ -3416,7 +3423,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForLiteral(
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfoForBuiltin(
literal->name(), Builtins::kCompileLazy, kind);
SharedFunctionInfo::InitFromFunctionLiteral(shared, literal, is_toplevel);
SharedFunctionInfo::SetScript(shared, script, false);
SharedFunctionInfo::SetScript(shared, script, literal->function_literal_id(),
false);
return shared;
}
......@@ -3504,7 +3512,6 @@ 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,10 +728,12 @@ class V8_EXPORT_PRIVATE Factory {
Handle<UncompiledDataWithoutPreParsedScope>
NewUncompiledDataWithoutPreParsedScope(int32_t start_position,
int32_t end_position);
int32_t end_position,
int32_t function_literal_id);
Handle<UncompiledDataWithPreParsedScope> NewUncompiledDataWithPreParsedScope(
int32_t start_position, int32_t end_position, Handle<PreParsedScopeData>);
int32_t start_position, int32_t end_position, int32_t function_literal_id,
Handle<PreParsedScopeData>);
// Create an External object for V8's external API.
Handle<JSObject> NewExternal(void* value);
......
......@@ -12895,9 +12895,8 @@ 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;
......@@ -13018,7 +13017,6 @@ 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)
......@@ -13736,8 +13734,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();
......@@ -13755,15 +13753,14 @@ void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
Handle<WeakFixedArray> list =
handle(script->shared_function_infos(), isolate);
#ifdef DEBUG
DCHECK_LT(shared->function_literal_id(), list->length());
MaybeObject* maybe_object = list->Get(shared->function_literal_id());
DCHECK_LT(function_literal_id, list->length());
MaybeObject* maybe_object = list->Get(function_literal_id);
HeapObject* heap_object;
if (maybe_object->ToWeakHeapObject(&heap_object)) {
DCHECK_EQ(heap_object, *shared);
}
#endif
list->Set(shared->function_literal_id(),
HeapObjectReference::Weak(*shared));
list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
} else {
Handle<Object> list = isolate->factory()->noscript_shared_function_infos();
......@@ -13789,15 +13786,14 @@ 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 (shared->function_literal_id() < infos->length()) {
MaybeObject* raw = old_script->shared_function_infos()->Get(
shared->function_literal_id());
if (function_literal_id < infos->length()) {
MaybeObject* raw =
old_script->shared_function_infos()->Get(function_literal_id);
HeapObject* heap_object;
if (raw->ToWeakHeapObject(&heap_object) && heap_object == *shared) {
old_script->shared_function_infos()->Set(
shared->function_literal_id(),
HeapObjectReference::Strong(
ReadOnlyRoots(isolate).undefined_value()));
function_literal_id, HeapObjectReference::Strong(
ReadOnlyRoots(isolate).undefined_value()));
}
}
} else {
......@@ -13910,6 +13906,27 @@ 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,
......@@ -14052,7 +14069,6 @@ 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(
......@@ -14099,7 +14115,7 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
Handle<UncompiledData> data =
isolate->factory()->NewUncompiledDataWithPreParsedScope(
lit->start_position(), lit->end_position(),
pre_parsed_scope_data);
lit->function_literal_id(), pre_parsed_scope_data);
shared_info->set_uncompiled_data(*data);
needs_position_info = false;
}
......@@ -14109,7 +14125,8 @@ void SharedFunctionInfo::InitFromFunctionLiteral(
if (needs_position_info) {
Handle<UncompiledData> data =
isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
lit->start_position(), lit->end_position());
lit->start_position(), lit->end_position(),
lit->function_literal_id());
shared_info->set_uncompiled_data(*data);
}
}
......
......@@ -55,6 +55,16 @@ 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)
void UncompiledData::clear_padding() {
// For archs where kIntSize < kPointerSize, there will be padding at the end
// of the data.
if (kUnalignedSize < kSize) {
memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0,
kSize - kUnalignedSize);
}
}
CAST_ACCESSOR(UncompiledDataWithoutPreParsedScope)
......@@ -77,7 +87,6 @@ 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,6 +659,21 @@ 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();
}
......@@ -737,8 +761,11 @@ 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();
......@@ -764,7 +791,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);
start_position, end_position, function_literal_id);
shared_info->set_function_data(*data);
}
}
......
......@@ -70,13 +70,15 @@ 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) \
/* Total size. */ \
#define UNCOMPILED_DATA_FIELDS(V) \
V(kStartPositionOffset, kInt32Size) \
V(kEndPositionOffset, kInt32Size) \
V(kFunctionLiteralIdOffset, kInt32Size) \
/* Total size. */ \
V(kUnalignedSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, UNCOMPILED_DATA_FIELDS)
......@@ -84,6 +86,9 @@ class UncompiledData : public HeapObject {
static const int kSize = POINTER_SIZE_ALIGN(kUnalignedSize);
// Clear uninitialized padding space.
inline void clear_padding();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(UncompiledData);
};
......@@ -118,16 +123,17 @@ class UncompiledDataWithPreParsedScope : public UncompiledData {
V(kPreParsedScopeDataOffset, kPointerSize) \
V(kEndOfPointerFieldsOffset, 0) \
/* Total size. */ \
V(kUnalignedSize, 0)
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(UncompiledData::kSize,
UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_FIELDS)
#undef UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_FIELDS
static const int kSize = POINTER_SIZE_ALIGN(kUnalignedSize);
// Make sure the size is aligned
STATIC_ASSERT(kSize == POINTER_SIZE_ALIGN(kSize));
typedef FixedBodyDescriptor<kStartOfPointerFieldsOffset,
kEndOfPointerFieldsOffset, kUnalignedSize>
kEndOfPointerFieldsOffset, kSize>
BodyDescriptor;
// No weak fields.
typedef BodyDescriptor BodyDescriptorWeak;
......@@ -185,7 +191,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,
bool reset_preparsed_scope_data = true);
int function_literal_id, bool reset_preparsed_scope_data = true);
// Layout description of the optimized code map.
static const int kEntriesStart = 0;
......@@ -255,11 +261,6 @@ 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.
......@@ -341,6 +342,9 @@ 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,6 +534,7 @@ 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);
......@@ -582,7 +587,6 @@ 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,6 +666,10 @@ 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->function_literal_id();
function_literal_id_ = shared->FunctionLiteralId(isolate);
set_language_mode(shared->language_mode());
set_asm_wasm_broken(shared->is_asm_wasm_broken());
......
......@@ -114,16 +114,17 @@ 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());
isolate->factory()->undefined_value(),
function_literal_id);
}
SharedFunctionInfo::SetScript(target_shared, source_script);
SharedFunctionInfo::SetScript(target_shared, source_script,
function_literal_id);
// Set the code of the target function.
target->set_code(source_shared->GetCode());
......
This diff is collapsed.
......@@ -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()));
0, source->length(), function_literal_id));
// 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));
shared->set_function_literal_id(1);
SharedFunctionInfo::SetScript(shared, script);
SharedFunctionInfo::SetScript(shared, script, function_literal_id);
return scope.CloseAndEscape(shared);
}
......
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