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:
parent
89270b1ef8
commit
6394fd3571
@ -210,9 +210,11 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
|
||||
int local_index = var->index() - Context::MIN_CONTEXT_SLOTS;
|
||||
DCHECK_LE(0, local_index);
|
||||
DCHECK_LT(local_index, context_local_count);
|
||||
uint32_t info = VariableModeField::encode(var->mode()) |
|
||||
InitFlagField::encode(var->initialization_flag()) |
|
||||
MaybeAssignedFlagField::encode(var->maybe_assigned());
|
||||
uint32_t info =
|
||||
VariableModeField::encode(var->mode()) |
|
||||
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_info_base + local_index,
|
||||
Smi::FromInt(info));
|
||||
@ -226,7 +228,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone, Scope* scope,
|
||||
uint32_t properties =
|
||||
VariableModeField::encode(var->mode()) |
|
||||
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,
|
||||
Smi::FromInt(properties));
|
||||
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;
|
||||
|
||||
// If the receiver is allocated, add its index.
|
||||
@ -400,9 +422,11 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
|
||||
}
|
||||
DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
|
||||
if (context_local_count) {
|
||||
const uint32_t value = VariableModeField::encode(VariableMode::kConst) |
|
||||
InitFlagField::encode(kCreatedInitialized) |
|
||||
MaybeAssignedFlagField::encode(kNotAssigned);
|
||||
const uint32_t value =
|
||||
VariableModeField::encode(VariableMode::kConst) |
|
||||
InitFlagField::encode(kCreatedInitialized) |
|
||||
MaybeAssignedFlagField::encode(kNotAssigned) |
|
||||
ParameterNumberField::encode(ParameterNumberField::kMax);
|
||||
scope_info->set(index++, Smi::FromInt(value));
|
||||
}
|
||||
|
||||
@ -581,12 +605,12 @@ String* ScopeInfo::FunctionDebugName() const {
|
||||
|
||||
int ScopeInfo::StartPosition() const {
|
||||
DCHECK(HasPositionInfo());
|
||||
return Smi::cast(get(PositionInfoIndex()))->value();
|
||||
return Smi::ToInt(get(PositionInfoIndex()));
|
||||
}
|
||||
|
||||
int ScopeInfo::EndPosition() const {
|
||||
DCHECK(HasPositionInfo());
|
||||
return Smi::cast(get(PositionInfoIndex() + 1))->value();
|
||||
return Smi::ToInt(get(PositionInfoIndex() + 1));
|
||||
}
|
||||
|
||||
void ScopeInfo::SetPositionInfo(int start, int end) {
|
||||
@ -636,6 +660,22 @@ InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
|
||||
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 {
|
||||
DCHECK_LE(0, var);
|
||||
DCHECK_LT(var, ContextLocalCount());
|
||||
@ -955,9 +995,8 @@ String* ModuleInfo::RegularExportLocalName(int i) const {
|
||||
}
|
||||
|
||||
int ModuleInfo::RegularExportCellIndex(int i) const {
|
||||
return Smi::cast(regular_exports()->get(i * kRegularExportLength +
|
||||
kRegularExportCellIndexOffset))
|
||||
->value();
|
||||
return Smi::ToInt(regular_exports()->get(i * kRegularExportLength +
|
||||
kRegularExportCellIndexOffset));
|
||||
}
|
||||
|
||||
FixedArray* ModuleInfo::RegularExportExportNames(int i) const {
|
||||
|
@ -120,6 +120,9 @@ class ScopeInfo : public FixedArray {
|
||||
// Return the initialization flag of the given context local.
|
||||
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.
|
||||
MaybeAssignedFlag ContextLocalMaybeAssignedFlag(int var) const;
|
||||
|
||||
@ -321,6 +324,8 @@ class ScopeInfo : public FixedArray {
|
||||
class VariableModeField : public BitField<VariableMode, 0, 3> {};
|
||||
class InitFlagField : public BitField<InitializationFlag, 3, 1> {};
|
||||
class MaybeAssignedFlagField : public BitField<MaybeAssignedFlag, 4, 1> {};
|
||||
class ParameterNumberField
|
||||
: public BitField<uint32_t, MaybeAssignedFlagField::kNext, 16> {};
|
||||
|
||||
friend class ScopeIterator;
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
|
@ -428,43 +428,24 @@ Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
|
||||
--index;
|
||||
}
|
||||
|
||||
Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
|
||||
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;
|
||||
}
|
||||
}
|
||||
Handle<ScopeInfo> scope_info(callee->shared()->scope_info(), isolate);
|
||||
|
||||
if (duplicate) {
|
||||
// This goes directly in the arguments array with a hole in the
|
||||
// parameter map.
|
||||
arguments->set(index, parameters[index]);
|
||||
parameter_map->set_the_hole(index + 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;
|
||||
}
|
||||
}
|
||||
// First mark all mappable slots as unmapped and copy the values into the
|
||||
// arguments object.
|
||||
for (int i = 0; i < mapped_count; i++) {
|
||||
arguments->set(i, parameters[i]);
|
||||
parameter_map->set_the_hole(i + 2);
|
||||
}
|
||||
|
||||
DCHECK_GE(context_index, 0);
|
||||
arguments->set_the_hole(index);
|
||||
parameter_map->set(
|
||||
index + 2,
|
||||
Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
|
||||
}
|
||||
|
||||
--index;
|
||||
// Walk all context slots to find context allocated parameters. Mark each
|
||||
// found parameter as mapped.
|
||||
for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
|
||||
if (!scope_info->ContextLocalIsParameter(i)) continue;
|
||||
int parameter = scope_info->ContextLocalParameterNumber(i);
|
||||
if (parameter >= mapped_count) continue;
|
||||
arguments->set_the_hole(parameter);
|
||||
Smi* slot = Smi::FromInt(Context::MIN_CONTEXT_SLOTS + i);
|
||||
parameter_map->set(parameter + 2, slot);
|
||||
}
|
||||
} else {
|
||||
// If there is no aliasing, the arguments object elements are not
|
||||
|
Loading…
Reference in New Issue
Block a user