| Index: src/hydrogen.cc
|
| ===================================================================
|
| --- src/hydrogen.cc (revision 8094)
|
| +++ src/hydrogen.cc (working copy)
|
| @@ -521,6 +521,12 @@
|
| return GetConstant(&constant_false_, isolate()->heap()->false_value());
|
| }
|
|
|
| +
|
| +HConstant* HGraph::GetConstantHole() {
|
| + return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
|
| +}
|
| +
|
| +
|
| HGraphBuilder::HGraphBuilder(CompilationInfo* info,
|
| TypeFeedbackOracle* oracle)
|
| : function_state_(NULL),
|
| @@ -826,6 +832,10 @@
|
| phi_list_->Add(phi);
|
| // We don't support phi uses of arguments for now.
|
| if (phi->CheckFlag(HValue::kIsArguments)) return false;
|
| + // Check for the hole value (from an uninitialized const).
|
| + for (int k = 0; k < phi->OperandCount(); k++) {
|
| + if (phi->OperandAt(k) == GetConstantHole()) return false;
|
| + }
|
| }
|
| }
|
| return true;
|
| @@ -2225,7 +2235,7 @@
|
| graph()->EliminateRedundantPhis();
|
| if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
|
| if (!graph()->CollectPhis()) {
|
| - Bailout("Phi-use of arguments object");
|
| + Bailout("Unsupported phi-use");
|
| return NULL;
|
| }
|
|
|
| @@ -2996,7 +3006,12 @@
|
| if (variable == NULL) {
|
| return Bailout("reference to rewritten variable");
|
| } else if (variable->IsStackAllocated()) {
|
| - ast_context()->ReturnValue(environment()->Lookup(variable));
|
| + HValue* value = environment()->Lookup(variable);
|
| + if (variable->mode() == Variable::CONST &&
|
| + value == graph()->GetConstantHole()) {
|
| + return Bailout("reference to uninitialized const variable");
|
| + }
|
| + ast_context()->ReturnValue(value);
|
| } else if (variable->IsContextSlot()) {
|
| if (variable->mode() == Variable::CONST) {
|
| return Bailout("reference to const context slot");
|
| @@ -3451,6 +3466,10 @@
|
| BinaryOperation* operation = expr->binary_operation();
|
|
|
| if (var != NULL) {
|
| + if (var->mode() == Variable::CONST) {
|
| + return Bailout("unsupported const compound assignment");
|
| + }
|
| +
|
| CHECK_ALIVE(VisitForValue(operation));
|
|
|
| if (var->is_global()) {
|
| @@ -3557,6 +3576,16 @@
|
| }
|
|
|
| if (var != NULL) {
|
| + if (var->mode() == Variable::CONST) {
|
| + if (expr->op() != Token::INIT_CONST) {
|
| + return Bailout("non-initializer assignment to const");
|
| + }
|
| + // 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);
|
| + AddInstruction(new HUseConst(old_value));
|
| + }
|
| +
|
| if (proxy->IsArguments()) return Bailout("assignment to arguments");
|
|
|
| // Handle the assignment.
|
| @@ -4871,6 +4900,9 @@
|
| HValue* after = NULL; // The result after incrementing or decrementing.
|
|
|
| if (var != NULL) {
|
| + if (var->mode() == Variable::CONST) {
|
| + return Bailout("unsupported count operation with const");
|
| + }
|
| // Argument of the count operation is a variable, not a property.
|
| ASSERT(prop == NULL);
|
| CHECK_ALIVE(VisitForValue(target));
|
| @@ -5335,17 +5367,20 @@
|
|
|
| void HGraphBuilder::VisitDeclaration(Declaration* decl) {
|
| // We allow only declarations that do not require code generation.
|
| - // The following all require code generation: global variables and
|
| - // functions, variables with slot type LOOKUP, declarations with
|
| - // mode CONST, and functions.
|
| + // The following all require code generation: global variables,
|
| + // functions, and variables with slot type LOOKUP
|
| Variable* var = decl->proxy()->var();
|
| Slot* slot = var->AsSlot();
|
| if (var->is_global() ||
|
| + !var->IsStackAllocated() ||
|
| (slot != NULL && slot->type() == Slot::LOOKUP) ||
|
| - decl->mode() == Variable::CONST ||
|
| decl->fun() != NULL) {
|
| return Bailout("unsupported declaration");
|
| }
|
| +
|
| + if (decl->mode() == Variable::CONST) {
|
| + environment()->Bind(var, graph()->GetConstantHole());
|
| + }
|
| }
|
|
|
|
|
|
|