diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc index 255d2ee029..20b8d96053 100644 --- a/src/asmjs/asm-typer.cc +++ b/src/asmjs/asm-typer.cc @@ -605,8 +605,10 @@ AsmType* AsmTyper::ValidateModule(FunctionLiteral* fun) { if (estatement != nullptr) { Assignment* assignment = estatement->expression()->AsAssignment(); if (assignment != nullptr && assignment->target()->IsVariableProxy() && - assignment->target()->AsVariableProxy()->var()->mode() == - CONST_LEGACY) { + assignment->target() + ->AsVariableProxy() + ->var() + ->is_sloppy_function_name()) { use_asm_directive = iter.Next(); } } diff --git a/src/asmjs/asm-wasm-builder.cc b/src/asmjs/asm-wasm-builder.cc index dd17621d83..00e304bbcb 100644 --- a/src/asmjs/asm-wasm-builder.cc +++ b/src/asmjs/asm-wasm-builder.cc @@ -833,7 +833,7 @@ class AsmWasmBuilderImpl final : public AstVisitor { // Skip extra assignment inserted by the parser when in this form: // (function Module(a, b, c) {... }) if (expr->target()->IsVariableProxy() && - expr->target()->AsVariableProxy()->var()->mode() == CONST_LEGACY) { + expr->target()->AsVariableProxy()->var()->is_sloppy_function_name()) { return; } Property* prop = expr->value()->AsProperty(); diff --git a/src/ast/scopeinfo.cc b/src/ast/scopeinfo.cc index d4f5c29411..20a96938c2 100644 --- a/src/ast/scopeinfo.cc +++ b/src/ast/scopeinfo.cc @@ -76,7 +76,6 @@ Handle ScopeInfo::Create(Isolate* isolate, Zone* zone, // Determine use and location of the function variable if it is present. VariableAllocationInfo function_name_info; - VariableMode function_variable_mode; if (scope->is_function_scope() && scope->AsDeclarationScope()->function_var() != nullptr) { Variable* var = scope->AsDeclarationScope()->function_var(); @@ -88,10 +87,8 @@ Handle ScopeInfo::Create(Isolate* isolate, Zone* zone, DCHECK(var->IsStackLocal()); function_name_info = STACK; } - function_variable_mode = var->mode(); } else { function_name_info = NONE; - function_variable_mode = VAR; } const bool has_function_name = function_name_info != NONE; @@ -127,7 +124,6 @@ Handle ScopeInfo::Create(Isolate* isolate, Zone* zone, ReceiverVariableField::encode(receiver_info) | HasNewTargetField::encode(has_new_target) | FunctionVariableField::encode(function_name_info) | - FunctionVariableMode::encode(function_variable_mode) | AsmModuleField::encode(asm_module) | AsmFunctionField::encode(asm_function) | HasSimpleParametersField::encode(has_simple_parameters) | @@ -254,7 +250,6 @@ Handle ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { const bool has_simple_parameters = true; const VariableAllocationInfo receiver_info = CONTEXT; const VariableAllocationInfo function_name_info = NONE; - const VariableMode function_variable_mode = VAR; const bool has_function_name = false; const bool has_receiver = true; const int parameter_count = 0; @@ -272,7 +267,6 @@ Handle ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) { DeclarationScopeField::encode(true) | ReceiverVariableField::encode(receiver_info) | FunctionVariableField::encode(function_name_info) | - FunctionVariableMode::encode(function_variable_mode) | AsmModuleField::encode(false) | AsmFunctionField::encode(false) | HasSimpleParametersField::encode(has_simple_parameters) | FunctionKindField::encode(FunctionKind::kNormalFunction); @@ -625,14 +619,11 @@ int ScopeInfo::ReceiverContextSlotIndex() { return -1; } - -int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { +int ScopeInfo::FunctionContextSlotIndex(String* name) { DCHECK(name->IsInternalizedString()); - DCHECK_NOT_NULL(mode); if (length() > 0) { if (FunctionVariableField::decode(Flags()) == CONTEXT && FunctionName() == name) { - *mode = FunctionVariableMode::decode(Flags()); return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); } } diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc index 072ec3f276..02b3433526 100644 --- a/src/ast/scopes.cc +++ b/src/ast/scopes.cc @@ -415,11 +415,9 @@ void Scope::DeserializeScopeInfo(Isolate* isolate, if (scope_info_->HasFunctionName()) { Handle name_handle(scope_info_->FunctionName(), isolate); const AstRawString* name = ast_value_factory->GetString(name_handle); - VariableMode mode; - int index = scope_info_->FunctionContextSlotIndex(*name_handle, &mode); + int index = scope_info_->FunctionContextSlotIndex(*name_handle); if (index >= 0) { Variable* result = AsDeclarationScope()->DeclareFunctionVar(name); - DCHECK_EQ(mode, result->mode()); result->AllocateTo(VariableLocation::CONTEXT, index); } } @@ -518,9 +516,11 @@ void DeclarationScope::DeclareDefaultFunctionVariables( Variable* DeclarationScope::DeclareFunctionVar(const AstRawString* name) { DCHECK(is_function_scope()); DCHECK_NULL(function_); - VariableMode mode = is_strict(language_mode()) ? CONST : CONST_LEGACY; - function_ = new (zone()) - Variable(this, name, mode, Variable::NORMAL, kCreatedInitialized); + Variable::Kind kind = is_sloppy(language_mode()) + ? Variable::SLOPPY_FUNCTION_NAME + : Variable::NORMAL; + function_ = + new (zone()) Variable(this, name, CONST, kind, kCreatedInitialized); return function_; } @@ -682,11 +682,9 @@ Variable* DeclarationScope::LookupFunctionVar(const AstRawString* name) { return function_; } else if (!scope_info_.is_null()) { // If we are backed by a scope info, try to lookup the variable there. - VariableMode mode; - int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); + int index = scope_info_->FunctionContextSlotIndex(*(name->string())); if (index < 0) return nullptr; Variable* var = DeclareFunctionVar(name); - DCHECK_EQ(mode, var->mode()); var->AllocateTo(VariableLocation::CONTEXT, index); return var; } else { @@ -748,7 +746,7 @@ Variable* Scope::DeclareVariable( Declaration* declaration, VariableMode mode, InitializationFlag init, bool allow_harmony_restrictive_generators, bool* sloppy_mode_block_scope_function_redefinition, bool* ok) { - DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY); + DCHECK(IsDeclaredVariableMode(mode)); DCHECK(!already_resolved_); if (mode == VAR && !is_declaration_scope()) { diff --git a/src/ast/variables.cc b/src/ast/variables.cc index 93b9c1853e..e4362bac3d 100644 --- a/src/ast/variables.cc +++ b/src/ast/variables.cc @@ -16,7 +16,6 @@ namespace internal { const char* Variable::Mode2String(VariableMode mode) { switch (mode) { case VAR: return "VAR"; - case CONST_LEGACY: return "CONST_LEGACY"; case LET: return "LET"; case CONST: return "CONST"; case DYNAMIC: return "DYNAMIC"; diff --git a/src/ast/variables.h b/src/ast/variables.h index 2b0d55ca3b..b56fb5b348 100644 --- a/src/ast/variables.h +++ b/src/ast/variables.h @@ -22,7 +22,8 @@ class Variable final : public ZoneObject { FUNCTION, THIS, ARGUMENTS, - kLastKind = ARGUMENTS + SLOPPY_FUNCTION_NAME, + kLastKind = SLOPPY_FUNCTION_NAME }; Variable(Scope* scope, const AstRawString* name, VariableMode mode, Kind kind, @@ -77,16 +78,21 @@ class Variable final : public ZoneObject { bool IsStaticGlobalObjectProperty() const; bool is_dynamic() const { return IsDynamicVariableMode(mode()); } - bool is_const_mode() const { return IsImmutableVariableMode(mode()); } bool binding_needs_init() const { DCHECK(initialization_flag() != kNeedsInitialization || IsLexicalVariableMode(mode())); return initialization_flag() == kNeedsInitialization; } + bool throw_on_const_assignment(LanguageMode language_mode) const { + return kind() != SLOPPY_FUNCTION_NAME || is_strict(language_mode); + } bool is_function() const { return kind() == FUNCTION; } bool is_this() const { return kind() == THIS; } bool is_arguments() const { return kind() == ARGUMENTS; } + bool is_sloppy_function_name() const { + return kind() == SLOPPY_FUNCTION_NAME; + } Variable* local_if_not_shadowed() const { DCHECK(mode() == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL); @@ -129,7 +135,7 @@ class Variable final : public ZoneObject { uint16_t bit_field_; class VariableModeField : public BitField16 {}; - class KindField : public BitField16 {}; + class KindField : public BitField16 {}; class LocationField : public BitField16 {}; class ForceContextAllocationField diff --git a/src/bailout-reason.h b/src/bailout-reason.h index 31122a5c82..96943a03ce 100644 --- a/src/bailout-reason.h +++ b/src/bailout-reason.h @@ -242,10 +242,6 @@ namespace internal { V(kUnexpectedTypeForRegExpDataFixedArrayExpected, \ "Unexpected type for RegExp data, FixedArray expected") \ V(kUnexpectedValue, "Unexpected value") \ - V(kUnsupportedConstCompoundAssignment, \ - "Unsupported const compound assignment") \ - V(kUnsupportedCountOperationWithConst, \ - "Unsupported count operation with const") \ V(kUnsupportedDoubleImmediate, "Unsupported double immediate") \ V(kUnsupportedLetCompoundAssignment, "Unsupported let compound assignment") \ V(kUnsupportedLookupSlotInDeclaration, \ diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 423c1ded9d..efd6493703 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -536,7 +536,7 @@ bool AstGraphBuilder::CreateGraph(bool stack_check) { // TODO(mstarzinger): For now we cannot assume that the {this} parameter is // not {the_hole}, because for derived classes {this} has a TDZ and the // JSConstructStubForDerived magically passes {the_hole} as a receiver. - if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) { + if (scope->has_this_declaration() && scope->receiver()->mode() == CONST) { env.RawParameterBind(0, jsgraph()->TheHoleConstant()); } @@ -3442,15 +3442,7 @@ Node* AstGraphBuilder::BuildVariableAssignment( case VariableLocation::PARAMETER: case VariableLocation::LOCAL: // Local var, const, or let variable. - if (mode == CONST_LEGACY && op != Token::INIT) { - // Non-initializing assignment to legacy const is - // - exception in strict mode. - // - ignored in sloppy mode. - if (is_strict(language_mode())) { - return BuildThrowConstAssignError(bailout_id); - } - return value; - } else if (mode == LET && op == Token::INIT) { + if (mode == LET && op == Token::INIT) { // No initialization check needed because scoping guarantees it. Note // that we still perform a lookup to keep the variable live, because // baseline code might contain debug code that inspects the variable. @@ -3473,6 +3465,16 @@ Node* AstGraphBuilder::BuildVariableAssignment( if (current->op() != the_hole->op() && variable->is_this()) { value = BuildHoleCheckElseThrow(current, variable, value, bailout_id); } + } else if (mode == CONST && op != Token::INIT && + variable->is_sloppy_function_name()) { + // Non-initializing assignment to sloppy function names is + // - exception in strict mode. + // - ignored in sloppy mode. + DCHECK(!variable->binding_needs_init()); + if (variable->throw_on_const_assignment(language_mode())) { + return BuildThrowConstAssignError(bailout_id); + } + return value; } else if (mode == CONST && op != Token::INIT) { if (variable->binding_needs_init()) { Node* current = environment()->Lookup(variable); @@ -3490,16 +3492,7 @@ Node* AstGraphBuilder::BuildVariableAssignment( case VariableLocation::CONTEXT: { // Context variable (potentially up the context chain). int depth = current_scope()->ContextChainLength(variable->scope()); - if (mode == CONST_LEGACY && op != Token::INIT) { - // Non-initializing assignment to legacy const is - // - exception in strict mode. - // - ignored in sloppy mode. - if (is_strict(language_mode())) { - return BuildThrowConstAssignError(bailout_id); - } - return value; - } else if (mode == LET && op != Token::INIT && - variable->binding_needs_init()) { + if (mode == LET && op != Token::INIT && variable->binding_needs_init()) { // Perform an initialization check for let declared variables. const Operator* op = javascript()->LoadContext(depth, variable->index(), false); @@ -3515,6 +3508,16 @@ Node* AstGraphBuilder::BuildVariableAssignment( Node* current = NewNode(op, current_context()); value = BuildHoleCheckElseThrow(current, variable, value, bailout_id); } + } else if (mode == CONST && op != Token::INIT && + variable->is_sloppy_function_name()) { + // Non-initializing assignment to sloppy function names is + // - exception in strict mode. + // - ignored in sloppy mode. + DCHECK(!variable->binding_needs_init()); + if (variable->throw_on_const_assignment(language_mode())) { + return BuildThrowConstAssignError(bailout_id); + } + return value; } else if (mode == CONST && op != Token::INIT) { if (variable->binding_needs_init()) { const Operator* op = diff --git a/src/compiler/js-global-object-specialization.cc b/src/compiler/js-global-object-specialization.cc index 7ef07c1bb3..f76ce0e383 100644 --- a/src/compiler/js-global-object-specialization.cc +++ b/src/compiler/js-global-object-specialization.cc @@ -247,7 +247,7 @@ bool JSGlobalObjectSpecialization::LookupInScriptContextTable( Handle script_context = ScriptContextTable::GetContext( script_context_table, lookup_result.context_index); result->context = script_context; - result->immutable = IsImmutableVariableMode(lookup_result.mode); + result->immutable = lookup_result.mode == CONST; result->index = lookup_result.slot_index; return true; } diff --git a/src/contexts.cc b/src/contexts.cc index c62eb452ab..0822e45cd0 100644 --- a/src/contexts.cc +++ b/src/contexts.cc @@ -178,7 +178,7 @@ static Maybe UnscopableLookup(LookupIterator* it) { static PropertyAttributes GetAttributesForMode(VariableMode mode) { DCHECK(IsDeclaredVariableMode(mode)); - return IsImmutableVariableMode(mode) ? READ_ONLY : NONE; + return mode == CONST ? READ_ONLY : NONE; } Handle Context::Lookup(Handle name, ContextLookupFlags flags, @@ -307,10 +307,11 @@ Handle Context::Lookup(Handle name, ContextLookupFlags flags, } // Check the slot corresponding to the intermediate context holding - // only the function name variable. - if (follow_context_chain && context->IsFunctionContext()) { - VariableMode mode; - int function_index = scope_info->FunctionContextSlotIndex(*name, &mode); + // only the function name variable. It's conceptually (and spec-wise) + // in an outer scope of the function's declaration scope. + if (follow_context_chain && (flags & STOP_AT_DECLARATION_SCOPE) == 0 && + context->IsFunctionContext()) { + int function_index = scope_info->FunctionContextSlotIndex(*name); if (function_index >= 0) { if (FLAG_trace_contexts) { PrintF("=> found intermediate function in context slot %d\n", @@ -318,9 +319,8 @@ Handle Context::Lookup(Handle name, ContextLookupFlags flags, } *index = function_index; *attributes = READ_ONLY; - DCHECK(mode == CONST_LEGACY || mode == CONST); *init_flag = kCreatedInitialized; - *variable_mode = mode; + *variable_mode = CONST; return context; } } diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc index 6a0a0c5474..5be03497c9 100644 --- a/src/crankshaft/hydrogen.cc +++ b/src/crankshaft/hydrogen.cc @@ -6956,9 +6956,6 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (var->mode() == CONST_LEGACY) { - return Bailout(kUnsupportedConstCompoundAssignment); - } if (var->mode() == CONST) { return Bailout(kNonInitializerAssignmentToConst); } @@ -6988,9 +6985,7 @@ void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { mode = HStoreContextSlot::kCheckDeoptimize; break; case CONST: - return Bailout(kNonInitializerAssignmentToConst); - case CONST_LEGACY: - if (is_strict(function_language_mode())) { + if (var->throw_on_const_assignment(function_language_mode())) { return Bailout(kNonInitializerAssignmentToConst); } else { return ast_context()->ReturnValue(Pop()); @@ -7062,26 +7057,13 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { if (var->mode() == CONST) { if (expr->op() != Token::INIT) { - return Bailout(kNonInitializerAssignmentToConst); - } - } else if (var->mode() == CONST_LEGACY) { - if (expr->op() != Token::INIT) { - if (is_strict(function_language_mode())) { + if (var->throw_on_const_assignment(function_language_mode())) { return Bailout(kNonInitializerAssignmentToConst); } else { CHECK_ALIVE(VisitForValue(expr->value())); return ast_context()->ReturnValue(Pop()); } } - - // TODO(adamk): Is this required? Legacy const variables are always - // initialized before use. - if (var->IsStackAllocated()) { - // We insert a use of the old value to detect unsupported uses of const - // variables (e.g. initialization inside a loop). - HValue* old_value = environment()->Lookup(var); - Add(old_value); - } } if (var->is_arguments()) return Bailout(kAssignmentToArguments); @@ -7137,10 +7119,10 @@ void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { mode = HStoreContextSlot::kCheckDeoptimize; break; case CONST: - // This case is checked statically so no need to - // perform checks here - UNREACHABLE(); - case CONST_LEGACY: + // If we reached this point, the only possibility + // is a sloppy assignment to a function name. + DCHECK(function_language_mode() == SLOPPY && + !var->throw_on_const_assignment(SLOPPY)); return ast_context()->ReturnValue(Pop()); default: mode = HStoreContextSlot::kNoCheck; @@ -10751,9 +10733,6 @@ void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { if (proxy != NULL) { Variable* var = proxy->var(); - if (var->mode() == CONST_LEGACY) { - return Bailout(kUnsupportedCountOperationWithConst); - } if (var->mode() == CONST) { return Bailout(kNonInitializerAssignmentToConst); } diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index 9139fbf2d0..b1d82f8b2f 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -2169,10 +2169,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { // Initializing assignment to const {this} needs a write barrier. @@ -2188,7 +2188,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { // Assignment to var. __ Push(var->name()); @@ -2209,13 +2210,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index 46cf3a607f..06c381d96c 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -2062,10 +2062,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ Bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { // Initializing assignment to const {this} needs a write barrier. @@ -2080,7 +2080,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { // Assignment to var. __ Push(var->name()); @@ -2100,13 +2101,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index b7f65faac4..3de520217e 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -2075,10 +2075,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { // Initializing assignment to const {this} needs a write barrier. @@ -2093,7 +2093,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { // Assignment to var. __ Push(Immediate(var->name())); @@ -2114,13 +2115,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index 2933fc6f24..c92147474d 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -2174,10 +2174,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { // Initializing assignment to const {this} needs a write barrier. @@ -2193,7 +2193,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { // Assignment to var. __ Push(var->name()); @@ -2214,13 +2215,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index cc5236e673..783ec9d892 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -2174,10 +2174,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { // Initializing assignment to const {this} needs a write barrier. @@ -2193,7 +2193,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { __ Push(var->name()); __ Push(v0); @@ -2213,13 +2214,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index 155dd3a6df..38102c5568 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -2066,10 +2066,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { @@ -2085,7 +2085,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { // Assignment to var. __ Push(var->name()); @@ -2106,13 +2107,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } diff --git a/src/globals.h b/src/globals.h index 96c004f340..52a1d981ff 100644 --- a/src/globals.h +++ b/src/globals.h @@ -884,8 +884,6 @@ enum VariableMode : uint8_t { // User declared variables: VAR, // declared via 'var', and 'function' declarations - CONST_LEGACY, // declared via legacy 'const' declarations - LET, // declared via 'let' declarations (first lexical) CONST, // declared via 'const' declarations (last lexical) @@ -924,11 +922,6 @@ inline bool IsLexicalVariableMode(VariableMode mode) { return mode >= LET && mode <= CONST; } - -inline bool IsImmutableVariableMode(VariableMode mode) { - return mode == CONST || mode == CONST_LEGACY; -} - enum VariableLocation : uint8_t { // Before and during variable allocation, a variable whose location is // not yet determined. After allocation, a variable looked up as a diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc index 0afa8e2c4e..8f43b0764d 100644 --- a/src/interpreter/bytecode-generator.cc +++ b/src/interpreter/bytecode-generator.cc @@ -2083,7 +2083,6 @@ void BytecodeGenerator::BuildThrowIfNotHole(Handle name) { void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable, Token::Value op) { - DCHECK(variable->mode() != CONST_LEGACY); if (op != Token::INIT) { // Perform an initialization check for let/const declared variables. // E.g. let x = (x = 20); is not allowed. @@ -2128,17 +2127,11 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable, builder()->LoadAccumulatorWithRegister(value_temp); } - if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) { - if (mode == CONST || is_strict(language_mode())) { - builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), - 0); - } - // Non-initializing assignments to legacy constants are ignored - // in sloppy mode. Break here to avoid storing into variable. - break; + if (mode != CONST || op == Token::INIT) { + builder()->StoreAccumulatorInRegister(destination); + } else if (variable->throw_on_const_assignment(language_mode())) { + builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); } - - builder()->StoreAccumulatorInRegister(destination); break; } case VariableLocation::GLOBAL: @@ -2185,21 +2178,14 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable, builder()->LoadAccumulatorWithRegister(value_temp); } - if ((mode == CONST || mode == CONST_LEGACY) && op != Token::INIT) { - if (mode == CONST || is_strict(language_mode())) { - builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), - 0); - } - // Non-initializing assignments to legacy constants are ignored - // in sloppy mode. Break here to avoid storing into variable. - break; + if (mode != CONST || op == Token::INIT) { + builder()->StoreContextSlot(context_reg, variable->index()); + } else if (variable->throw_on_const_assignment(language_mode())) { + builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(), 0); } - - builder()->StoreContextSlot(context_reg, variable->index()); break; } case VariableLocation::LOOKUP: { - DCHECK_NE(CONST_LEGACY, variable->mode()); builder()->StoreLookupSlot(variable->name(), language_mode()); break; } diff --git a/src/objects.h b/src/objects.h index 7889644274..7e49bf8cb0 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4384,7 +4384,7 @@ class ScopeInfo : public FixedArray { // slot index if the function name is present and context-allocated (named // function expressions, only), otherwise returns a value < 0. The name // must be an internalized string. - int FunctionContextSlotIndex(String* name, VariableMode* mode); + int FunctionContextSlotIndex(String* name); // Lookup support for serialized scope info. Returns the receiver context // slot index if scope has a "this" binding, and the binding is @@ -4502,10 +4502,8 @@ class ScopeInfo : public FixedArray { : public BitField {}; class FunctionVariableField : public BitField {}; - class FunctionVariableMode - : public BitField {}; - class AsmModuleField : public BitField { - }; + class AsmModuleField + : public BitField {}; class AsmFunctionField : public BitField {}; class HasSimpleParametersField : public BitField {}; diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc index ef44372503..af6060a44b 100644 --- a/src/parsing/pattern-rewriter.cc +++ b/src/parsing/pattern-rewriter.cc @@ -140,13 +140,6 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { // which the variable or constant is declared. Only function variables have // an initial value in the declaration (because they are initialized upon // entering the function). - // - // If we have a legacy const declaration, in an inner scope, the proxy - // is always bound to the declared variable (independent of possibly - // surrounding 'with' statements). - // For let/const declarations in harmony mode, we can also immediately - // pre-resolve the proxy because it resides in the same scope as the - // declaration. const AstRawString* name = pattern->raw_name(); VariableProxy* proxy = descriptor_->scope->NewUnresolved( factory(), name, parser_->scanner()->location().beg_pos, diff --git a/src/profiler/heap-snapshot-generator.cc b/src/profiler/heap-snapshot-generator.cc index 9273168f80..9f36797ff3 100644 --- a/src/profiler/heap-snapshot-generator.cc +++ b/src/profiler/heap-snapshot-generator.cc @@ -1216,8 +1216,7 @@ void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) { } if (scope_info->HasFunctionName()) { String* name = scope_info->FunctionName(); - VariableMode mode; - int idx = scope_info->FunctionContextSlotIndex(name, &mode); + int idx = scope_info->FunctionContextSlotIndex(name); if (idx >= 0) { SetContextReference(context, entry, name, context->get(idx), Context::OffsetOfElementAt(idx));