Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(575)

Side by Side Diff: src/hydrogen.cc

Issue 8360001: Fix bug in environment simulation after inlined call-as-function. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Added r9619. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 void HBasicBlock::Finish(HControlInstruction* end) { 157 void HBasicBlock::Finish(HControlInstruction* end) {
158 ASSERT(!IsFinished()); 158 ASSERT(!IsFinished());
159 AddInstruction(end); 159 AddInstruction(end);
160 end_ = end; 160 end_ = end;
161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
162 it.Current()->RegisterPredecessor(this); 162 it.Current()->RegisterPredecessor(this);
163 } 163 }
164 } 164 }
165 165
166 166
167 void HBasicBlock::Goto(HBasicBlock* block) { 167 void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
168 if (block->IsInlineReturnTarget()) { 168 if (block->IsInlineReturnTarget()) {
169 AddInstruction(new(zone()) HLeaveInlined); 169 AddInstruction(new(zone()) HLeaveInlined);
170 last_environment_ = last_environment()->outer(); 170 last_environment_ = last_environment()->outer();
171 if (drop_extra) last_environment_->Drop(1);
171 } 172 }
172 AddSimulate(AstNode::kNoNumber); 173 AddSimulate(AstNode::kNoNumber);
173 HGoto* instr = new(zone()) HGoto(block); 174 HGoto* instr = new(zone()) HGoto(block);
174 Finish(instr); 175 Finish(instr);
175 } 176 }
176 177
177 178
178 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 179 void HBasicBlock::AddLeaveInlined(HValue* return_value,
180 HBasicBlock* target,
181 bool drop_extra) {
179 ASSERT(target->IsInlineReturnTarget()); 182 ASSERT(target->IsInlineReturnTarget());
180 ASSERT(return_value != NULL); 183 ASSERT(return_value != NULL);
181 AddInstruction(new(zone()) HLeaveInlined); 184 AddInstruction(new(zone()) HLeaveInlined);
182 last_environment_ = last_environment()->outer(); 185 last_environment_ = last_environment()->outer();
186 if (drop_extra) last_environment_->Drop(1);
183 last_environment()->Push(return_value); 187 last_environment()->Push(return_value);
184 AddSimulate(AstNode::kNoNumber); 188 AddSimulate(AstNode::kNoNumber);
185 HGoto* instr = new(zone()) HGoto(target); 189 HGoto* instr = new(zone()) HGoto(target);
186 Finish(instr); 190 Finish(instr);
187 } 191 }
188 192
189 193
190 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 194 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
191 ASSERT(!HasEnvironment()); 195 ASSERT(!HasEnvironment());
192 ASSERT(first() == NULL); 196 ASSERT(first() == NULL);
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 538
535 539
536 HConstant* HGraph::GetConstantHole() { 540 HConstant* HGraph::GetConstantHole() {
537 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value()); 541 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
538 } 542 }
539 543
540 544
541 HGraphBuilder::HGraphBuilder(CompilationInfo* info, 545 HGraphBuilder::HGraphBuilder(CompilationInfo* info,
542 TypeFeedbackOracle* oracle) 546 TypeFeedbackOracle* oracle)
543 : function_state_(NULL), 547 : function_state_(NULL),
544 initial_function_state_(this, info, oracle), 548 initial_function_state_(this, info, oracle, false),
545 ast_context_(NULL), 549 ast_context_(NULL),
546 break_scope_(NULL), 550 break_scope_(NULL),
547 graph_(NULL), 551 graph_(NULL),
548 current_block_(NULL), 552 current_block_(NULL),
549 inlined_count_(0), 553 inlined_count_(0),
550 zone_(info->isolate()->zone()), 554 zone_(info->isolate()->zone()),
551 inline_bailout_(false) { 555 inline_bailout_(false) {
552 // This is not initialized in the initializer list because the 556 // This is not initialized in the initializer list because the
553 // constructor for the initial state relies on function_state_ == NULL 557 // constructor for the initial state relies on function_state_ == NULL
554 // to know it's the initial state. 558 // to know it's the initial state.
(...skipping 1443 matching lines...) Expand 10 before | Expand all | Expand 10 after
1998 } 2002 }
1999 } 2003 }
2000 } 2004 }
2001 } 2005 }
2002 2006
2003 2007
2004 // Implementation of utility class to encapsulate the translation state for 2008 // Implementation of utility class to encapsulate the translation state for
2005 // a (possibly inlined) function. 2009 // a (possibly inlined) function.
2006 FunctionState::FunctionState(HGraphBuilder* owner, 2010 FunctionState::FunctionState(HGraphBuilder* owner,
2007 CompilationInfo* info, 2011 CompilationInfo* info,
2008 TypeFeedbackOracle* oracle) 2012 TypeFeedbackOracle* oracle,
2013 bool drop_extra)
2009 : owner_(owner), 2014 : owner_(owner),
2010 compilation_info_(info), 2015 compilation_info_(info),
2011 oracle_(oracle), 2016 oracle_(oracle),
2012 call_context_(NULL), 2017 call_context_(NULL),
2018 drop_extra_(drop_extra),
2013 function_return_(NULL), 2019 function_return_(NULL),
2014 test_context_(NULL), 2020 test_context_(NULL),
2015 outer_(owner->function_state()) { 2021 outer_(owner->function_state()) {
2016 if (outer_ != NULL) { 2022 if (outer_ != NULL) {
2017 // State for an inline function. 2023 // State for an inline function.
2018 if (owner->ast_context()->IsTest()) { 2024 if (owner->ast_context()->IsTest()) {
2019 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2025 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2020 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2026 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2021 if_true->MarkAsInlineReturnTarget(); 2027 if_true->MarkAsInlineReturnTarget();
2022 if_false->MarkAsInlineReturnTarget(); 2028 if_false->MarkAsInlineReturnTarget();
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2161 } 2167 }
2162 2168
2163 2169
2164 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { 2170 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2165 ASSERT(!instr->HasSideEffects()); 2171 ASSERT(!instr->HasSideEffects());
2166 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 2172 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2167 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 2173 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2168 instr->SetSuccessorAt(0, empty_true); 2174 instr->SetSuccessorAt(0, empty_true);
2169 instr->SetSuccessorAt(1, empty_false); 2175 instr->SetSuccessorAt(1, empty_false);
2170 owner()->current_block()->Finish(instr); 2176 owner()->current_block()->Finish(instr);
2171 empty_true->Goto(if_true()); 2177 empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
2172 empty_false->Goto(if_false()); 2178 empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
2173 owner()->set_current_block(NULL); 2179 owner()->set_current_block(NULL);
2174 } 2180 }
2175 2181
2176 2182
2177 void TestContext::BuildBranch(HValue* value) { 2183 void TestContext::BuildBranch(HValue* value) {
2178 // We expect the graph to be in edge-split form: there is no edge that 2184 // We expect the graph to be in edge-split form: there is no edge that
2179 // connects a branch node to a join node. We conservatively ensure that 2185 // connects a branch node to a join node. We conservatively ensure that
2180 // property by always adding an empty block on the outgoing edges of this 2186 // property by always adding an empty block on the outgoing edges of this
2181 // branch. 2187 // branch.
2182 HGraphBuilder* builder = owner(); 2188 HGraphBuilder* builder = owner();
2183 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2189 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2184 builder->Bailout("arguments object value in a test context"); 2190 builder->Bailout("arguments object value in a test context");
2185 } 2191 }
2186 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2192 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2187 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2193 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2188 unsigned test_id = condition()->test_id(); 2194 unsigned test_id = condition()->test_id();
2189 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id)); 2195 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
2190 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); 2196 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2191 builder->current_block()->Finish(test); 2197 builder->current_block()->Finish(test);
2192 2198
2193 empty_true->Goto(if_true()); 2199 empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
2194 empty_false->Goto(if_false()); 2200 empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
2195 builder->set_current_block(NULL); 2201 builder->set_current_block(NULL);
2196 } 2202 }
2197 2203
2198 2204
2199 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2205 // HGraphBuilder infrastructure for bailing out and checking bailouts.
2200 #define CHECK_BAILOUT(call) \ 2206 #define CHECK_BAILOUT(call) \
2201 do { \ 2207 do { \
2202 call; \ 2208 call; \
2203 if (HasStackOverflow()) return; \ 2209 if (HasStackOverflow()) return; \
2204 } while (false) 2210 } while (false)
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2645 } else { 2651 } else {
2646 // Return from an inlined function, visit the subexpression in the 2652 // Return from an inlined function, visit the subexpression in the
2647 // expression context of the call. 2653 // expression context of the call.
2648 if (context->IsTest()) { 2654 if (context->IsTest()) {
2649 TestContext* test = TestContext::cast(context); 2655 TestContext* test = TestContext::cast(context);
2650 VisitForControl(stmt->expression(), 2656 VisitForControl(stmt->expression(),
2651 test->if_true(), 2657 test->if_true(),
2652 test->if_false()); 2658 test->if_false());
2653 } else if (context->IsEffect()) { 2659 } else if (context->IsEffect()) {
2654 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2660 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2655 current_block()->Goto(function_return()); 2661 current_block()->Goto(function_return(), function_state()->drop_extra());
2656 } else { 2662 } else {
2657 ASSERT(context->IsValue()); 2663 ASSERT(context->IsValue());
2658 CHECK_ALIVE(VisitForValue(stmt->expression())); 2664 CHECK_ALIVE(VisitForValue(stmt->expression()));
2659 HValue* return_value = environment()->Pop(); 2665 HValue* return_value = environment()->Pop();
2660 current_block()->AddLeaveInlined(return_value, function_return()); 2666 current_block()->AddLeaveInlined(return_value,
2667 function_return(),
2668 function_state()->drop_extra());
2661 } 2669 }
2662 set_current_block(NULL); 2670 set_current_block(NULL);
2663 } 2671 }
2664 } 2672 }
2665 2673
2666 2674
2667 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2675 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2668 ASSERT(!HasStackOverflow()); 2676 ASSERT(!HasStackOverflow());
2669 ASSERT(current_block() != NULL); 2677 ASSERT(current_block() != NULL);
2670 ASSERT(current_block()->HasPredecessor()); 2678 ASSERT(current_block()->HasPredecessor());
(...skipping 1868 matching lines...) Expand 10 before | Expand all | Expand 10 after
4539 if (reason == NULL) { 4547 if (reason == NULL) {
4540 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 4548 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
4541 } else { 4549 } else {
4542 PrintF("Did not inline %s called from %s (%s).\n", 4550 PrintF("Did not inline %s called from %s (%s).\n",
4543 *target_name, *caller_name, reason); 4551 *target_name, *caller_name, reason);
4544 } 4552 }
4545 } 4553 }
4546 } 4554 }
4547 4555
4548 4556
4549 bool HGraphBuilder::TryInline(Call* expr) { 4557 bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
4550 if (!FLAG_use_inlining) return false; 4558 if (!FLAG_use_inlining) return false;
4551 4559
4552 // The function call we are inlining is a method call if the call 4560 // The function call we are inlining is a method call if the call
4553 // is a property call. 4561 // is a property call.
4554 CallKind call_kind = (expr->expression()->AsProperty() == NULL) 4562 CallKind call_kind = (expr->expression()->AsProperty() == NULL)
4555 ? CALL_AS_FUNCTION 4563 ? CALL_AS_FUNCTION
4556 : CALL_AS_METHOD; 4564 : CALL_AS_METHOD;
4557 4565
4558 // Precondition: call is monomorphic and we have found a target with the 4566 // Precondition: call is monomorphic and we have found a target with the
4559 // appropriate arity. 4567 // appropriate arity.
4560 Handle<JSFunction> caller = info()->closure(); 4568 Handle<JSFunction> caller = info()->closure();
4561 Handle<JSFunction> target = expr->target(); 4569 Handle<JSFunction> target = expr->target();
4562 Handle<SharedFunctionInfo> target_shared(target->shared()); 4570 Handle<SharedFunctionInfo> target_shared(target->shared());
4563 4571
4564 // Do a quick check on source code length to avoid parsing large 4572 // Do a quick check on source code length to avoid parsing large
4565 // inlining candidates. 4573 // inlining candidates.
4566 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { 4574 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
4567 TraceInline(target, caller, "target text too big"); 4575 TraceInline(target, caller, "target text too big");
4568 return false; 4576 return false;
4569 } 4577 }
4570 4578
4571 // Target must be inlineable. 4579 // Target must be inlineable.
4572 if (!target->IsInlineable()) { 4580 if (!target->IsInlineable()) {
4573 TraceInline(target, caller, "target not inlineable"); 4581 TraceInline(target, caller, "target not inlineable");
4574 return false; 4582 return false;
4575 } 4583 }
4576 4584
4577 CompilationInfo* outer_info = info();
4578 #if !defined(V8_TARGET_ARCH_IA32) 4585 #if !defined(V8_TARGET_ARCH_IA32)
4579 // Target must be able to use caller's context. 4586 // Target must be able to use caller's context.
4587 CompilationInfo* outer_info = info();
4580 if (target->context() != outer_info->closure()->context() || 4588 if (target->context() != outer_info->closure()->context() ||
4581 outer_info->scope()->contains_with() || 4589 outer_info->scope()->contains_with() ||
4582 outer_info->scope()->num_heap_slots() > 0) { 4590 outer_info->scope()->num_heap_slots() > 0) {
4583 TraceInline(target, caller, "target requires context change"); 4591 TraceInline(target, caller, "target requires context change");
4584 return false; 4592 return false;
4585 } 4593 }
4586 #endif 4594 #endif
4587 4595
4588 4596
4589 // Don't inline deeper than kMaxInliningLevels calls. 4597 // Don't inline deeper than kMaxInliningLevels calls.
4590 HEnvironment* env = environment(); 4598 HEnvironment* env = environment();
4591 int current_level = 1; 4599 int current_level = 1;
4592 while (env->outer() != NULL) { 4600 while (env->outer() != NULL) {
4593 if (current_level == Compiler::kMaxInliningLevels) { 4601 if (current_level == Compiler::kMaxInliningLevels) {
4594 TraceInline(target, caller, "inline depth limit reached"); 4602 TraceInline(target, caller, "inline depth limit reached");
4595 return false; 4603 return false;
4596 } 4604 }
4597 current_level++; 4605 current_level++;
4598 env = env->outer(); 4606 env = env->outer();
4599 } 4607 }
4600 4608
4601 // Don't inline recursive functions. 4609 // Don't inline recursive functions.
4602 if (*target_shared == outer_info->closure()->shared()) { 4610 for (FunctionState* state = function_state();
4603 TraceInline(target, caller, "target is recursive"); 4611 state != NULL;
4604 return false; 4612 state = state->outer()) {
4613 if (state->compilation_info()->closure()->shared() == *target_shared) {
4614 TraceInline(target, caller, "target is recursive");
4615 return false;
4616 }
4605 } 4617 }
4606 4618
4607 // We don't want to add more than a certain number of nodes from inlining. 4619 // We don't want to add more than a certain number of nodes from inlining.
4608 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 4620 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
4609 TraceInline(target, caller, "cumulative AST node limit reached"); 4621 TraceInline(target, caller, "cumulative AST node limit reached");
4610 return false; 4622 return false;
4611 } 4623 }
4612 4624
4613 int count_before = AstNode::Count(); 4625 int count_before = AstNode::Count();
4614 4626
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4691 // After this point, we've made a decision to inline this function (so 4703 // After this point, we've made a decision to inline this function (so
4692 // TryInline should always return true). 4704 // TryInline should always return true).
4693 4705
4694 // Save the pending call context and type feedback oracle. Set up new ones 4706 // Save the pending call context and type feedback oracle. Set up new ones
4695 // for the inlined function. 4707 // for the inlined function.
4696 ASSERT(target_shared->has_deoptimization_support()); 4708 ASSERT(target_shared->has_deoptimization_support());
4697 TypeFeedbackOracle target_oracle( 4709 TypeFeedbackOracle target_oracle(
4698 Handle<Code>(target_shared->code()), 4710 Handle<Code>(target_shared->code()),
4699 Handle<Context>(target->context()->global_context()), 4711 Handle<Context>(target->context()->global_context()),
4700 isolate()); 4712 isolate());
4701 FunctionState target_state(this, &target_info, &target_oracle); 4713 FunctionState target_state(this, &target_info, &target_oracle, drop_extra);
4702 4714
4703 HConstant* undefined = graph()->GetConstantUndefined(); 4715 HConstant* undefined = graph()->GetConstantUndefined();
4704 HEnvironment* inner_env = 4716 HEnvironment* inner_env =
4705 environment()->CopyForInlining(target, 4717 environment()->CopyForInlining(target,
4706 function, 4718 function,
4707 undefined, 4719 undefined,
4708 call_kind); 4720 call_kind);
4709 #ifdef V8_TARGET_ARCH_IA32 4721 #ifdef V8_TARGET_ARCH_IA32
4710 // IA32 only, overwrite the caller's context in the deoptimization 4722 // IA32 only, overwrite the caller's context in the deoptimization
4711 // environment with the correct one. 4723 // environment with the correct one.
(...skipping 28 matching lines...) Expand all
4740 4752
4741 TraceInline(target, caller, NULL); 4753 TraceInline(target, caller, NULL);
4742 4754
4743 if (current_block() != NULL) { 4755 if (current_block() != NULL) {
4744 // Add a return of undefined if control can fall off the body. In a 4756 // Add a return of undefined if control can fall off the body. In a
4745 // test context, undefined is false. 4757 // test context, undefined is false.
4746 if (inlined_test_context() == NULL) { 4758 if (inlined_test_context() == NULL) {
4747 ASSERT(function_return() != NULL); 4759 ASSERT(function_return() != NULL);
4748 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); 4760 ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4749 if (call_context()->IsEffect()) { 4761 if (call_context()->IsEffect()) {
4750 current_block()->Goto(function_return()); 4762 current_block()->Goto(function_return(), drop_extra);
4751 } else { 4763 } else {
4752 current_block()->AddLeaveInlined(undefined, function_return()); 4764 current_block()->AddLeaveInlined(undefined,
4765 function_return(),
4766 drop_extra);
4753 } 4767 }
4754 } else { 4768 } else {
4755 // The graph builder assumes control can reach both branches of a 4769 // The graph builder assumes control can reach both branches of a
4756 // test, so we materialize the undefined value and test it rather than 4770 // test, so we materialize the undefined value and test it rather than
4757 // simply jumping to the false target. 4771 // simply jumping to the false target.
4758 // 4772 //
4759 // TODO(3168478): refactor to avoid this. 4773 // TODO(3168478): refactor to avoid this.
4774 ASSERT(call_context()->IsTest());
4760 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4775 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4761 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4776 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4762 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false); 4777 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false);
4763 current_block()->Finish(test); 4778 current_block()->Finish(test);
4764 4779
4765 empty_true->Goto(inlined_test_context()->if_true()); 4780 empty_true->Goto(inlined_test_context()->if_true(), drop_extra);
4766 empty_false->Goto(inlined_test_context()->if_false()); 4781 empty_false->Goto(inlined_test_context()->if_false(), drop_extra);
4767 } 4782 }
4768 } 4783 }
4769 4784
4770 // Fix up the function exits. 4785 // Fix up the function exits.
4771 if (inlined_test_context() != NULL) { 4786 if (inlined_test_context() != NULL) {
4772 HBasicBlock* if_true = inlined_test_context()->if_true(); 4787 HBasicBlock* if_true = inlined_test_context()->if_true();
4773 HBasicBlock* if_false = inlined_test_context()->if_false(); 4788 HBasicBlock* if_false = inlined_test_context()->if_false();
4774 4789
4775 // Pop the return test context from the expression context stack. 4790 // Pop the return test context from the expression context stack.
4776 ASSERT(ast_context() == inlined_test_context()); 4791 ASSERT(ast_context() == inlined_test_context());
4777 ClearInlinedTestContext(); 4792 ClearInlinedTestContext();
4778 4793
4779 // Forward to the real test context. 4794 // Forward to the real test context.
4780 if (if_true->HasPredecessor()) { 4795 if (if_true->HasPredecessor()) {
4781 if_true->SetJoinId(expr->id()); 4796 if_true->SetJoinId(expr->id());
4782 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4797 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4783 if_true->Goto(true_target); 4798 if_true->Goto(true_target, drop_extra);
4784 } 4799 }
4785 if (if_false->HasPredecessor()) { 4800 if (if_false->HasPredecessor()) {
4786 if_false->SetJoinId(expr->id()); 4801 if_false->SetJoinId(expr->id());
4787 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4802 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4788 if_false->Goto(false_target); 4803 if_false->Goto(false_target, drop_extra);
4789 } 4804 }
4790 set_current_block(NULL); 4805 set_current_block(NULL);
4791 4806
4792 } else if (function_return()->HasPredecessor()) { 4807 } else if (function_return()->HasPredecessor()) {
4793 function_return()->SetJoinId(expr->id()); 4808 function_return()->SetJoinId(expr->id());
4794 set_current_block(function_return()); 4809 set_current_block(function_return());
4795 } else { 4810 } else {
4796 set_current_block(NULL); 4811 set_current_block(NULL);
4797 } 4812 }
4798 4813
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
5095 // evaluation of the arguments. 5110 // evaluation of the arguments.
5096 CHECK_ALIVE(VisitForValue(expr->expression())); 5111 CHECK_ALIVE(VisitForValue(expr->expression()));
5097 HValue* function = Top(); 5112 HValue* function = Top();
5098 HValue* context = environment()->LookupContext(); 5113 HValue* context = environment()->LookupContext();
5099 HGlobalObject* global = new(zone()) HGlobalObject(context); 5114 HGlobalObject* global = new(zone()) HGlobalObject(context);
5100 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 5115 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
5101 AddInstruction(global); 5116 AddInstruction(global);
5102 PushAndAdd(receiver); 5117 PushAndAdd(receiver);
5103 CHECK_ALIVE(VisitExpressions(expr->arguments())); 5118 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5104 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 5119 AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5105 if (TryInline(expr)) { 5120 if (TryInline(expr, true)) { // Drop function from environment.
5106 // The function is lingering in the deoptimization environment.
5107 // Handle it by case analysis on the AST context.
5108 if (ast_context()->IsEffect()) {
5109 Drop(1);
5110 } else if (ast_context()->IsValue()) {
5111 HValue* result = Pop();
5112 Drop(1);
5113 Push(result);
5114 } else if (ast_context()->IsTest()) {
5115 TestContext* context = TestContext::cast(ast_context());
5116 if (context->if_true()->HasPredecessor()) {
5117 context->if_true()->last_environment()->Drop(1);
5118 }
5119 if (context->if_false()->HasPredecessor()) {
5120 context->if_true()->last_environment()->Drop(1);
5121 }
5122 } else {
5123 UNREACHABLE();
5124 }
5125 return; 5121 return;
5126 } else { 5122 } else {
5127 call = PreProcessCall(new(zone()) HInvokeFunction(context, 5123 call = PreProcessCall(new(zone()) HInvokeFunction(context,
5128 function, 5124 function,
5129 argument_count)); 5125 argument_count));
5130 Drop(1); // The function. 5126 Drop(1); // The function.
5131 } 5127 }
5132 5128
5133 } else { 5129 } else {
5134 CHECK_ALIVE(VisitArgument(expr->expression())); 5130 CHECK_ALIVE(VisitArgument(expr->expression()));
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
5330 if (info.IsUninitialized()) { 5326 if (info.IsUninitialized()) {
5331 AddInstruction(new(zone()) HSoftDeoptimize); 5327 AddInstruction(new(zone()) HSoftDeoptimize);
5332 current_block()->MarkAsDeoptimizing(); 5328 current_block()->MarkAsDeoptimizing();
5333 } 5329 }
5334 HInstruction* instr = new(zone()) HBitNot(value); 5330 HInstruction* instr = new(zone()) HBitNot(value);
5335 return ast_context()->ReturnInstruction(instr, expr->id()); 5331 return ast_context()->ReturnInstruction(instr, expr->id());
5336 } 5332 }
5337 5333
5338 5334
5339 void HGraphBuilder::VisitNot(UnaryOperation* expr) { 5335 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
5340 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
5341 if (ast_context()->IsTest()) { 5336 if (ast_context()->IsTest()) {
5342 TestContext* context = TestContext::cast(ast_context()); 5337 TestContext* context = TestContext::cast(ast_context());
5343 VisitForControl(expr->expression(), 5338 VisitForControl(expr->expression(),
5344 context->if_false(), 5339 context->if_false(),
5345 context->if_true()); 5340 context->if_true());
5346 return; 5341 return;
5347 } 5342 }
5348 5343
5349 if (ast_context()->IsEffect()) { 5344 if (ast_context()->IsEffect()) {
5350 VisitForEffect(expr->expression()); 5345 VisitForEffect(expr->expression());
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after
7013 } 7008 }
7014 } 7009 }
7015 7010
7016 #ifdef DEBUG 7011 #ifdef DEBUG
7017 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7012 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7018 if (allocator_ != NULL) allocator_->Verify(); 7013 if (allocator_ != NULL) allocator_->Verify();
7019 #endif 7014 #endif
7020 } 7015 }
7021 7016
7022 } } // namespace v8::internal 7017 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698