X87: [fullcodegen] Implement operand stack depth tracking.
port 38915ed71c
(r34211)
original commit message:
This implements a mechanism to track the exact depth of the operand
stack in full-codegen for every sub-expression visitation. So far we
only tracked the depth at statement level, but not at expression level.
With the introduction of do-expressions it will be possible to construct
local control flow (i.e. break, continue and friends) that target labels
at an arbitrary operand stack depth, making this tracking a prerequisite
for full do-expression support.
BUG=
Review URL: https://codereview.chromium.org/1728953003
Cr-Commit-Position: refs/heads/master@{#34231}
This commit is contained in:
parent
a59f62fcd8
commit
9458a6e4d8
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user