Index: src/full-codegen/arm64/full-codegen-arm64.cc |
diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc |
index 4f9ce1ddd87f71687f4abac565a1f5782bf27d6b..d0278e742199519cc9cc226992b5654bf5f38199 100644 |
--- a/src/full-codegen/arm64/full-codegen-arm64.cc |
+++ b/src/full-codegen/arm64/full-codegen-arm64.cc |
@@ -135,7 +135,7 @@ void FullCodeGenerator::Generate() { |
int locals_count = info->scope()->num_stack_slots(); |
// Generators allocate locals, if any, in context slots. |
DCHECK(!IsGeneratorFunction(info->literal()->kind()) || locals_count == 0); |
- |
+ OperandStackDepthIncrement(locals_count); |
if (locals_count > 0) { |
if (locals_count >= 128) { |
Label ok; |
@@ -470,7 +470,7 @@ void FullCodeGenerator::EmitReturnSequence() { |
void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
codegen()->GetVar(result_register(), var); |
- __ Push(result_register()); |
+ codegen()->PushOperand(result_register()); |
} |
@@ -488,7 +488,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug( |
void FullCodeGenerator::StackValueContext::Plug( |
Heap::RootListIndex index) const { |
__ LoadRoot(result_register(), index); |
- __ Push(result_register()); |
+ codegen()->PushOperand(result_register()); |
} |
@@ -521,7 +521,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug( |
void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
// Immediates cannot be pushed directly. |
__ Mov(result_register(), Operand(lit)); |
- __ Push(result_register()); |
+ codegen()->PushOperand(result_register()); |
} |
@@ -555,41 +555,14 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
} |
-void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
- Register reg) const { |
- DCHECK(count > 0); |
- __ Drop(count); |
-} |
- |
- |
-void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
- int count, |
- Register reg) const { |
- DCHECK(count > 0); |
- __ Drop(count); |
- __ Move(result_register(), reg); |
-} |
- |
- |
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); |
__ Poke(reg, 0); |
} |
-void FullCodeGenerator::TestContext::DropAndPlug(int count, |
- Register reg) const { |
- DCHECK(count > 0); |
- // For simplicity we always test the accumulator register. |
- __ Drop(count); |
- __ Mov(result_register(), reg); |
- codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); |
- codegen()->DoTest(this); |
-} |
- |
- |
void FullCodeGenerator::EffectContext::Plug(Label* materialize_true, |
Label* materialize_false) const { |
DCHECK(materialize_true == materialize_false); |
@@ -620,7 +593,7 @@ void FullCodeGenerator::StackValueContext::Plug( |
__ Bind(materialize_false); |
__ LoadRoot(x10, Heap::kFalseValueRootIndex); |
__ Bind(&done); |
- __ Push(x10); |
+ codegen()->PushOperand(x10); |
} |
@@ -642,7 +615,7 @@ void FullCodeGenerator::StackValueContext::Plug(bool flag) const { |
Heap::RootListIndex value_root_index = |
flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; |
__ LoadRoot(x10, value_root_index); |
- __ Push(x10); |
+ codegen()->PushOperand(x10); |
} |
@@ -892,11 +865,11 @@ void FullCodeGenerator::VisitFunctionDeclaration( |
case VariableLocation::LOOKUP: { |
Comment cmnt(masm_, "[ Function Declaration"); |
__ Mov(x2, Operand(variable->name())); |
- __ Push(x2); |
+ PushOperand(x2); |
// Push initial value for function declaration. |
VisitForStackValue(declaration->fun()); |
- __ Push(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
- __ CallRuntime(Runtime::kDeclareLookupSlot); |
+ PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes())); |
+ CallRuntimeWithOperands(Runtime::kDeclareLookupSlot); |
break; |
} |
} |
@@ -994,7 +967,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) { |
__ B(nested_statement.break_label()); |
} else { |
@@ -1031,6 +1004,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. |
@@ -1182,7 +1156,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
// Remove the pointers stored on the stack. |
__ Bind(loop_statement.break_label()); |
- __ Drop(5); |
+ DropOperands(5); |
// Exit and decrement the loop depth. |
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
@@ -1451,7 +1425,7 @@ void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) { |
Expression* expression = (property == NULL) ? NULL : property->value(); |
if (expression == NULL) { |
__ LoadRoot(x10, Heap::kNullValueRootIndex); |
- __ Push(x10); |
+ PushOperand(x10); |
} else { |
VisitForStackValue(expression); |
if (NeedsHomeObject(expression)) { |
@@ -1496,7 +1470,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
Literal* key = property->key()->AsLiteral(); |
Expression* value = property->value(); |
if (!result_saved) { |
- __ Push(x0); // Save result on stack |
+ PushOperand(x0); // Save result on stack |
result_saved = true; |
} |
switch (property->kind()) { |
@@ -1527,7 +1501,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
break; |
} |
__ Peek(x0, 0); |
- __ Push(x0); |
+ PushOperand(x0); |
VisitForStackValue(key); |
VisitForStackValue(value); |
if (property->emit_store()) { |
@@ -1535,19 +1509,19 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
EmitSetHomeObject(value, 2, property->GetSlot()); |
} |
__ Mov(x0, Smi::FromInt(SLOPPY)); // Language mode |
- __ Push(x0); |
- __ CallRuntime(Runtime::kSetProperty); |
+ PushOperand(x0); |
+ CallRuntimeWithOperands(Runtime::kSetProperty); |
} else { |
- __ Drop(3); |
+ DropOperands(3); |
} |
break; |
case ObjectLiteral::Property::PROTOTYPE: |
DCHECK(property->emit_store()); |
// Duplicate receiver on stack. |
__ Peek(x0, 0); |
- __ Push(x0); |
+ PushOperand(x0); |
VisitForStackValue(value); |
- __ CallRuntime(Runtime::kInternalSetPrototype); |
+ CallRuntimeWithOperands(Runtime::kInternalSetPrototype); |
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index), |
NO_REGISTERS); |
break; |
@@ -1570,13 +1544,13 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
it != accessor_table.end(); |
++it) { |
__ Peek(x10, 0); // Duplicate receiver. |
- __ Push(x10); |
+ PushOperand(x10); |
VisitForStackValue(it->first); |
EmitAccessor(it->second->getter); |
EmitAccessor(it->second->setter); |
__ Mov(x10, Smi::FromInt(NONE)); |
- __ Push(x10); |
- __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked); |
+ PushOperand(x10); |
+ CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked); |
} |
// Object literals have two parts. The "static" part on the left contains no |
@@ -1593,18 +1567,18 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
Expression* value = property->value(); |
if (!result_saved) { |
- __ Push(x0); // Save result on stack |
+ PushOperand(x0); // Save result on stack |
result_saved = true; |
} |
__ Peek(x10, 0); // Duplicate receiver. |
- __ Push(x10); |
+ PushOperand(x10); |
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 { |
@@ -1619,11 +1593,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; |
@@ -1632,13 +1606,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; |
} |
} |
@@ -1702,7 +1676,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
if (!result_saved) { |
- __ Push(x0); |
+ PushOperand(x0); |
result_saved = true; |
} |
VisitForAccumulatorValue(subexpr); |
@@ -1723,16 +1697,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(x0); |
+ PopOperand(x0); |
result_saved = false; |
} |
for (; array_index < length; array_index++) { |
Expression* subexpr = subexprs->at(array_index); |
- __ Push(x0); |
+ PushOperand(x0); |
DCHECK(!subexpr->IsSpread()); |
VisitForStackValue(subexpr); |
- __ CallRuntime(Runtime::kAppendElement); |
+ CallRuntimeWithOperands(Runtime::kAppendElement); |
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS); |
} |
@@ -1773,11 +1747,11 @@ 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()) { |
const Register scratch = x10; |
__ Peek(scratch, kPointerSize); |
- __ Push(scratch, result_register()); |
+ PushOperands(scratch, result_register()); |
} |
break; |
case KEYED_SUPER_PROPERTY: |
@@ -1786,13 +1760,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
VisitForStackValue( |
property->obj()->AsSuperPropertyReference()->home_object()); |
VisitForAccumulatorValue(property->key()); |
- __ Push(result_register()); |
+ PushOperand(result_register()); |
if (expr->is_compound()) { |
const Register scratch1 = x10; |
const Register scratch2 = x11; |
__ Peek(scratch1, 2 * kPointerSize); |
__ Peek(scratch2, kPointerSize); |
- __ Push(scratch1, scratch2, result_register()); |
+ PushOperands(scratch1, scratch2, result_register()); |
} |
break; |
case KEYED_PROPERTY: |
@@ -1837,7 +1811,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
} |
Token::Value op = expr->binary_op(); |
- __ Push(x0); // Left operand goes on the stack. |
+ PushOperand(x0); // Left operand goes on the stack. |
VisitForAccumulatorValue(expr->value()); |
AccumulatorValueContext context(this); |
@@ -1896,35 +1870,6 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
} |
-void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
- // Stack: receiver, home_object. |
- SetExpressionPosition(prop); |
- Literal* key = prop->key()->AsLiteral(); |
- DCHECK(!key->value()->IsSmi()); |
- DCHECK(prop->IsSuperAccess()); |
- |
- __ Push(key->value()); |
- __ CallRuntime(Runtime::kLoadFromSuper); |
-} |
- |
- |
-void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
- SetExpressionPosition(prop); |
- // Call keyed load IC. It has arguments key and receiver in x0 and x1. |
- Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); |
- __ Mov(LoadDescriptor::SlotRegister(), |
- SmiFromSlot(prop->PropertyFeedbackSlot())); |
- CallIC(ic); |
-} |
- |
- |
-void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
- // Stack: receiver, home_object, key. |
- SetExpressionPosition(prop); |
- __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
-} |
- |
- |
void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
Token::Value op, |
Expression* left_expr, |
@@ -1935,7 +1880,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
Register left = x1; |
Register right = x0; |
Register result = x0; |
- __ Pop(left); |
+ PopOperand(left); |
// Perform combined smi check on both operands. |
__ Orr(x10, left, right); |
@@ -2025,7 +1970,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
- __ Pop(x1); |
+ PopOperand(x1); |
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
JumpPatchSite patch_site(masm_); // Unbound, signals no inlined smi code. |
{ |
@@ -2048,7 +1993,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { |
} else { |
__ Peek(scratch, 0); // prototype |
} |
- __ Push(scratch); |
+ PushOperand(scratch); |
EmitPropertyKey(property, lit->GetIdForProperty(i)); |
// The static prototype property is read only. We handle the non computed |
@@ -2071,19 +2016,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; |
default: |
@@ -2108,12 +2053,12 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case NAMED_PROPERTY: { |
- __ Push(x0); // Preserve value. |
+ PushOperand(x0); // Preserve value. |
VisitForAccumulatorValue(prop->obj()); |
// TODO(all): We could introduce a VisitForRegValue(reg, expr) to avoid |
// this copy. |
__ Mov(StoreDescriptor::ReceiverRegister(), x0); |
- __ Pop(StoreDescriptor::ValueRegister()); // Restore value. |
+ PopOperand(StoreDescriptor::ValueRegister()); // Restore value. |
__ Mov(StoreDescriptor::NameRegister(), |
Operand(prop->key()->AsLiteral()->value())); |
EmitLoadStoreICSlot(slot); |
@@ -2121,7 +2066,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case NAMED_SUPER_PROPERTY: { |
- __ Push(x0); |
+ PushOperand(x0); |
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
VisitForAccumulatorValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
@@ -2138,7 +2083,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case KEYED_SUPER_PROPERTY: { |
- __ Push(x0); |
+ PushOperand(x0); |
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
VisitForStackValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
@@ -2158,12 +2103,12 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, |
break; |
} |
case KEYED_PROPERTY: { |
- __ Push(x0); // Preserve value. |
+ PushOperand(x0); // Preserve value. |
VisitForStackValue(prop->obj()); |
VisitForAccumulatorValue(prop->key()); |
__ Mov(StoreDescriptor::NameRegister(), x0); |
- __ Pop(StoreDescriptor::ReceiverRegister(), |
- StoreDescriptor::ValueRegister()); |
+ PopOperands(StoreDescriptor::ReceiverRegister(), |
+ StoreDescriptor::ValueRegister()); |
EmitLoadStoreICSlot(slot); |
Handle<Code> ic = |
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
@@ -2298,7 +2243,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
__ Mov(StoreDescriptor::NameRegister(), |
Operand(prop->key()->AsLiteral()->value())); |
- __ Pop(StoreDescriptor::ReceiverRegister()); |
+ PopOperand(StoreDescriptor::ReceiverRegister()); |
EmitLoadStoreICSlot(expr->AssignmentSlot()); |
CallStoreIC(); |
@@ -2315,10 +2260,11 @@ void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { |
Literal* key = prop->key()->AsLiteral(); |
DCHECK(key != NULL); |
- __ Push(key->value()); |
- __ Push(x0); |
- __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
- : Runtime::kStoreToSuper_Sloppy)); |
+ PushOperand(key->value()); |
+ PushOperand(x0); |
+ CallRuntimeWithOperands(is_strict(language_mode()) |
+ ? Runtime::kStoreToSuper_Strict |
+ : Runtime::kStoreToSuper_Sloppy); |
} |
@@ -2328,10 +2274,10 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
// stack : receiver ('this'), home_object, key |
DCHECK(prop != NULL); |
- __ Push(x0); |
- __ CallRuntime((is_strict(language_mode()) |
- ? Runtime::kStoreKeyedToSuper_Strict |
- : Runtime::kStoreKeyedToSuper_Sloppy)); |
+ PushOperand(x0); |
+ CallRuntimeWithOperands(is_strict(language_mode()) |
+ ? Runtime::kStoreKeyedToSuper_Strict |
+ : Runtime::kStoreKeyedToSuper_Sloppy); |
} |
@@ -2340,7 +2286,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
// Assignment to a property, using a keyed store IC. |
// TODO(all): Could we pass this in registers rather than on the stack? |
- __ Pop(StoreDescriptor::NameRegister(), StoreDescriptor::ReceiverRegister()); |
+ PopOperands(StoreDescriptor::NameRegister(), |
+ StoreDescriptor::ReceiverRegister()); |
DCHECK(StoreDescriptor::ValueRegister().is(x0)); |
Handle<Code> ic = |
@@ -2374,7 +2321,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) { |
VisitForStackValue(expr->obj()); |
VisitForAccumulatorValue(expr->key()); |
__ Move(LoadDescriptor::NameRegister(), x0); |
- __ Pop(LoadDescriptor::ReceiverRegister()); |
+ PopOperand(LoadDescriptor::ReceiverRegister()); |
EmitKeyedPropertyLoad(expr); |
} else { |
VisitForStackValue(expr->obj()->AsSuperPropertyReference()->this_var()); |
@@ -2416,7 +2363,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { |
UseScratchRegisterScope temps(masm_); |
Register temp = temps.AcquireX(); |
__ LoadRoot(temp, Heap::kUndefinedValueRootIndex); |
- __ Push(temp); |
+ PushOperand(temp); |
} |
convert_mode = ConvertReceiverMode::kNullOrUndefined; |
} else { |
@@ -2427,8 +2374,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { |
EmitNamedPropertyLoad(callee->AsProperty()); |
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
// Push the target function under the receiver. |
- __ Pop(x10); |
- __ Push(x0, x10); |
+ PopOperand(x10); |
+ PushOperands(x0, x10); |
convert_mode = ConvertReceiverMode::kNotNullOrUndefined; |
} |
@@ -2453,17 +2400,18 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { |
callee->AsProperty()->obj()->AsSuperPropertyReference(); |
VisitForStackValue(super_ref->home_object()); |
VisitForAccumulatorValue(super_ref->this_var()); |
- __ Push(x0); |
+ PushOperand(x0); |
__ Peek(scratch, kPointerSize); |
- __ Push(x0, scratch); |
- __ Push(key->value()); |
+ PushOperands(x0, scratch); |
+ PushOperand(key->value()); |
// Stack here: |
// - home_object |
// - this (receiver) |
// - this (receiver) <-- LoadFromSuper will pop here and below. |
// - home_object |
- __ CallRuntime(Runtime::kLoadFromSuper); |
+ // - key |
+ CallRuntimeWithOperands(Runtime::kLoadFromSuper); |
// Replace home_object with target function. |
__ Poke(x0, kPointerSize); |
@@ -2492,8 +2440,8 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
// Push the target function under the receiver. |
- __ Pop(x10); |
- __ Push(x0, x10); |
+ PopOperand(x10); |
+ PushOperands(x0, x10); |
EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined); |
} |
@@ -2513,9 +2461,9 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) { |
callee->AsProperty()->obj()->AsSuperPropertyReference(); |
VisitForStackValue(super_ref->home_object()); |
VisitForAccumulatorValue(super_ref->this_var()); |
- __ Push(x0); |
+ PushOperand(x0); |
__ Peek(scratch, kPointerSize); |
- __ Push(x0, scratch); |
+ PushOperands(x0, scratch); |
VisitForStackValue(prop->key()); |
// Stack here: |
@@ -2524,7 +2472,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. |
__ Poke(x0, kPointerSize); |
@@ -2563,6 +2511,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); |
// Restore context register. |
@@ -2611,7 +2560,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
// and the object holding it (returned in x1). |
__ Push(callee->name()); |
__ CallRuntime(Runtime::kLoadLookupSlotForCall); |
- __ Push(x0, x1); // Receiver, function. |
+ PushOperands(x0, x1); // Receiver, function. |
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS); |
// If fast case code has been generated, emit code to push the |
@@ -2632,7 +2581,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
VisitForStackValue(callee); |
// refEnv.WithBaseObject() |
__ LoadRoot(x10, Heap::kUndefinedValueRootIndex); |
- __ Push(x10); // Reserved receiver slot. |
+ PushOperand(x10); // Reserved receiver slot. |
} |
} |
@@ -2672,6 +2621,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. |
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
@@ -2712,6 +2662,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. |
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
@@ -2733,7 +2684,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
FieldMemOperand(result_register(), HeapObject::kMapOffset)); |
__ Ldr(result_register(), |
FieldMemOperand(result_register(), Map::kPrototypeOffset)); |
- __ Push(result_register()); |
+ PushOperand(result_register()); |
// Push the arguments ("left-to-right") on the stack. |
ZoneList<Expression*>* args = expr->arguments(); |
@@ -2755,6 +2706,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
__ Peek(x1, arg_count * kXRegSize); |
__ Call(isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(arg_count + 1); |
RecordJSReturnSite(expr); |
@@ -2978,7 +2930,7 @@ void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
VisitForStackValue(args->at(0)); // index |
VisitForStackValue(args->at(1)); // value |
VisitForAccumulatorValue(args->at(2)); // string |
- __ Pop(value, index); |
+ PopOperands(value, index); |
if (FLAG_debug_code) { |
__ AssertSmi(value, kNonSmiValue); |
@@ -3008,7 +2960,7 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
VisitForStackValue(args->at(0)); // index |
VisitForStackValue(args->at(1)); // value |
VisitForAccumulatorValue(args->at(2)); // string |
- __ Pop(value, index); |
+ PopOperands(value, index); |
if (FLAG_debug_code) { |
__ AssertSmi(value, kNonSmiValue); |
@@ -3076,7 +3028,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
Register index = x0; |
Register result = x3; |
- __ Pop(object); |
+ PopOperand(object); |
Label need_conversion; |
Label index_out_of_range; |
@@ -3121,7 +3073,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
Register index = x0; |
Register result = x0; |
- __ Pop(object); |
+ PopOperand(object); |
Label need_conversion; |
Label index_out_of_range; |
@@ -3171,6 +3123,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) { |
// Call the target. |
__ Mov(x0, argc); |
__ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(argc + 1); |
// Restore context register. |
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
// Discard the function left on TOS. |
@@ -3267,7 +3220,7 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
__ B(&done); |
__ Bind(&runtime); |
- __ CallRuntime(Runtime::kCreateIterResultObject); |
+ CallRuntimeWithOperands(Runtime::kCreateIterResultObject); |
__ Bind(&done); |
context()->Plug(x0); |
@@ -3277,7 +3230,7 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) { |
// Push undefined as the receiver. |
__ LoadRoot(x0, Heap::kUndefinedValueRootIndex); |
- __ Push(x0); |
+ PushOperand(x0); |
__ LoadNativeContextSlot(expr->context_index(), x0); |
} |
@@ -3292,6 +3245,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
__ Mov(x0, arg_count); |
__ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
RelocInfo::CODE_TARGET); |
+ OperandStackDepthDecrement(arg_count + 1); |
} |
@@ -3304,8 +3258,8 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
EmitLoadJSRuntimeFunction(expr); |
// Push the target function under the receiver. |
- __ Pop(x10); |
- __ Push(x0, x10); |
+ PopOperand(x10); |
+ PushOperands(x0, x10); |
for (int i = 0; i < arg_count; i++) { |
VisitForStackValue(args->at(i)); |
@@ -3339,6 +3293,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(x0); |
} |
} |
@@ -3356,9 +3311,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(x0); |
} else if (proxy != NULL) { |
Variable* var = proxy->var(); |
@@ -3421,6 +3376,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); |
@@ -3473,7 +3429,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
} else { |
// Reserve space for result of postfix operation. |
if (expr->is_postfix() && !context()->IsEffect()) { |
- __ Push(xzr); |
+ PushOperand(xzr); |
} |
switch (assign_type) { |
case NAMED_PROPERTY: { |
@@ -3488,10 +3444,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
VisitForStackValue(prop->obj()->AsSuperPropertyReference()->this_var()); |
VisitForAccumulatorValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
- __ Push(result_register()); |
+ PushOperand(result_register()); |
const Register scratch = x10; |
__ Peek(scratch, kPointerSize); |
- __ Push(scratch, result_register()); |
+ PushOperands(scratch, result_register()); |
EmitNamedSuperPropertyLoad(prop); |
break; |
} |
@@ -3501,12 +3457,12 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
VisitForStackValue( |
prop->obj()->AsSuperPropertyReference()->home_object()); |
VisitForAccumulatorValue(prop->key()); |
- __ Push(result_register()); |
+ PushOperand(result_register()); |
const Register scratch1 = x10; |
const Register scratch2 = x11; |
__ Peek(scratch1, 2 * kPointerSize); |
__ Peek(scratch2, kPointerSize); |
- __ Push(scratch1, scratch2, result_register()); |
+ PushOperands(scratch1, scratch2, result_register()); |
EmitKeyedSuperPropertyLoad(prop); |
break; |
} |
@@ -3589,7 +3545,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
// of the stack. |
switch (assign_type) { |
case VARIABLE: |
- __ Push(x0); |
+ PushOperand(x0); |
break; |
case NAMED_PROPERTY: |
__ Poke(x0, kXRegSize); |
@@ -3649,7 +3605,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
case NAMED_PROPERTY: { |
__ Mov(StoreDescriptor::NameRegister(), |
Operand(prop->key()->AsLiteral()->value())); |
- __ Pop(StoreDescriptor::ReceiverRegister()); |
+ PopOperand(StoreDescriptor::ReceiverRegister()); |
EmitLoadStoreICSlot(expr->CountSlot()); |
CallStoreIC(); |
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
@@ -3685,8 +3641,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()); |
@@ -3817,7 +3773,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); |
__ CompareRoot(x0, Heap::kTrueValueRootIndex); |
Split(eq, if_true, if_false, fall_through); |
@@ -3825,7 +3781,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
case Token::INSTANCEOF: { |
VisitForAccumulatorValue(expr->right()); |
- __ Pop(x1); |
+ PopOperand(x1); |
InstanceOfStub stub(isolate()); |
__ CallStub(&stub); |
PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); |
@@ -3839,7 +3795,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
Condition cond = CompareIC::ComputeCondition(op); |
// Pop the stack value. |
- __ Pop(x1); |
+ PopOperand(x1); |
JumpPatchSite patch_site(masm_); |
if (ShouldInlineSmiCase(op)) { |
@@ -3954,7 +3910,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) { |
__ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
__ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
__ Bind(&post_runtime); |
- __ Pop(result_register()); |
+ PopOperand(result_register()); |
EmitReturnSequence(); |
__ Bind(&resume); |
@@ -3964,6 +3920,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; |
@@ -3990,7 +3947,7 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
// will hold the generator object until the activation has been resumed. |
VisitForStackValue(generator); |
VisitForAccumulatorValue(value); |
- __ Pop(generator_object); |
+ PopOperand(generator_object); |
// Store input value into generator object. |
__ Str(result_register(), |
@@ -4075,6 +4032,31 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
context()->Plug(result_register()); |
} |
+void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { |
+ OperandStackDepthIncrement(2); |
+ __ Push(reg1, reg2); |
+} |
+ |
+void FullCodeGenerator::PushOperands(Register reg1, Register reg2, |
+ Register reg3) { |
+ OperandStackDepthIncrement(3); |
+ __ Push(reg1, reg2, reg3); |
+} |
+ |
+void FullCodeGenerator::PopOperands(Register reg1, Register reg2) { |
+ OperandStackDepthDecrement(2); |
+ __ Pop(reg1, reg2); |
+} |
+ |
+void FullCodeGenerator::EmitOperandStackDepthCheck() { |
+ if (FLAG_debug_code) { |
+ int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + |
+ operand_stack_depth_ * kPointerSize; |
+ __ Sub(x0, fp, jssp); |
+ __ Cmp(x0, Operand(expected_diff)); |
+ __ Assert(eq, kUnexpectedStackDepth); |
+ } |
+} |
void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
Label allocate, done_allocate; |
@@ -4162,7 +4144,7 @@ void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { |
DCHECK(closure_scope->is_function_scope()); |
__ Ldr(x10, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
} |
- __ Push(x10); |
+ PushOperand(x10); |
} |
@@ -4174,7 +4156,7 @@ void FullCodeGenerator::EnterFinallyBlock() { |
ExternalReference::address_of_pending_message_obj(isolate()); |
__ Mov(x10, pending_message_obj); |
__ Ldr(x10, MemOperand(x10)); |
- __ Push(x10); |
+ PushOperand(x10); |
ClearPendingMessage(); |
} |
@@ -4185,7 +4167,7 @@ void FullCodeGenerator::ExitFinallyBlock() { |
DCHECK(!result_register().is(x10)); |
// Restore pending message from stack. |
- __ Pop(x10); |
+ PopOperand(x10); |
ExternalReference pending_message_obj = |
ExternalReference::address_of_pending_message_obj(isolate()); |
__ Mov(x13, pending_message_obj); |