diff --git a/src/objects/scope-info.cc b/src/objects/scope-info.cc index 659c13aa82..1274ef32b5 100644 --- a/src/objects/scope-info.cc +++ b/src/objects/scope-info.cc @@ -210,9 +210,11 @@ Handle 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::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::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::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 { diff --git a/src/objects/scope-info.h b/src/objects/scope-info.h index 6f534115f3..430daa8328 100644 --- a/src/objects/scope-info.h +++ b/src/objects/scope-info.h @@ -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 {}; class InitFlagField : public BitField {}; class MaybeAssignedFlagField : public BitField {}; + class ParameterNumberField + : public BitField {}; friend class ScopeIterator; friend std::ostream& operator<<(std::ostream& os, diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc index fc29f46636..25e1ceec37 100644 --- a/src/runtime/runtime-scopes.cc +++ b/src/runtime/runtime-scopes.cc @@ -428,43 +428,24 @@ Handle NewSloppyArguments(Isolate* isolate, Handle callee, --index; } - Handle scope_info(callee->shared()->scope_info()); - while (index >= 0) { - // Detect duplicate names to the right in the parameter list. - Handle 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 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