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

Unified Diff: src/full-codegen.cc

Issue 192513002: Checking for stack height equality between full codegen and hydrogen. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 years, 7 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/full-codegen.h ('k') | src/hydrogen.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/full-codegen.cc
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 6ae927c9018a16a5462f2448f5ae79bdc3e997a1..1409f90629b8e2e2fed0380955bc0abd19735d42 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -381,6 +381,9 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
for (int i = 0; i < length; i++) {
data->SetAstId(i, bailout_entries_[i].id);
data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
+#if defined(COMPARE_OPT_STACK_HEIGHT)
+ data->SetStackHeight(i, Smi::FromInt(bailout_entries_[i].stack_height));
+#endif
}
code->set_deoptimization_data(*data);
}
@@ -448,7 +451,12 @@ void FullCodeGenerator::RecordJSReturnSite(Call* call) {
void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
// There's no need to prepare this code for bailouts from already optimized
// code or code that can't be optimized.
- if (!info_->HasDeoptimizationSupport()) return;
+ if (!info_->HasDeoptimizationSupport()) {
+ // We still need to insert the check to make sure that we generate exactly
+ // the same code
+ CheckStackHeight();
+ return;
+ }
unsigned pc_and_state =
StateField::encode(state) | PcField::encode(masm_->pc_offset());
ASSERT(Smi::IsValid(pc_and_state));
@@ -457,8 +465,11 @@ void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
ASSERT(bailout_entries_[i].id != id);
}
#endif
- BailoutEntry entry = { id, pc_and_state };
+ // If the we store the top of the stack register, pretend it is on the stack
+ int stack_height = stack_height_.get() + (state == TOS_REG ? 1 : 0);
+ BailoutEntry entry = { id, pc_and_state, stack_height };
bailout_entries_.Add(entry, zone());
+ CheckStackHeight();
}
@@ -492,7 +503,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
- __ Push(reg);
+ codegen()->AsmPush(reg);
}
@@ -505,12 +516,12 @@ void FullCodeGenerator::TestContext::Plug(Register reg) const {
void FullCodeGenerator::EffectContext::PlugTOS() const {
- __ Drop(1);
+ codegen()->AsmDrop(1);
}
void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
- __ Pop(result_register());
+ codegen()->AsmPop(result_register());
}
@@ -520,7 +531,7 @@ void FullCodeGenerator::StackValueContext::PlugTOS() const {
void FullCodeGenerator::TestContext::PlugTOS() const {
// For simplicity we always test the accumulator register.
- __ Pop(result_register());
+ codegen()->AsmPop(result_register());
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this);
}
@@ -597,9 +608,9 @@ void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) {
// Set up module context.
ASSERT(scope->interface()->Index() >= 0);
- __ Push(Smi::FromInt(scope->interface()->Index()));
- __ Push(scope->GetScopeInfo());
- __ CallRuntime(Runtime::kHiddenPushModuleContext, 2);
+ AsmPushSmi(Smi::FromInt(scope->interface()->Index()));
+ AsmPushHandle(scope->GetScopeInfo());
+ AsmCallRuntime(Runtime::kHiddenPushModuleContext, 2);
StoreToFrameField(StandardFrameConstants::kContextOffset,
context_register());
@@ -688,6 +699,7 @@ void FullCodeGenerator::VisitDeclarations(
// This is a scope hosting modules. Allocate a descriptor array to pass
// to the runtime for initialization.
Comment cmnt(masm_, "[ Allocate modules");
+
ASSERT(scope_->is_global_scope());
modules_ =
isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED);
@@ -737,9 +749,9 @@ void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
// Set up module context.
ASSERT(interface->Index() >= 0);
- __ Push(Smi::FromInt(interface->Index()));
- __ Push(Smi::FromInt(0));
- __ CallRuntime(Runtime::kHiddenPushModuleContext, 2);
+ AsmPushSmi(Smi::FromInt(interface->Index()));
+ AsmPushSmi(Smi::FromInt(0));
+ AsmCallRuntime(Runtime::kHiddenPushModuleContext, 2);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
{
@@ -970,32 +982,32 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
} else {
VisitForControl(left, test->true_label(), &eval_right, &eval_right);
}
- PrepareForBailoutForId(right_id, NO_REGISTERS);
__ bind(&eval_right);
-
+ PrepareForBailoutForId(right_id, NO_REGISTERS);
} else if (context()->IsAccumulatorValue()) {
VisitForAccumulatorValue(left);
// We want the value in the accumulator for the test, and on the stack in
// case we need it.
- __ Push(result_register());
+ AsmPush(result_register());
Label discard, restore;
if (is_logical_and) {
DoTest(left, &discard, &restore, &restore);
} else {
DoTest(left, &restore, &discard, &restore);
}
+ StackHeightWrapper branch_stack_height = CurrentStackHeight();
__ bind(&restore);
- __ Pop(result_register());
+ AsmPop(result_register());
__ jmp(&done);
__ bind(&discard);
- __ Drop(1);
+ SetStackHeight(branch_stack_height);
+ AsmDrop(1);
PrepareForBailoutForId(right_id, NO_REGISTERS);
-
} else if (context()->IsStackValue()) {
VisitForAccumulatorValue(left);
// We want the value in the accumulator for the test, and on the stack in
// case we need it.
- __ Push(result_register());
+ AsmPush(result_register());
Label discard;
if (is_logical_and) {
DoTest(left, &discard, &done, &discard);
@@ -1003,9 +1015,8 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
DoTest(left, &done, &discard, &discard);
}
__ bind(&discard);
- __ Drop(1);
+ AsmDrop(1);
PrepareForBailoutForId(right_id, NO_REGISTERS);
-
} else {
ASSERT(context()->IsEffect());
Label eval_right;
@@ -1014,8 +1025,8 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
} else {
VisitForControl(left, &done, &eval_right, &eval_right);
}
- PrepareForBailoutForId(right_id, NO_REGISTERS);
__ bind(&eval_right);
+ PrepareForBailoutForId(right_id, NO_REGISTERS);
}
VisitInDuplicateContext(right);
@@ -1056,9 +1067,9 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
scope_ = stmt->scope();
ASSERT(!scope_->is_module_scope());
{ Comment cmnt(masm_, "[ Extend block context");
- __ Push(scope_->GetScopeInfo());
+ AsmPushHandle(scope_->GetScopeInfo());
PushFunctionArgumentForContextAllocation();
- __ CallRuntime(Runtime::kHiddenPushBlockContext, 2);
+ AsmCallRuntime(Runtime::kHiddenPushBlockContext, 2);
// Replace the context stored in the frame.
StoreToFrameField(StandardFrameConstants::kContextOffset,
@@ -1088,9 +1099,9 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) {
Comment cmnt(masm_, "[ Module context");
- __ Push(Smi::FromInt(stmt->proxy()->interface()->Index()));
- __ Push(Smi::FromInt(0));
- __ CallRuntime(Runtime::kHiddenPushModuleContext, 2);
+ AsmPushSmi(Smi::FromInt(stmt->proxy()->interface()->Index()));
+ AsmPushSmi(Smi::FromInt(0));
+ AsmCallRuntime(Runtime::kHiddenPushModuleContext, 2);
StoreToFrameField(
StandardFrameConstants::kContextOffset, context_register());
@@ -1125,18 +1136,20 @@ void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
if (stmt->HasElseStatement()) {
VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
- PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
+ StackHeightWrapper if_stack_height = CurrentStackHeight();
__ bind(&then_part);
+ PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
Visit(stmt->then_statement());
__ jmp(&done);
- PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
__ bind(&else_part);
+ SetStackHeight(if_stack_height);
+ PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
Visit(stmt->else_statement());
} else {
VisitForControl(stmt->condition(), &then_part, &done, &then_part);
- PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
__ bind(&then_part);
+ PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
Visit(stmt->then_statement());
PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
@@ -1150,6 +1163,7 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
Comment cmnt(masm_, "[ ContinueStatement");
SetStatementPosition(stmt);
NestedStatement* current = nesting_stack_;
+ StackHeightWrapper original_stack_height = CurrentStackHeight();
int stack_depth = 0;
int context_length = 0;
// When continuing, we clobber the unpredictable value in the accumulator
@@ -1160,7 +1174,7 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
while (!current->IsContinueTarget(stmt->target())) {
current = current->Exit(&stack_depth, &context_length);
}
- __ Drop(stack_depth);
+ AsmDrop(stack_depth);
if (context_length > 0) {
while (context_length > 0) {
LoadContextField(context_register(), Context::PREVIOUS_INDEX);
@@ -1171,6 +1185,7 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
}
__ jmp(current->AsIteration()->continue_label());
+ SetStackHeight(original_stack_height);
}
@@ -1178,6 +1193,7 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
Comment cmnt(masm_, "[ BreakStatement");
SetStatementPosition(stmt);
NestedStatement* current = nesting_stack_;
+ StackHeightWrapper original_stack_height = CurrentStackHeight();
int stack_depth = 0;
int context_length = 0;
// When breaking, we clobber the unpredictable value in the accumulator
@@ -1188,7 +1204,7 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
while (!current->IsBreakTarget(stmt->target())) {
current = current->Exit(&stack_depth, &context_length);
}
- __ Drop(stack_depth);
+ AsmDrop(stack_depth);
if (context_length > 0) {
while (context_length > 0) {
LoadContextField(context_register(), Context::PREVIOUS_INDEX);
@@ -1199,6 +1215,7 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
}
__ jmp(current->AsBreakable()->break_label());
+ SetStackHeight(original_stack_height);
}
@@ -1209,7 +1226,7 @@ void FullCodeGenerator::EmitUnwindBeforeReturn() {
while (current != NULL) {
current = current->Exit(&stack_depth, &context_length);
}
- __ Drop(stack_depth);
+ AsmDrop(stack_depth);
}
@@ -1218,8 +1235,11 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
SetStatementPosition(stmt);
Expression* expr = stmt->expression();
VisitForAccumulatorValue(expr);
+ StackHeightWrapper previous_stack_height = CurrentStackHeight();
EmitUnwindBeforeReturn();
EmitReturnSequence();
+ // Reset the expected stack height
+ SetStackHeight(previous_stack_height);
}
@@ -1229,7 +1249,7 @@ void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
VisitForStackValue(stmt->expression());
PushFunctionArgumentForContextAllocation();
- __ CallRuntime(Runtime::kHiddenPushWithContext, 2);
+ AsmCallRuntime(Runtime::kHiddenPushWithContext, 2);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
Scope* saved_scope = scope();
@@ -1268,13 +1288,13 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
&book_keeping);
// Check stack before looping.
- PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
__ bind(&book_keeping);
+ PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
EmitBackEdgeBookkeeping(stmt, &body);
__ jmp(&body);
- PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
+ PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
decrement_loop_depth();
}
@@ -1289,8 +1309,8 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
// Emit the test at the bottom of the loop.
__ jmp(&test);
- PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&body);
+ PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
Visit(stmt->body());
// Emit the statement position here as this is where the while
@@ -1307,8 +1327,8 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
loop_statement.break_label(),
loop_statement.break_label());
- PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
+ PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
decrement_loop_depth();
}
@@ -1330,12 +1350,12 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
// Emit the test at the bottom of the loop (even if empty).
__ jmp(&test);
- PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&body);
+ PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
Visit(stmt->body());
- PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
__ bind(loop_statement.continue_label());
+ PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
if (stmt->next() != NULL) {
Visit(stmt->next());
}
@@ -1357,8 +1377,8 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
__ jmp(&body);
}
- PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
+ PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
decrement_loop_depth();
}
@@ -1379,10 +1399,10 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// Exception handler code, the exception is in the result register.
// Extend the context before executing the catch block.
{ Comment cmnt(masm_, "[ Extend catch context");
- __ Push(stmt->variable()->name());
- __ Push(result_register());
+ AsmPushHandle(stmt->variable()->name());
+ AsmPush(result_register());
PushFunctionArgumentForContextAllocation();
- __ CallRuntime(Runtime::kHiddenPushCatchContext, 3);
+ AsmCallRuntime(Runtime::kHiddenPushCatchContext, 3);
StoreToFrameField(StandardFrameConstants::kContextOffset,
context_register());
}
@@ -1401,11 +1421,11 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
// Try block code. Sets up the exception handler chain.
__ bind(&try_entry);
- __ PushTryHandler(StackHandler::CATCH, stmt->index());
+ AsmPushTryHandler(StackHandler::CATCH, stmt->index());
{ TryCatch try_body(this);
Visit(stmt->try_block());
}
- __ PopTryHandler();
+ AsmPopTryHandler();
__ bind(&exit);
}
@@ -1445,11 +1465,13 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// preserved by the finally block. Call the finally block and then
// rethrow the exception if it returns.
__ Call(&finally_entry);
- __ Push(result_register());
- __ CallRuntime(Runtime::kHiddenReThrow, 1);
+ AsmPush(result_register());
+ AsmCallRuntime(Runtime::kHiddenReThrow, 1);
// Finally block implementation.
__ bind(&finally_entry);
+ // The return address is on the stack -> update the height
+ UpdateStackHeight(1);
EnterFinallyBlock();
{ Finally finally_body(this);
Visit(stmt->finally_block());
@@ -1458,11 +1480,11 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
// Set up try handler.
__ bind(&try_entry);
- __ PushTryHandler(StackHandler::FINALLY, stmt->index());
+ AsmPushTryHandler(StackHandler::FINALLY, stmt->index());
{ TryFinally try_body(this, &finally_entry);
Visit(stmt->try_block());
}
- __ PopTryHandler();
+ AsmPopTryHandler();
// Execute the finally block on the way out. Clobber the unpredictable
// value in the result register with one that's safe for GC because the
// finally block will unconditionally preserve the result register on the
@@ -1490,9 +1512,10 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
Comment cmnt(masm_, "[ Conditional");
Label true_case, false_case, done;
VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
+ StackHeightWrapper if_stack_height = CurrentStackHeight();
- PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
__ bind(&true_case);
+ PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
SetExpressionPosition(expr->then_expression());
if (context()->IsTest()) {
const TestContext* for_test = TestContext::cast(context());
@@ -1505,8 +1528,9 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
__ jmp(&done);
}
- PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
__ bind(&false_case);
+ SetStackHeight(if_stack_height);
+ PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
SetExpressionPosition(expr->else_expression());
VisitInDuplicateContext(expr->else_expression());
// If control flow falls through Visit, merge it with true case here.
@@ -1572,8 +1596,12 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
void FullCodeGenerator::VisitThrow(Throw* expr) {
Comment cmnt(masm_, "[ Throw");
VisitForStackValue(expr->exception());
- __ CallRuntime(Runtime::kHiddenThrow, 1);
- // Never returns here.
+ AsmCallRuntime(Runtime::kHiddenThrow, 1);
+ // Never returns here. Update stack height so that we do not confuse the
+ // stack height checker.
+ if (context() != NULL && !context()->IsEffect()) {
+ UpdateStackHeight(1);
+ }
}
@@ -1581,8 +1609,8 @@ FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
int* stack_depth,
int* context_length) {
// The macros used here must preserve the result register.
- __ Drop(*stack_depth);
- __ PopTryHandler();
+ codegen()->AsmDrop(*stack_depth);
+ codegen()->AsmPopTryHandler();
*stack_depth = 0;
return previous_;
}
« no previous file with comments | « src/full-codegen.h ('k') | src/hydrogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698