| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 2d9d58a2352ee085db34da87b5edcf33bca010ea..ec272f532420d54cd13c3286a7ca3bb472db8595 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -3228,11 +3228,11 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
| ASSERT(current_block() != NULL);
|
| ASSERT(current_block()->HasPredecessor());
|
| Variable* variable = expr->var();
|
| - if (variable->mode() == LET) {
|
| - return Bailout("reference to let variable");
|
| - }
|
| switch (variable->location()) {
|
| case Variable::UNALLOCATED: {
|
| + if (variable->mode() == LET || variable->mode() == CONST_HARMONY) {
|
| + return Bailout("reference to global harmony declared variable");
|
| + }
|
| // Handle known global constants like 'undefined' specially to avoid a
|
| // load from a global cell for them.
|
| Handle<Object> constant_value =
|
| @@ -3275,14 +3275,19 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
| case Variable::PARAMETER:
|
| case Variable::LOCAL: {
|
| HValue* value = environment()->Lookup(variable);
|
| - if (variable->mode() == CONST &&
|
| - value == graph()->GetConstantHole()) {
|
| - return Bailout("reference to uninitialized const variable");
|
| + if (value == graph()->GetConstantHole()) {
|
| + ASSERT(variable->mode() == CONST ||
|
| + variable->mode() == CONST_HARMONY ||
|
| + variable->mode() == LET);
|
| + return Bailout("reference to uninitialized variable");
|
| }
|
| return ast_context()->ReturnValue(value);
|
| }
|
|
|
| case Variable::CONTEXT: {
|
| + if (variable->mode() == LET || variable->mode() == CONST_HARMONY) {
|
| + return Bailout("reference to harmony declared context slot");
|
| + }
|
| if (variable->mode() == CONST) {
|
| return Bailout("reference to const context slot");
|
| }
|
| @@ -3963,7 +3968,16 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
|
| HValue* old_value = environment()->Lookup(var);
|
| AddInstruction(new HUseConst(old_value));
|
| } else if (var->mode() == LET) {
|
| - return Bailout("unsupported assignment to let");
|
| + if (!var->IsStackAllocated()) {
|
| + return Bailout("assignment to let context slot");
|
| + }
|
| + } else if (var->mode() == CONST_HARMONY) {
|
| + if (expr->op() != Token::INIT_CONST_HARMONY) {
|
| + return Bailout("non-initializer assignment to const");
|
| + }
|
| + if (!var->IsStackAllocated()) {
|
| + return Bailout("assignment to const context slot");
|
| + }
|
| }
|
|
|
| if (proxy->IsArguments()) return Bailout("assignment to arguments");
|
| @@ -3980,6 +3994,14 @@ void HGraphBuilder::VisitAssignment(Assignment* expr) {
|
|
|
| case Variable::PARAMETER:
|
| case Variable::LOCAL: {
|
| + // Perform an initialization check for let declared variables
|
| + // or parameters.
|
| + if (var->mode() == LET && expr->op() == Token::ASSIGN) {
|
| + HValue* env_value = environment()->Lookup(var);
|
| + if (env_value == graph()->GetConstantHole()) {
|
| + return Bailout("assignment to let variable before initialization");
|
| + }
|
| + }
|
| // We do not allow the arguments object to occur in a context where it
|
| // may escape, but assignments to stack-allocated locals are
|
| // permitted.
|
| @@ -6191,23 +6213,22 @@ void HGraphBuilder::VisitDeclaration(Declaration* decl) {
|
| void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
|
| VariableMode mode,
|
| FunctionLiteral* function) {
|
| - if (mode == LET || mode == CONST_HARMONY) {
|
| - return Bailout("unsupported harmony declaration");
|
| - }
|
| Variable* var = proxy->var();
|
| + bool binding_needs_init =
|
| + (mode == CONST || mode == CONST_HARMONY || mode == LET);
|
| switch (var->location()) {
|
| case Variable::UNALLOCATED:
|
| return Bailout("unsupported global declaration");
|
| case Variable::PARAMETER:
|
| case Variable::LOCAL:
|
| case Variable::CONTEXT:
|
| - if (mode == CONST || function != NULL) {
|
| + if (binding_needs_init || function != NULL) {
|
| HValue* value = NULL;
|
| - if (mode == CONST) {
|
| - value = graph()->GetConstantHole();
|
| - } else {
|
| + if (function != NULL) {
|
| VisitForValue(function);
|
| value = Pop();
|
| + } else {
|
| + value = graph()->GetConstantHole();
|
| }
|
| if (var->IsContextSlot()) {
|
| HValue* context = environment()->LookupContext();
|
|
|