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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
===================================================================
--- src/hydrogen.cc (revision 9754)
+++ src/hydrogen.cc (working copy)
@@ -164,10 +164,11 @@
}
-void HBasicBlock::Goto(HBasicBlock* block) {
+void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
if (block->IsInlineReturnTarget()) {
AddInstruction(new(zone()) HLeaveInlined);
last_environment_ = last_environment()->outer();
+ if (drop_extra) last_environment_->Drop(1);
}
AddSimulate(AstNode::kNoNumber);
HGoto* instr = new(zone()) HGoto(block);
@@ -175,11 +176,14 @@
}
-void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
+void HBasicBlock::AddLeaveInlined(HValue* return_value,
+ HBasicBlock* target,
+ bool drop_extra) {
ASSERT(target->IsInlineReturnTarget());
ASSERT(return_value != NULL);
AddInstruction(new(zone()) HLeaveInlined);
last_environment_ = last_environment()->outer();
+ if (drop_extra) last_environment_->Drop(1);
last_environment()->Push(return_value);
AddSimulate(AstNode::kNoNumber);
HGoto* instr = new(zone()) HGoto(target);
@@ -541,7 +545,7 @@
HGraphBuilder::HGraphBuilder(CompilationInfo* info,
TypeFeedbackOracle* oracle)
: function_state_(NULL),
- initial_function_state_(this, info, oracle),
+ initial_function_state_(this, info, oracle, false),
ast_context_(NULL),
break_scope_(NULL),
graph_(NULL),
@@ -2005,11 +2009,13 @@
// a (possibly inlined) function.
FunctionState::FunctionState(HGraphBuilder* owner,
CompilationInfo* info,
- TypeFeedbackOracle* oracle)
+ TypeFeedbackOracle* oracle,
+ bool drop_extra)
: owner_(owner),
compilation_info_(info),
oracle_(oracle),
call_context_(NULL),
+ drop_extra_(drop_extra),
function_return_(NULL),
test_context_(NULL),
outer_(owner->function_state()) {
@@ -2168,8 +2174,8 @@
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());
+ empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
+ empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
owner()->set_current_block(NULL);
}
@@ -2190,8 +2196,8 @@
HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
builder->current_block()->Finish(test);
- empty_true->Goto(if_true());
- empty_false->Goto(if_false());
+ empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
+ empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
builder->set_current_block(NULL);
}
@@ -2652,12 +2658,14 @@
test->if_false());
} else if (context->IsEffect()) {
CHECK_ALIVE(VisitForEffect(stmt->expression()));
- current_block()->Goto(function_return());
+ current_block()->Goto(function_return(), function_state()->drop_extra());
} else {
ASSERT(context->IsValue());
CHECK_ALIVE(VisitForValue(stmt->expression()));
HValue* return_value = environment()->Pop();
- current_block()->AddLeaveInlined(return_value, function_return());
+ current_block()->AddLeaveInlined(return_value,
+ function_return(),
+ function_state()->drop_extra());
}
set_current_block(NULL);
}
@@ -4546,7 +4554,7 @@
}
-bool HGraphBuilder::TryInline(Call* expr) {
+bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
if (!FLAG_use_inlining) return false;
// The function call we are inlining is a method call if the call
@@ -4574,9 +4582,9 @@
return false;
}
- CompilationInfo* outer_info = info();
#if !defined(V8_TARGET_ARCH_IA32)
// Target must be able to use caller's context.
+ CompilationInfo* outer_info = info();
if (target->context() != outer_info->closure()->context() ||
outer_info->scope()->contains_with() ||
outer_info->scope()->num_heap_slots() > 0) {
@@ -4599,9 +4607,13 @@
}
// Don't inline recursive functions.
- if (*target_shared == outer_info->closure()->shared()) {
- TraceInline(target, caller, "target is recursive");
- return false;
+ for (FunctionState* state = function_state();
+ state != NULL;
+ state = state->outer()) {
+ if (state->compilation_info()->closure()->shared() == *target_shared) {
+ TraceInline(target, caller, "target is recursive");
+ return false;
+ }
}
// We don't want to add more than a certain number of nodes from inlining.
@@ -4698,7 +4710,7 @@
Handle<Code>(target_shared->code()),
Handle<Context>(target->context()->global_context()),
isolate());
- FunctionState target_state(this, &target_info, &target_oracle);
+ FunctionState target_state(this, &target_info, &target_oracle, drop_extra);
HConstant* undefined = graph()->GetConstantUndefined();
HEnvironment* inner_env =
@@ -4747,9 +4759,11 @@
ASSERT(function_return() != NULL);
ASSERT(call_context()->IsEffect() || call_context()->IsValue());
if (call_context()->IsEffect()) {
- current_block()->Goto(function_return());
+ current_block()->Goto(function_return(), drop_extra);
} else {
- current_block()->AddLeaveInlined(undefined, function_return());
+ current_block()->AddLeaveInlined(undefined,
+ function_return(),
+ drop_extra);
}
} else {
// The graph builder assumes control can reach both branches of a
@@ -4757,13 +4771,14 @@
// simply jumping to the false target.
//
// TODO(3168478): refactor to avoid this.
+ ASSERT(call_context()->IsTest());
HBasicBlock* empty_true = graph()->CreateBasicBlock();
HBasicBlock* empty_false = graph()->CreateBasicBlock();
HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false);
current_block()->Finish(test);
- empty_true->Goto(inlined_test_context()->if_true());
- empty_false->Goto(inlined_test_context()->if_false());
+ empty_true->Goto(inlined_test_context()->if_true(), drop_extra);
+ empty_false->Goto(inlined_test_context()->if_false(), drop_extra);
}
}
@@ -4780,12 +4795,12 @@
if (if_true->HasPredecessor()) {
if_true->SetJoinId(expr->id());
HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
- if_true->Goto(true_target);
+ if_true->Goto(true_target, drop_extra);
}
if (if_false->HasPredecessor()) {
if_false->SetJoinId(expr->id());
HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
- if_false->Goto(false_target);
+ if_false->Goto(false_target, drop_extra);
}
set_current_block(NULL);
@@ -5102,26 +5117,7 @@
PushAndAdd(receiver);
CHECK_ALIVE(VisitExpressions(expr->arguments()));
AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
- if (TryInline(expr)) {
- // The function is lingering in the deoptimization environment.
- // Handle it by case analysis on the AST context.
- if (ast_context()->IsEffect()) {
- Drop(1);
- } else if (ast_context()->IsValue()) {
- HValue* result = Pop();
- Drop(1);
- Push(result);
- } else if (ast_context()->IsTest()) {
- TestContext* context = TestContext::cast(ast_context());
- if (context->if_true()->HasPredecessor()) {
- context->if_true()->last_environment()->Drop(1);
- }
- if (context->if_false()->HasPredecessor()) {
- context->if_true()->last_environment()->Drop(1);
- }
- } else {
- UNREACHABLE();
- }
+ if (TryInline(expr, true)) { // Drop function from environment.
return;
} else {
call = PreProcessCall(new(zone()) HInvokeFunction(context,
@@ -5337,7 +5333,6 @@
void HGraphBuilder::VisitNot(UnaryOperation* expr) {
- // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
if (ast_context()->IsTest()) {
TestContext* context = TestContext::cast(ast_context());
VisitForControl(expr->expression(),
« 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