Chromium Code Reviews| Index: src/full-codegen/ia32/full-codegen-ia32.cc |
| diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc |
| index 8a3811748326cf7d67ade16894b3d1d37cee3626..64ba57bbf9b17c9debac91d3168fc90e2ea66951 100644 |
| --- a/src/full-codegen/ia32/full-codegen-ia32.cc |
| +++ b/src/full-codegen/ia32/full-codegen-ia32.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,6 +429,7 @@ void FullCodeGenerator::EmitReturnSequence() { |
| void FullCodeGenerator::StackValueContext::Plug(Variable* var) const { |
| + codegen()->OperandStackDepthIncrement(1); |
| DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| MemOperand operand = codegen()->VarOperand(var, result_register()); |
| // Memory operands can be pushed directly. |
| @@ -472,6 +474,7 @@ void FullCodeGenerator::AccumulatorValueContext::Plug( |
| void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { |
| + codegen()->OperandStackDepthIncrement(1); |
| if (lit->IsSmi()) { |
| __ SafePush(Immediate(lit)); |
| } else { |
| @@ -512,6 +515,7 @@ void FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { |
| void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| Register reg) const { |
| + codegen()->OperandStackDepthDecrement(count); |
| DCHECK(count > 0); |
| __ Drop(count); |
| } |
| @@ -520,6 +524,7 @@ void FullCodeGenerator::EffectContext::DropAndPlug(int count, |
| void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| int count, |
| Register reg) const { |
| + codegen()->OperandStackDepthDecrement(count); |
| DCHECK(count > 0); |
| __ Drop(count); |
| __ Move(result_register(), reg); |
| @@ -528,6 +533,7 @@ void FullCodeGenerator::AccumulatorValueContext::DropAndPlug( |
| void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
| Register reg) const { |
| + codegen()->OperandStackDepthDecrement(count - 1); |
| DCHECK(count > 0); |
| if (count > 1) __ Drop(count - 1); |
| __ mov(Operand(esp, 0), reg); |
| @@ -536,6 +542,7 @@ void FullCodeGenerator::StackValueContext::DropAndPlug(int count, |
| void FullCodeGenerator::TestContext::DropAndPlug(int count, |
| Register reg) const { |
| + codegen()->OperandStackDepthDecrement(count); |
| DCHECK(count > 0); |
| // For simplicity we always test the accumulator register. |
| __ Drop(count); |
| @@ -568,6 +575,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())); |
| @@ -594,6 +602,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(); |
| @@ -831,11 +840,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; |
| } |
| } |
| @@ -931,7 +939,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 { |
| @@ -965,6 +973,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. |
| @@ -1113,6 +1122,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); |
| @@ -1384,7 +1394,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)) { |
| @@ -1434,7 +1444,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()) { |
| @@ -1463,24 +1473,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; |
| @@ -1502,14 +1512,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 |
| @@ -1526,17 +1536,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 { |
| @@ -1551,11 +1561,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; |
| @@ -1564,13 +1574,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; |
| } |
| } |
| @@ -1635,7 +1645,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); |
| @@ -1656,16 +1666,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); |
| } |
| @@ -1697,10 +1707,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: |
| @@ -1718,11 +1728,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: { |
| @@ -1769,7 +1779,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)) { |
| @@ -1862,7 +1872,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); |
| @@ -1872,6 +1882,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; |
| @@ -1892,7 +1903,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()); |
| @@ -1974,6 +1985,19 @@ void FullCodeGenerator::EmitGeneratorResume(Expression *generator, |
| context()->Plug(result_register()); |
| } |
| +void FullCodeGenerator::EmitOperandStackDepthCheck() { |
| + if (generate_debug_code_) { |
| + Vector<char> buf = Vector<char>::New(50); |
| + SNPrintF(buf, " > depth=%d", operand_stack_depth_); |
| + Comment cmnt(masm(), buf.start()); |
| + int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + |
| + operand_stack_depth_ * kPointerSize; |
| + __ mov(eax, ebp); |
| + __ sub(eax, esp); |
| + __ cmp(eax, Immediate(expected_diff)); |
| + __ Assert(equal, kUnexpectedStackDepth); |
|
Jarin
2016/02/19 06:52:04
Hmm, just wondering: is it ok to clobber eax here?
Michael Starzinger
2016/02/19 09:24:04
Acknowledged. As discussed offline: We are current
|
| + } |
| +} |
| void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
| Label allocate, done_allocate; |
| @@ -2020,8 +2044,8 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { |
| DCHECK(!key->value()->IsSmi()); |
| DCHECK(prop->IsSuperAccess()); |
| - __ push(Immediate(key->value())); |
| - __ CallRuntime(Runtime::kLoadFromSuper); |
| + PushOperand(key->value()); |
| + CallRuntimeWithOperands(Runtime::kLoadFromSuper); |
| } |
| @@ -2037,7 +2061,7 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
| // Stack: receiver, home_object, key. |
| SetExpressionPosition(prop); |
| - __ CallRuntime(Runtime::kLoadKeyedFromSuper); |
| + CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper); |
| } |
| @@ -2048,7 +2072,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_); |
| @@ -2141,9 +2165,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)); |
| @@ -2167,19 +2191,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; |
| } |
| } |
| @@ -2187,7 +2211,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()); |
| @@ -2211,10 +2235,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); |
| @@ -2222,7 +2246,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()); |
| @@ -2239,7 +2263,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()); |
| @@ -2259,12 +2283,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(); |
| @@ -2401,7 +2425,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); |
| @@ -2417,10 +2441,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); |
| } |
| @@ -2429,10 +2454,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); |
| } |
| @@ -2442,8 +2467,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(); |
| @@ -2475,7 +2500,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 { |
| @@ -2511,7 +2536,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. |
| @@ -2521,7 +2546,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; |
| } |
| @@ -2543,17 +2568,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); |
| @@ -2581,7 +2606,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); |
| @@ -2599,9 +2624,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 |
| @@ -2609,7 +2634,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); |
| @@ -2647,6 +2672,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); |
| @@ -2694,8 +2720,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 |
| @@ -2714,7 +2740,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) { |
| } else { |
| VisitForStackValue(callee); |
| // refEnv.WithBaseObject() |
| - __ push(Immediate(isolate()->factory()->undefined_value())); |
| + PushOperand(isolate()->factory()->undefined_value()); |
| } |
| } |
| @@ -2747,6 +2773,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) { |
| __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); |
| __ Set(eax, arg_count); |
| __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| + OperandStackDepthDecrement(arg_count + 1); |
| RecordJSReturnSite(expr); |
| // Restore context register. |
| __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| @@ -2787,6 +2814,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)); |
| @@ -2805,7 +2833,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(); |
| @@ -2827,6 +2855,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); |
| @@ -3047,8 +3076,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)); |
| @@ -3082,8 +3111,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)); |
| @@ -3151,7 +3180,7 @@ void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { |
| Register index = eax; |
| Register result = edx; |
| - __ pop(object); |
| + PopOperand(object); |
| Label need_conversion; |
| Label index_out_of_range; |
| @@ -3198,7 +3227,7 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { |
| Register scratch = edx; |
| Register result = eax; |
| - __ pop(object); |
| + PopOperand(object); |
| Label need_conversion; |
| Label index_out_of_range; |
| @@ -3248,6 +3277,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. |
| @@ -3334,6 +3364,7 @@ void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { |
| Operand separator_operand = Operand(esp, 2 * kPointerSize); |
| Operand result_operand = Operand(esp, 1 * kPointerSize); |
| Operand array_length_operand = Operand(esp, 0); |
| + OperandStackDepthIncrement(2); |
| __ sub(esp, Immediate(2 * kPointerSize)); |
| __ cld(); |
| // Check that the array is a JSArray |
| @@ -3566,6 +3597,7 @@ void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { |
| __ bind(&done); |
| __ mov(eax, result_operand); |
| // Drop temp values from the stack, and restore context register. |
| + OperandStackDepthDecrement(3); |
| __ add(esp, Immediate(3 * kPointerSize)); |
| __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| @@ -3605,7 +3637,7 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) { |
| __ jmp(&done, Label::kNear); |
| __ bind(&runtime); |
| - __ CallRuntime(Runtime::kCreateIterResultObject); |
| + CallRuntimeWithOperands(Runtime::kCreateIterResultObject); |
| __ bind(&done); |
| context()->Plug(eax); |
| @@ -3614,7 +3646,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); |
| } |
| @@ -3629,6 +3661,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) { |
| __ Set(eax, arg_count); |
| __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined), |
| RelocInfo::CODE_TARGET); |
| + OperandStackDepthDecrement(arg_count + 1); |
| } |
| @@ -3641,7 +3674,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"). |
| @@ -3676,6 +3709,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); |
| } |
| } |
| @@ -3693,9 +3727,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(); |
| @@ -3763,6 +3797,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| &materialize_true, |
| &materialize_true); |
| __ bind(&materialize_true); |
| + if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1); |
| PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); |
| if (context()->IsAccumulatorValue()) { |
| __ mov(eax, isolate()->factory()->true_value()); |
| @@ -3817,7 +3852,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: { |
| @@ -3832,9 +3867,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; |
| } |
| @@ -3844,10 +3879,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; |
| } |
| @@ -3937,7 +3972,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); |
| @@ -3997,7 +4032,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); |
| @@ -4033,8 +4068,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()); |
| @@ -4155,7 +4190,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); |
| @@ -4163,7 +4198,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); |
| @@ -4175,7 +4210,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_); |
| @@ -4269,15 +4304,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)); |
| } |
| } |
| @@ -4290,7 +4325,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(); |
| } |
| @@ -4299,7 +4334,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); |