| Index: src/interpreter/bytecode-generator.cc
|
| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
|
| index 7a0b9aced657ad162cb873a84bde5d99a4d17185..98fab3548d23b28442997fd98d02ecdf6de76df8 100644
|
| --- a/src/interpreter/bytecode-generator.cc
|
| +++ b/src/interpreter/bytecode-generator.cc
|
| @@ -2001,30 +2001,16 @@ void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
|
| builder()->Bind(&no_reference_error);
|
| }
|
|
|
| -void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
|
| - // TODO(mythria): This will be replaced by a new bytecode that throws an
|
| - // appropriate error depending on the whether the value is a hole or not.
|
| - BytecodeLabel const_assign_error;
|
| - builder()->JumpIfNotHole(&const_assign_error);
|
| - BuildThrowReferenceError(name);
|
| - builder()
|
| - ->Bind(&const_assign_error)
|
| - .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
|
| -}
|
| -
|
| void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
|
| Token::Value op) {
|
| - VariableMode mode = variable->mode();
|
| - DCHECK(mode != CONST_LEGACY);
|
| - if (mode == CONST && op != Token::INIT) {
|
| - // Non-intializing assignments to constant is not allowed.
|
| - BuildThrowReassignConstant(variable->name());
|
| - } else if (mode == LET && op != Token::INIT) {
|
| - // Perform an initialization check for let declared variables.
|
| + 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.
|
| BuildThrowIfHole(variable->name());
|
| } else {
|
| - DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
|
| + DCHECK(variable->is_this() && variable->mode() == CONST &&
|
| + op == Token::INIT);
|
| // Perform an initialization check for 'this'. 'this' variable is the
|
| // only variable able to trigger bind operations outside the TDZ
|
| // via 'super' calls.
|
| @@ -2039,9 +2025,9 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| RegisterAllocationScope assignment_register_scope(this);
|
| BytecodeLabel end_label;
|
| bool hole_check_required =
|
| - (mode == LET && op != Token::INIT) ||
|
| - (mode == CONST && op != Token::INIT) ||
|
| - (mode == CONST && op == Token::INIT && variable->is_this());
|
| + variable->binding_needs_init() &&
|
| + ((IsLexicalVariableMode(mode) && op != Token::INIT) ||
|
| + (mode == CONST && op == Token::INIT && variable->is_this()));
|
| switch (variable->location()) {
|
| case VariableLocation::PARAMETER:
|
| case VariableLocation::LOCAL: {
|
| @@ -2052,16 +2038,6 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| destination = Register(variable->index());
|
| }
|
|
|
| - if (mode == CONST_LEGACY && op != Token::INIT) {
|
| - if (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 (hole_check_required) {
|
| // Load destination to check for hole.
|
| Register value_temp = register_allocator()->NewRegister();
|
| @@ -2072,6 +2048,17 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| BuildHoleCheckForVariableAssignment(variable, op);
|
| 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;
|
| + }
|
| +
|
| builder()->StoreAccumulatorInRegister(destination);
|
| break;
|
| }
|
| @@ -2108,16 +2095,6 @@ void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
|
| builder()->LoadAccumulatorWithRegister(value_temp);
|
| }
|
|
|
| - if (mode == CONST_LEGACY && op != Token::INIT) {
|
| - if (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 (hole_check_required) {
|
| // Load destination to check for hole.
|
| Register value_temp = register_allocator()->NewRegister();
|
| @@ -2129,6 +2106,16 @@ 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;
|
| + }
|
| +
|
| builder()->StoreContextSlot(context_reg, variable->index());
|
| break;
|
| }
|
|
|