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

Unified Diff: src/ia32/full-codegen-ia32.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/hydrogen.cc ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/full-codegen-ia32.cc
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 07afba6c80d7ad264907a42904c29cc3689aac32..74e62296d41fc4bd97568dc8040669ad32fad4d3 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -165,7 +165,7 @@ void FullCodeGenerator::Generate() {
// Generators allocate locals, if any, in context slots.
ASSERT(!info->function()->is_generator() || locals_count == 0);
if (locals_count == 1) {
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
} else if (locals_count > 1) {
if (locals_count >= 128) {
EmitStackCheck(masm_, locals_count, ecx);
@@ -189,6 +189,7 @@ void FullCodeGenerator::Generate() {
for (int i = 0; i < remaining; i++) {
__ push(eax);
}
+ UpdateStackHeight(locals_count);
}
}
@@ -200,15 +201,15 @@ void FullCodeGenerator::Generate() {
Comment cmnt(masm_, "[ Allocate context");
// Argument to NewContext is the function, which is still in edi.
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
- __ push(edi);
- __ Push(info->scope()->GetScopeInfo());
- __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2);
+ AsmPush(edi);
+ AsmPushHandle(info->scope()->GetScopeInfo());
+ AsmCallRuntime(Runtime::kHiddenNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(isolate(), heap_slots);
__ CallStub(&stub);
} else {
- __ push(edi);
- __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1);
+ AsmPush(edi);
+ AsmCallRuntime(Runtime::kHiddenNewFunctionContext, 1);
}
function_in_register = false;
// Context is returned in eax. It replaces the context passed to us.
@@ -243,17 +244,17 @@ void FullCodeGenerator::Generate() {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
if (function_in_register) {
- __ push(edi);
+ AsmPush(edi);
} else {
- __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ AsmPush(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ lea(edx,
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
- __ push(edx);
- __ push(Immediate(Smi::FromInt(num_parameters)));
+ AsmPush(edx);
+ AsmPushSmi(Smi::FromInt(num_parameters));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
@@ -267,13 +268,13 @@ void FullCodeGenerator::Generate() {
type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(isolate(), type);
- __ CallStub(&stub);
+ AsmCallStub(&stub, 3);
SetVar(arguments, eax, ebx, edx);
}
if (FLAG_trace) {
- __ CallRuntime(Runtime::kTraceEnter, 0);
+ AsmCallRuntime(Runtime::kTraceEnter, 0);
}
// Visit the declarations and body unless there is an illegal
@@ -375,8 +376,8 @@ void FullCodeGenerator::EmitReturnSequence() {
// Common return label
__ bind(&return_label_);
if (FLAG_trace) {
- __ push(eax);
- __ CallRuntime(Runtime::kTraceExit, 1);
+ AsmPush(eax);
+ AsmCallRuntime(Runtime::kTraceExit, 1);
}
// Pretend that the exit is a backwards jump to the entry.
int weight = 1;
@@ -390,10 +391,10 @@ void FullCodeGenerator::EmitReturnSequence() {
EmitProfilingCounterDecrement(weight);
Label ok;
__ j(positive, &ok, Label::kNear);
- __ push(eax);
+ AsmPush(eax);
__ call(isolate()->builtins()->InterruptCheck(),
RelocInfo::CODE_TARGET);
- __ pop(eax);
+ AsmPop(eax);
EmitProfilingCounterReset();
__ bind(&ok);
#ifdef DEBUG
@@ -435,7 +436,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
MemOperand operand = codegen()->VarOperand(var, result_register());
// Memory operands can be pushed directly.
- __ push(operand);
+ codegen()->AsmPush(operand);
}
@@ -486,8 +487,9 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(
void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
if (lit->IsSmi()) {
__ SafePush(Immediate(lit));
+ codegen()->UpdateStackHeight(1);
} else {
- __ push(Immediate(lit));
+ codegen()->AsmPushHandle(lit);
}
}
@@ -525,7 +527,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const {
void FullCodeGenerator::EffectContext::DropAndPlug(int count,
Register reg) const {
ASSERT(count > 0);
- __ Drop(count);
+ codegen()->AsmDrop(count);
}
@@ -533,7 +535,7 @@ void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
int count,
Register reg) const {
ASSERT(count > 0);
- __ Drop(count);
+ codegen()->AsmDrop(count);
__ Move(result_register(), reg);
}
@@ -541,7 +543,7 @@ void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
Register reg) const {
ASSERT(count > 0);
- if (count > 1) __ Drop(count - 1);
+ if (count > 1) codegen()->AsmDrop(count - 1);
__ mov(Operand(esp, 0), reg);
}
@@ -550,7 +552,7 @@ void FullCodeGenerator::TestContext::DropAndPlug(int count,
Register reg) const {
ASSERT(count > 0);
// For simplicity we always test the accumulator register.
- __ Drop(count);
+ codegen()->AsmDrop(count);
__ Move(result_register(), reg);
codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
codegen()->DoTest(this);
@@ -580,12 +582,14 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(
void FullCodeGenerator::StackValueContext::Plug(
Label* materialize_true,
Label* materialize_false) const {
+ StackHeightWrapper stack_height = codegen()->CurrentStackHeight();
Label done;
__ bind(materialize_true);
- __ push(Immediate(isolate()->factory()->true_value()));
+ codegen()->AsmPushHandle(isolate()->factory()->true_value());
__ jmp(&done, Label::kNear);
__ bind(materialize_false);
- __ push(Immediate(isolate()->factory()->false_value()));
+ codegen()->SetStackHeight(stack_height);
+ codegen()->AsmPushHandle(isolate()->factory()->false_value());
__ bind(&done);
}
@@ -613,7 +617,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
Handle<Object> value = flag
? isolate()->factory()->true_value()
: isolate()->factory()->false_value();
- __ push(Immediate(value));
+ codegen()->AsmPushHandle(value);
}
@@ -783,23 +787,23 @@ void FullCodeGenerator::VisitVariableDeclaration(
case Variable::LOOKUP: {
Comment cmnt(masm_, "[ VariableDeclaration");
- __ push(esi);
- __ push(Immediate(variable->name()));
+ AsmPush(esi);
+ AsmPushHandle(variable->name());
// VariableDeclaration nodes are always introduced in one of four modes.
ASSERT(IsDeclaredVariableMode(mode));
PropertyAttributes attr =
IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
- __ push(Immediate(Smi::FromInt(attr)));
+ AsmPushSmi(Smi::FromInt(attr));
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
if (hole_init) {
- __ push(Immediate(isolate()->factory()->the_hole_value()));
+ AsmPushHandle(isolate()->factory()->the_hole_value());
} else {
- __ push(Immediate(Smi::FromInt(0))); // Indicates no initial value.
+ AsmPushSmi(Smi::FromInt(0)); // Indicates no initial value.
}
- __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
+ AsmCallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
break;
}
}
@@ -848,11 +852,11 @@ void FullCodeGenerator::VisitFunctionDeclaration(
case Variable::LOOKUP: {
Comment cmnt(masm_, "[ FunctionDeclaration");
- __ push(esi);
- __ push(Immediate(variable->name()));
- __ push(Immediate(Smi::FromInt(NONE)));
+ AsmPush(esi);
+ AsmPushHandle(variable->name());
+ AsmPushSmi(Smi::FromInt(NONE));
VisitForStackValue(declaration->fun());
- __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
+ AsmCallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
break;
}
}
@@ -919,18 +923,18 @@ void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) {
void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
- __ push(esi); // The context is the first argument.
- __ Push(pairs);
- __ Push(Smi::FromInt(DeclareGlobalsFlags()));
- __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3);
+ AsmPush(esi); // The context is the first argument.
+ AsmPushHandle(pairs);
+ AsmPushSmi(Smi::FromInt(DeclareGlobalsFlags()));
+ AsmCallRuntime(Runtime::kHiddenDeclareGlobals, 3);
// Return value is ignored.
}
void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
// Call the runtime to declare the modules.
- __ Push(descriptions);
- __ CallRuntime(Runtime::kHiddenDeclareModules, 1);
+ AsmPushHandle(descriptions);
+ AsmCallRuntime(Runtime::kHiddenDeclareModules, 1);
// Return value is ignored.
}
@@ -947,6 +951,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
+ StackHeightWrapper case_stack_height = CurrentStackHeight();
Label next_test; // Recycled for each test.
// Compile all the tests with branches to their bodies.
for (int i = 0; i < clauses->length(); i++) {
@@ -961,6 +966,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case comparison");
__ bind(&next_test);
+ SetStackHeight(case_stack_height);
next_test.Unuse();
// Compile the label expression.
@@ -978,9 +984,10 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ cmp(edx, eax);
__ j(not_equal, &next_test);
- __ Drop(1); // Switch value is no longer needed.
+ AsmDrop(1); // Switch value is no longer needed.
__ jmp(clause->body_target());
__ bind(&slow_case);
+ SetStackHeight(case_stack_height);
}
// Record position before stub call for type feedback.
@@ -992,22 +999,26 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ jmp(&skip, Label::kNear);
PrepareForBailout(clause, TOS_REG);
+
+ ASSERT(case_stack_height.get() == stack_height_.get());
__ cmp(eax, isolate()->factory()->true_value());
__ j(not_equal, &next_test);
- __ Drop(1);
+ AsmDrop(1);
__ jmp(clause->body_target());
__ bind(&skip);
+ SetStackHeight(case_stack_height);
__ test(eax, eax);
__ j(not_equal, &next_test);
- __ Drop(1); // Switch value is no longer needed.
+ AsmDrop(1); // Switch value is no longer needed.
__ jmp(clause->body_target());
}
// Discard the test value and jump to the default if present, otherwise to
// the end of the statement.
__ bind(&next_test);
- __ Drop(1); // Switch value is no longer needed.
+ SetStackHeight(case_stack_height);
+ AsmDrop(1); // Switch value is no longer needed.
if (default_clause == NULL) {
__ jmp(nested_statement.break_label());
} else {
@@ -1054,10 +1065,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ AsmPush(eax);
+ AsmInvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
__ bind(&done_convert);
- __ push(eax);
+ AsmPush(eax);
// Check for proxies.
Label call_runtime, use_cache, fixed_array;
@@ -1076,10 +1087,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Get the set of properties to enumerate.
__ bind(&call_runtime);
- __ push(eax);
- __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
+ AsmPush(eax);
+ AsmCallRuntime(Runtime::kGetPropertyNamesFast, 1);
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->meta_map());
+ StackHeightWrapper top_stack_height = CurrentStackHeight();
__ j(not_equal, &fixed_array);
@@ -1096,19 +1108,22 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset));
// Set up the four remaining stack slots.
- __ push(eax); // Map.
- __ push(ecx); // Enumeration cache.
- __ push(edx); // Number of valid entries for the map in the enum cache.
- __ push(Immediate(Smi::FromInt(0))); // Initial index.
+ AsmPush(eax); // Map.
+ AsmPush(ecx); // Enumeration cache.
+ AsmPush(edx); // Number of valid entries for the map in the enum cache.
+ AsmPushSmi(Smi::FromInt(0)); // Initial index.
__ jmp(&loop);
__ bind(&no_descriptors);
- __ add(esp, Immediate(kPointerSize));
+ SetStackHeight(top_stack_height);
+ AsmDrop(1);
+ StackHeightWrapper exit_stack_height = CurrentStackHeight();
__ jmp(&exit);
// We got a fixed array in register eax. Iterate through that.
Label non_proxy;
__ bind(&fixed_array);
+ SetStackHeight(top_stack_height);
// No need for a write barrier, we are storing a Smi in the feedback vector.
__ LoadHeapObject(ebx, FeedbackVector());
@@ -1122,15 +1137,15 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ j(above, &non_proxy);
__ Move(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy
__ bind(&non_proxy);
- __ push(ebx); // Smi
- __ push(eax); // Array
+ AsmPush(ebx); // Smi
+ AsmPush(eax); // Array
__ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
- __ push(eax); // Fixed array length (as smi).
- __ push(Immediate(Smi::FromInt(0))); // Initial index.
+ AsmPush(eax); // Fixed array length (as smi).
+ AsmPushSmi(Smi::FromInt(0)); // Initial index.
// Generate code for doing the condition check.
- PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&loop);
+ PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
__ j(above_equal, loop_statement.break_label());
@@ -1154,14 +1169,15 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
ASSERT(Smi::FromInt(0) == 0);
__ test(edx, edx);
+ StackHeightWrapper update_each_stack_height = CurrentStackHeight();
__ j(zero, &update_each);
// Convert the entry to a string or null if it isn't a property
// anymore. If the property has been removed while iterating, we
// just skip it.
- __ push(ecx); // Enumerable.
- __ push(ebx); // Current entry.
- __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
+ AsmPush(ecx); // Enumerable.
+ AsmPush(ebx); // Current entry.
+ AsmInvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION, 2);
__ test(eax, eax);
__ j(equal, loop_statement.continue_label());
__ mov(ebx, eax);
@@ -1169,6 +1185,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Update the 'each' property or variable from the possibly filtered
// entry in register ebx.
__ bind(&update_each);
+ USE(update_each_stack_height);
+ ASSERT(update_each_stack_height.get() == stack_height_.get());
__ mov(result_register(), ebx);
// Perform the assignment as if via '='.
{ EffectContext context(this);
@@ -1188,12 +1206,13 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Remove the pointers stored on the stack.
__ bind(loop_statement.break_label());
- __ add(esp, Immediate(5 * kPointerSize));
+ AsmDrop(5);
// Exit and decrement the loop depth.
- PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
+ PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
decrement_loop_depth();
+ SetStackHeight(exit_stack_height);
}
@@ -1219,8 +1238,8 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &done_convert);
__ bind(&convert);
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ AsmPush(eax);
+ AsmInvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1);
__ bind(&done_convert);
// Loop entry.
@@ -1274,12 +1293,12 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
__ mov(ebx, Immediate(info));
__ CallStub(&stub);
} else {
- __ push(esi);
- __ push(Immediate(info));
- __ push(Immediate(pretenure
- ? isolate()->factory()->true_value()
- : isolate()->factory()->false_value()));
- __ CallRuntime(Runtime::kHiddenNewClosure, 3);
+ AsmPush(esi);
+ AsmPushHandle(info);
+ AsmPushHandle(pretenure
+ ? isolate()->factory()->true_value()
+ : isolate()->factory()->false_value());
+ AsmCallRuntime(Runtime::kHiddenNewClosure, 3);
}
context()->Plug(eax);
}
@@ -1403,8 +1422,8 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
if (local->mode() == CONST_LEGACY) {
__ mov(eax, isolate()->factory()->undefined_value());
} else { // LET || CONST
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
+ AsmPushHandle(var->name());
+ AsmCallRuntime(Runtime::kHiddenThrowReferenceError, 1);
}
}
__ jmp(done);
@@ -1480,8 +1499,8 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
+ AsmPushHandle(var->name());
+ AsmCallRuntime(Runtime::kHiddenThrowReferenceError, 1);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
ASSERT(var->mode() == CONST_LEGACY);
@@ -1503,9 +1522,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
// by eval-introduced variables.
EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
- __ push(esi); // Context.
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
+ AsmPush(esi); // Context.
+ AsmPushHandle(var->name());
+ AsmCallRuntime(Runtime::kHiddenLoadContextSlot, 2);
__ bind(&done);
context()->Plug(eax);
break;
@@ -1532,11 +1551,11 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
// Create regexp literal using runtime function
// Result will be in eax.
- __ push(ecx);
- __ push(Immediate(Smi::FromInt(expr->literal_index())));
- __ push(Immediate(expr->pattern()));
- __ push(Immediate(expr->flags()));
- __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4);
+ AsmPush(ecx);
+ AsmPushSmi(Smi::FromInt(expr->literal_index()));
+ AsmPushHandle(expr->pattern());
+ AsmPushHandle(expr->flags());
+ AsmCallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4);
__ mov(ebx, eax);
__ bind(&materialized);
@@ -1546,10 +1565,10 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
__ jmp(&allocated);
__ bind(&runtime_allocate);
- __ push(ebx);
- __ push(Immediate(Smi::FromInt(size)));
- __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
- __ pop(ebx);
+ AsmPush(ebx);
+ AsmPushSmi(Smi::FromInt(size));
+ AsmCallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
+ AsmPop(ebx);
__ bind(&allocated);
// Copy the content into the newly allocated memory.
@@ -1570,7 +1589,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
void FullCodeGenerator::EmitAccessor(Expression* expression) {
if (expression == NULL) {
- __ push(Immediate(isolate()->factory()->null_value()));
+ AsmPushHandle(isolate()->factory()->null_value());
} else {
VisitForStackValue(expression);
}
@@ -1594,11 +1613,11 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
flags != ObjectLiteral::kFastElements ||
properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
- __ push(FieldOperand(edi, JSFunction::kLiteralsOffset));
- __ push(Immediate(Smi::FromInt(expr->literal_index())));
- __ push(Immediate(constant_properties));
- __ push(Immediate(Smi::FromInt(flags)));
- __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4);
+ AsmPush(FieldOperand(edi, JSFunction::kLiteralsOffset));
+ AsmPushSmi(Smi::FromInt(expr->literal_index()));
+ AsmPushHandle(constant_properties);
+ AsmPushSmi(Smi::FromInt(flags));
+ AsmCallRuntime(Runtime::kHiddenCreateObjectLiteral, 4);
} else {
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset));
@@ -1626,7 +1645,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Literal* key = property->key();
Expression* value = property->value();
if (!result_saved) {
- __ push(eax); // Save result on the stack
+ AsmPush(eax); // Save result on the stack
result_saved = true;
}
switch (property->kind()) {
@@ -1648,23 +1667,23 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
break;
}
- __ push(Operand(esp, 0)); // Duplicate receiver.
+ AsmPush(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
- __ CallRuntime(Runtime::kSetProperty, 4);
+ AsmPushSmi(Smi::FromInt(NONE)); // PropertyAttributes
+ AsmCallRuntime(Runtime::kSetProperty, 4);
} else {
- __ Drop(3);
+ AsmDrop(3);
}
break;
case ObjectLiteral::Property::PROTOTYPE:
- __ push(Operand(esp, 0)); // Duplicate receiver.
+ AsmPush(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(value);
if (property->emit_store()) {
- __ CallRuntime(Runtime::kSetPrototype, 2);
+ AsmCallRuntime(Runtime::kSetPrototype, 2);
} else {
- __ Drop(2);
+ AsmDrop(2);
}
break;
case ObjectLiteral::Property::GETTER:
@@ -1676,23 +1695,24 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
}
+
// Emit code to define accessors, using only a single call to the runtime for
// each pair of corresponding getters and setters.
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end();
++it) {
- __ push(Operand(esp, 0)); // Duplicate receiver.
+ AsmPush(Operand(esp, 0)); // Duplicate receiver.
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
- __ push(Immediate(Smi::FromInt(NONE)));
- __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
+ AsmPushSmi(Smi::FromInt(NONE));
+ AsmCallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
}
if (expr->has_function()) {
ASSERT(result_saved);
- __ push(Operand(esp, 0));
- __ CallRuntime(Runtime::kToFastProperties, 1);
+ AsmPush(Operand(esp, 0));
+ AsmCallRuntime(Runtime::kToFastProperties, 1);
}
if (result_saved) {
@@ -1731,11 +1751,11 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
if (expr->depth() > 1) {
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
- __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
- __ push(Immediate(Smi::FromInt(expr->literal_index())));
- __ push(Immediate(constant_elements));
- __ push(Immediate(Smi::FromInt(flags)));
- __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
+ AsmPush(FieldOperand(ebx, JSFunction::kLiteralsOffset));
+ AsmPushSmi(Smi::FromInt(expr->literal_index()));
+ AsmPushHandle(constant_elements);
+ AsmPushSmi(Smi::FromInt(flags));
+ AsmCallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
} else {
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset));
@@ -1756,8 +1776,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
if (!result_saved) {
- __ push(eax); // array literal.
- __ push(Immediate(Smi::FromInt(expr->literal_index())));
+ AsmPush(eax); // array literal.
+ AsmPushSmi(Smi::FromInt(expr->literal_index()));
result_saved = true;
}
VisitForAccumulatorValue(subexpr);
@@ -1786,7 +1806,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
if (result_saved) {
- __ add(esp, Immediate(kPointerSize)); // literal index
+ AsmDrop(1);
context()->PlugTOS();
} else {
context()->Plug(eax);
@@ -1860,7 +1880,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
Token::Value op = expr->binary_op();
- __ push(eax); // Left operand goes on the stack.
+ AsmPush(eax); // Left operand goes on the stack.
VisitForAccumulatorValue(expr->value());
OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
@@ -1914,7 +1934,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
case Yield::SUSPEND:
// Pop value from top-of-stack slot; box result into result register.
EmitCreateIteratorResult(false);
- __ push(result_register());
+ AsmPush(result_register());
// Fall through.
case Yield::INITIAL: {
Label suspend, continuation, post_runtime, resume;
@@ -1936,12 +1956,12 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
__ cmp(esp, ebx);
__ j(equal, &post_runtime);
- __ push(eax); // generator object
- __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
+ AsmPush(eax); // generator object
+ AsmCallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ bind(&post_runtime);
- __ pop(result_register());
+ AsmPop(result_register());
EmitReturnSequence();
__ bind(&resume);
@@ -1956,8 +1976,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
// Pop value from top-of-stack slot, box result into result register.
EmitCreateIteratorResult(true);
+ StackHeightWrapper final_stack_height = CurrentStackHeight();
EmitUnwindBeforeReturn();
EmitReturnSequence();
+ SetStackHeight(final_stack_height);
break;
}
@@ -1972,32 +1994,35 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
Label l_next, l_call, l_loop;
// Initial send value is undefined.
__ mov(eax, isolate()->factory()->undefined_value());
+ StackHeightWrapper next_stack_height = CurrentStackHeight();
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
__ mov(ecx, isolate()->factory()->throw_string()); // "throw"
- __ push(ecx); // "throw"
- __ push(Operand(esp, 2 * kPointerSize)); // iter
- __ push(eax); // exception
+ AsmPush(ecx); // "throw"
+ AsmPush(Operand(esp, 2 * kPointerSize)); // iter
+ AsmPush(eax); // exception
__ jmp(&l_call);
// try { received = %yield result }
// Shuffle the received result above a try handler and yield it without
// re-boxing.
__ bind(&l_try);
- __ pop(eax); // result
- __ PushTryHandler(StackHandler::CATCH, expr->index());
+ SetStackHeight(next_stack_height);
+ UpdateStackHeight(1);
+ AsmPop(eax); // result
+ AsmPushTryHandler(StackHandler::CATCH, expr->index());
const int handler_size = StackHandlerConstants::kSize;
- __ push(eax); // result
+ AsmPush(eax); // result
__ jmp(&l_suspend);
__ bind(&l_continuation);
__ jmp(&l_resume);
__ bind(&l_suspend);
const int generator_object_depth = kPointerSize + handler_size;
__ mov(eax, Operand(esp, generator_object_depth));
- __ push(eax); // g
+ AsmPush(eax); // g
ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
Immediate(Smi::FromInt(l_continuation.pos())));
@@ -2005,20 +2030,21 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ mov(ecx, esi);
__ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
kDontSaveFPRegs);
- __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
+ AsmCallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
- __ pop(eax); // result
+ AsmPop(eax); // result
EmitReturnSequence();
__ bind(&l_resume); // received in eax
- __ PopTryHandler();
+ AsmPopTryHandler();
// receiver = iter; f = iter.next; arg = received;
__ bind(&l_next);
+ SetStackHeight(next_stack_height);
__ mov(ecx, isolate()->factory()->next_string()); // "next"
- __ push(ecx);
- __ push(Operand(esp, 2 * kPointerSize)); // iter
- __ push(eax); // received
+ AsmPush(ecx);
+ AsmPush(Operand(esp, 2 * kPointerSize)); // iter
+ AsmPush(eax); // received
// result = receiver[f](arg);
__ bind(&l_call);
@@ -2028,14 +2054,14 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ mov(edi, eax);
__ mov(Operand(esp, 2 * kPointerSize), edi);
CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
- __ CallStub(&stub);
+ AsmCallStub(&stub, 2);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ Drop(1); // The function is still on the stack; drop it.
+ AsmDrop(1); // The key is still on the stack; drop it.
// if (!result.done) goto l_try;
__ bind(&l_loop);
- __ push(eax); // save result
+ AsmPush(eax); // save result
__ mov(edx, eax); // result
__ mov(ecx, isolate()->factory()->done_string()); // "done"
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
@@ -2045,7 +2071,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ j(zero, &l_try);
// result.value
- __ pop(edx); // result
+ AsmPop(edx); // result
__ mov(ecx, isolate()->factory()->value_string()); // "value"
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
context()->DropAndPlug(2, eax); // drop iter and g
@@ -2064,7 +2090,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
// ebx will hold the generator object until the activation has been resumed.
VisitForStackValue(generator);
VisitForAccumulatorValue(value);
- __ pop(ebx);
+ AsmPop(ebx);
// Check generator state.
Label wrong_state, closed_state, done;
@@ -2147,20 +2173,20 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
__ bind(&closed_state);
if (resume_mode == JSGeneratorObject::NEXT) {
// Return completed iterator result when generator is closed.
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
// Pop value from top-of-stack slot; box result into result register.
EmitCreateIteratorResult(true);
} else {
// Throw the provided value.
- __ push(eax);
- __ CallRuntime(Runtime::kHiddenThrow, 1);
+ AsmPush(eax);
+ AsmCallRuntime(Runtime::kHiddenThrow, 1);
}
__ jmp(&done);
// Throw error if we attempt to operate on a running generator.
__ bind(&wrong_state);
- __ push(ebx);
- __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1);
+ AsmPush(ebx);
+ AsmCallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1);
__ bind(&done);
context()->Plug(result_register());
@@ -2177,14 +2203,14 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
__ jmp(&allocated);
__ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
+ AsmPushSmi(Smi::FromInt(map->instance_size()));
+ AsmCallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
__ mov(ebx, map);
- __ pop(ecx);
+ AsmPop(ecx);
__ mov(edx, isolate()->factory()->ToBoolean(done));
ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
__ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
@@ -2226,7 +2252,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
// Do combined smi check of the operands. Left operand is on the
// stack. Right operand is in eax.
Label smi_case, done, stub_call;
- __ pop(edx);
+ AsmPop(edx);
__ mov(ecx, eax);
__ or_(eax, edx);
JumpPatchSite patch_site(masm_);
@@ -2316,7 +2342,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
Token::Value op,
OverwriteMode mode) {
- __ pop(edx);
+ AsmPop(edx);
BinaryOpICStub stub(isolate(), op, mode);
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
@@ -2347,21 +2373,21 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
break;
}
case NAMED_PROPERTY: {
- __ push(eax); // Preserve value.
+ AsmPush(eax); // Preserve value.
VisitForAccumulatorValue(prop->obj());
__ mov(edx, eax);
- __ pop(eax); // Restore value.
+ AsmPop(eax); // Restore value.
__ mov(ecx, prop->key()->AsLiteral()->value());
CallStoreIC();
break;
}
case KEYED_PROPERTY: {
- __ push(eax); // Preserve value.
+ AsmPush(eax); // Preserve value.
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
__ mov(ecx, eax);
- __ pop(edx); // Receiver.
- __ pop(eax); // Restore value.
+ AsmPop(edx); // Receiver.
+ AsmPop(eax); // Restore value.
Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -2406,10 +2432,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
- __ push(eax);
- __ push(esi);
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3);
+ AsmPush(eax);
+ AsmPush(esi);
+ AsmPushHandle(var->name());
+ AsmCallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3);
} else {
ASSERT(var->IsStackLocal() || var->IsContextSlot());
Label skip;
@@ -2432,8 +2458,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ mov(edx, location);
__ cmp(edx, isolate()->factory()->the_hole_value());
__ j(not_equal, &assign, Label::kNear);
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
+ AsmPushHandle(var->name());
+ AsmCallRuntime(Runtime::kHiddenThrowReferenceError, 1);
__ bind(&assign);
EmitStoreToStackLocalOrContextSlot(var, location);
}
@@ -2471,7 +2497,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
// Record source code position before IC call.
SetSourcePosition(expr->position());
__ mov(ecx, prop->key()->AsLiteral()->value());
- __ pop(edx);
+ AsmPop(edx);
CallStoreIC(expr->AssignmentFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
@@ -2484,8 +2510,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
// esp[0] : key
// esp[kPointerSize] : receiver
- __ pop(ecx); // Key.
- __ pop(edx);
+ AsmPop(ecx); // Key.
+ AsmPop(edx);
// Record source code position before IC call.
SetSourcePosition(expr->position());
Handle<Code> ic = strict_mode() == SLOPPY
@@ -2511,7 +2537,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ pop(edx); // Object.
+ AsmPop(edx); // Object.
__ mov(ecx, result_register()); // Key.
EmitKeyedPropertyLoad(expr);
context()->Plug(eax);
@@ -2541,7 +2567,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
}
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
} else {
// Load the function from the receiver.
ASSERT(callee->IsProperty());
@@ -2549,7 +2575,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
- __ push(Operand(esp, 0));
+ AsmPush(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
}
@@ -2574,7 +2600,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
- __ push(Operand(esp, 0));
+ AsmPush(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
EmitCall(expr, CallIC::METHOD);
@@ -2600,9 +2626,9 @@ void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
// Don't assign a type feedback id to the IC, since type feedback is provided
// by the vector above.
CallIC(ic);
+ UpdateStackHeight(-(arg_count + 1));
RecordJSReturnSite(expr);
-
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -2613,21 +2639,21 @@ void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
- __ push(Operand(esp, arg_count * kPointerSize));
+ AsmPush(Operand(esp, arg_count * kPointerSize));
} else {
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
}
// Push the receiver of the enclosing function.
- __ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
+ AsmPush(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
// Push the language mode.
- __ push(Immediate(Smi::FromInt(strict_mode())));
+ AsmPushSmi(Smi::FromInt(strict_mode()));
// Push the start position of the scope the calls resides in.
- __ push(Immediate(Smi::FromInt(scope()->start_position())));
+ AsmPushSmi(Smi::FromInt(scope()->start_position()));
// Do the runtime call.
- __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5);
+ AsmCallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5);
}
@@ -2651,7 +2677,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope pos_scope(masm()->positions_recorder());
VisitForStackValue(callee);
// Reserved receiver slot.
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
@@ -2659,7 +2685,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Push a copy of the function (found below the arguments) and
// resolve eval.
- __ push(Operand(esp, (arg_count + 1) * kPointerSize));
+ AsmPush(Operand(esp, (arg_count + 1) * kPointerSize));
EmitResolvePossiblyDirectEval(arg_count);
// The runtime call returns a pair of values in eax (function) and
@@ -2672,6 +2698,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
__ CallStub(&stub);
+ UpdateStackHeight(-(arg_count + 1));
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -2690,13 +2717,14 @@ void FullCodeGenerator::VisitCall(Call* expr) {
EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
}
__ bind(&slow);
+ StackHeightWrapper branch_stack_height = CurrentStackHeight();
// Call the runtime to find the function to call (returned in eax) and
// the object holding it (returned in edx).
- __ push(context_register());
- __ push(Immediate(proxy->name()));
- __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
- __ push(eax); // Function.
- __ push(edx); // Receiver.
+ AsmPush(context_register());
+ AsmPushHandle(proxy->name());
+ AsmCallRuntime(Runtime::kHiddenLoadContextSlot, 2);
+ AsmPush(eax); // Function.
+ AsmPush(edx); // Receiver.
// If fast case code has been generated, emit code to push the function
// and receiver and have the slow path jump around this code.
@@ -2704,11 +2732,12 @@ void FullCodeGenerator::VisitCall(Call* expr) {
Label call;
__ jmp(&call, Label::kNear);
__ bind(&done);
+ SetStackHeight(branch_stack_height);
// Push function.
- __ push(eax);
+ AsmPush(eax);
// The receiver is implicitly the global receiver. Indicate this by
// passing the hole to the call function stub.
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
__ bind(&call);
}
@@ -2733,7 +2762,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
}
- __ push(Immediate(isolate()->factory()->undefined_value()));
+ AsmPushHandle(isolate()->factory()->undefined_value());
// Emit function call.
EmitCall(expr);
}
@@ -2783,6 +2812,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET);
__ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
+ UpdateStackHeight(-(arg_count + 1));
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
context()->Plug(eax);
}
@@ -3140,7 +3170,7 @@ void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
context()->PrepareTest(&materialize_true, &materialize_false,
&if_true, &if_false, &fall_through);
- __ pop(ebx);
+ AsmPop(ebx);
__ cmp(eax, ebx);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(equal, if_true, if_false, fall_through);
@@ -3256,7 +3286,7 @@ void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
VisitForStackValue(args->at(2));
- __ CallStub(&stub);
+ AsmCallStub(&stub, 3);
context()->Plug(eax);
}
@@ -3270,7 +3300,7 @@ void FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) {
VisitForStackValue(args->at(1));
VisitForStackValue(args->at(2));
VisitForStackValue(args->at(3));
- __ CallStub(&stub);
+ AsmCallStub(&stub, 4);
context()->Plug(eax);
}
@@ -3333,7 +3363,7 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
}
__ bind(&not_date_object);
- __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0);
+ AsmCallRuntime(Runtime::kHiddenThrowNotDateError, 0);
__ bind(&done);
context()->Plug(result);
}
@@ -3351,8 +3381,8 @@ void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
VisitForStackValue(args->at(2)); // value
VisitForAccumulatorValue(args->at(0)); // string
- __ pop(value);
- __ pop(index);
+ AsmPop(value);
+ AsmPop(index);
if (FLAG_debug_code) {
__ test(value, Immediate(kSmiTagMask));
@@ -3386,8 +3416,8 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
VisitForStackValue(args->at(1)); // index
VisitForStackValue(args->at(2)); // value
VisitForAccumulatorValue(args->at(0)); // string
- __ pop(value);
- __ pop(index);
+ AsmPop(value);
+ AsmPop(index);
if (FLAG_debug_code) {
__ test(value, Immediate(kSmiTagMask));
@@ -3416,7 +3446,7 @@ void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
VisitForStackValue(args->at(1));
MathPowStub stub(isolate(), MathPowStub::ON_STACK);
- __ CallStub(&stub);
+ AsmCallStub(&stub, 2);
context()->Plug(eax);
}
@@ -3427,7 +3457,7 @@ void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
VisitForStackValue(args->at(0)); // Load the object.
VisitForAccumulatorValue(args->at(1)); // Load the value.
- __ pop(ebx); // eax = value. ebx = object.
+ AsmPop(ebx); // eax = value. ebx = object.
Label done;
// If the object is a smi, return the value.
@@ -3493,7 +3523,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
Register index = eax;
Register result = edx;
- __ pop(object);
+ AsmPop(object);
Label need_conversion;
Label index_out_of_range;
@@ -3540,7 +3570,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
Register scratch = edx;
Register result = eax;
- __ pop(object);
+ AsmPop(object);
Label need_conversion;
Label index_out_of_range;
@@ -3582,7 +3612,7 @@ void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
VisitForStackValue(args->at(0));
VisitForAccumulatorValue(args->at(1));
- __ pop(edx);
+ AsmPop(edx);
StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
__ CallStub(&stub);
context()->Plug(eax);
@@ -3597,7 +3627,7 @@ void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
VisitForStackValue(args->at(1));
StringCompareStub stub(isolate());
- __ CallStub(&stub);
+ AsmCallStub(&stub, 2);
context()->Plug(eax);
}
@@ -3616,18 +3646,21 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
// Check for non-function argument (including proxy).
__ JumpIfSmi(eax, &runtime);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
+ StackHeightWrapper branch_stack_height = CurrentStackHeight();
__ j(not_equal, &runtime);
// InvokeFunction requires the function in edi. Move it in there.
__ mov(edi, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(edi, count, CALL_FUNCTION, NullCallWrapper());
+ UpdateStackHeight(-(arg_count + 1));
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ jmp(&done);
__ bind(&runtime);
- __ push(eax);
- __ CallRuntime(Runtime::kCall, args->length());
+ SetStackHeight(branch_stack_height);
+ AsmPush(eax);
+ AsmCallRuntime(Runtime::kCall, args->length());
__ bind(&done);
context()->Plug(eax);
@@ -3642,8 +3675,8 @@ void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
VisitForAccumulatorValue(args->at(2));
- __ pop(ebx);
- __ pop(ecx);
+ AsmPop(ebx);
+ AsmPop(ecx);
__ CallStub(&stub);
context()->Plug(eax);
}
@@ -3689,9 +3722,9 @@ void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
__ bind(&not_found);
// Call runtime to perform the lookup.
- __ push(cache);
- __ push(key);
- __ CallRuntime(Runtime::kHiddenGetFromCache, 2);
+ AsmPush(cache);
+ AsmPush(key);
+ AsmCallRuntime(Runtime::kHiddenGetFromCache, 2);
__ bind(&done);
context()->Plug(eax);
@@ -3767,6 +3800,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
Operand result_operand = Operand(esp, 1 * kPointerSize);
Operand array_length_operand = Operand(esp, 0);
__ sub(esp, Immediate(2 * kPointerSize));
+ UpdateStackHeight(2);
__ cld();
// Check that the array is a JSArray
__ JumpIfSmi(array, &bailout);
@@ -3993,7 +4027,7 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
__ bind(&done);
__ mov(eax, result_operand);
// Drop temp values from the stack, and restore context register.
- __ add(esp, Immediate(3 * kPointerSize));
+ AsmDrop(3);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->Plug(eax);
@@ -4014,7 +4048,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
if (expr->is_jsruntime()) {
// Push the builtins object as receiver.
__ mov(eax, GlobalObjectOperand());
- __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
+ AsmPush(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
// Load the function from the receiver.
__ mov(edx, Operand(esp, 0));
@@ -4022,7 +4056,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
// Push the target function under the receiver.
- __ push(Operand(esp, 0));
+ AsmPush(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
// Code common for calls using the IC.
@@ -4036,7 +4070,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
SetSourcePosition(expr->position());
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
- __ CallStub(&stub);
+ AsmCallStub(&stub, arg_count + 1);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->DropAndPlug(1, eax);
@@ -4049,7 +4083,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
}
// Call the C runtime function.
- __ CallRuntime(expr->function(), arg_count);
+ AsmCallRuntime(expr->function(), arg_count);
context()->Plug(eax);
}
@@ -4066,8 +4100,8 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- __ push(Immediate(Smi::FromInt(strict_mode())));
- __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+ AsmPushSmi(Smi::FromInt(strict_mode()));
+ AsmInvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
context()->Plug(eax);
} else if (proxy != NULL) {
Variable* var = proxy->var();
@@ -4075,10 +4109,10 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// but "delete this" is allowed.
ASSERT(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
- __ push(GlobalObjectOperand());
- __ push(Immediate(var->name()));
- __ push(Immediate(Smi::FromInt(SLOPPY)));
- __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
+ AsmPush(GlobalObjectOperand());
+ AsmPushHandle(var->name());
+ AsmPushSmi(Smi::FromInt(SLOPPY));
+ AsmInvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 3);
context()->Plug(eax);
} else if (var->IsStackAllocated() || var->IsContextSlot()) {
// Result of deleting non-global variables is false. 'this' is
@@ -4088,9 +4122,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
- __ push(context_register());
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2);
+ AsmPush(context_register());
+ AsmPushHandle(var->name());
+ AsmCallRuntime(Runtime::kHiddenDeleteContextSlot, 2);
context()->Plug(eax);
}
} else {
@@ -4134,20 +4168,22 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
&materialize_false,
&materialize_true,
&materialize_true);
+ StackHeightWrapper branch_stack_height = CurrentStackHeight();
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ mov(eax, isolate()->factory()->true_value());
} else {
- __ Push(isolate()->factory()->true_value());
+ AsmPushHandle(isolate()->factory()->true_value());
}
__ jmp(&done, Label::kNear);
__ bind(&materialize_false);
+ SetStackHeight(branch_stack_height);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ mov(eax, isolate()->factory()->false_value());
} else {
- __ Push(isolate()->factory()->false_value());
+ AsmPushHandle(isolate()->factory()->false_value());
}
__ bind(&done);
}
@@ -4159,7 +4195,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
{ StackValueContext context(this);
VisitForTypeofValue(expr->expression());
}
- __ CallRuntime(Runtime::kTypeof, 1);
+ AsmCallRuntime(Runtime::kTypeof, 1);
context()->Plug(eax);
break;
}
@@ -4196,12 +4232,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
// Reserve space for result of postfix operation.
if (expr->is_postfix() && !context()->IsEffect()) {
- __ push(Immediate(Smi::FromInt(0)));
+ AsmPushSmi(Smi::FromInt(0));
}
if (assign_type == NAMED_PROPERTY) {
// Put the object both on the stack and in edx.
VisitForAccumulatorValue(prop->obj());
- __ push(eax);
+ AsmPush(eax);
__ mov(edx, eax);
EmitNamedPropertyLoad(prop);
} else {
@@ -4228,6 +4264,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Label slow;
patch_site.EmitJumpIfNotSmi(eax, &slow, Label::kNear);
+ StackHeightWrapper smi_stack_height = CurrentStackHeight();
+
// Save result for postfix expressions.
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@@ -4236,7 +4274,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// of the stack.
switch (assign_type) {
case VARIABLE:
- __ push(eax);
+ AsmPush(eax);
break;
case NAMED_PROPERTY:
__ mov(Operand(esp, kPointerSize), eax);
@@ -4262,6 +4300,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
__ jmp(&stub_call, Label::kNear);
__ bind(&slow);
+ SetStackHeight(smi_stack_height);
}
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
@@ -4274,7 +4313,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// of the stack.
switch (assign_type) {
case VARIABLE:
- __ push(eax);
+ AsmPush(eax);
break;
case NAMED_PROPERTY:
__ mov(Operand(esp, kPointerSize), eax);
@@ -4324,7 +4363,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
break;
case NAMED_PROPERTY: {
__ mov(ecx, prop->key()->AsLiteral()->value());
- __ pop(edx);
+ AsmPop(edx);
CallStoreIC(expr->CountStoreFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
@@ -4337,8 +4376,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
break;
}
case KEYED_PROPERTY: {
- __ pop(ecx);
- __ pop(edx);
+ AsmPop(ecx);
+ AsmPop(edx);
Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
@@ -4381,9 +4420,9 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
- __ push(esi);
- __ push(Immediate(proxy->name()));
- __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2);
+ AsmPush(esi);
+ AsmPushHandle(proxy->name());
+ AsmCallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2);
PrepareForBailout(expr, TOS_REG);
__ bind(&done);
@@ -4496,7 +4535,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
switch (op) {
case Token::IN:
VisitForStackValue(expr->right());
- __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
+ AsmInvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
__ cmp(eax, isolate()->factory()->true_value());
Split(equal, if_true, if_false, fall_through);
@@ -4505,7 +4544,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
case Token::INSTANCEOF: {
VisitForStackValue(expr->right());
InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
- __ CallStub(&stub);
+ AsmCallStub(&stub, 2);
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
__ test(eax, eax);
// The stub returns 0 for true.
@@ -4516,7 +4555,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
default: {
VisitForAccumulatorValue(expr->right());
Condition cc = CompareIC::ComputeCondition(op);
- __ pop(edx);
+ AsmPop(edx);
bool inline_smi_code = ShouldInlineSmiCase(op);
JumpPatchSite patch_site(masm_);
@@ -4612,15 +4651,15 @@ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
// as their closure, not the anonymous closure containing the global
// code. Pass a smi sentinel and let the runtime look up the empty
// function.
- __ push(Immediate(Smi::FromInt(0)));
+ AsmPushSmi(Smi::FromInt(0));
} else if (declaration_scope->is_eval_scope()) {
// Contexts nested inside eval code have the same closure as the context
// calling eval, not the anonymous closure containing the eval code.
// Fetch it from the context.
- __ push(ContextOperand(esi, Context::CLOSURE_INDEX));
+ AsmPush(ContextOperand(esi, Context::CLOSURE_INDEX));
} else {
ASSERT(declaration_scope->is_function_scope());
- __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ AsmPush(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
}
@@ -4631,65 +4670,90 @@ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
void FullCodeGenerator::EnterFinallyBlock() {
// Cook return address on top of stack (smi encoded Code* delta)
ASSERT(!result_register().is(edx));
- __ pop(edx);
+ AsmPop(edx);
__ sub(edx, Immediate(masm_->CodeObject()));
STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
STATIC_ASSERT(kSmiTag == 0);
__ SmiTag(edx);
- __ push(edx);
+ AsmPush(edx);
// Store result register while executing finally block.
- __ push(result_register());
+ AsmPush(result_register());
// Store pending message while executing finally block.
ExternalReference pending_message_obj =
ExternalReference::address_of_pending_message_obj(isolate());
__ mov(edx, Operand::StaticVariable(pending_message_obj));
- __ push(edx);
+ AsmPush(edx);
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
__ mov(edx, Operand::StaticVariable(has_pending_message));
__ SmiTag(edx);
- __ push(edx);
+ AsmPush(edx);
ExternalReference pending_message_script =
ExternalReference::address_of_pending_message_script(isolate());
__ mov(edx, Operand::StaticVariable(pending_message_script));
- __ push(edx);
+ AsmPush(edx);
}
void FullCodeGenerator::ExitFinallyBlock() {
ASSERT(!result_register().is(edx));
// Restore pending message from stack.
- __ pop(edx);
+ AsmPop(edx);
ExternalReference pending_message_script =
ExternalReference::address_of_pending_message_script(isolate());
__ mov(Operand::StaticVariable(pending_message_script), edx);
- __ pop(edx);
+ AsmPop(edx);
__ SmiUntag(edx);
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
__ mov(Operand::StaticVariable(has_pending_message), edx);
- __ pop(edx);
+ AsmPop(edx);
ExternalReference pending_message_obj =
ExternalReference::address_of_pending_message_obj(isolate());
__ mov(Operand::StaticVariable(pending_message_obj), edx);
// Restore result register from stack.
- __ pop(result_register());
+ AsmPop(result_register());
// Uncook return address.
- __ pop(edx);
+ AsmPop(edx);
__ SmiUntag(edx);
__ add(edx, Immediate(masm_->CodeObject()));
__ jmp(edx);
}
+#if defined(VERIFY_STACK_HEIGHT)
+void FullCodeGenerator::AddStackHeightVerifier() {
+ // Insert code that verifies at runtime that our stack height calculation
+ // is correct
+ Label L;
+ __ push(eax);
+ __ pushfd();
+ __ mov(eax, ebp);
+ __ sub(eax, esp);
+ const int stack_diff = 4; // We need to account for the pushed stuff
+ __ cmp(eax, (stack_height_.get() + stack_diff) * kPointerSize);
+ __ j(equal, &L);
+ __ int3();
+ __ bind(&L);
+ __ popfd();
+ __ pop(eax);
+}
+#endif // defined(VERIFY_STACK_HEIGHT)
+
+void FullCodeGenerator::AsmPush(const Operand& op) {
+ masm()->push(op);
+ UpdateStackHeight(1);
+}
+
+
#undef __
#define __ ACCESS_MASM(masm())
@@ -4703,13 +4767,13 @@ FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
// code, we can restore it directly from there for the finally code
// rather than iteratively unwinding contexts via their previous
// links.
- __ Drop(*stack_depth); // Down to the handler block.
+ codegen()->AsmDrop(*stack_depth); // Down to the handler block.
if (*context_length > 0) {
// Restore the context to its dedicated register and the stack.
__ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset));
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
}
- __ PopTryHandler();
+ codegen()->AsmPopTryHandler();
__ call(finally_entry_);
*stack_depth = 0;
@@ -4719,7 +4783,6 @@ FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
#undef __
-
static const byte kJnsInstruction = 0x79;
static const byte kJnsOffset = 0x11;
static const byte kNopByteOne = 0x66;
« no previous file with comments | « src/hydrogen.cc ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698