Index: src/full-codegen/x87/full-codegen-x87.cc |
diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc |
index d23e2c18f5dbef7f90ec1a05ea57a11133eafa14..36b7c5d63687ebce3b2d736ad63a0f96c5812c48 100644 |
--- a/src/full-codegen/x87/full-codegen-x87.cc |
+++ b/src/full-codegen/x87/full-codegen-x87.cc |
@@ -119,6 +119,7 @@ void FullCodeGenerator::Generate() { |
int locals_count = info->scope()->num_stack_slots(); |
// Generators allocate locals, if any, in context slots. |
DCHECK(!IsGeneratorFunction(literal()->kind()) || locals_count == 0); |
+ OperandStackDepthIncrement(locals_count); |
if (locals_count == 1) { |
__ push(Immediate(isolate()->factory()->undefined_value())); |
} else if (locals_count > 1) { |
@@ -428,7 +429,7 @@ void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
MemOperand operand = codegen()->VarOperand(var, result_register()); |
// Memory operands can be pushed directly. |
- __ push(operand); |
+ codegen()->PushOperand(operand); |
} |
@@ -469,6 +470,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug( |
void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
+ codegen()->OperandStackDepthIncrement(1); |
if (lit->IsSmi()) { |
__ SafePush(Immediate(lit)); |
} else { |
@@ -510,7 +512,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
Register reg) const { |
DCHECK(count > 0); |
- if (count > 1) __ Drop(count - 1); |
+ if (count > 1) codegen()->DropOperands(count - 1); |
__ mov(Operand(esp, 0), reg); |
} |
@@ -538,6 +540,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug( |
void FullCodeGenerator::StackValueContext::Plug( |
Label* materialize_true, |
Label* materialize_false) const { |
+ codegen()->OperandStackDepthIncrement(1); |
Label done; |
__ bind(materialize_true); |
__ push(Immediate(isolate()->factory()->true_value())); |
@@ -564,6 +567,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { |
void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
+ codegen()->OperandStackDepthIncrement(1); |
Handle<Object> value = flag |
? isolate()->factory()->true_value() |
: isolate()->factory()->false_value(); |
@@ -796,11 +800,10 @@ void FullCodeGenerator::VisitFunctionDeclaration( |
case VariableLocation::LOOKUP: { |
Comment cmnt(masm_, "[ FunctionDeclaration"); |
- __ push(Immediate(variable->name())); |
+ PushOperand(variable->name()); |
VisitForStackValue(declaration->fun()); |
- __ push( |
- Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes()))); |
- __ CallRuntime(Runtime::kDeclareLookupSlot); |
+ PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
+ CallRuntimeWithOperands(Runtime::kDeclareLookupSlot); |
break; |
} |
} |
@@ -896,7 +899,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
// 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. |
+ DropOperands(1); // Switch value is no longer needed. |
if (default_clause == NULL) { |
__ jmp(nested_statement.break_label()); |
} else { |
@@ -930,6 +933,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
// Get the object to enumerate over. |
SetExpressionAsStatementPosition(stmt->enumerable()); |
VisitForAccumulatorValue(stmt->enumerable()); |
+ OperandStackDepthIncrement(ForIn::kElementCount); |
// If the object is null or undefined, skip over the loop, otherwise convert |
// it to a JS receiver. See ECMA-262 version 5, section 12.6.4. |
@@ -1078,6 +1082,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
// Remove the pointers stored on the stack. |
__ bind(loop_statement.break_label()); |
__ add(esp, Immediate(5 * kPointerSize)); |
+ OperandStackDepthDecrement(ForIn::kElementCount); |
// Exit and decrement the loop depth. |
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
@@ -1349,7 +1354,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
Expression* expression = (property == NULL) ? NULL : property->value(); |
if (expression == NULL) { |
- __ push(Immediate(isolate()->factory()->null_value())); |
+ PushOperand(isolate()->factory()->null_value()); |
} else { |
VisitForStackValue(expression); |
if (NeedsHomeObject(expression)) { |
@@ -1399,7 +1404,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
Literal* key = property->key()->AsLiteral(); |
Expression* value = property->value(); |
if (!result_saved) { |
- __ push(eax); // Save result on the stack |
+ PushOperand(eax); // Save result on the stack |
result_saved = true; |
} |
switch (property->kind()) { |
@@ -1428,24 +1433,24 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
} |
break; |
} |
- __ push(Operand(esp, 0)); // Duplicate receiver. |
+ PushOperand(Operand(esp, 0)); // Duplicate receiver. |
VisitForStackValue(key); |
VisitForStackValue(value); |
if (property->emit_store()) { |
if (NeedsHomeObject(value)) { |
EmitSetHomeObject(value, 2, property->GetSlot()); |
} |
- __ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode |
- __ CallRuntime(Runtime::kSetProperty); |
+ PushOperand(Smi::FromInt(SLOPPY)); // Language mode |
+ CallRuntimeWithOperands(Runtime::kSetProperty); |
} else { |
- __ Drop(3); |
+ DropOperands(3); |
} |
break; |
case ObjectLiteral::Property::PROTOTYPE: |
- __ push(Operand(esp, 0)); // Duplicate receiver. |
+ PushOperand(Operand(esp, 0)); // Duplicate receiver. |
VisitForStackValue(value); |
DCHECK(property->emit_store()); |
- __ CallRuntime(Runtime::kInternalSetPrototype); |
+ CallRuntimeWithOperands(Runtime::kInternalSetPrototype); |
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), |
NO_REGISTERS); |
break; |
@@ -1467,14 +1472,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
for (AccessorTable::Iterator it = accessor_table.begin(); |
it != accessor_table.end(); |
++it) { |
- __ push(Operand(esp, 0)); // Duplicate receiver. |
+ PushOperand(Operand(esp, 0)); // Duplicate receiver. |
VisitForStackValue(it->first); |
EmitAccessor(it->second->getter); |
EmitAccessor(it->second->setter); |
- __ push(Immediate(Smi::FromInt(NONE))); |
- __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
+ PushOperand(Smi::FromInt(NONE)); |
+ CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked); |
} |
// Object literals have two parts. The "static" part on the left contains no |
@@ -1491,17 +1496,17 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
Expression* value = property->value(); |
if (!result_saved) { |
- __ push(eax); // Save result on the stack |
+ PushOperand(eax); // Save result on the stack |
result_saved = true; |
} |
- __ push(Operand(esp, 0)); // Duplicate receiver. |
+ PushOperand(Operand(esp, 0)); // Duplicate receiver. |
if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
DCHECK(!property->is_computed_name()); |
VisitForStackValue(value); |
DCHECK(property->emit_store()); |
- __ CallRuntime(Runtime::kInternalSetPrototype); |
+ CallRuntimeWithOperands(Runtime::kInternalSetPrototype); |
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), |
NO_REGISTERS); |
} else { |
@@ -1516,11 +1521,11 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
case ObjectLiteral::Property::COMPUTED: |
if (property->emit_store()) { |
- __ Push(Smi::FromInt(NONE)); |
- __ Push(Smi::FromInt(property->NeedsSetFunctionName())); |
- __ CallRuntime(Runtime::kDefineDataPropertyInLiteral); |
+ PushOperand(Smi::FromInt(NONE)); |
+ PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); |
+ CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); |
} else { |
- __ Drop(3); |
+ DropOperands(3); |
} |
break; |
@@ -1529,13 +1534,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
break; |
case ObjectLiteral::Property::GETTER: |
- __ Push(Smi::FromInt(NONE)); |
- __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
+ PushOperand(Smi::FromInt(NONE)); |
+ CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); |
break; |
case ObjectLiteral::Property::SETTER: |
- __ Push(Smi::FromInt(NONE)); |
- __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
+ PushOperand(Smi::FromInt(NONE)); |
+ CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); |
break; |
} |
} |
@@ -1600,7 +1605,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
if (!result_saved) { |
- __ push(eax); // array literal. |
+ PushOperand(eax); // array literal. |
result_saved = true; |
} |
VisitForAccumulatorValue(subexpr); |
@@ -1621,16 +1626,16 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
// (inclusive) and these elements gets appended to the array. Note that the |
// number elements an iterable produces is unknown ahead of time. |
if (array_index < length && result_saved) { |
- __ Pop(eax); |
+ PopOperand(eax); |
result_saved = false; |
} |
for (; array_index < length; array_index++) { |
Expression* subexpr = subexprs->at(array_index); |
- __ Push(eax); |
+ PushOperand(eax); |
DCHECK(!subexpr->IsSpread()); |
VisitForStackValue(subexpr); |
- __ CallRuntime(Runtime::kAppendElement); |
+ CallRuntimeWithOperands(Runtime::kAppendElement); |
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
} |
@@ -1662,10 +1667,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
property->obj()->AsSuperPropertyReference()->this_var()); |
VisitForAccumulatorValue( |
property->obj()->AsSuperPropertyReference()->home_object()); |
- __ push(result_register()); |
+ PushOperand(result_register()); |
if (expr->is_compound()) { |
- __ push(MemOperand(esp, kPointerSize)); |
- __ push(result_register()); |
+ PushOperand(MemOperand(esp, kPointerSize)); |
+ PushOperand(result_register()); |
} |
break; |
case NAMED_PROPERTY: |
@@ -1683,11 +1688,11 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
VisitForStackValue( |
property->obj()->AsSuperPropertyReference()->home_object()); |
VisitForAccumulatorValue(property->key()); |
- __ Push(result_register()); |
+ PushOperand(result_register()); |
if (expr->is_compound()) { |
- __ push(MemOperand(esp, 2 * kPointerSize)); |
- __ push(MemOperand(esp, 2 * kPointerSize)); |
- __ push(result_register()); |
+ PushOperand(MemOperand(esp, 2 * kPointerSize)); |
+ PushOperand(MemOperand(esp, 2 * kPointerSize)); |
+ PushOperand(result_register()); |
} |
break; |
case KEYED_PROPERTY: { |
@@ -1734,7 +1739,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
} |
Token::Value op = expr->binary_op(); |
- __ push(eax); // Left operand goes on the stack. |
+ PushOperand(eax); // Left operand goes on the stack. |
VisitForAccumulatorValue(expr->value()); |
if (ShouldInlineSmiCase(op)) { |
@@ -1827,7 +1832,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { |
__ mov(context_register(), |
Operand(ebp, StandardFrameConstants::kContextOffset)); |
__ bind(&post_runtime); |
- __ pop(result_register()); |
+ PopOperand(result_register()); |
EmitReturnSequence(); |
__ bind(&resume); |
@@ -1837,6 +1842,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { |
case Yield::kFinal: { |
// Pop value from top-of-stack slot, box result into result register. |
+ OperandStackDepthDecrement(1); |
EmitCreateIteratorResult(true); |
EmitUnwindAndReturn(); |
break; |
@@ -1857,7 +1863,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
// ebx will hold the generator object until the activation has been resumed. |
VisitForStackValue(generator); |
VisitForAccumulatorValue(value); |
- __ pop(ebx); |
+ PopOperand(ebx); |
// Store input value into generator object. |
__ mov(FieldOperand(ebx, JSGeneratorObject::kInputOffset), result_register()); |
@@ -1939,6 +1945,21 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
context()->Plug(result_register()); |
} |
+void FullCodeGenerator::PushOperand(MemOperand operand) { |
+ OperandStackDepthIncrement(1); |
+ __ Push(operand); |
+} |
+ |
+void FullCodeGenerator::EmitOperandStackDepthCheck() { |
+ if (FLAG_debug_code) { |
+ int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + |
+ operand_stack_depth_ * kPointerSize; |
+ __ mov(eax, ebp); |
+ __ sub(eax, esp); |
+ __ cmp(eax, Immediate(expected_diff)); |
+ __ Assert(equal, kUnexpectedStackDepth); |
+ } |
+} |
void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
Label allocate, done_allocate; |
@@ -1985,7 +2006,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); |
+ PopOperand(edx); |
__ mov(ecx, eax); |
__ or_(eax, edx); |
JumpPatchSite patch_site(masm_); |
@@ -2078,9 +2099,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
Expression* value = property->value(); |
if (property->is_static()) { |
- __ push(Operand(esp, kPointerSize)); // constructor |
+ PushOperand(Operand(esp, kPointerSize)); // constructor |
} else { |
- __ push(Operand(esp, 0)); // prototype |
+ PushOperand(Operand(esp, 0)); // prototype |
} |
EmitPropertyKey(property, lit->GetIdForProperty(i)); |
@@ -2104,19 +2125,19 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
case ObjectLiteral::Property::PROTOTYPE: |
UNREACHABLE(); |
case ObjectLiteral::Property::COMPUTED: |
- __ Push(Smi::FromInt(DONT_ENUM)); |
- __ Push(Smi::FromInt(property->NeedsSetFunctionName())); |
- __ CallRuntime(Runtime::kDefineDataPropertyInLiteral); |
+ PushOperand(Smi::FromInt(DONT_ENUM)); |
+ PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); |
+ CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); |
break; |
case ObjectLiteral::Property::GETTER: |
- __ Push(Smi::FromInt(DONT_ENUM)); |
- __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked); |
+ PushOperand(Smi::FromInt(DONT_ENUM)); |
+ CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); |
break; |
case ObjectLiteral::Property::SETTER: |
- __ Push(Smi::FromInt(DONT_ENUM)); |
- __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked); |
+ PushOperand(Smi::FromInt(DONT_ENUM)); |
+ CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); |
break; |
} |
} |
@@ -2124,7 +2145,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
- __ pop(edx); |
+ PopOperand(edx); |
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
CallIC(code, expr->BinaryOperationFeedbackId()); |
@@ -2148,10 +2169,10 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case NAMED_PROPERTY: { |
- __ push(eax); // Preserve value. |
+ PushOperand(eax); // Preserve value. |
VisitForAccumulatorValue(prop->obj()); |
__ Move(StoreDescriptor::ReceiverRegister(), eax); |
- __ pop(StoreDescriptor::ValueRegister()); // Restore value. |
+ PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
__ mov(StoreDescriptor::NameRegister(), |
prop->key()->AsLiteral()->value()); |
EmitLoadStoreICSlot(slot); |
@@ -2159,7 +2180,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case NAMED_SUPER_PROPERTY: { |
- __ push(eax); |
+ PushOperand(eax); |
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
VisitForAccumulatorValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
@@ -2176,7 +2197,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case KEYED_SUPER_PROPERTY: { |
- __ push(eax); |
+ PushOperand(eax); |
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
VisitForStackValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
@@ -2196,12 +2217,12 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case KEYED_PROPERTY: { |
- __ push(eax); // Preserve value. |
+ PushOperand(eax); // Preserve value. |
VisitForStackValue(prop->obj()); |
VisitForAccumulatorValue(prop->key()); |
__ Move(StoreDescriptor::NameRegister(), eax); |
- __ pop(StoreDescriptor::ReceiverRegister()); // Receiver. |
- __ pop(StoreDescriptor::ValueRegister()); // Restore value. |
+ PopOperand(StoreDescriptor::ReceiverRegister()); // Receiver. |
+ PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
EmitLoadStoreICSlot(slot); |
Handle<Code> ic = |
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
@@ -2338,7 +2359,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
DCHECK(prop->key()->IsLiteral()); |
__ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value()); |
- __ pop(StoreDescriptor::ReceiverRegister()); |
+ PopOperand(StoreDescriptor::ReceiverRegister()); |
EmitLoadStoreICSlot(expr->AssignmentSlot()); |
CallStoreIC(); |
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
@@ -2354,10 +2375,11 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { |
Literal* key = prop->key()->AsLiteral(); |
DCHECK(key != NULL); |
- __ push(Immediate(key->value())); |
- __ push(eax); |
- __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
- : Runtime::kStoreToSuper_Sloppy)); |
+ PushOperand(key->value()); |
+ PushOperand(eax); |
+ CallRuntimeWithOperands(is_strict(language_mode()) |
+ ? Runtime::kStoreToSuper_Strict |
+ : Runtime::kStoreToSuper_Sloppy); |
} |
@@ -2366,10 +2388,10 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
// eax : value |
// stack : receiver ('this'), home_object, key |
- __ push(eax); |
- __ CallRuntime((is_strict(language_mode()) |
- ? Runtime::kStoreKeyedToSuper_Strict |
- : Runtime::kStoreKeyedToSuper_Sloppy)); |
+ PushOperand(eax); |
+ CallRuntimeWithOperands(is_strict(language_mode()) |
+ ? Runtime::kStoreKeyedToSuper_Strict |
+ : Runtime::kStoreKeyedToSuper_Sloppy); |
} |
@@ -2379,8 +2401,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
// esp[0] : key |
// esp[kPointerSize] : receiver |
- __ pop(StoreDescriptor::NameRegister()); // Key. |
- __ pop(StoreDescriptor::ReceiverRegister()); |
+ PopOperand(StoreDescriptor::NameRegister()); // Key. |
+ PopOperand(StoreDescriptor::ReceiverRegister()); |
DCHECK(StoreDescriptor::ValueRegister().is(eax)); |
Handle<Code> ic = |
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
@@ -2412,7 +2434,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) { |
if (!expr->IsSuperAccess()) { |
VisitForStackValue(expr->obj()); |
VisitForAccumulatorValue(expr->key()); |
- __ pop(LoadDescriptor::ReceiverRegister()); // Object. |
+ PopOperand(LoadDescriptor::ReceiverRegister()); // Object. |
__ Move(LoadDescriptor::NameRegister(), result_register()); // Key. |
EmitKeyedPropertyLoad(expr); |
} else { |
@@ -2448,7 +2470,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())); |
+ PushOperand(isolate()->factory()->undefined_value()); |
convert_mode = ConvertReceiverMode::kNullOrUndefined; |
} else { |
// Load the function from the receiver. |
@@ -2458,7 +2480,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)); |
+ PushOperand(Operand(esp, 0)); |
__ mov(Operand(esp, kPointerSize), eax); |
convert_mode = ConvertReceiverMode::kNotNullOrUndefined; |
} |
@@ -2480,17 +2502,17 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); |
VisitForStackValue(super_ref->home_object()); |
VisitForAccumulatorValue(super_ref->this_var()); |
- __ push(eax); |
- __ push(eax); |
- __ push(Operand(esp, kPointerSize * 2)); |
- __ push(Immediate(key->value())); |
+ PushOperand(eax); |
+ PushOperand(eax); |
+ PushOperand(Operand(esp, kPointerSize * 2)); |
+ PushOperand(key->value()); |
// Stack here: |
// - home_object |
// - this (receiver) |
// - this (receiver) <-- LoadFromSuper will pop here and below. |
// - home_object |
// - key |
- __ CallRuntime(Runtime::kLoadFromSuper); |
+ CallRuntimeWithOperands(Runtime::kLoadFromSuper); |
// Replace home_object with target function. |
__ mov(Operand(esp, kPointerSize), eax); |
@@ -2518,7 +2540,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
// Push the target function under the receiver. |
- __ push(Operand(esp, 0)); |
+ PushOperand(Operand(esp, 0)); |
__ mov(Operand(esp, kPointerSize), eax); |
EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); |
@@ -2536,9 +2558,9 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { |
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference(); |
VisitForStackValue(super_ref->home_object()); |
VisitForAccumulatorValue(super_ref->this_var()); |
- __ push(eax); |
- __ push(eax); |
- __ push(Operand(esp, kPointerSize * 2)); |
+ PushOperand(eax); |
+ PushOperand(eax); |
+ PushOperand(Operand(esp, kPointerSize * 2)); |
VisitForStackValue(prop->key()); |
// Stack here: |
// - home_object |
@@ -2546,7 +2568,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { |
// - this (receiver) <-- LoadKeyedFromSuper will pop here and below. |
// - home_object |
// - key |
- __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
+ CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); |
// Replace home_object with target function. |
__ mov(Operand(esp, kPointerSize), eax); |
@@ -2584,6 +2606,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) { |
// Don't assign a type feedback id to the IC, since type feedback is provided |
// by the vector above. |
CallIC(ic); |
+ OperandStackDepthDecrement(arg_count + 1); |
RecordJSReturnSite(expr); |
@@ -2631,8 +2654,8 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
// the object holding it (returned in edx). |
__ Push(callee->name()); |
__ CallRuntime(Runtime::kLoadLookupSlotForCall); |
- __ Push(eax); // Function. |
- __ Push(edx); // Receiver. |
+ PushOperand(eax); // Function. |
+ PushOperand(edx); // Receiver. |
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
// If fast case code has been generated, emit code to push the function |
@@ -2651,7 +2674,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
} else { |
VisitForStackValue(callee); |
// refEnv.WithBaseObject() |
- __ push(Immediate(isolate()->factory()->undefined_value())); |
+ PushOperand(isolate()->factory()->undefined_value()); |
} |
} |
@@ -2686,6 +2709,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { |
__ Call(isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
expr->tail_call_mode()), |
RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(arg_count + 1); |
RecordJSReturnSite(expr); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
@@ -2726,6 +2750,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
CallConstructStub stub(isolate()); |
__ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(arg_count + 1); |
PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
@@ -2744,7 +2769,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
__ AssertFunction(result_register()); |
__ mov(result_register(), |
FieldOperand(result_register(), HeapObject::kMapOffset)); |
- __ Push(FieldOperand(result_register(), Map::kPrototypeOffset)); |
+ PushOperand(FieldOperand(result_register(), Map::kPrototypeOffset)); |
// Push the arguments ("left-to-right") on the stack. |
ZoneList<Expression*>* args = expr->arguments(); |
@@ -2766,6 +2791,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
__ mov(edi, Operand(esp, arg_count * kPointerSize)); |
__ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(arg_count + 1); |
RecordJSReturnSite(expr); |
@@ -2986,8 +3012,8 @@ void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
VisitForStackValue(args->at(1)); // value |
VisitForAccumulatorValue(args->at(2)); // string |
- __ pop(value); |
- __ pop(index); |
+ PopOperand(value); |
+ PopOperand(index); |
if (FLAG_debug_code) { |
__ test(value, Immediate(kSmiTagMask)); |
@@ -3021,8 +3047,8 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
VisitForStackValue(args->at(0)); // index |
VisitForStackValue(args->at(1)); // value |
VisitForAccumulatorValue(args->at(2)); // string |
- __ pop(value); |
- __ pop(index); |
+ PopOperand(value); |
+ PopOperand(index); |
if (FLAG_debug_code) { |
__ test(value, Immediate(kSmiTagMask)); |
@@ -3090,7 +3116,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
Register index = eax; |
Register result = edx; |
- __ pop(object); |
+ PopOperand(object); |
Label need_conversion; |
Label index_out_of_range; |
@@ -3137,7 +3163,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
Register scratch = edx; |
Register result = eax; |
- __ pop(object); |
+ PopOperand(object); |
Label need_conversion; |
Label index_out_of_range; |
@@ -3187,6 +3213,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) { |
// Call the target. |
__ mov(eax, Immediate(argc)); |
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(argc + 1); |
// Restore context register. |
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
// Discard the function left on TOS. |
@@ -3275,7 +3302,7 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
__ jmp(&done, Label::kNear); |
__ bind(&runtime); |
- __ CallRuntime(Runtime::kCreateIterResultObject); |
+ CallRuntimeWithOperands(Runtime::kCreateIterResultObject); |
__ bind(&done); |
context()->Plug(eax); |
@@ -3284,7 +3311,7 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
// Push undefined as receiver. |
- __ push(Immediate(isolate()->factory()->undefined_value())); |
+ PushOperand(isolate()->factory()->undefined_value()); |
__ LoadGlobalFunction(expr->context_index(), eax); |
} |
@@ -3299,6 +3326,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
__ Set(eax, arg_count); |
__ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(arg_count + 1); |
} |
@@ -3311,7 +3339,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
EmitLoadJSRuntimeFunction(expr); |
// Push the target function under the receiver. |
- __ push(Operand(esp, 0)); |
+ PushOperand(Operand(esp, 0)); |
__ mov(Operand(esp, kPointerSize), eax); |
// Push the arguments ("left-to-right"). |
@@ -3346,6 +3374,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
// Call the C runtime function. |
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS); |
__ CallRuntime(expr->function(), arg_count); |
+ OperandStackDepthDecrement(arg_count); |
context()->Plug(eax); |
} |
} |
@@ -3363,9 +3392,9 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
if (property != NULL) { |
VisitForStackValue(property->obj()); |
VisitForStackValue(property->key()); |
- __ CallRuntime(is_strict(language_mode()) |
- ? Runtime::kDeleteProperty_Strict |
- : Runtime::kDeleteProperty_Sloppy); |
+ CallRuntimeWithOperands(is_strict(language_mode()) |
+ ? Runtime::kDeleteProperty_Strict |
+ : Runtime::kDeleteProperty_Sloppy); |
context()->Plug(eax); |
} else if (proxy != NULL) { |
Variable* var = proxy->var(); |
@@ -3432,6 +3461,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
&materialize_false, |
&materialize_true, |
&materialize_true); |
+ if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1); |
__ bind(&materialize_true); |
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
if (context()->IsAccumulatorValue()) { |
@@ -3487,7 +3517,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
} else { |
// Reserve space for result of postfix operation. |
if (expr->is_postfix() && !context()->IsEffect()) { |
- __ push(Immediate(Smi::FromInt(0))); |
+ PushOperand(Smi::FromInt(0)); |
} |
switch (assign_type) { |
case NAMED_PROPERTY: { |
@@ -3502,9 +3532,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
VisitForAccumulatorValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
- __ push(result_register()); |
- __ push(MemOperand(esp, kPointerSize)); |
- __ push(result_register()); |
+ PushOperand(result_register()); |
+ PushOperand(MemOperand(esp, kPointerSize)); |
+ PushOperand(result_register()); |
EmitNamedSuperPropertyLoad(prop); |
break; |
} |
@@ -3514,10 +3544,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
VisitForStackValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
VisitForAccumulatorValue(prop->key()); |
- __ push(result_register()); |
- __ push(MemOperand(esp, 2 * kPointerSize)); |
- __ push(MemOperand(esp, 2 * kPointerSize)); |
- __ push(result_register()); |
+ PushOperand(result_register()); |
+ PushOperand(MemOperand(esp, 2 * kPointerSize)); |
+ PushOperand(MemOperand(esp, 2 * kPointerSize)); |
+ PushOperand(result_register()); |
EmitKeyedSuperPropertyLoad(prop); |
break; |
} |
@@ -3607,7 +3637,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
// of the stack. |
switch (assign_type) { |
case VARIABLE: |
- __ push(eax); |
+ PushOperand(eax); |
break; |
case NAMED_PROPERTY: |
__ mov(Operand(esp, kPointerSize), eax); |
@@ -3667,7 +3697,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
case NAMED_PROPERTY: { |
__ mov(StoreDescriptor::NameRegister(), |
prop->key()->AsLiteral()->value()); |
- __ pop(StoreDescriptor::ReceiverRegister()); |
+ PopOperand(StoreDescriptor::ReceiverRegister()); |
EmitLoadStoreICSlot(expr->CountSlot()); |
CallStoreIC(); |
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
@@ -3703,8 +3733,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
break; |
} |
case KEYED_PROPERTY: { |
- __ pop(StoreDescriptor::NameRegister()); |
- __ pop(StoreDescriptor::ReceiverRegister()); |
+ PopOperand(StoreDescriptor::NameRegister()); |
+ PopOperand(StoreDescriptor::ReceiverRegister()); |
Handle<Code> ic = |
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
EmitLoadStoreICSlot(expr->CountSlot()); |
@@ -3825,7 +3855,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
switch (op) { |
case Token::IN: |
VisitForStackValue(expr->right()); |
- __ CallRuntime(Runtime::kHasProperty); |
+ CallRuntimeWithOperands(Runtime::kHasProperty); |
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
__ cmp(eax, isolate()->factory()->true_value()); |
Split(equal, if_true, if_false, fall_through); |
@@ -3833,7 +3863,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
case Token::INSTANCEOF: { |
VisitForAccumulatorValue(expr->right()); |
- __ Pop(edx); |
+ PopOperand(edx); |
InstanceOfStub stub(isolate()); |
__ CallStub(&stub); |
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
@@ -3845,7 +3875,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
default: { |
VisitForAccumulatorValue(expr->right()); |
Condition cc = CompareIC::ComputeCondition(op); |
- __ pop(edx); |
+ PopOperand(edx); |
bool inline_smi_code = ShouldInlineSmiCase(op); |
JumpPatchSite patch_site(masm_); |
@@ -3939,15 +3969,15 @@ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
// as their closure, not the anonymous closure containing the global |
// code. |
__ mov(eax, NativeContextOperand()); |
- __ push(ContextOperand(eax, Context::CLOSURE_INDEX)); |
+ PushOperand(ContextOperand(eax, Context::CLOSURE_INDEX)); |
} else if (closure_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)); |
+ PushOperand(ContextOperand(esi, Context::CLOSURE_INDEX)); |
} else { |
DCHECK(closure_scope->is_function_scope()); |
- __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
+ PushOperand(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
} |
} |
@@ -3960,7 +3990,7 @@ void FullCodeGenerator::EnterFinallyBlock() { |
ExternalReference pending_message_obj = |
ExternalReference::address_of_pending_message_obj(isolate()); |
__ mov(edx, Operand::StaticVariable(pending_message_obj)); |
- __ push(edx); |
+ PushOperand(edx); |
ClearPendingMessage(); |
} |
@@ -3969,7 +3999,7 @@ void FullCodeGenerator::EnterFinallyBlock() { |
void FullCodeGenerator::ExitFinallyBlock() { |
DCHECK(!result_register().is(edx)); |
// Restore pending message from stack. |
- __ pop(edx); |
+ PopOperand(edx); |
ExternalReference pending_message_obj = |
ExternalReference::address_of_pending_message_obj(isolate()); |
__ mov(Operand::StaticVariable(pending_message_obj), edx); |