[runtime][parser] Store the inferred function name on the ScopeInfo

This is another small step towards detaching the JSFunction from Contexts.
In order to not break the debugger protocol we need the inferred name on the
ScopeInfo chain. This CL might increase memory usage slightly, given that the
inferred name field is duplicated on the ScopeInfo.

Bug: v8:7066, chromium:818642
Change-Id: I0dd9f18ae69791f774cf835669afa50491f7433b
Reviewed-on: https://chromium-review.googlesource.com/995792
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52415}
This commit is contained in:
Camillo Bruni 2018-04-05 16:08:08 +02:00 committed by Commit Bot
parent e32c5946d2
commit 54f2aac554
7 changed files with 88 additions and 23 deletions

View File

@ -211,6 +211,23 @@ Assignment::Assignment(NodeType node_type, Token::Value op, Expression* target,
bit_field_ |= TokenField::encode(op);
}
void FunctionLiteral::set_inferred_name(Handle<String> inferred_name) {
DCHECK(!inferred_name.is_null());
inferred_name_ = inferred_name;
DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
raw_inferred_name_ = nullptr;
scope()->set_has_inferred_function_name(true);
}
void FunctionLiteral::set_raw_inferred_name(
const AstConsString* raw_inferred_name) {
DCHECK_NOT_NULL(raw_inferred_name);
raw_inferred_name_ = raw_inferred_name;
DCHECK(inferred_name_.is_null());
inferred_name_ = Handle<String>();
scope()->set_has_inferred_function_name(true);
}
bool FunctionLiteral::ShouldEagerCompile() const {
return scope()->ShouldEagerCompile();
}

View File

@ -2246,23 +2246,11 @@ class FunctionLiteral final : public Expression {
}
UNREACHABLE();
}
// Only one of {set_inferred_name, set_raw_inferred_name} should be called.
void set_inferred_name(Handle<String> inferred_name) {
DCHECK(!inferred_name.is_null());
inferred_name_ = inferred_name;
DCHECK(raw_inferred_name_ == nullptr || raw_inferred_name_->IsEmpty());
raw_inferred_name_ = nullptr;
}
const AstConsString* raw_inferred_name() { return raw_inferred_name_; }
void set_raw_inferred_name(const AstConsString* raw_inferred_name) {
DCHECK_NOT_NULL(raw_inferred_name);
raw_inferred_name_ = raw_inferred_name;
DCHECK(inferred_name_.is_null());
inferred_name_ = Handle<String>();
}
// Only one of {set_inferred_name, set_raw_inferred_name} should be called.
void set_inferred_name(Handle<String> inferred_name);
void set_raw_inferred_name(const AstConsString* raw_inferred_name);
bool pretenure() const { return Pretenure::decode(bit_field_); }
void set_pretenure() { bit_field_ = Pretenure::update(bit_field_, true); }

View File

@ -901,6 +901,14 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
is_skipped_function_ = is_skipped_function;
}
bool has_inferred_function_name() const {
return has_inferred_function_name_;
}
void set_has_inferred_function_name(bool value) {
DCHECK(is_function_scope());
has_inferred_function_name_ = value;
}
// Save data describing the context allocation of the variables in this scope
// and its subscopes (except scopes at the laziness boundary). The data is
// saved in produced_preparsed_scope_data_.
@ -952,6 +960,7 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
bool is_being_lazily_parsed_ : 1;
#endif
bool is_skipped_function_ : 1;
bool has_inferred_function_name_ : 1;
// Parameter list in source order.
ZoneList<Variable*> params_;

View File

@ -1788,9 +1788,12 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT
os << "\n - outer scope info: " << Brief(OuterScopeInfo());
}
if (HasFunctionName()) {
os << "\n - function name: ";
FunctionName()->ShortPrint(os);
os << "\n - function name: " << Brief(FunctionName());
}
if (HasInferredFunctionName()) {
os << "\n - inferred function name: " << Brief(InferredFunctionName());
}
if (HasPositionInfo()) {
os << "\n - start position: " << StartPosition();
os << "\n - end position: " << EndPosition();

View File

@ -106,9 +106,11 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
receiver_info = NONE;
}
bool has_new_target =
const bool has_new_target =
scope->is_declaration_scope() &&
scope->AsDeclarationScope()->new_target_var() != nullptr;
// TODO(cbruni): Don't always waste a field for the inferred name.
const bool has_inferred_function_name = scope->is_function_scope();
// Determine use and location of the function variable if it is present.
VariableAllocationInfo function_name_info;
@ -144,6 +146,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
(1 + stack_local_count) + 2 * context_local_count +
(has_receiver ? 1 : 0) +
(has_function_name ? kFunctionNameEntries : 0) +
(has_inferred_function_name ? 1 : 0) +
(has_position_info ? kPositionInfoEntries : 0) +
(has_outer_scope_info ? 1 : 0) +
(scope->is_module_scope()
@ -176,6 +179,7 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
ReceiverVariableField::encode(receiver_info) |
HasNewTargetField::encode(has_new_target) |
FunctionVariableField::encode(function_name_info) |
HasInferredFunctionNameField::encode(has_inferred_function_name) |
AsmModuleField::encode(asm_module) |
HasSimpleParametersField::encode(has_simple_parameters) |
FunctionKindField::encode(function_kind) |
@ -280,6 +284,12 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
var_index == scope_info->ContextLength() - 1);
}
DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
if (has_inferred_function_name) {
// The inferred function name is taken from the SFI.
index++;
}
DCHECK_EQ(index, scope_info->PositionInfoIndex());
if (has_position_info) {
scope_info->set(index++, Smi::FromInt(scope->start_position()));
@ -343,6 +353,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
DCHECK_EQ(index, scope_info->StackLocalNamesIndex());
DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
DCHECK_EQ(index, scope_info->PositionInfoIndex());
DCHECK(index == scope_info->OuterScopeInfoIndex());
if (has_outer_scope_info) {
@ -410,6 +421,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
scope_info->set(index++, Smi::FromInt(receiver_index));
DCHECK_EQ(index, scope_info->FunctionNameInfoIndex());
DCHECK_EQ(index, scope_info->InferredFunctionNameIndex());
DCHECK_EQ(index, scope_info->PositionInfoIndex());
// Store dummy position to be in sync with the {scope_type}.
scope_info->set(index++, Smi::kZero);
@ -502,6 +514,11 @@ bool ScopeInfo::HasFunctionName() const {
return NONE != FunctionVariableField::decode(Flags());
}
bool ScopeInfo::HasInferredFunctionName() const {
if (length() == 0) return false;
return HasInferredFunctionNameField::decode(Flags());
}
bool ScopeInfo::HasPositionInfo() const {
if (length() == 0) return false;
return NeedsPositionInfo(scope_type());
@ -523,6 +540,11 @@ void ScopeInfo::SetFunctionName(Object* name) {
set(FunctionNameInfoIndex(), name);
}
void ScopeInfo::SetInferredFunctionName(String* name) {
DCHECK(HasInferredFunctionName());
set(InferredFunctionNameIndex(), name);
}
bool ScopeInfo::HasOuterScopeInfo() const {
if (length() == 0) return false;
return HasOuterScopeInfoField::decode(Flags());
@ -549,6 +571,11 @@ Object* ScopeInfo::FunctionName() const {
return get(FunctionNameInfoIndex());
}
Object* ScopeInfo::InferredFunctionName() const {
DCHECK(HasInferredFunctionName());
return get(InferredFunctionNameIndex());
}
int ScopeInfo::StartPosition() const {
DCHECK(HasPositionInfo());
return Smi::cast(get(PositionInfoIndex()))->value();
@ -797,11 +824,15 @@ int ScopeInfo::FunctionNameInfoIndex() const {
return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
}
int ScopeInfo::PositionInfoIndex() const {
int ScopeInfo::InferredFunctionNameIndex() const {
return FunctionNameInfoIndex() +
(HasFunctionName() ? kFunctionNameEntries : 0);
}
int ScopeInfo::PositionInfoIndex() const {
return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
}
int ScopeInfo::OuterScopeInfoIndex() const {
return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
}

View File

@ -84,7 +84,10 @@ class ScopeInfo : public FixedArray {
// See SharedFunctionInfo::HasSharedName.
bool HasSharedFunctionName() const;
bool HasInferredFunctionName() const;
void SetFunctionName(Object* name);
void SetInferredFunctionName(String* name);
// Does this scope belong to a function?
bool HasPositionInfo() const;
@ -100,6 +103,10 @@ class ScopeInfo : public FixedArray {
// Return the function_name if present.
Object* FunctionName() const;
// Return the function's inferred name if present.
// See SharedFunctionInfo::function_identifier.
Object* InferredFunctionName() const;
// Position information accessors.
int StartPosition() const;
int EndPosition() const;
@ -262,12 +269,14 @@ class ScopeInfo : public FixedArray {
// information about the function variable. It always occupies two array
// slots: a. The name of the function variable.
// b. The context or stack slot index for the variable.
// 8. SourcePosition:
// 8. InferredFunctionName:
// Contains the function's inferred name.
// 9. SourcePosition:
// Contains two slots with a) the startPosition and b) the endPosition if
// the scope belongs to a function or script.
// 9. OuterScopeInfoIndex:
// 10. OuterScopeInfoIndex:
// The outer scope's ScopeInfo or the hole if there's none.
// 10. ModuleInfo, ModuleVariableCount, and ModuleVariables:
// 11. ModuleInfo, ModuleVariableCount, and ModuleVariables:
// For a module scope, this part contains the ModuleInfo, the number of
// MODULE-allocated variables, and the metadata of those variables. For
// non-module scopes it is empty.
@ -278,6 +287,7 @@ class ScopeInfo : public FixedArray {
int ContextLocalInfosIndex() const;
int ReceiverInfoIndex() const;
int FunctionNameInfoIndex() const;
int InferredFunctionNameIndex() const;
int PositionInfoIndex() const;
int OuterScopeInfoIndex() const;
int ModuleInfoIndex() const;
@ -321,8 +331,12 @@ class ScopeInfo : public FixedArray {
: public BitField<bool, ReceiverVariableField::kNext, 1> {};
class FunctionVariableField
: public BitField<VariableAllocationInfo, HasNewTargetField::kNext, 2> {};
class AsmModuleField
// TODO(cbruni): Combine with function variable field when only storing the
// function name.
class HasInferredFunctionNameField
: public BitField<bool, FunctionVariableField::kNext, 1> {};
class AsmModuleField
: public BitField<bool, HasInferredFunctionNameField::kNext, 1> {};
class HasSimpleParametersField
: public BitField<bool, AsmModuleField::kNext, 1> {};
class FunctionKindField

View File

@ -322,6 +322,9 @@ void SharedFunctionInfo::set_scope_info(ScopeInfo* scope_info,
DCHECK(name->IsString() || name == kNoSharedNameSentinel);
// Only set the function name for function scopes.
scope_info->SetFunctionName(name);
if (HasInferredName() && inferred_name()->length() != 0) {
scope_info->SetInferredFunctionName(inferred_name());
}
WRITE_FIELD(this, kNameOrScopeInfoOffset,
reinterpret_cast<Object*>(scope_info));
CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kNameOrScopeInfoOffset,