PPC/S390: [Interpreter] Remove InterpreterExitTrampoline and replace with returning to the entry trampoline.
port 39738bc905
Original Commit Message:
In order to support compiling to baseline on return we need to be able to
return to the actual return address. With this change this is what the
Return bytecode now does, removing the need for the
InterpreterExitTrampoline.
This change also removes the InterpreterNotifyDeoptXXX builtins and
unifies FCG and Igntion to both use NotifyDeoptXXX. As part of this
change, FullCodegenerator::State is moved to Deoptimize::BailoutState.
R=rmcilroy@chromium.org, joransiu@ca.ibm.com, michael_dawson@ca.ibm.com, mbrandy@us.ibm.com
BUG=v8:4280
LOG=N
Review-Url: https://codereview.chromium.org/1989983002
Cr-Commit-Position: refs/heads/master@{#36336}
This commit is contained in:
parent
0aa3707dc4
commit
a207b6400e
@ -182,7 +182,8 @@ void FullCodeGenerator::Generate() {
|
||||
__ push(r4);
|
||||
__ Push(info->scope()->GetScopeInfo(info->isolate()));
|
||||
__ CallRuntime(Runtime::kNewScriptContext);
|
||||
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
|
||||
PrepareForBailoutForId(BailoutId::ScriptContext(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
// The new target value is not used, clobbering is safe.
|
||||
DCHECK_NULL(info->scope()->new_target_var());
|
||||
} else {
|
||||
@ -238,7 +239,8 @@ void FullCodeGenerator::Generate() {
|
||||
// Register holding this function and new target are both trashed in case we
|
||||
// bailout here. But since that can happen only when new target is not used
|
||||
// and we allocate a context, the value of |function_in_register| is correct.
|
||||
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(BailoutId::FunctionContext(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
|
||||
// Possibly set up a local binding to the this function which is used in
|
||||
// derived constructors with super calls.
|
||||
@ -300,7 +302,8 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
|
||||
// Visit the declarations and body.
|
||||
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(BailoutId::FunctionEntry(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
{
|
||||
Comment cmnt(masm_, "[ Declarations");
|
||||
VisitDeclarations(scope()->declarations());
|
||||
@ -313,7 +316,8 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
{
|
||||
Comment cmnt(masm_, "[ Stack check");
|
||||
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(BailoutId::Declarations(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
Label ok;
|
||||
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
|
||||
__ cmpl(sp, ip);
|
||||
@ -390,11 +394,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
|
||||
EmitProfilingCounterReset();
|
||||
|
||||
__ bind(&ok);
|
||||
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
|
||||
// Record a mapping of the OSR id to this PC. This is used if the OSR
|
||||
// entry becomes the target of a bailout. We don't expect it to be, but
|
||||
// we want it to work if it is.
|
||||
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
|
||||
@ -693,7 +697,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
|
||||
|
||||
Label skip;
|
||||
if (should_normalize) __ b(&skip);
|
||||
PrepareForBailout(expr, TOS_REG);
|
||||
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
|
||||
if (should_normalize) {
|
||||
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
||||
__ cmp(r3, ip);
|
||||
@ -751,7 +755,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
|
||||
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
||||
__ StoreP(ip, ContextMemOperand(cp, variable->index()), r0);
|
||||
// No write barrier since the_hole_value is in old space.
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -772,7 +776,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
|
||||
__ Push(r5, r3);
|
||||
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
|
||||
__ CallRuntime(Runtime::kDeclareLookupSlot);
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -814,7 +818,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
|
||||
__ RecordWriteContextSlot(cp, offset, result_register(), r5,
|
||||
kLRHasBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -826,7 +830,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
|
||||
VisitForStackValue(declaration->fun());
|
||||
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
|
||||
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -858,7 +862,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
// Keep the switch value on the stack until a case matches.
|
||||
VisitForStackValue(stmt->tag());
|
||||
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
|
||||
|
||||
ZoneList<CaseClause*>* clauses = stmt->cases();
|
||||
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
|
||||
@ -907,7 +911,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
Label skip;
|
||||
__ b(&skip);
|
||||
PrepareForBailout(clause, TOS_REG);
|
||||
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
|
||||
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
|
||||
__ cmp(r3, ip);
|
||||
__ bne(&next_test);
|
||||
@ -936,12 +940,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ Case body");
|
||||
CaseClause* clause = clauses->at(i);
|
||||
__ bind(clause->body_target());
|
||||
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
|
||||
@ -974,7 +978,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
ToObjectStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
__ bind(&done_convert);
|
||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
|
||||
__ push(r3);
|
||||
|
||||
// Check cache validity in generated code. If we cannot guarantee cache
|
||||
@ -994,7 +998,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ bind(&call_runtime);
|
||||
__ push(r3); // Duplicate the enumerable object on the stack.
|
||||
__ CallRuntime(Runtime::kForInEnumerate);
|
||||
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
|
||||
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// If we got a map from the runtime call, we can do a fast
|
||||
// modification check. Otherwise, we got a fixed array, and we have
|
||||
@ -1036,7 +1040,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ Push(r4, r3); // Smi and array
|
||||
__ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset));
|
||||
__ Push(r4); // Fixed array length (as smi).
|
||||
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
|
||||
__ LoadSmiLiteral(r3, Smi::FromInt(0));
|
||||
__ Push(r3); // Initial index.
|
||||
|
||||
@ -1080,7 +1084,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// just skip it.
|
||||
__ Push(r4, r6); // Enumerable and current entry.
|
||||
__ CallRuntime(Runtime::kForInFilter);
|
||||
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
|
||||
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
|
||||
__ mr(r6, r3);
|
||||
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
||||
__ cmp(r3, r0);
|
||||
@ -1094,11 +1098,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
{
|
||||
EffectContext context(this);
|
||||
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
|
||||
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
|
||||
// Generate code for the body of the loop.
|
||||
Visit(stmt->body());
|
||||
|
||||
@ -1117,7 +1121,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
DropOperands(5);
|
||||
|
||||
// Exit and decrement the loop depth.
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
|
||||
__ bind(&exit);
|
||||
decrement_loop_depth();
|
||||
}
|
||||
@ -1276,7 +1280,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||
TypeofMode typeof_mode) {
|
||||
// Record position before possible IC call.
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
// Three cases: global variables, lookup variables, and all other types of
|
||||
@ -1383,7 +1387,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ CallStub(&stub);
|
||||
RestoreContext();
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// If result_saved is true the result is on top of the stack. If
|
||||
// result_saved is false the result is in r3.
|
||||
@ -1419,7 +1423,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
|
||||
EmitLoadStoreICSlot(property->GetSlot(0));
|
||||
CallStoreIC();
|
||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
|
||||
|
||||
if (NeedsHomeObject(value)) {
|
||||
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
|
||||
@ -1453,7 +1457,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
DCHECK(property->emit_store());
|
||||
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
|
||||
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
|
||||
NO_REGISTERS);
|
||||
BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
if (property->emit_store()) {
|
||||
@ -1509,7 +1513,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
DCHECK(property->emit_store());
|
||||
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
|
||||
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
|
||||
NO_REGISTERS);
|
||||
BailoutState::NO_REGISTERS);
|
||||
} else {
|
||||
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
|
||||
VisitForStackValue(value);
|
||||
@ -1582,7 +1586,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
@ -1612,7 +1616,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
|
||||
CallIC(ic);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index),
|
||||
BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
// In case the array literal contains spread expressions it has two parts. The
|
||||
@ -1632,7 +1637,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
VisitForStackValue(subexpr);
|
||||
CallRuntimeWithOperands(Runtime::kAppendElement);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index),
|
||||
BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
if (result_saved) {
|
||||
@ -1715,23 +1721,27 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
switch (assign_type) {
|
||||
case VARIABLE:
|
||||
EmitVariableLoad(expr->target()->AsVariableProxy());
|
||||
PrepareForBailout(expr->target(), TOS_REG);
|
||||
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case NAMED_PROPERTY:
|
||||
EmitNamedPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
EmitNamedSuperPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
EmitKeyedSuperPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case KEYED_PROPERTY:
|
||||
EmitKeyedPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1749,7 +1759,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
// Deoptimization point in case the binary operation may have side effects.
|
||||
PrepareForBailout(expr->binary_operation(), TOS_REG);
|
||||
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
|
||||
} else {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
@ -1761,7 +1771,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
case VARIABLE:
|
||||
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
|
||||
expr->op(), expr->AssignmentSlot());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r3);
|
||||
break;
|
||||
case NAMED_PROPERTY:
|
||||
@ -2273,7 +2283,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
EmitLoadStoreICSlot(expr->AssignmentSlot());
|
||||
CallStoreIC();
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r3);
|
||||
}
|
||||
|
||||
@ -2318,7 +2328,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
EmitLoadStoreICSlot(expr->AssignmentSlot());
|
||||
CallIC(ic);
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r3);
|
||||
}
|
||||
|
||||
@ -2339,7 +2349,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
{
|
||||
StackValueContext context(this);
|
||||
EmitVariableLoad(callee->AsVariableProxy());
|
||||
PrepareForBailout(callee, NO_REGISTERS);
|
||||
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
|
||||
}
|
||||
// Push undefined as receiver. This is patched in the method prologue if it
|
||||
// is a sloppy mode method.
|
||||
@ -2352,7 +2362,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
DCHECK(!callee->AsProperty()->IsSuperAccess());
|
||||
__ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
// Push the target function under the receiver.
|
||||
__ LoadP(r0, MemOperand(sp, 0));
|
||||
PushOperand(r0);
|
||||
@ -2389,7 +2400,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - home_object
|
||||
// - key
|
||||
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
|
||||
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ StoreP(r3, MemOperand(sp, kPointerSize));
|
||||
@ -2413,7 +2424,8 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, Expression* key) {
|
||||
__ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ Move(LoadDescriptor::NameRegister(), r3);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
|
||||
// Push the target function under the receiver.
|
||||
__ LoadP(ip, MemOperand(sp, 0));
|
||||
@ -2447,7 +2459,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - home_object
|
||||
// - key
|
||||
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
|
||||
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ StoreP(r3, MemOperand(sp, kPointerSize));
|
||||
@ -2467,7 +2479,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
|
||||
SetCallPosition(expr, expr->tail_call_mode());
|
||||
if (expr->tail_call_mode() == TailCallMode::kAllow) {
|
||||
if (FLAG_trace) {
|
||||
@ -2536,7 +2548,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
__ Push(callee->name());
|
||||
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
|
||||
PushOperands(r3, r4); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
@ -2585,7 +2597,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
|
||||
|
||||
// Record source position for debugger.
|
||||
SetCallPosition(expr);
|
||||
@ -2635,7 +2647,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
CallConstructStub stub(isolate());
|
||||
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
|
||||
OperandStackDepthDecrement(arg_count + 1);
|
||||
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
|
||||
RestoreContext();
|
||||
context()->Plug(r3);
|
||||
}
|
||||
@ -3058,7 +3070,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
|
||||
for (Expression* const arg : *args) {
|
||||
VisitForStackValue(arg);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
|
||||
// Move target to r4.
|
||||
int const argc = args->length() - 2;
|
||||
__ LoadP(r4, MemOperand(sp, (argc + 1) * kPointerSize));
|
||||
@ -3259,12 +3271,14 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
&materialize_true, &materialize_true);
|
||||
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
|
||||
__ bind(&materialize_true);
|
||||
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->MaterializeTrueId(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
__ LoadRoot(r3, Heap::kTrueValueRootIndex);
|
||||
if (context()->IsStackValue()) __ push(r3);
|
||||
__ b(&done);
|
||||
__ bind(&materialize_false);
|
||||
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->MaterializeFalseId(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
__ LoadRoot(r3, Heap::kFalseValueRootIndex);
|
||||
if (context()->IsStackValue()) __ push(r3);
|
||||
__ bind(&done);
|
||||
@ -3364,9 +3378,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
// We need a second deoptimization point after loading the value
|
||||
// in case evaluating the property load my have a side effect.
|
||||
if (assign_type == VARIABLE) {
|
||||
PrepareForBailout(expr->expression(), TOS_REG);
|
||||
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
|
||||
} else {
|
||||
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
|
||||
}
|
||||
|
||||
// Inline smi case if we are in a loop.
|
||||
@ -3418,7 +3432,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
// Convert old value into a number.
|
||||
ToNumberStub convert_stub(isolate());
|
||||
__ CallStub(&convert_stub);
|
||||
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// Save result for postfix expressions.
|
||||
if (expr->is_postfix()) {
|
||||
@ -3465,7 +3479,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
EffectContext context(this);
|
||||
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
||||
Token::ASSIGN, expr->CountSlot());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
context.Plug(r3);
|
||||
}
|
||||
// For all contexts except EffectConstant We have the result on
|
||||
@ -3476,7 +3491,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
} else {
|
||||
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
||||
Token::ASSIGN, expr->CountSlot());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r3);
|
||||
}
|
||||
break;
|
||||
@ -3486,7 +3502,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
PopOperand(StoreDescriptor::ReceiverRegister());
|
||||
EmitLoadStoreICSlot(expr->CountSlot());
|
||||
CallStoreIC();
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
context()->PlugTOS();
|
||||
@ -3525,7 +3541,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
|
||||
EmitLoadStoreICSlot(expr->CountSlot());
|
||||
CallIC(ic);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
context()->PlugTOS();
|
||||
|
@ -187,7 +187,8 @@ void FullCodeGenerator::Generate() {
|
||||
__ push(r3);
|
||||
__ Push(info->scope()->GetScopeInfo(info->isolate()));
|
||||
__ CallRuntime(Runtime::kNewScriptContext);
|
||||
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
|
||||
PrepareForBailoutForId(BailoutId::ScriptContext(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
// The new target value is not used, clobbering is safe.
|
||||
DCHECK_NULL(info->scope()->new_target_var());
|
||||
} else {
|
||||
@ -243,7 +244,8 @@ void FullCodeGenerator::Generate() {
|
||||
// Register holding this function and new target are both trashed in case we
|
||||
// bailout here. But since that can happen only when new target is not used
|
||||
// and we allocate a context, the value of |function_in_register| is correct.
|
||||
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(BailoutId::FunctionContext(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
|
||||
// Possibly set up a local binding to the this function which is used in
|
||||
// derived constructors with super calls.
|
||||
@ -307,7 +309,8 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
|
||||
// Visit the declarations and body.
|
||||
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(BailoutId::FunctionEntry(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
{
|
||||
Comment cmnt(masm_, "[ Declarations");
|
||||
VisitDeclarations(scope()->declarations());
|
||||
@ -320,7 +323,8 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
{
|
||||
Comment cmnt(masm_, "[ Stack check");
|
||||
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(BailoutId::Declarations(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
Label ok;
|
||||
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
|
||||
__ CmpLogicalP(sp, ip);
|
||||
@ -392,11 +396,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
|
||||
EmitProfilingCounterReset();
|
||||
|
||||
__ bind(&ok);
|
||||
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
|
||||
// Record a mapping of the OSR id to this PC. This is used if the OSR
|
||||
// entry becomes the target of a bailout. We don't expect it to be, but
|
||||
// we want it to work if it is.
|
||||
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
|
||||
@ -674,7 +678,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
|
||||
|
||||
Label skip;
|
||||
if (should_normalize) __ b(&skip);
|
||||
PrepareForBailout(expr, TOS_REG);
|
||||
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
|
||||
if (should_normalize) {
|
||||
__ CompareRoot(r2, Heap::kTrueValueRootIndex);
|
||||
Split(eq, if_true, if_false, NULL);
|
||||
@ -729,7 +733,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
|
||||
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
||||
__ StoreP(ip, ContextMemOperand(cp, variable->index()));
|
||||
// No write barrier since the_hole_value is in old space.
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -750,7 +754,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
|
||||
__ Push(r4, r2);
|
||||
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
|
||||
__ CallRuntime(Runtime::kDeclareLookupSlot);
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -790,7 +794,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
|
||||
__ RecordWriteContextSlot(cp, offset, result_register(), r4,
|
||||
kLRHasBeenSaved, kDontSaveFPRegs,
|
||||
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -802,7 +806,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
|
||||
VisitForStackValue(declaration->fun());
|
||||
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
|
||||
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
|
||||
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -831,7 +835,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
// Keep the switch value on the stack until a case matches.
|
||||
VisitForStackValue(stmt->tag());
|
||||
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
|
||||
|
||||
ZoneList<CaseClause*>* clauses = stmt->cases();
|
||||
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
|
||||
@ -881,7 +885,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
Label skip;
|
||||
__ b(&skip);
|
||||
PrepareForBailout(clause, TOS_REG);
|
||||
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
|
||||
__ CompareRoot(r2, Heap::kTrueValueRootIndex);
|
||||
__ bne(&next_test);
|
||||
__ Drop(1);
|
||||
@ -909,12 +913,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ Case body");
|
||||
CaseClause* clause = clauses->at(i);
|
||||
__ bind(clause->body_target());
|
||||
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
@ -946,7 +950,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
ToObjectStub stub(isolate());
|
||||
__ CallStub(&stub);
|
||||
__ bind(&done_convert);
|
||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
|
||||
__ push(r2);
|
||||
|
||||
// Check cache validity in generated code. If we cannot guarantee cache
|
||||
@ -966,7 +970,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ bind(&call_runtime);
|
||||
__ push(r2); // Duplicate the enumerable object on the stack.
|
||||
__ CallRuntime(Runtime::kForInEnumerate);
|
||||
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
|
||||
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// If we got a map from the runtime call, we can do a fast
|
||||
// modification check. Otherwise, we got a fixed array, and we have
|
||||
@ -1007,7 +1011,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ Push(r3, r2); // Smi and array
|
||||
__ LoadP(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
|
||||
__ Push(r3); // Fixed array length (as smi).
|
||||
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
|
||||
__ LoadSmiLiteral(r2, Smi::FromInt(0));
|
||||
__ Push(r2); // Initial index.
|
||||
|
||||
@ -1051,7 +1055,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// just skip it.
|
||||
__ Push(r3, r5); // Enumerable and current entry.
|
||||
__ CallRuntime(Runtime::kForInFilter);
|
||||
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
|
||||
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
|
||||
__ LoadRR(r5, r2);
|
||||
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
|
||||
__ CmpP(r2, r0);
|
||||
@ -1065,11 +1069,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
{
|
||||
EffectContext context(this);
|
||||
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
|
||||
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
|
||||
// Generate code for the body of the loop.
|
||||
Visit(stmt->body());
|
||||
|
||||
@ -1088,7 +1092,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
DropOperands(5);
|
||||
|
||||
// Exit and decrement the loop depth.
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
|
||||
__ bind(&exit);
|
||||
decrement_loop_depth();
|
||||
}
|
||||
@ -1239,7 +1243,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||
TypeofMode typeof_mode) {
|
||||
// Record position before possible IC call.
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
// Three cases: global variables, lookup variables, and all other types of
|
||||
@ -1343,7 +1347,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ CallStub(&stub);
|
||||
RestoreContext();
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// If result_saved is true the result is on top of the stack. If
|
||||
// result_saved is false the result is in r2.
|
||||
@ -1379,7 +1383,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
__ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
|
||||
EmitLoadStoreICSlot(property->GetSlot(0));
|
||||
CallStoreIC();
|
||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
|
||||
|
||||
if (NeedsHomeObject(value)) {
|
||||
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
|
||||
@ -1413,7 +1417,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
DCHECK(property->emit_store());
|
||||
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
|
||||
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
|
||||
NO_REGISTERS);
|
||||
BailoutState::NO_REGISTERS);
|
||||
break;
|
||||
case ObjectLiteral::Property::GETTER:
|
||||
if (property->emit_store()) {
|
||||
@ -1469,7 +1473,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
DCHECK(property->emit_store());
|
||||
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
|
||||
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
|
||||
NO_REGISTERS);
|
||||
BailoutState::NO_REGISTERS);
|
||||
} else {
|
||||
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
|
||||
VisitForStackValue(value);
|
||||
@ -1541,7 +1545,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
bool result_saved = false; // Is the result saved to the stack?
|
||||
ZoneList<Expression*>* subexprs = expr->values();
|
||||
@ -1571,7 +1575,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
|
||||
CallIC(ic);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index),
|
||||
BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
// In case the array literal contains spread expressions it has two parts. The
|
||||
@ -1591,7 +1596,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
VisitForStackValue(subexpr);
|
||||
CallRuntimeWithOperands(Runtime::kAppendElement);
|
||||
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->GetIdForElement(array_index),
|
||||
BailoutState::NO_REGISTERS);
|
||||
}
|
||||
|
||||
if (result_saved) {
|
||||
@ -1673,23 +1679,27 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
switch (assign_type) {
|
||||
case VARIABLE:
|
||||
EmitVariableLoad(expr->target()->AsVariableProxy());
|
||||
PrepareForBailout(expr->target(), TOS_REG);
|
||||
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case NAMED_PROPERTY:
|
||||
EmitNamedPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case NAMED_SUPER_PROPERTY:
|
||||
EmitNamedSuperPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
EmitKeyedSuperPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
case KEYED_PROPERTY:
|
||||
EmitKeyedPropertyLoad(property);
|
||||
PrepareForBailoutForId(property->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(property->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1707,7 +1717,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
|
||||
// Deoptimization point in case the binary operation may have side effects.
|
||||
PrepareForBailout(expr->binary_operation(), TOS_REG);
|
||||
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
|
||||
} else {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
@ -1719,7 +1729,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
case VARIABLE:
|
||||
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
|
||||
expr->op(), expr->AssignmentSlot());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r2);
|
||||
break;
|
||||
case NAMED_PROPERTY:
|
||||
@ -2226,7 +2236,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
EmitLoadStoreICSlot(expr->AssignmentSlot());
|
||||
CallStoreIC();
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r2);
|
||||
}
|
||||
|
||||
@ -2268,7 +2278,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
EmitLoadStoreICSlot(expr->AssignmentSlot());
|
||||
CallIC(ic);
|
||||
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r2);
|
||||
}
|
||||
|
||||
@ -2287,7 +2297,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
{
|
||||
StackValueContext context(this);
|
||||
EmitVariableLoad(callee->AsVariableProxy());
|
||||
PrepareForBailout(callee, NO_REGISTERS);
|
||||
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
|
||||
}
|
||||
// Push undefined as receiver. This is patched in the method prologue if it
|
||||
// is a sloppy mode method.
|
||||
@ -2300,7 +2310,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
DCHECK(!callee->AsProperty()->IsSuperAccess());
|
||||
__ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
|
||||
EmitNamedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
// Push the target function under the receiver.
|
||||
__ LoadP(r1, MemOperand(sp, 0));
|
||||
PushOperand(r1);
|
||||
@ -2336,7 +2347,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
// - home_object
|
||||
// - key
|
||||
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
|
||||
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ StoreP(r2, MemOperand(sp, kPointerSize));
|
||||
@ -2359,7 +2370,8 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, Expression* key) {
|
||||
__ LoadP(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
|
||||
__ Move(LoadDescriptor::NameRegister(), r2);
|
||||
EmitKeyedPropertyLoad(callee->AsProperty());
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
|
||||
// Push the target function under the receiver.
|
||||
__ LoadP(ip, MemOperand(sp, 0));
|
||||
@ -2392,7 +2404,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
// - home_object
|
||||
// - key
|
||||
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
|
||||
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// Replace home_object with target function.
|
||||
__ StoreP(r2, MemOperand(sp, kPointerSize));
|
||||
@ -2411,7 +2423,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
|
||||
SetCallPosition(expr, expr->tail_call_mode());
|
||||
if (expr->tail_call_mode() == TailCallMode::kAllow) {
|
||||
if (FLAG_trace) {
|
||||
@ -2478,7 +2490,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
__ Push(callee->name());
|
||||
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
|
||||
PushOperands(r2, r3); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
@ -2526,7 +2538,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ StoreP(r2, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
|
||||
|
||||
// Record source position for debugger.
|
||||
SetCallPosition(expr);
|
||||
@ -2575,7 +2587,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
CallConstructStub stub(isolate());
|
||||
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
|
||||
OperandStackDepthDecrement(arg_count + 1);
|
||||
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
|
||||
RestoreContext();
|
||||
context()->Plug(r2);
|
||||
}
|
||||
@ -2983,7 +2995,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
|
||||
for (Expression* const arg : *args) {
|
||||
VisitForStackValue(arg);
|
||||
}
|
||||
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
|
||||
// Move target to r3.
|
||||
int const argc = args->length() - 2;
|
||||
__ LoadP(r3, MemOperand(sp, (argc + 1) * kPointerSize));
|
||||
@ -3175,12 +3187,14 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
&materialize_true, &materialize_true);
|
||||
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
|
||||
__ bind(&materialize_true);
|
||||
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->MaterializeTrueId(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
__ LoadRoot(r2, Heap::kTrueValueRootIndex);
|
||||
if (context()->IsStackValue()) __ push(r2);
|
||||
__ b(&done);
|
||||
__ bind(&materialize_false);
|
||||
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->MaterializeFalseId(),
|
||||
BailoutState::NO_REGISTERS);
|
||||
__ LoadRoot(r2, Heap::kFalseValueRootIndex);
|
||||
if (context()->IsStackValue()) __ push(r2);
|
||||
__ bind(&done);
|
||||
@ -3279,9 +3293,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
// We need a second deoptimization point after loading the value
|
||||
// in case evaluating the property load my have a side effect.
|
||||
if (assign_type == VARIABLE) {
|
||||
PrepareForBailout(expr->expression(), TOS_REG);
|
||||
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
|
||||
} else {
|
||||
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
|
||||
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
|
||||
}
|
||||
|
||||
// Inline smi case if we are in a loop.
|
||||
@ -3333,7 +3347,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
// Convert old value into a number.
|
||||
ToNumberStub convert_stub(isolate());
|
||||
__ CallStub(&convert_stub);
|
||||
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
|
||||
|
||||
// Save result for postfix expressions.
|
||||
if (expr->is_postfix()) {
|
||||
@ -3380,7 +3394,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
EffectContext context(this);
|
||||
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
||||
Token::ASSIGN, expr->CountSlot());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
context.Plug(r2);
|
||||
}
|
||||
// For all contexts except EffectConstant We have the result on
|
||||
@ -3391,7 +3406,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
} else {
|
||||
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
|
||||
Token::ASSIGN, expr->CountSlot());
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(),
|
||||
BailoutState::TOS_REGISTER);
|
||||
context()->Plug(r2);
|
||||
}
|
||||
break;
|
||||
@ -3401,7 +3417,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
PopOperand(StoreDescriptor::ReceiverRegister());
|
||||
EmitLoadStoreICSlot(expr->CountSlot());
|
||||
CallStoreIC();
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
context()->PlugTOS();
|
||||
@ -3440,7 +3456,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
|
||||
EmitLoadStoreICSlot(expr->CountSlot());
|
||||
CallIC(ic);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
|
||||
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
|
||||
if (expr->is_postfix()) {
|
||||
if (!context()->IsEffect()) {
|
||||
context()->PlugTOS();
|
||||
|
@ -1074,8 +1074,19 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ LoadPX(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
|
||||
__ Call(ip);
|
||||
|
||||
// Even though the first bytecode handler was called, we will never return.
|
||||
__ Abort(kUnexpectedReturnFromBytecodeHandler);
|
||||
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
|
||||
|
||||
// The return value is in r3.
|
||||
|
||||
// Get the arguments + reciever count.
|
||||
__ LoadP(r5, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
|
||||
__ lwz(r5, FieldMemOperand(r5, BytecodeArray::kParameterSizeOffset));
|
||||
|
||||
// Leave the frame (also dropping the register file).
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
|
||||
__ add(sp, sp, r5);
|
||||
__ blr();
|
||||
|
||||
// If the bytecode array is no longer present, then the underlying function
|
||||
// has been switched to a different kind of code and we heal the closure by
|
||||
@ -1091,20 +1102,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
||||
// The return value is in accumulator, which is already in r3.
|
||||
|
||||
// Leave the frame (also dropping the register file).
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
|
||||
// Drop receiver + arguments and return.
|
||||
__ lwz(r0, FieldMemOperand(kInterpreterBytecodeArrayRegister,
|
||||
BytecodeArray::kParameterSizeOffset));
|
||||
__ add(sp, sp, r0);
|
||||
__ blr();
|
||||
}
|
||||
|
||||
|
||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
||||
Register count, Register scratch) {
|
||||
Label loop;
|
||||
@ -1116,7 +1113,6 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
||||
__ bdnz(&loop);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode) {
|
||||
@ -1140,7 +1136,6 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
@ -1165,8 +1160,17 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
// Set the return address to the correct point in the interpreter entry
|
||||
// trampoline.
|
||||
Smi* interpreter_entry_return_pc_offset(
|
||||
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
|
||||
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
|
||||
__ Move(r5, masm->isolate()->builtins()->InterpreterEntryTrampoline());
|
||||
__ addi(r0, r5, Operand(interpreter_entry_return_pc_offset->value() +
|
||||
Code::kHeaderSize - kHeapObjectTag));
|
||||
__ mtlr(r0);
|
||||
|
||||
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
// Initialize the dispatch table register.
|
||||
__ mov(kInterpreterDispatchTableRegister,
|
||||
Operand(ExternalReference::interpreter_dispatch_table_address(
|
||||
@ -1199,56 +1203,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_InterpreterNotifyDeoptimizedHelper(
|
||||
MacroAssembler* masm, Deoptimizer::BailoutType type) {
|
||||
// Enter an internal frame.
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Pass the deoptimization type to the runtime system.
|
||||
__ LoadSmiLiteral(r4, Smi::FromInt(static_cast<int>(type)));
|
||||
__ Push(r4);
|
||||
__ CallRuntime(Runtime::kNotifyDeoptimized);
|
||||
// Tear down internal frame.
|
||||
}
|
||||
|
||||
// Drop state (we don't use these for interpreter deopts) and and pop the
|
||||
// accumulator value into the accumulator register.
|
||||
__ Drop(1);
|
||||
__ Pop(kInterpreterAccumulatorRegister);
|
||||
|
||||
// Enter the bytecode dispatch.
|
||||
Generate_EnterBytecodeDispatch(masm);
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
|
||||
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
|
||||
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
|
||||
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
// Set the address of the interpreter entry trampoline as a return address.
|
||||
// This simulates the initial call to bytecode handlers in interpreter entry
|
||||
// trampoline. The return will never actually be taken, but our stack walker
|
||||
// uses this address to determine whether a frame is interpreted.
|
||||
__ mov(r0,
|
||||
Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
|
||||
__ mtlr(r0);
|
||||
|
||||
Generate_EnterBytecodeDispatch(masm);
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r3 : argument count (preserved for callee)
|
||||
@ -1541,14 +1495,17 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
|
||||
__ SmiUntag(r9);
|
||||
// Switch on the state.
|
||||
Label with_tos_register, unknown_state;
|
||||
__ cmpi(r9, Operand(FullCodeGenerator::NO_REGISTERS));
|
||||
__ cmpi(r9,
|
||||
Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
|
||||
__ bne(&with_tos_register);
|
||||
__ addi(sp, sp, Operand(1 * kPointerSize)); // Remove state.
|
||||
__ Ret();
|
||||
|
||||
__ bind(&with_tos_register);
|
||||
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r3.code());
|
||||
__ LoadP(r3, MemOperand(sp, 1 * kPointerSize));
|
||||
__ cmpi(r9, Operand(FullCodeGenerator::TOS_REG));
|
||||
__ cmpi(r9,
|
||||
Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
|
||||
__ bne(&unknown_state);
|
||||
__ addi(sp, sp, Operand(2 * kPointerSize)); // Remove state.
|
||||
__ Ret();
|
||||
|
@ -1064,8 +1064,19 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ LoadP(ip, MemOperand(kInterpreterDispatchTableRegister, ip));
|
||||
__ Call(ip);
|
||||
|
||||
// Even though the first bytecode handler was called, we will never return.
|
||||
__ Abort(kUnexpectedReturnFromBytecodeHandler);
|
||||
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
|
||||
|
||||
// The return value is in r2.
|
||||
|
||||
// Get the arguments + reciever count.
|
||||
__ LoadP(r4, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
|
||||
__ LoadlW(r4, FieldMemOperand(r4, BytecodeArray::kParameterSizeOffset));
|
||||
|
||||
// Leave the frame (also dropping the register file).
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
|
||||
__ lay(sp, MemOperand(sp, r4));
|
||||
__ Ret();
|
||||
|
||||
// If the bytecode array is no longer present, then the underlying function
|
||||
// has been switched to a different kind of code and we heal the closure by
|
||||
@ -1080,19 +1091,6 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
|
||||
__ JumpToJSEntry(r6);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
||||
// The return value is in accumulator, which is already in r2.
|
||||
|
||||
// Leave the frame (also dropping the register file).
|
||||
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
|
||||
|
||||
// Drop receiver + arguments and return.
|
||||
__ LoadlW(r0, FieldMemOperand(kInterpreterBytecodeArrayRegister,
|
||||
BytecodeArray::kParameterSizeOffset));
|
||||
__ AddP(sp, sp, r0);
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
||||
Register count, Register scratch) {
|
||||
Label loop;
|
||||
@ -1153,7 +1151,16 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
// Set the return address to the correct point in the interpreter entry
|
||||
// trampoline.
|
||||
Smi* interpreter_entry_return_pc_offset(
|
||||
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
|
||||
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
|
||||
__ Move(r4, masm->isolate()->builtins()->InterpreterEntryTrampoline());
|
||||
__ AddP(r14, r4, Operand(interpreter_entry_return_pc_offset->value() +
|
||||
Code::kHeaderSize - kHeapObjectTag));
|
||||
|
||||
// Initialize the dispatch table register.
|
||||
__ mov(kInterpreterDispatchTableRegister,
|
||||
Operand(ExternalReference::interpreter_dispatch_table_address(
|
||||
@ -1185,51 +1192,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
__ Jump(ip);
|
||||
}
|
||||
|
||||
static void Generate_InterpreterNotifyDeoptimizedHelper(
|
||||
MacroAssembler* masm, Deoptimizer::BailoutType type) {
|
||||
// Enter an internal frame.
|
||||
{
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Pass the deoptimization type to the runtime system.
|
||||
__ LoadSmiLiteral(r3, Smi::FromInt(static_cast<int>(type)));
|
||||
__ Push(r3);
|
||||
__ CallRuntime(Runtime::kNotifyDeoptimized);
|
||||
// Tear down internal frame.
|
||||
}
|
||||
|
||||
// Drop state (we don't use these for interpreter deopts) and and pop the
|
||||
// accumulator value into the accumulator register.
|
||||
__ Drop(1);
|
||||
__ Pop(kInterpreterAccumulatorRegister);
|
||||
|
||||
// Enter the bytecode dispatch.
|
||||
Generate_EnterBytecodeDispatch(masm);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
|
||||
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
|
||||
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
|
||||
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
|
||||
}
|
||||
|
||||
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
|
||||
// Set the address of the interpreter entry trampoline as a return address.
|
||||
// This simulates the initial call to bytecode handlers in interpreter entry
|
||||
// trampoline. The return will never actually be taken, but our stack walker
|
||||
// uses this address to determine whether a frame is interpreted.
|
||||
__ mov(r14,
|
||||
Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
|
||||
|
||||
Generate_EnterBytecodeDispatch(masm);
|
||||
}
|
||||
|
||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : argument count (preserved for callee)
|
||||
@ -1517,14 +1479,17 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
|
||||
__ SmiUntag(r8);
|
||||
// Switch on the state.
|
||||
Label with_tos_register, unknown_state;
|
||||
__ CmpP(r8, Operand(FullCodeGenerator::NO_REGISTERS));
|
||||
__ CmpP(r8,
|
||||
Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
|
||||
__ bne(&with_tos_register);
|
||||
__ la(sp, MemOperand(sp, 1 * kPointerSize)); // Remove state.
|
||||
__ Ret();
|
||||
|
||||
__ bind(&with_tos_register);
|
||||
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r2.code());
|
||||
__ LoadP(r2, MemOperand(sp, 1 * kPointerSize));
|
||||
__ CmpP(r8, Operand(FullCodeGenerator::TOS_REG));
|
||||
__ CmpP(r8,
|
||||
Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
|
||||
__ bne(&unknown_state);
|
||||
__ la(sp, MemOperand(sp, 2 * kPointerSize)); // Remove state.
|
||||
__ Ret();
|
||||
|
Loading…
Reference in New Issue
Block a user