summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/instruction-selector.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/instruction-selector.cc')
-rw-r--r--deps/v8/src/compiler/instruction-selector.cc342
1 files changed, 198 insertions, 144 deletions
diff --git a/deps/v8/src/compiler/instruction-selector.cc b/deps/v8/src/compiler/instruction-selector.cc
index 541e0452fa..f36b07ea7e 100644
--- a/deps/v8/src/compiler/instruction-selector.cc
+++ b/deps/v8/src/compiler/instruction-selector.cc
@@ -21,9 +21,9 @@ InstructionSelector::InstructionSelector(InstructionSequence* sequence,
source_positions_(source_positions),
features_(features),
current_block_(NULL),
- instructions_(InstructionDeque::allocator_type(zone())),
- defined_(graph()->NodeCount(), false, BoolVector::allocator_type(zone())),
- used_(graph()->NodeCount(), false, BoolVector::allocator_type(zone())) {}
+ instructions_(zone()),
+ defined_(graph()->NodeCount(), false, zone()),
+ used_(graph()->NodeCount(), false, zone()) {}
void InstructionSelector::SelectInstructions() {
@@ -91,7 +91,7 @@ Instruction* InstructionSelector::Emit(InstructionCode opcode,
InstructionOperand** temps) {
size_t output_count = output == NULL ? 0 : 1;
InstructionOperand* inputs[] = {a, b};
- size_t input_count = ARRAY_SIZE(inputs);
+ size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
}
@@ -105,7 +105,7 @@ Instruction* InstructionSelector::Emit(InstructionCode opcode,
InstructionOperand** temps) {
size_t output_count = output == NULL ? 0 : 1;
InstructionOperand* inputs[] = {a, b, c};
- size_t input_count = ARRAY_SIZE(inputs);
+ size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
}
@@ -117,7 +117,7 @@ Instruction* InstructionSelector::Emit(
size_t temp_count, InstructionOperand** temps) {
size_t output_count = output == NULL ? 0 : 1;
InstructionOperand* inputs[] = {a, b, c, d};
- size_t input_count = ARRAY_SIZE(inputs);
+ size_t input_count = arraysize(inputs);
return Emit(opcode, output_count, &output, input_count, inputs, temp_count,
temps);
}
@@ -198,14 +198,6 @@ void InstructionSelector::MarkAsDouble(Node* node) {
DCHECK_NOT_NULL(node);
DCHECK(!IsReference(node));
sequence()->MarkAsDouble(node->id());
-
- // Propagate "doubleness" throughout phis.
- for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
- Node* user = *i;
- if (user->opcode() != IrOpcode::kPhi) continue;
- if (IsDouble(user)) continue;
- MarkAsDouble(user);
- }
}
@@ -219,40 +211,39 @@ void InstructionSelector::MarkAsReference(Node* node) {
DCHECK_NOT_NULL(node);
DCHECK(!IsDouble(node));
sequence()->MarkAsReference(node->id());
-
- // Propagate "referenceness" throughout phis.
- for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
- Node* user = *i;
- if (user->opcode() != IrOpcode::kPhi) continue;
- if (IsReference(user)) continue;
- MarkAsReference(user);
- }
}
void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) {
DCHECK_NOT_NULL(node);
- if (rep == kMachineFloat64) MarkAsDouble(node);
- if (rep == kMachineTagged) MarkAsReference(node);
+ switch (RepresentationOf(rep)) {
+ case kRepFloat32:
+ case kRepFloat64:
+ MarkAsDouble(node);
+ break;
+ case kRepTagged:
+ MarkAsReference(node);
+ break;
+ default:
+ break;
+ }
}
// TODO(bmeurer): Get rid of the CallBuffer business and make
// InstructionSelector::VisitCall platform independent instead.
-CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d)
- : output_count(0),
- descriptor(d),
- output_nodes(zone->NewArray<Node*>(d->ReturnCount())),
- outputs(zone->NewArray<InstructionOperand*>(d->ReturnCount())),
- fixed_and_control_args(
- zone->NewArray<InstructionOperand*>(input_count() + control_count())),
- fixed_count(0),
- pushed_nodes(zone->NewArray<Node*>(input_count())),
- pushed_count(0) {
- if (d->ReturnCount() > 1) {
- memset(output_nodes, 0, sizeof(Node*) * d->ReturnCount()); // NOLINT
- }
- memset(pushed_nodes, 0, sizeof(Node*) * input_count()); // NOLINT
+CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d,
+ FrameStateDescriptor* frame_desc)
+ : descriptor(d),
+ frame_state_descriptor(frame_desc),
+ output_nodes(zone),
+ outputs(zone),
+ instruction_args(zone),
+ pushed_nodes(zone) {
+ output_nodes.reserve(d->ReturnCount());
+ outputs.reserve(d->ReturnCount());
+ pushed_nodes.reserve(input_count());
+ instruction_args.reserve(input_count() + frame_state_value_count());
}
@@ -260,96 +251,109 @@ CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d)
// InstructionSelector::VisitCall platform independent instead.
void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
bool call_code_immediate,
- bool call_address_immediate,
- BasicBlock* cont_node,
- BasicBlock* deopt_node) {
+ bool call_address_immediate) {
OperandGenerator g(this);
DCHECK_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount());
DCHECK_EQ(OperatorProperties::GetValueInputCount(call->op()),
- buffer->input_count());
+ buffer->input_count() + buffer->frame_state_count());
if (buffer->descriptor->ReturnCount() > 0) {
// Collect the projections that represent multiple outputs from this call.
if (buffer->descriptor->ReturnCount() == 1) {
- buffer->output_nodes[0] = call;
+ buffer->output_nodes.push_back(call);
} else {
- call->CollectProjections(buffer->descriptor->ReturnCount(),
- buffer->output_nodes);
+ buffer->output_nodes.resize(buffer->descriptor->ReturnCount(), NULL);
+ call->CollectProjections(&buffer->output_nodes);
}
// Filter out the outputs that aren't live because no projection uses them.
- for (int i = 0; i < buffer->descriptor->ReturnCount(); i++) {
+ for (size_t i = 0; i < buffer->output_nodes.size(); i++) {
if (buffer->output_nodes[i] != NULL) {
Node* output = buffer->output_nodes[i];
- LinkageLocation location = buffer->descriptor->GetReturnLocation(i);
- MarkAsRepresentation(location.representation(), output);
- buffer->outputs[buffer->output_count++] =
- g.DefineAsLocation(output, location);
+ MachineType type =
+ buffer->descriptor->GetReturnType(static_cast<int>(i));
+ LinkageLocation location =
+ buffer->descriptor->GetReturnLocation(static_cast<int>(i));
+ MarkAsRepresentation(type, output);
+ buffer->outputs.push_back(g.DefineAsLocation(output, location, type));
}
}
}
- buffer->fixed_count = 1; // First argument is always the callee.
+ // The first argument is always the callee code.
Node* callee = call->InputAt(0);
switch (buffer->descriptor->kind()) {
case CallDescriptor::kCallCodeObject:
- buffer->fixed_and_control_args[0] =
+ buffer->instruction_args.push_back(
(call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant)
? g.UseImmediate(callee)
- : g.UseRegister(callee);
+ : g.UseRegister(callee));
break;
case CallDescriptor::kCallAddress:
- buffer->fixed_and_control_args[0] =
+ buffer->instruction_args.push_back(
(call_address_immediate &&
(callee->opcode() == IrOpcode::kInt32Constant ||
callee->opcode() == IrOpcode::kInt64Constant))
? g.UseImmediate(callee)
- : g.UseRegister(callee);
+ : g.UseRegister(callee));
break;
case CallDescriptor::kCallJSFunction:
- buffer->fixed_and_control_args[0] =
- g.UseLocation(callee, buffer->descriptor->GetInputLocation(0));
+ buffer->instruction_args.push_back(
+ g.UseLocation(callee, buffer->descriptor->GetInputLocation(0),
+ buffer->descriptor->GetInputType(0)));
break;
}
+ DCHECK_EQ(1, buffer->instruction_args.size());
+
+ // If the call needs a frame state, we insert the state information as
+ // follows (n is the number of value inputs to the frame state):
+ // arg 1 : deoptimization id.
+ // arg 2 - arg (n + 1) : value inputs to the frame state.
+ if (buffer->frame_state_descriptor != NULL) {
+ InstructionSequence::StateId state_id =
+ sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
+ buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
+
+ Node* frame_state =
+ call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
+ AddFrameStateInputs(frame_state, &buffer->instruction_args,
+ buffer->frame_state_descriptor);
+ }
+ DCHECK(1 + buffer->frame_state_value_count() ==
+ buffer->instruction_args.size());
- int input_count = buffer->input_count();
+ size_t input_count = static_cast<size_t>(buffer->input_count());
- // Split the arguments into pushed_nodes and fixed_args. Pushed arguments
- // require an explicit push instruction before the call and do not appear
- // as arguments to the call. Everything else ends up as an InstructionOperand
- // argument to the call.
+ // Split the arguments into pushed_nodes and instruction_args. Pushed
+ // arguments require an explicit push instruction before the call and do
+ // not appear as arguments to the call. Everything else ends up
+ // as an InstructionOperand argument to the call.
InputIter iter(call->inputs().begin());
- for (int index = 0; index < input_count; ++iter, ++index) {
+ int pushed_count = 0;
+ for (size_t index = 0; index < input_count; ++iter, ++index) {
DCHECK(iter != call->inputs().end());
- DCHECK(index == iter.index());
+ DCHECK(index == static_cast<size_t>(iter.index()));
+ DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
if (index == 0) continue; // The first argument (callee) is already done.
InstructionOperand* op =
- g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index));
+ g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index),
+ buffer->descriptor->GetInputType(index));
if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) {
int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1;
- DCHECK(buffer->pushed_nodes[stack_index] == NULL);
+ if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
+ buffer->pushed_nodes.resize(stack_index + 1, NULL);
+ }
+ DCHECK_EQ(NULL, buffer->pushed_nodes[stack_index]);
buffer->pushed_nodes[stack_index] = *iter;
- buffer->pushed_count++;
+ pushed_count++;
} else {
- buffer->fixed_and_control_args[buffer->fixed_count] = op;
- buffer->fixed_count++;
+ buffer->instruction_args.push_back(op);
}
}
-
- // If the call can deoptimize, we add the continuation and deoptimization
- // block labels.
- if (buffer->descriptor->CanLazilyDeoptimize()) {
- DCHECK(cont_node != NULL);
- DCHECK(deopt_node != NULL);
- buffer->fixed_and_control_args[buffer->fixed_count] = g.Label(cont_node);
- buffer->fixed_and_control_args[buffer->fixed_count + 1] =
- g.Label(deopt_node);
- } else {
- DCHECK(cont_node == NULL);
- DCHECK(deopt_node == NULL);
- }
-
- DCHECK(input_count == (buffer->fixed_count + buffer->pushed_count));
+ CHECK_EQ(pushed_count, static_cast<int>(buffer->pushed_nodes.size()));
+ DCHECK(static_cast<size_t>(input_count) ==
+ (buffer->instruction_args.size() + buffer->pushed_nodes.size() -
+ buffer->frame_state_value_count()));
}
@@ -422,14 +426,6 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
}
case BasicBlockData::kThrow:
return VisitThrow(input);
- case BasicBlockData::kDeoptimize:
- return VisitDeoptimize(input);
- case BasicBlockData::kCall: {
- BasicBlock* deoptimization = block->SuccessorAt(0);
- BasicBlock* continuation = block->SuccessorAt(1);
- VisitCall(input, continuation, deoptimization);
- break;
- }
case BasicBlockData::kNone: {
// TODO(titzer): exit block doesn't have control.
DCHECK(input == NULL);
@@ -460,27 +456,28 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kIfFalse:
case IrOpcode::kEffectPhi:
case IrOpcode::kMerge:
- case IrOpcode::kLazyDeoptimization:
- case IrOpcode::kContinuation:
// No code needed for these graph artifacts.
return;
+ case IrOpcode::kFinish:
+ return MarkAsReference(node), VisitFinish(node);
case IrOpcode::kParameter: {
- int index = OpParameter<int>(node);
- MachineType rep = linkage()
- ->GetIncomingDescriptor()
- ->GetInputLocation(index)
- .representation();
- MarkAsRepresentation(rep, node);
+ MachineType type = linkage()->GetParameterType(OpParameter<int>(node));
+ MarkAsRepresentation(type, node);
return VisitParameter(node);
}
- case IrOpcode::kPhi:
+ case IrOpcode::kPhi: {
+ MachineType type = OpParameter<MachineType>(node);
+ MarkAsRepresentation(type, node);
return VisitPhi(node);
+ }
case IrOpcode::kProjection:
return VisitProjection(node);
case IrOpcode::kInt32Constant:
case IrOpcode::kInt64Constant:
case IrOpcode::kExternalConstant:
return VisitConstant(node);
+ case IrOpcode::kFloat32Constant:
+ return MarkAsDouble(node), VisitConstant(node);
case IrOpcode::kFloat64Constant:
return MarkAsDouble(node), VisitConstant(node);
case IrOpcode::kHeapConstant:
@@ -493,8 +490,8 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kStateValues:
return;
case IrOpcode::kLoad: {
- MachineType load_rep = OpParameter<MachineType>(node);
- MarkAsRepresentation(load_rep, node);
+ LoadRepresentation rep = OpParameter<LoadRepresentation>(node);
+ MarkAsRepresentation(rep, node);
return VisitLoad(node);
}
case IrOpcode::kStore:
@@ -511,6 +508,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitWord32Shr(node);
case IrOpcode::kWord32Sar:
return VisitWord32Sar(node);
+ case IrOpcode::kWord32Ror:
+ return VisitWord32Ror(node);
case IrOpcode::kWord32Equal:
return VisitWord32Equal(node);
case IrOpcode::kWord64And:
@@ -525,6 +524,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitWord64Shr(node);
case IrOpcode::kWord64Sar:
return VisitWord64Sar(node);
+ case IrOpcode::kWord64Ror:
+ return VisitWord64Ror(node);
case IrOpcode::kWord64Equal:
return VisitWord64Equal(node);
case IrOpcode::kInt32Add:
@@ -571,10 +572,8 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitInt64LessThan(node);
case IrOpcode::kInt64LessThanOrEqual:
return VisitInt64LessThanOrEqual(node);
- case IrOpcode::kConvertInt32ToInt64:
- return VisitConvertInt32ToInt64(node);
- case IrOpcode::kConvertInt64ToInt32:
- return VisitConvertInt64ToInt32(node);
+ case IrOpcode::kChangeFloat32ToFloat64:
+ return MarkAsDouble(node), VisitChangeFloat32ToFloat64(node);
case IrOpcode::kChangeInt32ToFloat64:
return MarkAsDouble(node), VisitChangeInt32ToFloat64(node);
case IrOpcode::kChangeUint32ToFloat64:
@@ -583,6 +582,16 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitChangeFloat64ToInt32(node);
case IrOpcode::kChangeFloat64ToUint32:
return VisitChangeFloat64ToUint32(node);
+ case IrOpcode::kChangeInt32ToInt64:
+ return VisitChangeInt32ToInt64(node);
+ case IrOpcode::kChangeUint32ToUint64:
+ return VisitChangeUint32ToUint64(node);
+ case IrOpcode::kTruncateFloat64ToFloat32:
+ return MarkAsDouble(node), VisitTruncateFloat64ToFloat32(node);
+ case IrOpcode::kTruncateFloat64ToInt32:
+ return VisitTruncateFloat64ToInt32(node);
+ case IrOpcode::kTruncateInt64ToInt32:
+ return VisitTruncateInt64ToInt32(node);
case IrOpcode::kFloat64Add:
return MarkAsDouble(node), VisitFloat64Add(node);
case IrOpcode::kFloat64Sub:
@@ -593,6 +602,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsDouble(node), VisitFloat64Div(node);
case IrOpcode::kFloat64Mod:
return MarkAsDouble(node), VisitFloat64Mod(node);
+ case IrOpcode::kFloat64Sqrt:
+ return MarkAsDouble(node), VisitFloat64Sqrt(node);
case IrOpcode::kFloat64Equal:
return VisitFloat64Equal(node);
case IrOpcode::kFloat64LessThan:
@@ -684,6 +695,13 @@ void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
}
+void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
+}
+
+
void InstructionSelector::VisitFloat64Equal(Node* node) {
FlagsContinuation cont(kUnorderedEqual, node);
VisitFloat64Compare(node, &cont);
@@ -724,6 +742,9 @@ void InstructionSelector::VisitWord64Shr(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64Sar(Node* node) { UNIMPLEMENTED(); }
+void InstructionSelector::VisitWord64Ror(Node* node) { UNIMPLEMENTED(); }
+
+
void InstructionSelector::VisitInt64Add(Node* node) { UNIMPLEMENTED(); }
@@ -745,12 +766,17 @@ void InstructionSelector::VisitInt64Mod(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt64UMod(Node* node) { UNIMPLEMENTED(); }
-void InstructionSelector::VisitConvertInt64ToInt32(Node* node) {
+void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
UNIMPLEMENTED();
}
-void InstructionSelector::VisitConvertInt32ToInt64(Node* node) {
+void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
+ UNIMPLEMENTED();
+}
+
+
+void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
UNIMPLEMENTED();
}
@@ -774,10 +800,19 @@ void InstructionSelector::VisitWord64Compare(Node* node,
#endif // V8_TARGET_ARCH_32_BIT || !V8_TURBOFAN_BACKEND
+void InstructionSelector::VisitFinish(Node* node) {
+ OperandGenerator g(this);
+ Node* value = node->InputAt(0);
+ Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
+}
+
+
void InstructionSelector::VisitParameter(Node* node) {
OperandGenerator g(this);
- Emit(kArchNop, g.DefineAsLocation(node, linkage()->GetParameterLocation(
- OpParameter<int>(node))));
+ int index = OpParameter<int>(node);
+ Emit(kArchNop,
+ g.DefineAsLocation(node, linkage()->GetParameterLocation(index),
+ linkage()->GetParameterType(index)));
}
@@ -795,10 +830,10 @@ void InstructionSelector::VisitProjection(Node* node) {
switch (value->opcode()) {
case IrOpcode::kInt32AddWithOverflow:
case IrOpcode::kInt32SubWithOverflow:
- if (OpParameter<int32_t>(node) == 0) {
+ if (OpParameter<size_t>(node) == 0) {
Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
} else {
- DCHECK_EQ(1, OpParameter<int32_t>(node));
+ DCHECK(OpParameter<size_t>(node) == 1u);
MarkAsUsed(value);
}
break;
@@ -906,7 +941,7 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
case IrOpcode::kProjection:
// Check if this is the overflow output projection of an
// <Operation>WithOverflow node.
- if (OpParameter<int32_t>(value) == 1) {
+ if (OpParameter<size_t>(value) == 1u) {
// We cannot combine the <Operation>WithOverflow with this branch
// unless the 0th projection (the use of the actual value of the
// <Operation> is either NULL, which means there's no use of the
@@ -941,7 +976,8 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
void InstructionSelector::VisitReturn(Node* value) {
OperandGenerator g(this);
if (value != NULL) {
- Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation()));
+ Emit(kArchRet, NULL, g.UseLocation(value, linkage()->GetReturnLocation(),
+ linkage()->GetReturnType()));
} else {
Emit(kArchRet, NULL);
}
@@ -953,6 +989,26 @@ void InstructionSelector::VisitThrow(Node* value) {
}
+FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
+ Node* state) {
+ DCHECK(state->opcode() == IrOpcode::kFrameState);
+ DCHECK_EQ(5, state->InputCount());
+ FrameStateCallInfo state_info = OpParameter<FrameStateCallInfo>(state);
+ int parameters = OpParameter<int>(state->InputAt(0));
+ int locals = OpParameter<int>(state->InputAt(1));
+ int stack = OpParameter<int>(state->InputAt(2));
+
+ FrameStateDescriptor* outer_state = NULL;
+ Node* outer_node = state->InputAt(4);
+ if (outer_node->opcode() == IrOpcode::kFrameState) {
+ outer_state = GetFrameStateDescriptor(outer_node);
+ }
+
+ return new (instruction_zone())
+ FrameStateDescriptor(state_info, parameters, locals, stack, outer_state);
+}
+
+
static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) {
switch (input->opcode()) {
case IrOpcode::kInt32Constant:
@@ -961,48 +1017,46 @@ static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) {
case IrOpcode::kHeapConstant:
return g->UseImmediate(input);
default:
- return g->Use(input);
+ return g->UseUnique(input);
}
}
-void InstructionSelector::VisitDeoptimize(Node* deopt) {
- DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize);
- Node* state = deopt->InputAt(0);
- DCHECK(state->op()->opcode() == IrOpcode::kFrameState);
- BailoutId ast_id = OpParameter<BailoutId>(state);
+void InstructionSelector::AddFrameStateInputs(
+ Node* state, InstructionOperandVector* inputs,
+ FrameStateDescriptor* descriptor) {
+ DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
- // Add the inputs.
- Node* parameters = state->InputAt(0);
- int parameters_count = OpParameter<int>(parameters);
+ if (descriptor->outer_state() != NULL) {
+ AddFrameStateInputs(state->InputAt(4), inputs, descriptor->outer_state());
+ }
+ Node* parameters = state->InputAt(0);
Node* locals = state->InputAt(1);
- int locals_count = OpParameter<int>(locals);
-
Node* stack = state->InputAt(2);
- int stack_count = OpParameter<int>(stack);
+ Node* context = state->InputAt(3);
+
+ DCHECK_EQ(IrOpcode::kStateValues, parameters->op()->opcode());
+ DCHECK_EQ(IrOpcode::kStateValues, locals->op()->opcode());
+ DCHECK_EQ(IrOpcode::kStateValues, stack->op()->opcode());
+
+ DCHECK_EQ(descriptor->parameters_count(), parameters->InputCount());
+ DCHECK_EQ(descriptor->locals_count(), locals->InputCount());
+ DCHECK_EQ(descriptor->stack_count(), stack->InputCount());
OperandGenerator g(this);
- std::vector<InstructionOperand*> inputs;
- inputs.reserve(parameters_count + locals_count + stack_count);
- for (int i = 0; i < parameters_count; i++) {
- inputs.push_back(UseOrImmediate(&g, parameters->InputAt(i)));
+ for (int i = 0; i < static_cast<int>(descriptor->parameters_count()); i++) {
+ inputs->push_back(UseOrImmediate(&g, parameters->InputAt(i)));
}
- for (int i = 0; i < locals_count; i++) {
- inputs.push_back(UseOrImmediate(&g, locals->InputAt(i)));
+ if (descriptor->HasContext()) {
+ inputs->push_back(UseOrImmediate(&g, context));
}
- for (int i = 0; i < stack_count; i++) {
- inputs.push_back(UseOrImmediate(&g, stack->InputAt(i)));
+ for (int i = 0; i < static_cast<int>(descriptor->locals_count()); i++) {
+ inputs->push_back(UseOrImmediate(&g, locals->InputAt(i)));
+ }
+ for (int i = 0; i < static_cast<int>(descriptor->stack_count()); i++) {
+ inputs->push_back(UseOrImmediate(&g, stack->InputAt(i)));
}
-
- FrameStateDescriptor* descriptor = new (instruction_zone())
- FrameStateDescriptor(ast_id, parameters_count, locals_count, stack_count);
-
- DCHECK_EQ(descriptor->size(), inputs.size());
-
- int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor);
- Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), 0, NULL,
- inputs.size(), &inputs.front(), 0, NULL);
}