Chromium Code Reviews| Index: src/hydrogen.cc |
| =================================================================== |
| --- src/hydrogen.cc (revision 8460) |
| +++ src/hydrogen.cc (working copy) |
| @@ -886,9 +886,8 @@ |
| private: |
| void TraceRange(const char* msg, ...); |
| void Analyze(HBasicBlock* block); |
| - void InferControlFlowRange(HTest* test, HBasicBlock* dest); |
| - void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); |
| - void InferPhiRange(HPhi* phi); |
| + void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest); |
| + void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other); |
| void InferRange(HValue* value); |
| void RollBackTo(int index); |
| void AddRange(HValue* value, Range* range); |
| @@ -922,15 +921,15 @@ |
| // Infer range based on control flow. |
| if (block->predecessors()->length() == 1) { |
| HBasicBlock* pred = block->predecessors()->first(); |
| - if (pred->end()->IsTest()) { |
| - InferControlFlowRange(HTest::cast(pred->end()), block); |
| + if (pred->end()->IsCompareIDAndBranch()) { |
| + InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block); |
| } |
| } |
| // Process phi instructions. |
| for (int i = 0; i < block->phis()->length(); ++i) { |
| HPhi* phi = block->phis()->at(i); |
| - InferPhiRange(phi); |
| + InferRange(phi); |
| } |
| // Go through all instructions of the current block. |
| @@ -949,28 +948,26 @@ |
| } |
| -void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { |
| +void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, |
| + HBasicBlock* dest) { |
| ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); |
| - if (test->value()->IsCompare()) { |
| - HCompare* compare = HCompare::cast(test->value()); |
| - if (compare->GetInputRepresentation().IsInteger32()) { |
| - Token::Value op = compare->token(); |
| - if (test->SecondSuccessor() == dest) { |
| - op = Token::NegateCompareOp(op); |
| - } |
| - Token::Value inverted_op = Token::InvertCompareOp(op); |
| - InferControlFlowRange(op, compare->left(), compare->right()); |
| - InferControlFlowRange(inverted_op, compare->right(), compare->left()); |
| + if (test->GetInputRepresentation().IsInteger32()) { |
| + Token::Value op = test->token(); |
| + if (test->SecondSuccessor() == dest) { |
| + op = Token::NegateCompareOp(op); |
| } |
| + Token::Value inverted_op = Token::InvertCompareOp(op); |
| + UpdateControlFlowRange(op, test->left(), test->right()); |
| + UpdateControlFlowRange(inverted_op, test->right(), test->left()); |
| } |
| } |
| // We know that value [op] other. Use this information to update the range on |
| // value. |
| -void HRangeAnalysis::InferControlFlowRange(Token::Value op, |
| - HValue* value, |
| - HValue* other) { |
| +void HRangeAnalysis::UpdateControlFlowRange(Token::Value op, |
| + HValue* value, |
| + HValue* other) { |
| Range temp_range; |
| Range* range = other->range() != NULL ? other->range() : &temp_range; |
| Range* new_range = NULL; |
| @@ -1001,12 +998,6 @@ |
| } |
| -void HRangeAnalysis::InferPhiRange(HPhi* phi) { |
| - // TODO(twuerthinger): Infer loop phi ranges. |
| - InferRange(phi); |
| -} |
| - |
| - |
| void HRangeAnalysis::InferRange(HValue* value) { |
| ASSERT(!value->HasRange()); |
| if (!value->representation().IsNone()) { |
| @@ -1940,7 +1931,7 @@ |
| HPhase phase("MarkDeoptimizeOnUndefined", this); |
| // Compute DeoptimizeOnUndefined flag for phis. |
| // Any phi that can reach a use with DeoptimizeOnUndefined set must |
| - // have DeoptimizeOnUndefined set. Currently only HCompare, with |
| + // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with |
| // double input representation, has this flag set. |
| // The flag is used by HChange tagged->double, which must deoptimize |
| // if one of its uses has this flag set. |
| @@ -2078,14 +2069,28 @@ |
| void EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
| + ASSERT(!instr->IsControlInstruction()); |
| owner()->AddInstruction(instr); |
| if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); |
| } |
| +void EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) { |
| + ASSERT(!instr->HasSideEffects()); |
| + HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| + HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| + instr->SetSuccessorAt(0, empty_true); |
| + instr->SetSuccessorAt(1, empty_false); |
| + owner()->current_block()->Finish(instr); |
| + HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); |
| + owner()->set_current_block(join); |
| +} |
| + |
| + |
| void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
| + ASSERT(!instr->IsControlInstruction()); |
| if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| - owner()->Bailout("bad value context for arguments object value"); |
| + return owner()->Bailout("bad value context for arguments object value"); |
| } |
| owner()->AddInstruction(instr); |
| owner()->Push(instr); |
| @@ -2093,7 +2098,29 @@ |
| } |
| +void ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) { |
| + ASSERT(!instr->HasSideEffects()); |
| + if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { |
| + return owner()->Bailout("bad value context for arguments object value"); |
| + } |
| + HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); |
| + HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); |
| + instr->SetSuccessorAt(0, materialize_true); |
| + instr->SetSuccessorAt(1, materialize_false); |
| + owner()->current_block()->Finish(instr); |
| + owner()->set_current_block(materialize_true); |
| + owner()->Push(owner()->graph()->GetConstantTrue()); |
| + owner()->set_current_block(materialize_false); |
| + owner()->Push(owner()->graph()->GetConstantFalse()); |
| + HBasicBlock* join = |
| + owner()->CreateJoin(materialize_true, materialize_false, ast_id); |
| + owner()->set_current_block(join); |
| + ReturnValue(owner()->Pop()); |
|
Kevin Millikin (Chromium)
2011/06/30 13:31:05
No need for this last line. All it does is check
|
| +} |
| + |
| + |
| void TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { |
| + ASSERT(!instr->IsControlInstruction()); |
| HGraphBuilder* builder = owner(); |
| builder->AddInstruction(instr); |
| // We expect a simulate after every expression with side effects, though |
| @@ -2107,18 +2134,31 @@ |
| } |
| +void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { |
| + ASSERT(!instr->HasSideEffects()); |
| + HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); |
| + HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); |
| + instr->SetSuccessorAt(0, empty_true); |
| + instr->SetSuccessorAt(1, empty_false); |
| + owner()->current_block()->Finish(instr); |
| + empty_true->Goto(if_true()); |
| + empty_false->Goto(if_false()); |
| + owner()->set_current_block(NULL); |
| +} |
| + |
| + |
| void TestContext::BuildBranch(HValue* value) { |
| // We expect the graph to be in edge-split form: there is no edge that |
| // connects a branch node to a join node. We conservatively ensure that |
| // property by always adding an empty block on the outgoing edges of this |
| // branch. |
| HGraphBuilder* builder = owner(); |
| - if (value->CheckFlag(HValue::kIsArguments)) { |
| + if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { |
| builder->Bailout("arguments object value in a test context"); |
| } |
| HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
| HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
| - HTest* test = new(zone()) HTest(value, empty_true, empty_false); |
| + HBranch* test = new(zone()) HBranch(value, empty_true, empty_false); |
| builder->current_block()->Finish(test); |
| empty_true->Goto(if_true()); |
| @@ -2624,15 +2664,16 @@ |
| // Otherwise generate a compare and branch. |
| CHECK_ALIVE(VisitForValue(clause->label())); |
| HValue* label_value = Pop(); |
| - HCompare* compare = |
| - new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); |
| + HCompareIDAndBranch* compare = |
| + new(zone()) HCompareIDAndBranch(tag_value, |
| + label_value, |
| + Token::EQ_STRICT); |
| compare->SetInputRepresentation(Representation::Integer32()); |
| - ASSERT(!compare->HasSideEffects()); |
| - AddInstruction(compare); |
| HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| - HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); |
| - current_block()->Finish(branch); |
| + compare->SetSuccessorAt(0, body_block); |
| + compare->SetSuccessorAt(1, next_test_block); |
| + current_block()->Finish(compare); |
| set_current_block(next_test_block); |
| } |
| @@ -2718,7 +2759,7 @@ |
| HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| HValue* true_value = graph()->GetConstantTrue(); |
| - HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); |
| + HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); |
| current_block()->Finish(test); |
| HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
| @@ -2962,7 +3003,7 @@ |
| if (HasStackOverflow()) return; |
| HFunctionLiteral* instr = |
| new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
|
Kevin Millikin (Chromium)
2011/06/30 13:31:05
:)
|
| } |
| @@ -3007,7 +3048,7 @@ |
| HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); |
| set_current_block(join); |
| if (join != NULL && !ast_context()->IsEffect()) { |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } |
| } |
| } |
| @@ -3057,7 +3098,7 @@ |
| value == graph()->GetConstantHole()) { |
| return Bailout("reference to uninitialized const variable"); |
| } |
| - ast_context()->ReturnValue(value); |
| + return ast_context()->ReturnValue(value); |
| } else if (variable->IsContextSlot()) { |
| if (variable->mode() == Variable::CONST) { |
| return Bailout("reference to const context slot"); |
| @@ -3065,7 +3106,7 @@ |
| HValue* context = BuildContextChainWalk(variable); |
| int index = variable->AsSlot()->index(); |
| HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } else if (variable->is_global()) { |
| LookupResult lookup; |
| GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
| @@ -3080,7 +3121,7 @@ |
| Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } else { |
| HValue* context = environment()->LookupContext(); |
| HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| @@ -3092,7 +3133,7 @@ |
| ast_context()->is_for_typeof()); |
| instr->set_position(expr->position()); |
| ASSERT(instr->HasSideEffects()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| } else { |
| return Bailout("reference to a variable which requires dynamic lookup"); |
| @@ -3106,7 +3147,7 @@ |
| ASSERT(current_block()->HasPredecessor()); |
| HConstant* instr = |
| new(zone()) HConstant(expr->handle(), Representation::Tagged()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -3117,7 +3158,7 @@ |
| HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), |
| expr->flags(), |
| expr->literal_index()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -3187,9 +3228,9 @@ |
| // (e.g. because of code motion). |
| HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
| AddInstruction(result); |
| - ast_context()->ReturnValue(result); |
| + return ast_context()->ReturnValue(result); |
| } else { |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } |
| } |
| @@ -3233,7 +3274,7 @@ |
| AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); |
| AddSimulate(expr->GetIdForElement(i)); |
| } |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } |
| @@ -3395,15 +3436,14 @@ |
| Drop(1); |
| } |
| } |
| - ast_context()->ReturnValue(value); |
| - return; |
| + return ast_context()->ReturnValue(value); |
| } |
| } |
| ASSERT(join != NULL); |
| join->SetJoinId(expr->id()); |
| set_current_block(join); |
| - if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| + if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| } |
| @@ -3455,14 +3495,13 @@ |
| Push(value); |
| ASSERT(has_side_effects); // Stores always have side effects. |
| AddSimulate(expr->AssignmentId()); |
| - ast_context()->ReturnValue(Pop()); |
| - return; |
| + return ast_context()->ReturnValue(Pop()); |
| } |
| Push(value); |
| instr->set_position(expr->position()); |
| AddInstruction(instr); |
| if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } |
| @@ -3550,7 +3589,7 @@ |
| } else { |
| return Bailout("compound assignment to lookup slot"); |
| } |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } else if (prop != NULL) { |
| prop->RecordTypeFeedback(oracle()); |
| @@ -3585,7 +3624,7 @@ |
| Drop(2); |
| Push(instr); |
| if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } else { |
| // Keyed property. |
| @@ -3622,7 +3661,7 @@ |
| Push(instr); |
| ASSERT(has_side_effects); // Stores always have side effects. |
| AddSimulate(expr->AssignmentId()); |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } |
| } else { |
| @@ -3669,7 +3708,7 @@ |
| CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
| HValue* value = Pop(); |
| Bind(var, value); |
| - ast_context()->ReturnValue(value); |
| + return ast_context()->ReturnValue(value); |
| } else if (var->IsContextSlot()) { |
| ASSERT(var->mode() != Variable::CONST); |
| @@ -3694,7 +3733,7 @@ |
| new(zone()) HStoreContextSlot(context, index, Top()); |
| AddInstruction(instr); |
| if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } else if (var->is_global()) { |
| CHECK_ALIVE(VisitForValue(expr->value())); |
| @@ -3702,7 +3741,7 @@ |
| Top(), |
| expr->position(), |
| expr->AssignmentId()); |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } else { |
| return Bailout("assignment to LOOKUP or const CONTEXT variable"); |
| @@ -3955,23 +3994,24 @@ |
| if (type_todo[elements_kind]) { |
| HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| - HCompareConstantEq* compare = new(zone()) HCompareConstantEq( |
| - elements_kind_instr, |
| - elements_kind, |
| - Token::EQ_STRICT); |
| - AddInstruction(compare); |
| - HTest* branch = new(zone()) HTest(compare, if_true, if_false); |
| - current_block()->Finish(branch); |
| + HCompareConstantEqAndBranch* compare = |
| + new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, |
| + elements_kind, |
| + Token::EQ_STRICT); |
| + compare->SetSuccessorAt(0, if_true); |
| + compare->SetSuccessorAt(1, if_false); |
| + current_block()->Finish(compare); |
| set_current_block(if_true); |
| HInstruction* access; |
| if (elements_kind == JSObject::FAST_ELEMENTS) { |
| HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
| HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
| - HInstruction* typecheck = |
| - AddInstruction(new(zone()) HHasInstanceType(object, JS_ARRAY_TYPE)); |
| - HTest* test = new(zone()) HTest(typecheck, if_jsarray, if_fastobject); |
| - current_block()->Finish(test); |
| + HHasInstanceTypeAndBranch* typecheck = |
| + new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
| + typecheck->SetSuccessorAt(0, if_jsarray); |
| + typecheck->SetSuccessorAt(1, if_fastobject); |
| + current_block()->Finish(typecheck); |
| set_current_block(if_jsarray); |
| HInstruction* length = new(zone()) HJSArrayLength(object); |
| @@ -4178,11 +4218,10 @@ |
| Drop(1); |
| } |
| } |
| - ast_context()->ReturnValue(load); |
| - return; |
| + return ast_context()->ReturnValue(load); |
| } |
| instr->set_position(expr->position()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -4270,8 +4309,7 @@ |
| if (!ast_context()->IsEffect()) Push(call); |
| current_block()->Goto(join); |
| } else { |
| - ast_context()->ReturnInstruction(call, expr->id()); |
| - return; |
| + return ast_context()->ReturnInstruction(call, expr->id()); |
| } |
| } |
| @@ -4282,7 +4320,7 @@ |
| if (join->HasPredecessor()) { |
| set_current_block(join); |
| join->SetJoinId(expr->id()); |
| - if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| + if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| } else { |
| set_current_block(NULL); |
| } |
| @@ -4496,7 +4534,7 @@ |
| // TODO(3168478): refactor to avoid this. |
| HBasicBlock* empty_true = graph()->CreateBasicBlock(); |
| HBasicBlock* empty_false = graph()->CreateBasicBlock(); |
| - HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); |
| + HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false); |
| current_block()->Finish(test); |
| empty_true->Goto(inlined_test_context()->if_true()); |
| @@ -4709,8 +4747,7 @@ |
| call = new(zone()) HCallKeyed(context, key, argument_count); |
| call->set_position(expr->position()); |
| Drop(argument_count + 1); // 1 is the key. |
| - ast_context()->ReturnInstruction(call, expr->id()); |
| - return; |
| + return ast_context()->ReturnInstruction(call, expr->id()); |
| } |
| // Named function call. |
| @@ -4834,7 +4871,7 @@ |
| } |
| call->set_position(expr->position()); |
| - ast_context()->ReturnInstruction(call, expr->id()); |
| + return ast_context()->ReturnInstruction(call, expr->id()); |
| } |
| @@ -4856,7 +4893,7 @@ |
| HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); |
| call->set_position(expr->position()); |
| Drop(arg_count); |
| - ast_context()->ReturnInstruction(call, expr->id()); |
| + return ast_context()->ReturnInstruction(call, expr->id()); |
| } |
| @@ -4908,7 +4945,7 @@ |
| new(zone()) HCallRuntime(name, function, argument_count); |
| call->set_position(RelocInfo::kNoPosition); |
| Drop(argument_count); |
| - ast_context()->ReturnInstruction(call, expr->id()); |
| + return ast_context()->ReturnInstruction(call, expr->id()); |
| } |
| } |
| @@ -4936,26 +4973,26 @@ |
| // Result of deleting non-property, non-variable reference is true. |
| // Evaluate the subexpression for side effects. |
| CHECK_ALIVE(VisitForEffect(expr->expression())); |
| - ast_context()->ReturnValue(graph()->GetConstantTrue()); |
| + return ast_context()->ReturnValue(graph()->GetConstantTrue()); |
| } else if (var != NULL && |
| !var->is_global() && |
| var->AsSlot() != NULL && |
| var->AsSlot()->type() != Slot::LOOKUP) { |
| // Result of deleting non-global, non-dynamic variables is false. |
| // The subexpression does not have side effects. |
| - ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| + return ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| } else if (prop != NULL) { |
| if (prop->is_synthetic()) { |
| // Result of deleting parameters is false, even when they rewrite |
| // to accesses on the arguments object. |
| - ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| + return ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| } else { |
| CHECK_ALIVE(VisitForValue(prop->obj())); |
| CHECK_ALIVE(VisitForValue(prop->key())); |
| HValue* key = Pop(); |
| HValue* obj = Pop(); |
| HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| } else if (var->is_global()) { |
| Bailout("delete with global variable"); |
| @@ -4967,14 +5004,15 @@ |
| void HGraphBuilder::VisitVoid(UnaryOperation* expr) { |
| CHECK_ALIVE(VisitForEffect(expr->expression())); |
| - ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| + return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| } |
| void HGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
| HValue* value = Pop(); |
| - ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); |
| + return ast_context()->ReturnInstruction(new(zone()) HTypeof(value), |
| + expr->id()); |
| } |
| @@ -4982,7 +5020,7 @@ |
| CHECK_ALIVE(VisitForValue(expr->expression())); |
| HValue* value = Pop(); |
| HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -4999,7 +5037,7 @@ |
| Representation rep = ToRepresentation(info); |
| TraceRepresentation(expr->op(), info, instr, rep); |
| instr->AssumeRepresentation(rep); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -5012,7 +5050,7 @@ |
| current_block()->MarkAsDeoptimizing(); |
| } |
| HInstruction* instr = new(zone()) HBitNot(value); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -5057,7 +5095,7 @@ |
| HBasicBlock* join = |
| CreateJoin(materialize_false, materialize_true, expr->id()); |
| set_current_block(join); |
| - if (join != NULL) ast_context()->ReturnValue(Pop()); |
| + if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| } |
| @@ -5232,7 +5270,7 @@ |
| } |
| Drop(returns_original_input ? 2 : 1); |
| - ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| + return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
| } |
| @@ -5392,9 +5430,9 @@ |
| // We need an extra block to maintain edge-split form. |
| HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
| HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| - HTest* test = is_logical_and |
| - ? new(zone()) HTest(Top(), eval_right, empty_block) |
| - : new(zone()) HTest(Top(), empty_block, eval_right); |
| + HBranch* test = is_logical_and |
| + ? new(zone()) HBranch(Top(), eval_right, empty_block) |
| + : new(zone()) HBranch(Top(), empty_block, eval_right); |
| current_block()->Finish(test); |
| set_current_block(eval_right); |
| @@ -5404,7 +5442,7 @@ |
| HBasicBlock* join_block = |
| CreateJoin(empty_block, current_block(), expr->id()); |
| set_current_block(join_block); |
| - ast_context()->ReturnValue(Pop()); |
| + return ast_context()->ReturnValue(Pop()); |
| } else { |
| ASSERT(ast_context()->IsEffect()); |
| @@ -5456,7 +5494,7 @@ |
| HValue* left = Pop(); |
| HInstruction* instr = BuildBinaryOperation(expr, left, right); |
| instr->set_position(expr->position()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| + return ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -5494,9 +5532,9 @@ |
| Handle<String> check) { |
| CHECK_ALIVE(VisitForTypeOf(expr)); |
| HValue* expr_value = Pop(); |
| - HInstruction* instr = new(zone()) HTypeofIs(expr_value, check); |
| + HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check); |
| instr->set_position(compare_expr->position()); |
| - ast_context()->ReturnInstruction(instr, compare_expr->id()); |
| + return ast_context()->ReturnControl(instr, compare_expr->id()); |
| } |
| @@ -5505,10 +5543,10 @@ |
| CHECK_ALIVE(VisitForValue(expr)); |
| HValue* lhs = Pop(); |
| HValue* rhs = graph()->GetConstantUndefined(); |
| - HInstruction* instr = |
| - new(zone()) HCompareObjectEq(lhs, rhs); |
| + HCompareObjectEqAndBranch* instr = |
| + new(zone()) HCompareObjectEqAndBranch(lhs, rhs); |
| instr->set_position(compare_expr->position()); |
| - ast_context()->ReturnInstruction(instr, compare_expr->id()); |
| + return ast_context()->ReturnControl(instr, compare_expr->id()); |
| } |
| @@ -5518,14 +5556,15 @@ |
| ASSERT(current_block()->HasPredecessor()); |
| if (IsClassOfTest(expr)) { |
| CallRuntime* call = expr->left()->AsCallRuntime(); |
| + ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| Literal* literal = expr->right()->AsLiteral(); |
| Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| - HInstruction* instr = new(zone()) HClassOfTest(value, rhs); |
| + HClassOfTestAndBranch* instr = |
| + new(zone()) HClassOfTestAndBranch(value, rhs); |
| instr->set_position(expr->position()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| - return; |
| + return ast_context()->ReturnControl(instr, expr->id()); |
| } |
| // Check for special cases that compare against literals. |
| @@ -5556,7 +5595,6 @@ |
| HValue* left = Pop(); |
| Token::Value op = expr->op(); |
| - HInstruction* instr = NULL; |
| if (op == Token::INSTANCEOF) { |
| // Check to see if the rhs of the instanceof is a global function not |
| // residing in new space. If it is we assume that the function will stay the |
| @@ -5587,13 +5625,20 @@ |
| // assumed to stay the same for this instanceof. |
| if (target.is_null()) { |
| HValue* context = environment()->LookupContext(); |
| - instr = new(zone()) HInstanceOf(context, left, right); |
| + HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
| + result->set_position(expr->position()); |
| + return ast_context()->ReturnInstruction(result, expr->id()); |
| } else { |
| AddInstruction(new(zone()) HCheckFunction(right, target)); |
| - instr = new(zone()) HInstanceOfKnownGlobal(left, target); |
| + HInstanceOfKnownGlobal* result = |
| + new(zone()) HInstanceOfKnownGlobal(left, target); |
| + result->set_position(expr->position()); |
| + return ast_context()->ReturnInstruction(result, expr->id()); |
| } |
| } else if (op == Token::IN) { |
| - instr = new(zone()) HIn(left, right); |
| + HIn* result = new(zone()) HIn(left, right); |
| + result->set_position(expr->position()); |
| + return ast_context()->ReturnInstruction(result, expr->id()); |
| } else if (type_info.IsNonPrimitive()) { |
| switch (op) { |
| case Token::EQ: |
| @@ -5602,12 +5647,13 @@ |
| AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); |
| AddInstruction(new(zone()) HCheckNonSmi(right)); |
| AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); |
| - instr = new(zone()) HCompareObjectEq(left, right); |
| - break; |
| + HCompareObjectEqAndBranch* result = |
| + new(zone()) HCompareObjectEqAndBranch(left, right); |
| + result->set_position(expr->position()); |
| + return ast_context()->ReturnControl(result, expr->id()); |
| } |
| default: |
| return Bailout("Unsupported non-primitive compare"); |
| - break; |
| } |
| } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && |
| (op == Token::EQ || op == Token::EQ_STRICT)) { |
| @@ -5615,15 +5661,24 @@ |
| AddInstruction(HCheckInstanceType::NewIsSymbol(left)); |
| AddInstruction(new(zone()) HCheckNonSmi(right)); |
| AddInstruction(HCheckInstanceType::NewIsSymbol(right)); |
| - instr = new(zone()) HCompareObjectEq(left, right); |
| + HCompareObjectEqAndBranch* result = |
| + new(zone()) HCompareObjectEqAndBranch(left, right); |
| + result->set_position(expr->position()); |
| + return ast_context()->ReturnControl(result, expr->id()); |
| } else { |
| - HCompare* compare = new(zone()) HCompare(left, right, op); |
| Representation r = ToRepresentation(type_info); |
| - compare->SetInputRepresentation(r); |
| - instr = compare; |
| + if (r.IsTagged()) { |
| + HCompareGeneric* result = new(zone()) HCompareGeneric(left, right, op); |
| + result->set_position(expr->position()); |
| + return ast_context()->ReturnInstruction(result, expr->id()); |
| + } else { |
| + HCompareIDAndBranch* result = |
| + new(zone()) HCompareIDAndBranch(left, right, op); |
| + result->set_position(expr->position()); |
| + result->SetInputRepresentation(r); |
| + return ast_context()->ReturnControl(result, expr->id()); |
| + } |
| } |
| - instr->set_position(expr->position()); |
| - ast_context()->ReturnInstruction(instr, expr->id()); |
| } |
| @@ -5632,10 +5687,10 @@ |
| ASSERT(current_block() != NULL); |
| ASSERT(current_block()->HasPredecessor()); |
| CHECK_ALIVE(VisitForValue(expr->expression())); |
| - |
| HValue* value = Pop(); |
| - HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); |
| - ast_context()->ReturnInstruction(compare, expr->id()); |
| + HIsNullAndBranch* instr = |
| + new(zone()) HIsNullAndBranch(value, expr->is_strict()); |
| + return ast_context()->ReturnControl(instr, expr->id()); |
| } |
| @@ -5668,8 +5723,8 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HIsSmi* result = new(zone()) HIsSmi(value); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5677,11 +5732,11 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HHasInstanceType* result = |
| - new(zone()) HHasInstanceType(value, |
| - FIRST_SPEC_OBJECT_TYPE, |
| - LAST_SPEC_OBJECT_TYPE); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HHasInstanceTypeAndBranch* result = |
| + new(zone()) HHasInstanceTypeAndBranch(value, |
| + FIRST_SPEC_OBJECT_TYPE, |
| + LAST_SPEC_OBJECT_TYPE); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5689,9 +5744,9 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HHasInstanceType* result = |
| - new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HHasInstanceTypeAndBranch* result = |
| + new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5699,8 +5754,9 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HHasCachedArrayIndexAndBranch* result = |
| + new(zone()) HHasCachedArrayIndexAndBranch(value); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5708,8 +5764,9 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HHasInstanceTypeAndBranch* result = |
| + new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5717,9 +5774,9 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HHasInstanceType* result = |
| - new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HHasInstanceTypeAndBranch* result = |
| + new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5727,8 +5784,8 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - HIsObject* test = new(zone()) HIsObject(value); |
| - ast_context()->ReturnInstruction(test, call->id()); |
| + HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5741,8 +5798,9 @@ |
| ASSERT(call->arguments()->length() == 1); |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| - ast_context()->ReturnInstruction(new(zone()) HIsUndetectable(value), |
| - call->id()); |
| + HIsUndetectableAndBranch* result = |
| + new(zone()) HIsUndetectableAndBranch(value); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| @@ -5760,9 +5818,10 @@ |
| // We are generating graph for inlined function. Currently |
| // constructor inlining is not supported and we can just return |
| // false from %_IsConstructCall(). |
| - ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| + return ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| } else { |
| - ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); |
| + return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, |
| + call->id()); |
| } |
| } |
| @@ -5776,7 +5835,7 @@ |
| ASSERT(call->arguments()->length() == 0); |
| HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5792,7 +5851,7 @@ |
| HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| HAccessArgumentsAt* result = |
| new(zone()) HAccessArgumentsAt(elements, length, index); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5809,7 +5868,7 @@ |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HValueOf* result = new(zone()) HValueOf(value); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5826,7 +5885,7 @@ |
| HValue* index = Pop(); |
| HValue* string = Pop(); |
| HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5836,7 +5895,7 @@ |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* char_code = Pop(); |
| HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5850,7 +5909,7 @@ |
| HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| AddInstruction(char_code); |
| HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5861,14 +5920,15 @@ |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| - HCompareObjectEq* result = new(zone()) HCompareObjectEq(left, right); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + HCompareObjectEqAndBranch* result = |
| + new(zone()) HCompareObjectEqAndBranch(left, right); |
| + return ast_context()->ReturnControl(result, call->id()); |
| } |
| void HGraphBuilder::GenerateLog(CallRuntime* call) { |
| // %_Log is ignored in optimized code. |
| - ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| + return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| } |
| @@ -5885,7 +5945,7 @@ |
| HValue* context = environment()->LookupContext(); |
| HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
| Drop(2); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5896,7 +5956,7 @@ |
| HValue* context = environment()->LookupContext(); |
| HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| Drop(3); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5908,7 +5968,7 @@ |
| HCallStub* result = |
| new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
| Drop(2); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5919,7 +5979,7 @@ |
| HValue* context = environment()->LookupContext(); |
| HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
| Drop(4); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5931,7 +5991,7 @@ |
| HCallStub* result = |
| new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
| Drop(3); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5949,7 +6009,7 @@ |
| HCallStub* result = |
| new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
| Drop(1); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5976,7 +6036,7 @@ |
| HInvokeFunction* result = |
| new(zone()) HInvokeFunction(context, function, arg_count); |
| Drop(arg_count); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -5988,7 +6048,7 @@ |
| HValue* right = Pop(); |
| HValue* left = Pop(); |
| HPower* result = new(zone()) HPower(left, right); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -6000,7 +6060,7 @@ |
| new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| result->set_transcendental_type(TranscendentalCache::SIN); |
| Drop(1); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -6012,7 +6072,7 @@ |
| new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| result->set_transcendental_type(TranscendentalCache::COS); |
| Drop(1); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -6024,7 +6084,7 @@ |
| new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| result->set_transcendental_type(TranscendentalCache::LOG); |
| Drop(1); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |
| @@ -6044,7 +6104,7 @@ |
| CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| HValue* value = Pop(); |
| HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
| - ast_context()->ReturnInstruction(result, call->id()); |
| + return ast_context()->ReturnInstruction(result, call->id()); |
| } |