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;
|
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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user