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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/instruction-selector.h" 5 #include "src/compiler/instruction-selector.h"
6 6
7 #include "src/compiler/instruction-selector-impl.h" 7 #include "src/compiler/instruction-selector-impl.h"
8 #include "src/compiler/node-matchers.h" 8 #include "src/compiler/node-matchers.h"
9 #include "src/compiler/node-properties-inl.h" 9 #include "src/compiler/node-properties-inl.h"
10 #include "src/compiler/pipeline.h" 10 #include "src/compiler/pipeline.h"
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 244
245 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) { 245 void InstructionSelector::MarkAsRepresentation(MachineType rep, Node* node) {
246 DCHECK_NOT_NULL(node); 246 DCHECK_NOT_NULL(node);
247 if (RepresentationOf(rep) == kRepFloat64) MarkAsDouble(node); 247 if (RepresentationOf(rep) == kRepFloat64) MarkAsDouble(node);
248 if (RepresentationOf(rep) == kRepTagged) MarkAsReference(node); 248 if (RepresentationOf(rep) == kRepTagged) MarkAsReference(node);
249 } 249 }
250 250
251 251
252 // TODO(bmeurer): Get rid of the CallBuffer business and make 252 // TODO(bmeurer): Get rid of the CallBuffer business and make
253 // InstructionSelector::VisitCall platform independent instead. 253 // InstructionSelector::VisitCall platform independent instead.
254 CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d) 254 CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d,
255 : output_count(0), 255 FrameStateDescriptor* frame_desc)
256 descriptor(d), 256 : descriptor(d),
257 output_nodes(zone->NewArray<Node*>(d->ReturnCount())), 257 frame_state_descriptor(frame_desc),
258 outputs(zone->NewArray<InstructionOperand*>(d->ReturnCount())), 258 output_nodes(NodeVector::allocator_type(zone)),
259 fixed_and_control_args( 259 outputs(InstructionOperandVector::allocator_type(zone)),
260 zone->NewArray<InstructionOperand*>(input_count() + control_count())), 260 instruction_args(InstructionOperandVector::allocator_type(zone)),
261 fixed_count(0), 261 pushed_nodes(NodeVector::allocator_type(zone)) {
262 pushed_nodes(zone->NewArray<Node*>(input_count())), 262 output_nodes.reserve(d->ReturnCount());
263 pushed_count(0) { 263 outputs.reserve(d->ReturnCount());
264 if (d->ReturnCount() > 1) { 264 pushed_nodes.reserve(input_count());
265 memset(output_nodes, 0, sizeof(Node*) * d->ReturnCount()); // NOLINT 265 instruction_args.reserve(input_count() + control_count() +
266 } 266 frame_state_value_count());
267 memset(pushed_nodes, 0, sizeof(Node*) * input_count()); // NOLINT
268 } 267 }
269 268
270 269
271 // TODO(bmeurer): Get rid of the CallBuffer business and make 270 // TODO(bmeurer): Get rid of the CallBuffer business and make
272 // InstructionSelector::VisitCall platform independent instead. 271 // InstructionSelector::VisitCall platform independent instead.
273 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, 272 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
274 bool call_code_immediate, 273 bool call_code_immediate,
275 bool call_address_immediate, 274 bool call_address_immediate,
276 BasicBlock* cont_node, 275 BasicBlock* cont_node,
277 BasicBlock* deopt_node) { 276 BasicBlock* deopt_node) {
278 OperandGenerator g(this); 277 OperandGenerator g(this);
279 DCHECK_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount()); 278 DCHECK_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount());
280 DCHECK_EQ(OperatorProperties::GetValueInputCount(call->op()), 279 DCHECK_EQ(OperatorProperties::GetValueInputCount(call->op()),
281 buffer->input_count()); 280 buffer->input_count() + buffer->frame_state_count());
282 281
283 if (buffer->descriptor->ReturnCount() > 0) { 282 if (buffer->descriptor->ReturnCount() > 0) {
284 // Collect the projections that represent multiple outputs from this call. 283 // Collect the projections that represent multiple outputs from this call.
285 if (buffer->descriptor->ReturnCount() == 1) { 284 if (buffer->descriptor->ReturnCount() == 1) {
286 buffer->output_nodes[0] = call; 285 buffer->output_nodes.push_back(call);
287 } else { 286 } else {
288 call->CollectProjections(buffer->descriptor->ReturnCount(), 287 call->CollectProjections(&buffer->output_nodes);
289 buffer->output_nodes); 288 DCHECK(buffer->output_nodes.size() <=
289 static_cast<size_t>(buffer->descriptor->ReturnCount()));
290 } 290 }
291 291
292 // Filter out the outputs that aren't live because no projection uses them. 292 // Filter out the outputs that aren't live because no projection uses them.
293 for (int i = 0; i < buffer->descriptor->ReturnCount(); i++) { 293 for (size_t i = 0; i < buffer->output_nodes.size(); i++) {
294 if (buffer->output_nodes[i] != NULL) { 294 if (buffer->output_nodes[i] != NULL) {
295 Node* output = buffer->output_nodes[i]; 295 Node* output = buffer->output_nodes[i];
296 LinkageLocation location = buffer->descriptor->GetReturnLocation(i); 296 LinkageLocation location =
297 buffer->descriptor->GetReturnLocation(static_cast<int>(i));
297 MarkAsRepresentation(location.representation(), output); 298 MarkAsRepresentation(location.representation(), output);
298 buffer->outputs[buffer->output_count++] = 299 buffer->outputs.push_back(g.DefineAsLocation(output, location));
299 g.DefineAsLocation(output, location);
300 } 300 }
301 } 301 }
302 } 302 }
303 303
304 buffer->fixed_count = 1; // First argument is always the callee. 304 // The first argument is always the callee code.
305 Node* callee = call->InputAt(0); 305 Node* callee = call->InputAt(0);
306 switch (buffer->descriptor->kind()) { 306 switch (buffer->descriptor->kind()) {
307 case CallDescriptor::kCallCodeObject: 307 case CallDescriptor::kCallCodeObject:
308 buffer->fixed_and_control_args[0] = 308 buffer->instruction_args.push_back(
309 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant) 309 (call_code_immediate && callee->opcode() == IrOpcode::kHeapConstant)
310 ? g.UseImmediate(callee) 310 ? g.UseImmediate(callee)
311 : g.UseRegister(callee); 311 : g.UseRegister(callee));
312 break; 312 break;
313 case CallDescriptor::kCallAddress: 313 case CallDescriptor::kCallAddress:
314 buffer->fixed_and_control_args[0] = 314 buffer->instruction_args.push_back(
315 (call_address_immediate && 315 (call_address_immediate &&
316 (callee->opcode() == IrOpcode::kInt32Constant || 316 (callee->opcode() == IrOpcode::kInt32Constant ||
317 callee->opcode() == IrOpcode::kInt64Constant)) 317 callee->opcode() == IrOpcode::kInt64Constant))
318 ? g.UseImmediate(callee) 318 ? g.UseImmediate(callee)
319 : g.UseRegister(callee); 319 : g.UseRegister(callee));
320 break; 320 break;
321 case CallDescriptor::kCallJSFunction: 321 case CallDescriptor::kCallJSFunction:
322 buffer->fixed_and_control_args[0] = 322 buffer->instruction_args.push_back(
323 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0)); 323 g.UseLocation(callee, buffer->descriptor->GetInputLocation(0)));
324 break; 324 break;
325 } 325 }
326 DCHECK_EQ(1, buffer->instruction_args.size());
327
328 // If the call needs a frame state, we insert the state information as
329 // follows (n is the number of value inputs to the frame state):
330 // arg 1 : deoptimization id.
331 // arg 2 - arg (n + 1) : value inputs to the frame state.
332 if (buffer->frame_state_descriptor != NULL) {
333 int deoptimization_id =
334 sequence()->AddDeoptimizationEntry(buffer->frame_state_descriptor);
335 buffer->instruction_args.push_back(g.TempImmediate(deoptimization_id));
336
337 Node* frame_state = call->InputAt(buffer->descriptor->InputCount());
338 AddFrameStateInputs(frame_state, &buffer->instruction_args,
339 buffer->frame_state_descriptor);
340 }
341 DCHECK_EQ(1 + buffer->frame_state_value_count(),
342 buffer->instruction_args.size());
326 343
327 int input_count = buffer->input_count(); 344 int input_count = buffer->input_count();
328 345
329 // Split the arguments into pushed_nodes and fixed_args. Pushed arguments 346 // Split the arguments into pushed_nodes and instruction_args. Pushed
330 // require an explicit push instruction before the call and do not appear 347 // arguments require an explicit push instruction before the call and do
331 // as arguments to the call. Everything else ends up as an InstructionOperand 348 // not appear as arguments to the call. Everything else ends up
332 // argument to the call. 349 // as an InstructionOperand argument to the call.
333 InputIter iter(call->inputs().begin()); 350 InputIter iter(call->inputs().begin());
351 int pushed_count = 0;
334 for (int index = 0; index < input_count; ++iter, ++index) { 352 for (int index = 0; index < input_count; ++iter, ++index) {
335 DCHECK(iter != call->inputs().end()); 353 DCHECK(iter != call->inputs().end());
336 DCHECK(index == iter.index()); 354 DCHECK(index == iter.index());
355 DCHECK((*iter)->op()->opcode() != IrOpcode::kFrameState);
337 if (index == 0) continue; // The first argument (callee) is already done. 356 if (index == 0) continue; // The first argument (callee) is already done.
338 InstructionOperand* op = 357 InstructionOperand* op =
339 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index)); 358 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index));
340 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { 359 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) {
341 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; 360 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1;
342 DCHECK(buffer->pushed_nodes[stack_index] == NULL); 361 if (static_cast<size_t>(stack_index) >= buffer->pushed_nodes.size()) {
362 buffer->pushed_nodes.resize(stack_index + 1, NULL);
363 }
364 DCHECK_EQ(NULL, buffer->pushed_nodes[stack_index]);
343 buffer->pushed_nodes[stack_index] = *iter; 365 buffer->pushed_nodes[stack_index] = *iter;
344 buffer->pushed_count++; 366 pushed_count++;
345 } else { 367 } else {
346 buffer->fixed_and_control_args[buffer->fixed_count] = op; 368 buffer->instruction_args.push_back(op);
347 buffer->fixed_count++;
348 } 369 }
349 } 370 }
371 CHECK_EQ(pushed_count, static_cast<int>(buffer->pushed_nodes.size()));
350 372
351 // If the call can deoptimize, we add the continuation and deoptimization 373 // If the call can deoptimize, we add the continuation and deoptimization
352 // block labels. 374 // block labels.
353 if (buffer->descriptor->CanLazilyDeoptimize()) { 375 if (buffer->descriptor->CanLazilyDeoptimize()) {
354 DCHECK(cont_node != NULL); 376 DCHECK(cont_node != NULL);
355 DCHECK(deopt_node != NULL); 377 DCHECK(deopt_node != NULL);
356 buffer->fixed_and_control_args[buffer->fixed_count] = g.Label(cont_node); 378 buffer->instruction_args.push_back(g.Label(cont_node));
357 buffer->fixed_and_control_args[buffer->fixed_count + 1] = 379 buffer->instruction_args.push_back(g.Label(deopt_node));
358 g.Label(deopt_node);
359 } else { 380 } else {
360 DCHECK(cont_node == NULL); 381 DCHECK(cont_node == NULL);
361 DCHECK(deopt_node == NULL); 382 DCHECK(deopt_node == NULL);
362 } 383 }
363 384
364 DCHECK(input_count == (buffer->fixed_count + buffer->pushed_count)); 385 DCHECK(input_count ==
386 (buffer->instruction_args.size() - buffer->control_count() +
387 buffer->pushed_nodes.size() - buffer->frame_state_value_count()));
365 } 388 }
366 389
367 390
368 void InstructionSelector::VisitBlock(BasicBlock* block) { 391 void InstructionSelector::VisitBlock(BasicBlock* block) {
369 DCHECK_EQ(NULL, current_block_); 392 DCHECK_EQ(NULL, current_block_);
370 current_block_ = block; 393 current_block_ = block;
371 int current_block_end = static_cast<int>(instructions_.size()); 394 int current_block_end = static_cast<int>(instructions_.size());
372 395
373 // Generate code for the block control "top down", but schedule the code 396 // Generate code for the block control "top down", but schedule the code
374 // "bottom up". 397 // "bottom up".
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 Emit(kArchRet, NULL); 1010 Emit(kArchRet, NULL);
988 } 1011 }
989 } 1012 }
990 1013
991 1014
992 void InstructionSelector::VisitThrow(Node* value) { 1015 void InstructionSelector::VisitThrow(Node* value) {
993 UNIMPLEMENTED(); // TODO(titzer) 1016 UNIMPLEMENTED(); // TODO(titzer)
994 } 1017 }
995 1018
996 1019
1020 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
1021 Node* state) {
1022 DCHECK(state->op()->opcode() == IrOpcode::kFrameState);
1023 BailoutId ast_id = OpParameter<BailoutId>(state);
1024 Node* parameters = state->InputAt(0);
1025 Node* locals = state->InputAt(1);
1026 Node* stack = state->InputAt(2);
1027
1028 return new (instruction_zone())
1029 FrameStateDescriptor(ast_id, OpParameter<int>(parameters),
1030 OpParameter<int>(locals), OpParameter<int>(stack));
1031 }
1032
1033
997 static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) { 1034 static InstructionOperand* UseOrImmediate(OperandGenerator* g, Node* input) {
998 switch (input->opcode()) { 1035 switch (input->opcode()) {
999 case IrOpcode::kInt32Constant: 1036 case IrOpcode::kInt32Constant:
1000 case IrOpcode::kNumberConstant: 1037 case IrOpcode::kNumberConstant:
1001 case IrOpcode::kFloat64Constant: 1038 case IrOpcode::kFloat64Constant:
1002 case IrOpcode::kHeapConstant: 1039 case IrOpcode::kHeapConstant:
1003 return g->UseImmediate(input); 1040 return g->UseImmediate(input);
1004 default: 1041 default:
1005 return g->Use(input); 1042 return g->Use(input);
1006 } 1043 }
1007 } 1044 }
1008 1045
1009 1046
1047 void InstructionSelector::AddFrameStateInputs(
1048 Node* state, InstructionOperandVector* inputs,
1049 FrameStateDescriptor* descriptor) {
1050 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
1051
1052 Node* parameters = state->InputAt(0);
1053 Node* locals = state->InputAt(1);
1054 Node* stack = state->InputAt(2);
1055
1056 DCHECK_EQ(descriptor->parameters_count(), parameters->InputCount());
1057 DCHECK_EQ(descriptor->locals_count(), locals->InputCount());
1058 DCHECK_EQ(descriptor->stack_count(), stack->InputCount());
1059
1060 OperandGenerator g(this);
1061 for (int i = 0; i < descriptor->parameters_count(); i++) {
1062 inputs->push_back(UseOrImmediate(&g, parameters->InputAt(i)));
1063 }
1064 for (int i = 0; i < descriptor->locals_count(); i++) {
1065 inputs->push_back(UseOrImmediate(&g, locals->InputAt(i)));
1066 }
1067 for (int i = 0; i < descriptor->stack_count(); i++) {
1068 inputs->push_back(UseOrImmediate(&g, stack->InputAt(i)));
1069 }
1070 }
1071
1072
1010 void InstructionSelector::VisitDeoptimize(Node* deopt) { 1073 void InstructionSelector::VisitDeoptimize(Node* deopt) {
1011 DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize); 1074 DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize);
1012 Node* state = deopt->InputAt(0); 1075 Node* state = deopt->InputAt(0);
1013 DCHECK(state->op()->opcode() == IrOpcode::kFrameState); 1076 FrameStateDescriptor* descriptor = GetFrameStateDescriptor(state);
1014 BailoutId ast_id = OpParameter<BailoutId>(state);
1015 1077
1016 // Add the inputs. 1078 InstructionOperandVector inputs(
1017 Node* parameters = state->InputAt(0); 1079 (InstructionOperandVector::allocator_type(zone())));
1018 int parameters_count = OpParameter<int>(parameters); 1080 inputs.reserve(descriptor->size());
1019 1081
1020 Node* locals = state->InputAt(1); 1082 AddFrameStateInputs(state, &inputs, descriptor);
1021 int locals_count = OpParameter<int>(locals);
1022
1023 Node* stack = state->InputAt(2);
1024 int stack_count = OpParameter<int>(stack);
1025
1026 OperandGenerator g(this);
1027 std::vector<InstructionOperand*> inputs;
1028 inputs.reserve(parameters_count + locals_count + stack_count);
1029 for (int i = 0; i < parameters_count; i++) {
1030 inputs.push_back(UseOrImmediate(&g, parameters->InputAt(i)));
1031 }
1032 for (int i = 0; i < locals_count; i++) {
1033 inputs.push_back(UseOrImmediate(&g, locals->InputAt(i)));
1034 }
1035 for (int i = 0; i < stack_count; i++) {
1036 inputs.push_back(UseOrImmediate(&g, stack->InputAt(i)));
1037 }
1038
1039 FrameStateDescriptor* descriptor = new (instruction_zone())
1040 FrameStateDescriptor(ast_id, parameters_count, locals_count, stack_count);
1041 1083
1042 DCHECK_EQ(descriptor->size(), inputs.size()); 1084 DCHECK_EQ(descriptor->size(), inputs.size());
1043 1085
1044 int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor); 1086 int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor);
1045 Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), 0, NULL, 1087 Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), 0, NULL,
1046 inputs.size(), &inputs.front(), 0, NULL); 1088 inputs.size(), &inputs.front(), 0, NULL);
1047 } 1089 }
1048 1090
1049 1091
1050 #if !V8_TURBOFAN_BACKEND 1092 #if !V8_TURBOFAN_BACKEND
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 1127
1086 1128
1087 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, 1129 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation,
1088 BasicBlock* deoptimization) {} 1130 BasicBlock* deoptimization) {}
1089 1131
1090 #endif // !V8_TURBOFAN_BACKEND 1132 #endif // !V8_TURBOFAN_BACKEND
1091 1133
1092 } // namespace compiler 1134 } // namespace compiler
1093 } // namespace internal 1135 } // namespace internal
1094 } // namespace v8 1136 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698