[runtime] Update SavedClassVariable in ScopeInfo

ScopeInfo will contain either inlined (array) local names or
a hash table (names => index) containing the local names.

If we have the local names inlined, we should save the class
variable context slot index.

If we have a hash table instead, we should save the class
variable offset in the internal hash table storage.

Bug: v8:12315
Change-Id: Ifd9ae4f285d11fc034e8560c8558038b38a474fb
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3386599
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78621}
This commit is contained in:
Victor Gomes 2022-01-14 11:47:35 +01:00 committed by V8 LUCI CQ
parent 549ee6f367
commit 2fdc823a26
6 changed files with 41 additions and 30 deletions

View File

@ -206,11 +206,10 @@ ClassScope::ClassScope(IsolateT* isolate, Zone* zone,
// If the class variable is context-allocated and its index is
// saved for deserialization, deserialize it.
if (scope_info->HasSavedClassVariableIndex()) {
int index = scope_info->SavedClassVariableContextLocalIndex();
DCHECK_GE(index, 0);
DCHECK_LT(index, scope_info->ContextLocalCount());
String name = scope_info->ContextLocalName(index);
if (scope_info->HasSavedClassVariable()) {
String name;
int index;
std::tie(name, index) = scope_info->SavedClassVariable();
DCHECK_EQ(scope_info->ContextLocalMode(index), VariableMode::kConst);
DCHECK_EQ(scope_info->ContextLocalInitFlag(index),
InitializationFlag::kNeedsInitialization);

View File

@ -2350,7 +2350,7 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) {
os << "\n - receiver: " << ReceiverVariableBits::decode(flags);
}
if (HasClassBrand()) os << "\n - has class brand";
if (HasSavedClassVariableIndex()) os << "\n - has saved class variable index";
if (HasSavedClassVariable()) os << "\n - has saved class variable";
if (HasNewTarget()) os << "\n - needs new target";
if (HasFunctionName()) {
os << "\n - function name(" << FunctionVariableBits::decode(flags) << "): ";

View File

@ -204,8 +204,7 @@ Handle<ScopeInfo> ScopeInfo::Create(IsolateT* isolate, Zone* zone, Scope* scope,
DeclarationScopeBit::encode(scope->is_declaration_scope()) |
ReceiverVariableBits::encode(receiver_info) |
HasClassBrandBit::encode(has_brand) |
HasSavedClassVariableIndexBit::encode(
should_save_class_variable_index) |
HasSavedClassVariableBit::encode(should_save_class_variable_index) |
HasNewTargetBit::encode(has_new_target) |
FunctionVariableBits::encode(function_name_info) |
HasInferredFunctionNameBit::encode(has_inferred_function_name) |
@ -397,8 +396,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
DeclarationScopeBit::encode(false) |
ReceiverVariableBits::encode(VariableAllocationInfo::NONE) |
HasClassBrandBit::encode(false) |
HasSavedClassVariableIndexBit::encode(false) |
HasNewTargetBit::encode(false) |
HasSavedClassVariableBit::encode(false) | HasNewTargetBit::encode(false) |
FunctionVariableBits::encode(VariableAllocationInfo::NONE) |
IsAsmModuleBit::encode(false) | HasSimpleParametersBit::encode(true) |
FunctionKindBits::encode(FunctionKind::kNormalFunction) |
@ -471,8 +469,7 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
ReceiverVariableBits::encode(is_script ? VariableAllocationInfo::CONTEXT
: VariableAllocationInfo::UNUSED) |
HasClassBrandBit::encode(false) |
HasSavedClassVariableIndexBit::encode(false) |
HasNewTargetBit::encode(false) |
HasSavedClassVariableBit::encode(false) | HasNewTargetBit::encode(false) |
FunctionVariableBits::encode(is_empty_function
? VariableAllocationInfo::UNUSED
: VariableAllocationInfo::NONE) |
@ -685,8 +682,8 @@ bool ScopeInfo::HasClassBrand() const {
return HasClassBrandBit::decode(Flags());
}
bool ScopeInfo::HasSavedClassVariableIndex() const {
return HasSavedClassVariableIndexBit::decode(Flags());
bool ScopeInfo::HasSavedClassVariable() const {
return HasSavedClassVariableBit::decode(Flags());
}
bool ScopeInfo::HasNewTarget() const {
@ -919,12 +916,21 @@ int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
return -1;
}
int ScopeInfo::SavedClassVariableContextLocalIndex() const {
if (HasSavedClassVariableIndexBit::decode(Flags())) {
int index = saved_class_variable_info();
return index - Context::MIN_CONTEXT_SLOTS;
std::pair<String, int> ScopeInfo::SavedClassVariable() const {
DCHECK(HasSavedClassVariableBit::decode(Flags()));
if (HasInlinedLocalNames()) {
// The saved class variable info corresponds to the context slot index.
int index = saved_class_variable_info() - Context::MIN_CONTEXT_SLOTS;
DCHECK_GE(index, 0);
DCHECK_LT(index, ContextLocalCount());
String name = ContextLocalName(index);
return std::make_pair(name, index);
} else {
// The saved class variable info corresponds to the offset in the hash
// table storage.
// TODO(victorgomes, v8:12315): Implement this once we have a hash table.
UNREACHABLE();
}
return -1;
}
int ScopeInfo::ReceiverContextSlotIndex() const {

View File

@ -91,9 +91,9 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, HeapObject> {
// Does this scope has class brand (for private methods)?
bool HasClassBrand() const;
// Does this scope contain a saved class variable context local slot index
// for checking receivers of static private methods?
bool HasSavedClassVariableIndex() const;
// Does this scope contain a saved class variable for checking receivers of
// static private methods?
bool HasSavedClassVariable() const;
// Does this scope declare a "new.target" binding?
bool HasNewTarget() const;
@ -140,6 +140,12 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, HeapObject> {
SourceTextModuleInfo ModuleDescriptorInfo() const;
// Return true if the local names are inlined in the scope info object.
bool HasInlinedLocalNames() const {
// TODO(victorgomes, v8:12315): Currently, local names are always inlined.
return true;
}
// Return the name of the given context local.
String ContextLocalName(int var) const;
@ -193,11 +199,10 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, HeapObject> {
// Returns the first parameter context slot index.
int ParametersStartIndex() const;
// Lookup support for serialized scope info. Returns the index of the
// saved class variable in context local slots if scope is a class scope
// Lookup support for serialized scope info. Returns the name and index of
// the saved class variable in context local slots if scope is a class scope
// and it contains static private methods that may be accessed.
// Otherwise returns a value < 0.
int SavedClassVariableContextLocalIndex() const;
std::pair<String, int> SavedClassVariable() const;
FunctionKind function_kind() const;

View File

@ -54,7 +54,7 @@ bitfield struct ScopeFlags extends uint31 {
declaration_scope: bool: 1 bit;
receiver_variable: VariableAllocationInfo: 2 bit;
has_class_brand: bool: 1 bit;
has_saved_class_variable_index: bool: 1 bit;
has_saved_class_variable: bool: 1 bit;
has_new_target: bool: 1 bit;
// TODO(cbruni): Combine with function variable field when only storing the
// function name.
@ -119,8 +119,9 @@ extern class ScopeInfo extends HeapObject {
// If the scope is a class scope and it has static private methods that
// may be accessed directly or through eval, one slot is reserved to hold
// the context slot index for the class variable.
saved_class_variable_info?[flags.has_saved_class_variable_index]: Smi;
// the offset in the field storage of the hash table (or the slot index if
// local names are inlined) for the class variable.
saved_class_variable_info?[flags.has_saved_class_variable]: Smi;
// If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array

View File

@ -1346,7 +1346,7 @@ Handle<ScopeInfo> WebSnapshotDeserializer::CreateScopeInfo(
ScopeInfo::DeclarationScopeBit::encode(false) |
ScopeInfo::ReceiverVariableBits::encode(VariableAllocationInfo::NONE) |
ScopeInfo::HasClassBrandBit::encode(false) |
ScopeInfo::HasSavedClassVariableIndexBit::encode(false) |
ScopeInfo::HasSavedClassVariableBit::encode(false) |
ScopeInfo::HasNewTargetBit::encode(false) |
ScopeInfo::FunctionVariableBits::encode(VariableAllocationInfo::NONE) |
ScopeInfo::HasInferredFunctionNameBit::encode(false) |