Mark context slots with the parameter they represent so we can easily compute arguments objects

Change-Id: I566ab09800f4a2873aca86423c858b63c58d6d98
Reviewed-on: https://chromium-review.googlesource.com/1105049
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53823}
This commit is contained in:
Toon Verwaest 2018-06-19 10:38:06 +02:00 committed by Commit Bot
parent 89270b1ef8
commit 6394fd3571
3 changed files with 72 additions and 47 deletions

View File

@ -210,9 +210,11 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
int local_index = var->index() - Context::MIN_CONTEXT_SLOTS; int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
DCHECK_LE(0, local_index); DCHECK_LE(0, local_index);
DCHECK_LT(local_index, context_local_count); DCHECK_LT(local_index, context_local_count);
uint32_t info = VariableModeField::encode(var->mode()) | uint32_t info =
InitFlagField::encode(var->initialization_flag()) | VariableModeField::encode(var->mode()) |
MaybeAssignedFlagField::encode(var->maybe_assigned()); InitFlagField::encode(var->initialization_flag()) |
MaybeAssignedFlagField::encode(var->maybe_assigned()) |
ParameterNumberField::encode(ParameterNumberField::kMax);
scope_info->set(context_local_base + local_index, *var->name()); scope_info->set(context_local_base + local_index, *var->name());
scope_info->set(context_local_info_base + local_index, scope_info->set(context_local_info_base + local_index,
Smi::FromInt(info)); Smi::FromInt(info));
@ -226,7 +228,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
uint32_t properties = uint32_t properties =
VariableModeField::encode(var->mode()) | VariableModeField::encode(var->mode()) |
InitFlagField::encode(var->initialization_flag()) | InitFlagField::encode(var->initialization_flag()) |
MaybeAssignedFlagField::encode(var->maybe_assigned()); MaybeAssignedFlagField::encode(var->maybe_assigned()) |
ParameterNumberField::encode(ParameterNumberField::kMax);
scope_info->set(module_var_entry + kModuleVariablePropertiesOffset, scope_info->set(module_var_entry + kModuleVariablePropertiesOffset,
Smi::FromInt(properties)); Smi::FromInt(properties));
module_var_entry += kModuleVariableEntryLength; module_var_entry += kModuleVariableEntryLength;
@ -237,6 +240,25 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
} }
} }
if (scope->is_declaration_scope()) {
// Mark contexts slots with the parameter number they represent. We walk the
// list of parameters. That can include duplicate entries if a parameter
// name is repeated. By walking upwards, we'll automatically mark the
// context slot with the highest parameter number that uses this variable.
// That will be the parameter number that is represented by the context
// slot. All lower parameters will only be available on the stack through
// the arguments object.
for (int i = 0; i < parameter_count; i++) {
Variable* parameter = scope->AsDeclarationScope()->parameter(i);
if (parameter->location() != VariableLocation::CONTEXT) continue;
int index = parameter->index() - Context::MIN_CONTEXT_SLOTS;
int info_index = context_local_info_base + index;
int info = Smi::ToInt(scope_info->get(info_index));
info = ParameterNumberField::update(info, i);
scope_info->set(info_index, Smi::FromInt(info));
}
}
index += 2 * context_local_count; index += 2 * context_local_count;
// If the receiver is allocated, add its index. // If the receiver is allocated, add its index.
@ -400,9 +422,11 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
} }
DCHECK_EQ(index, scope_info->ContextLocalInfosIndex()); DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
if (context_local_count) { if (context_local_count) {
const uint32_t value = VariableModeField::encode(VariableMode::kConst) | const uint32_t value =
InitFlagField::encode(kCreatedInitialized) | VariableModeField::encode(VariableMode::kConst) |
MaybeAssignedFlagField::encode(kNotAssigned); InitFlagField::encode(kCreatedInitialized) |
MaybeAssignedFlagField::encode(kNotAssigned) |
ParameterNumberField::encode(ParameterNumberField::kMax);
scope_info->set(index++, Smi::FromInt(value)); scope_info->set(index++, Smi::FromInt(value));
} }
@ -581,12 +605,12 @@ String* ScopeInfo::FunctionDebugName() const {
int ScopeInfo::StartPosition() const { int ScopeInfo::StartPosition() const {
DCHECK(HasPositionInfo()); DCHECK(HasPositionInfo());
return Smi::cast(get(PositionInfoIndex()))->value(); return Smi::ToInt(get(PositionInfoIndex()));
} }
int ScopeInfo::EndPosition() const { int ScopeInfo::EndPosition() const {
DCHECK(HasPositionInfo()); DCHECK(HasPositionInfo());
return Smi::cast(get(PositionInfoIndex() + 1))->value(); return Smi::ToInt(get(PositionInfoIndex() + 1));
} }
void ScopeInfo::SetPositionInfo(int start, int end) { void ScopeInfo::SetPositionInfo(int start, int end) {
@ -636,6 +660,22 @@ InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
return InitFlagField::decode(value); return InitFlagField::decode(value);
} }
bool ScopeInfo::ContextLocalIsParameter(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
DCHECK_LT(var, ParameterCount());
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
}
uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
DCHECK(ContextLocalIsParameter(var));
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return ParameterNumberField::decode(value);
}
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const { MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
DCHECK_LE(0, var); DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount()); DCHECK_LT(var, ContextLocalCount());
@ -955,9 +995,8 @@ String* ModuleInfo::RegularExportLocalName(int i) const {
} }
int ModuleInfo::RegularExportCellIndex(int i) const { int ModuleInfo::RegularExportCellIndex(int i) const {
return Smi::cast(regular_exports()->get(i * kRegularExportLength + return Smi::ToInt(regular_exports()->get(i * kRegularExportLength +
kRegularExportCellIndexOffset)) kRegularExportCellIndexOffset));
->value();
} }
FixedArray* ModuleInfo::RegularExportExportNames(int i) const { FixedArray* ModuleInfo::RegularExportExportNames(int i) const {

View File

@ -120,6 +120,9 @@ class ScopeInfo : public FixedArray {
// Return the initialization flag of the given context local. // Return the initialization flag of the given context local.
InitializationFlag ContextLocalInitFlag(int var) const; InitializationFlag ContextLocalInitFlag(int var) const;
bool ContextLocalIsParameter(int var) const;
uint32_t ContextLocalParameterNumber(int var) const;
// Return the initialization flag of the given context local. // Return the initialization flag of the given context local.
MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const; MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const;
@ -321,6 +324,8 @@ class ScopeInfo : public FixedArray {
class VariableModeField : public BitField<VariableMode, 0, 3> {}; class VariableModeField : public BitField<VariableMode, 0, 3> {};
class InitFlagField : public BitField<InitializationFlag, 3, 1> {}; class InitFlagField : public BitField<InitializationFlag, 3, 1> {};
class MaybeAssignedFlagField : public BitField<MaybeAssignedFlag, 4, 1> {}; class MaybeAssignedFlagField : public BitField<MaybeAssignedFlag, 4, 1> {};
class ParameterNumberField
: public BitField<uint32_t, MaybeAssignedFlagField::kNext, 16> {};
friend class ScopeIterator; friend class ScopeIterator;
friend std::ostream& operator<<(std::ostream& os, friend std::ostream& operator<<(std::ostream& os,

View File

@ -428,43 +428,24 @@ Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
--index; --index;
} }
Handle<ScopeInfo> scope_info(callee->shared()->scope_info()); Handle<ScopeInfo> scope_info(callee->shared()->scope_info(), isolate);
while (index >= 0) {
// Detect duplicate names to the right in the parameter list.
Handle<String> name(scope_info->ParameterName(index));
int context_local_count = scope_info->ContextLocalCount();
bool duplicate = false;
for (int j = index + 1; j < parameter_count; ++j) {
if (scope_info->ParameterName(j) == *name) {
duplicate = true;
break;
}
}
if (duplicate) { // First mark all mappable slots as unmapped and copy the values into the
// This goes directly in the arguments array with a hole in the // arguments object.
// parameter map. for (int i = 0; i < mapped_count; i++) {
arguments->set(index, parameters[index]); arguments->set(i, parameters[i]);
parameter_map->set_the_hole(index + 2); parameter_map->set_the_hole(i + 2);
} else { }
// The context index goes in the parameter map with a hole in the
// arguments array.
int context_index = -1;
for (int j = 0; j < context_local_count; ++j) {
if (scope_info->ContextLocalName(j) == *name) {
context_index = j;
break;
}
}
DCHECK_GE(context_index, 0); // Walk all context slots to find context allocated parameters. Mark each
arguments->set_the_hole(index); // found parameter as mapped.
parameter_map->set( for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
index + 2, if (!scope_info->ContextLocalIsParameter(i)) continue;
Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index)); int parameter = scope_info->ContextLocalParameterNumber(i);
} if (parameter >= mapped_count) continue;
arguments->set_the_hole(parameter);
--index; Smi* slot = Smi::FromInt(Context::MIN_CONTEXT_SLOTS + i);
parameter_map->set(parameter + 2, slot);
} }
} else { } else {
// If there is no aliasing, the arguments object elements are not // If there is no aliasing, the arguments object elements are not