Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(664)

Unified Diff: src/compiler/instruction-selector.cc

Issue 492203002: Initial support for debugger frame state in Turbofan. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Another attempt to fix Win64 Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/compiler/instruction-selector.cc
diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc
index 78bcc96cc67177e778eb19c7eae9b624e6a40887..587afd72453e068ce165942682a21740fbc4d64c 100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -251,20 +251,19 @@ void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) {
// 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(NodeVector::allocator_type(zone)),
+ outputs(InstructionOperandVector::allocator_type(zone)),
+ instruction_args(InstructionOperandVector::allocator_type(zone)),
+ pushed_nodes(NodeVector::allocator_type(zone)) {
+ output_nodes.reserve(d->ReturnCount());
+ outputs.reserve(d->ReturnCount());
+ pushed_nodes.reserve(input_count());
+ instruction_args.reserve(input_count() + control_count() +
+ frame_state_value_count());
}
@@ -278,90 +277,114 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
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);
+ call->CollectProjections(&buffer->output_nodes);
+ DCHECK(buffer->output_nodes.size() <=
+ static_cast<size_t>(buffer->descriptor->ReturnCount()));
}
// 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);
+ LinkageLocation location =
+ buffer->descriptor->GetReturnLocation(static_cast<int>(i));
MarkAsRepresentation(location.representation(), output);
- buffer->outputs[buffer->output_count++] =
- g.DefineAsLocation(output, location);
+ buffer->outputs.push_back(g.DefineAsLocation(output, location));
}
}
}
- 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)));
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) {
+ int deoptimization_id =
+ sequence()->AddDeoptimizationEntry(buffer->frame_state_descriptor);
+ buffer->instruction_args.push_back(g.TempImmediate(deoptimization_id));
+
+ Node* frame_state = call->InputAt(buffer->descriptor->InputCount());
+ AddFrameStateInputs(frame_state, &buffer->instruction_args,
+ buffer->frame_state_descriptor);
+ }
+ DCHECK_EQ(1 + buffer->frame_state_value_count(),
+ buffer->instruction_args.size());
int input_count = 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());
+ int pushed_count = 0;
for (int index = 0; index < input_count; ++iter, ++index) {
DCHECK(iter != call->inputs().end());
DCHECK(index == 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));
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);
}
}
+ CHECK_EQ(pushed_count, static_cast<int>(buffer->pushed_nodes.size()));
// 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);
+ buffer->instruction_args.push_back(g.Label(cont_node));
+ buffer->instruction_args.push_back(g.Label(deopt_node));
} else {
DCHECK(cont_node == NULL);
DCHECK(deopt_node == NULL);
}
- DCHECK(input_count == (buffer->fixed_count + buffer->pushed_count));
+ DCHECK(input_count ==
+ (buffer->instruction_args.size() - buffer->control_count() +
+ buffer->pushed_nodes.size() - buffer->frame_state_value_count()));
}
@@ -994,6 +1017,20 @@ void InstructionSelector::VisitThrow(Node* value) {
}
+FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
+ Node* state) {
+ DCHECK(state->op()->opcode() == IrOpcode::kFrameState);
+ BailoutId ast_id = OpParameter<BailoutId>(state);
+ Node* parameters = state->InputAt(0);
+ Node* locals = state->InputAt(1);
+ Node* stack = state->InputAt(2);
+
+ return new (instruction_zone())
+ FrameStateDescriptor(ast_id, OpParameter<int>(parameters),
+ OpParameter<int>(locals), OpParameter<int>(stack));
+}
+
+
static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) {
switch (input->opcode()) {
case IrOpcode::kInt32Constant:
@@ -1007,37 +1044,42 @@ static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* 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);
-
Node* locals = state->InputAt(1);
- int locals_count = OpParameter<int>(locals);
-
Node* stack = state->InputAt(2);
- int stack_count = OpParameter<int>(stack);
+
+ 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 < 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)));
+ for (int i = 0; i < descriptor->locals_count(); i++) {
+ inputs->push_back(UseOrImmediate(&g, locals->InputAt(i)));
}
- for (int i = 0; i < stack_count; i++) {
- inputs.push_back(UseOrImmediate(&g, stack->InputAt(i)));
+ for (int i = 0; i < descriptor->stack_count(); i++) {
+ inputs->push_back(UseOrImmediate(&g, stack->InputAt(i)));
}
+}
+
+
+void InstructionSelector::VisitDeoptimize(Node* deopt) {
+ DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize);
+ Node* state = deopt->InputAt(0);
+ FrameStateDescriptor* descriptor = GetFrameStateDescriptor(state);
+
+ InstructionOperandVector inputs(
+ (InstructionOperandVector::allocator_type(zone())));
+ inputs.reserve(descriptor->size());
- FrameStateDescriptor* descriptor = new (instruction_zone())
- FrameStateDescriptor(ast_id, parameters_count, locals_count, stack_count);
+ AddFrameStateInputs(state, &inputs, descriptor);
DCHECK_EQ(descriptor->size(), inputs.size());

Powered by Google App Engine
This is Rietveld 408576698