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

Side by Side Diff: src/compiler/instruction-selector.cc

Issue 1485183002: [turbofan] Deopt support for escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@ea-local
Patch Set: Fix --always-opt triggered bug Created 5 years 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
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 <limits> 7 #include <limits>
8 8
9 #include "src/base/adapters.h" 9 #include "src/base/adapters.h"
10 #include "src/compiler/instruction-selector-impl.h" 10 #include "src/compiler/instruction-selector-impl.h"
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 rep = RepresentationOf(rep); 252 rep = RepresentationOf(rep);
253 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node)); 253 sequence()->MarkAsRepresentation(rep, GetVirtualRegister(node));
254 } 254 }
255 255
256 256
257 namespace { 257 namespace {
258 258
259 enum class FrameStateInputKind { kAny, kStackSlot }; 259 enum class FrameStateInputKind { kAny, kStackSlot };
260 260
261 261
262 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* input, 262 InstructionOperand OperandForDeopt(OperandGenerator* g, Node* node,
263 FrameStateInputKind kind) { 263 FrameStateInputKind kind) {
264 switch (input->opcode()) { 264 switch (node->opcode()) {
265 case IrOpcode::kInt32Constant: 265 case IrOpcode::kInt32Constant:
266 case IrOpcode::kNumberConstant: 266 case IrOpcode::kNumberConstant:
267 case IrOpcode::kFloat32Constant: 267 case IrOpcode::kFloat32Constant:
268 case IrOpcode::kFloat64Constant: 268 case IrOpcode::kFloat64Constant:
269 case IrOpcode::kHeapConstant: 269 case IrOpcode::kHeapConstant:
270 return g->UseImmediate(input); 270 return g->UseImmediate(node);
271 default: 271 default:
272 switch (kind) { 272 switch (kind) {
273 case FrameStateInputKind::kStackSlot: 273 case FrameStateInputKind::kStackSlot:
274 return g->UseUniqueSlot(input); 274 return g->UseUniqueSlot(node);
275 case FrameStateInputKind::kAny: 275 case FrameStateInputKind::kAny:
276 return g->UseAny(input); 276 return g->UseAny(node);
277 } 277 }
278 UNREACHABLE(); 278 }
279 return InstructionOperand(); 279 UNREACHABLE();
280 return InstructionOperand();
281 }
282
283
284 class StateObjectCache {
285 public:
286 explicit StateObjectCache(Zone* zone) : objects_(zone) {}
287 static const size_t kNotCached = SIZE_MAX;
288
289 size_t GetObjectId(Node* node) {
290 for (size_t i = 0; i < objects_.size(); ++i) {
291 if (objects_[i] == node) {
292 return i;
293 }
294 }
295 return kNotCached;
296 }
297
298 size_t InsertObject(Node* node) {
299 size_t id = objects_.size();
300 objects_.push_back(node);
301 return id;
302 }
303
304 private:
305 ZoneVector<Node*> objects_;
306 };
307
308
309 // Returns the number of instruction operands added to inputs.
310 size_t AddOperandToStateValueDescriptor(StateValueDescriptor* desc,
311 InstructionOperandVector* inputs,
312 OperandGenerator* g,
313 StateObjectCache* cache, Node* input,
314 MachineType type,
315 FrameStateInputKind kind, Zone* zone) {
316 switch (input->opcode()) {
317 case IrOpcode::kObjectState: {
318 size_t id = cache->GetObjectId(input);
319 if (id == StateObjectCache::kNotCached) {
320 size_t entries = 0;
321 id = cache->InsertObject(input);
322 desc->fields().push_back(StateValueDescriptor::Recursive(zone, id));
323 StateValueDescriptor* new_desc = &desc->fields().back();
324 for (Edge edge : input->input_edges()) {
325 entries += AddOperandToStateValueDescriptor(
326 new_desc, inputs, g, cache, edge.to(), kMachAnyTagged, kind,
327 zone);
328 }
329 return entries;
330 } else {
331 desc->fields().push_back(StateValueDescriptor::Duplicate(zone, id));
332 return 0;
333 }
334 break;
335 }
336 default:
337 inputs->push_back(OperandForDeopt(g, input, kind));
338 desc->fields().push_back(StateValueDescriptor::Plain(zone, type));
339 return 1;
280 } 340 }
281 } 341 }
282 342
283 343
284 void AddFrameStateInputs(Node* state, OperandGenerator* g, 344 // Returns the number of instruction operands added to inputs.
285 InstructionOperandVector* inputs, 345 size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* desc, Node* state,
286 FrameStateDescriptor* descriptor, 346 OperandGenerator* g,
287 FrameStateInputKind kind, Zone* zone) { 347 StateObjectCache* cache,
348 InstructionOperandVector* inputs,
349 FrameStateInputKind kind, Zone* zone) {
288 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); 350 DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
289 351
290 if (descriptor->outer_state()) { 352 size_t entries = 0;
291 AddFrameStateInputs(state->InputAt(kFrameStateOuterStateInput), g, inputs, 353 size_t initial_size = inputs->size();
292 descriptor->outer_state(), kind, zone); 354 USE(initial_size); // initial_size is only used for debug.
355
356 if (desc->outer_state()) {
357 entries += AddInputsToFrameStateDescriptor(
358 desc->outer_state(), state->InputAt(kFrameStateOuterStateInput), g,
359 cache, inputs, kind, zone);
293 } 360 }
294 361
295 Node* parameters = state->InputAt(kFrameStateParametersInput); 362 Node* parameters = state->InputAt(kFrameStateParametersInput);
296 Node* locals = state->InputAt(kFrameStateLocalsInput); 363 Node* locals = state->InputAt(kFrameStateLocalsInput);
297 Node* stack = state->InputAt(kFrameStateStackInput); 364 Node* stack = state->InputAt(kFrameStateStackInput);
298 Node* context = state->InputAt(kFrameStateContextInput); 365 Node* context = state->InputAt(kFrameStateContextInput);
299 Node* function = state->InputAt(kFrameStateFunctionInput); 366 Node* function = state->InputAt(kFrameStateFunctionInput);
300 367
301 DCHECK_EQ(descriptor->parameters_count(), 368 DCHECK_EQ(desc->parameters_count(), StateValuesAccess(parameters).size());
302 StateValuesAccess(parameters).size()); 369 DCHECK_EQ(desc->locals_count(), StateValuesAccess(locals).size());
303 DCHECK_EQ(descriptor->locals_count(), StateValuesAccess(locals).size()); 370 DCHECK_EQ(desc->stack_count(), StateValuesAccess(stack).size());
304 DCHECK_EQ(descriptor->stack_count(), StateValuesAccess(stack).size());
305 371
306 ZoneVector<MachineType> types(zone); 372 StateValueDescriptor* values_desc = desc->GetStateValueDescriptor();
307 types.reserve(descriptor->GetSize()); 373 entries += AddOperandToStateValueDescriptor(
308 374 values_desc, inputs, g, cache, function, kMachAnyTagged, kind, zone);
309 size_t value_index = 0;
310 inputs->push_back(OperandForDeopt(g, function, kind));
311 descriptor->SetType(value_index++, kMachAnyTagged);
312 for (StateValuesAccess::TypedNode input_node : 375 for (StateValuesAccess::TypedNode input_node :
313 StateValuesAccess(parameters)) { 376 StateValuesAccess(parameters)) {
314 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); 377 entries += AddOperandToStateValueDescriptor(values_desc, inputs, g, cache,
315 descriptor->SetType(value_index++, input_node.type); 378 input_node.node,
379 input_node.type, kind, zone);
316 } 380 }
317 if (descriptor->HasContext()) { 381 if (desc->HasContext()) {
318 inputs->push_back(OperandForDeopt(g, context, kind)); 382 entries += AddOperandToStateValueDescriptor(
319 descriptor->SetType(value_index++, kMachAnyTagged); 383 values_desc, inputs, g, cache, context, kMachAnyTagged, kind, zone);
320 } 384 }
321 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) { 385 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(locals)) {
322 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); 386 entries += AddOperandToStateValueDescriptor(values_desc, inputs, g, cache,
323 descriptor->SetType(value_index++, input_node.type); 387 input_node.node,
388 input_node.type, kind, zone);
324 } 389 }
325 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) { 390 for (StateValuesAccess::TypedNode input_node : StateValuesAccess(stack)) {
326 inputs->push_back(OperandForDeopt(g, input_node.node, kind)); 391 entries += AddOperandToStateValueDescriptor(values_desc, inputs, g, cache,
327 descriptor->SetType(value_index++, input_node.type); 392 input_node.node,
393 input_node.type, kind, zone);
328 } 394 }
329 DCHECK(value_index == descriptor->GetSize()); 395 DCHECK_EQ(initial_size + entries, inputs->size());
396 return entries;
330 } 397 }
331 398
332 } // namespace 399 } // namespace
333 400
334 401
335 // An internal helper class for generating the operands to calls. 402 // An internal helper class for generating the operands to calls.
336 // TODO(bmeurer): Get rid of the CallBuffer business and make 403 // TODO(bmeurer): Get rid of the CallBuffer business and make
337 // InstructionSelector::VisitCall platform independent instead. 404 // InstructionSelector::VisitCall platform independent instead.
338 struct CallBuffer { 405 struct CallBuffer {
339 CallBuffer(Zone* zone, const CallDescriptor* descriptor, 406 CallBuffer(Zone* zone, const CallDescriptor* descriptor,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 // The target is ignored, but we still need to pass a value here. 518 // The target is ignored, but we still need to pass a value here.
452 buffer->instruction_args.push_back(g.UseImmediate(callee)); 519 buffer->instruction_args.push_back(g.UseImmediate(callee));
453 break; 520 break;
454 } 521 }
455 DCHECK_EQ(1u, buffer->instruction_args.size()); 522 DCHECK_EQ(1u, buffer->instruction_args.size());
456 523
457 // If the call needs a frame state, we insert the state information as 524 // If the call needs a frame state, we insert the state information as
458 // follows (n is the number of value inputs to the frame state): 525 // follows (n is the number of value inputs to the frame state):
459 // arg 1 : deoptimization id. 526 // arg 1 : deoptimization id.
460 // arg 2 - arg (n + 1) : value inputs to the frame state. 527 // arg 2 - arg (n + 1) : value inputs to the frame state.
528 size_t frame_state_entries = 0;
529 USE(frame_state_entries); // frame_state_entries is only used for debug.
461 if (buffer->frame_state_descriptor != NULL) { 530 if (buffer->frame_state_descriptor != NULL) {
462 InstructionSequence::StateId state_id = 531 InstructionSequence::StateId state_id =
463 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor); 532 sequence()->AddFrameStateDescriptor(buffer->frame_state_descriptor);
464 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt())); 533 buffer->instruction_args.push_back(g.TempImmediate(state_id.ToInt()));
465 534
466 Node* frame_state = 535 Node* frame_state =
467 call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); 536 call->InputAt(static_cast<int>(buffer->descriptor->InputCount()));
468 AddFrameStateInputs(frame_state, &g, &buffer->instruction_args, 537
469 buffer->frame_state_descriptor, 538 StateObjectCache cache(instruction_zone());
470 FrameStateInputKind::kStackSlot, instruction_zone()); 539
540 frame_state_entries =
541 1 + AddInputsToFrameStateDescriptor(
542 buffer->frame_state_descriptor, frame_state, &g, &cache,
543 &buffer->instruction_args, FrameStateInputKind::kStackSlot,
544 instruction_zone());
545
546 DCHECK_EQ(1 + frame_state_entries, buffer->instruction_args.size());
471 } 547 }
472 DCHECK(1 + buffer->frame_state_value_count() ==
473 buffer->instruction_args.size());
474 548
475 size_t input_count = static_cast<size_t>(buffer->input_count()); 549 size_t input_count = static_cast<size_t>(buffer->input_count());
476 550
477 // Split the arguments into pushed_nodes and instruction_args. Pushed 551 // Split the arguments into pushed_nodes and instruction_args. Pushed
478 // arguments require an explicit push instruction before the call and do 552 // arguments require an explicit push instruction before the call and do
479 // not appear as arguments to the call. Everything else ends up 553 // not appear as arguments to the call. Everything else ends up
480 // as an InstructionOperand argument to the call. 554 // as an InstructionOperand argument to the call.
481 auto iter(call->inputs().begin()); 555 auto iter(call->inputs().begin());
482 size_t pushed_count = 0; 556 size_t pushed_count = 0;
483 bool call_tail = (flags & kCallTail) != 0; 557 bool call_tail = (flags & kCallTail) != 0;
(...skipping 15 matching lines...) Expand all
499 buffer->pushed_nodes.resize(stack_index + 1, NULL); 573 buffer->pushed_nodes.resize(stack_index + 1, NULL);
500 } 574 }
501 DCHECK(!buffer->pushed_nodes[stack_index]); 575 DCHECK(!buffer->pushed_nodes[stack_index]);
502 buffer->pushed_nodes[stack_index] = *iter; 576 buffer->pushed_nodes[stack_index] = *iter;
503 pushed_count++; 577 pushed_count++;
504 } else { 578 } else {
505 buffer->instruction_args.push_back(op); 579 buffer->instruction_args.push_back(op);
506 } 580 }
507 } 581 }
508 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count - 582 DCHECK_EQ(input_count, buffer->instruction_args.size() + pushed_count -
509 buffer->frame_state_value_count()); 583 frame_state_entries);
510 if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail && 584 if (V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK && call_tail &&
511 stack_param_delta != 0) { 585 stack_param_delta != 0) {
512 // For tail calls that change the size of their parameter list and keep 586 // For tail calls that change the size of their parameter list and keep
513 // their return address on the stack, move the return address to just above 587 // their return address on the stack, move the return address to just above
514 // the parameters. 588 // the parameters.
515 LinkageLocation saved_return_location = 589 LinkageLocation saved_return_location =
516 LinkageLocation::ForSavedCallerReturnAddress(); 590 LinkageLocation::ForSavedCallerReturnAddress();
517 InstructionOperand return_address = 591 InstructionOperand return_address =
518 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation( 592 g.UsePointerLocation(LinkageLocation::ConvertToTailCallerLocation(
519 saved_return_location, stack_param_delta), 593 saved_return_location, stack_param_delta),
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 return MarkAsReference(node), VisitConstant(node); 779 return MarkAsReference(node), VisitConstant(node);
706 case IrOpcode::kNumberConstant: { 780 case IrOpcode::kNumberConstant: {
707 double value = OpParameter<double>(node); 781 double value = OpParameter<double>(node);
708 if (!IsSmiDouble(value)) MarkAsReference(node); 782 if (!IsSmiDouble(value)) MarkAsReference(node);
709 return VisitConstant(node); 783 return VisitConstant(node);
710 } 784 }
711 case IrOpcode::kCall: 785 case IrOpcode::kCall:
712 return VisitCall(node); 786 return VisitCall(node);
713 case IrOpcode::kFrameState: 787 case IrOpcode::kFrameState:
714 case IrOpcode::kStateValues: 788 case IrOpcode::kStateValues:
789 case IrOpcode::kObjectState:
715 return; 790 return;
716 case IrOpcode::kLoad: { 791 case IrOpcode::kLoad: {
717 LoadRepresentation rep = OpParameter<LoadRepresentation>(node); 792 LoadRepresentation rep = OpParameter<LoadRepresentation>(node);
718 MarkAsRepresentation(rep, node); 793 MarkAsRepresentation(rep, node);
719 return VisitLoad(node); 794 return VisitLoad(node);
720 } 795 }
721 case IrOpcode::kStore: 796 case IrOpcode::kStore:
722 return VisitStore(node); 797 return VisitStore(node);
723 case IrOpcode::kWord32And: 798 case IrOpcode::kWord32And:
724 return MarkAsWord32(node), VisitWord32And(node); 799 return MarkAsWord32(node), VisitWord32And(node);
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 } 1475 }
1401 Emit(kArchRet, 0, nullptr, ret_count, value_locations); 1476 Emit(kArchRet, 0, nullptr, ret_count, value_locations);
1402 } 1477 }
1403 } 1478 }
1404 1479
1405 1480
1406 void InstructionSelector::VisitDeoptimize(Node* value) { 1481 void InstructionSelector::VisitDeoptimize(Node* value) {
1407 OperandGenerator g(this); 1482 OperandGenerator g(this);
1408 1483
1409 FrameStateDescriptor* desc = GetFrameStateDescriptor(value); 1484 FrameStateDescriptor* desc = GetFrameStateDescriptor(value);
1410 size_t arg_count = desc->GetTotalSize() + 1; // Include deopt id.
1411 1485
1412 InstructionOperandVector args(instruction_zone()); 1486 InstructionOperandVector args(instruction_zone());
1413 args.reserve(arg_count); 1487 args.reserve(desc->GetTotalSize() + 1); // Include deopt id.
1414 1488
1415 InstructionSequence::StateId state_id = 1489 InstructionSequence::StateId state_id =
1416 sequence()->AddFrameStateDescriptor(desc); 1490 sequence()->AddFrameStateDescriptor(desc);
1417 args.push_back(g.TempImmediate(state_id.ToInt())); 1491 args.push_back(g.TempImmediate(state_id.ToInt()));
1418 1492
1419 AddFrameStateInputs(value, &g, &args, desc, FrameStateInputKind::kAny, 1493 StateObjectCache cache(instruction_zone());
1420 instruction_zone());
1421 1494
1422 DCHECK_EQ(args.size(), arg_count); 1495 AddInputsToFrameStateDescriptor(desc, value, &g, &cache, &args,
1496 FrameStateInputKind::kAny,
1497 instruction_zone());
1423 1498
1424 Emit(kArchDeoptimize, 0, nullptr, arg_count, &args.front(), 0, nullptr); 1499 Emit(kArchDeoptimize, 0, nullptr, args.size(), &args.front(), 0, nullptr);
1425 } 1500 }
1426 1501
1427 1502
1428 void InstructionSelector::VisitThrow(Node* value) { 1503 void InstructionSelector::VisitThrow(Node* value) {
1429 OperandGenerator g(this); 1504 OperandGenerator g(this);
1430 Emit(kArchNop, g.NoOutput()); // TODO(titzer) 1505 Emit(kArchNop, g.NoOutput()); // TODO(titzer)
1431 } 1506 }
1432 1507
1433 1508
1434 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( 1509 FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
(...skipping 21 matching lines...) Expand all
1456 return new (instruction_zone()) FrameStateDescriptor( 1531 return new (instruction_zone()) FrameStateDescriptor(
1457 instruction_zone(), state_info.type(), state_info.bailout_id(), 1532 instruction_zone(), state_info.type(), state_info.bailout_id(),
1458 state_info.state_combine(), parameters, locals, stack, 1533 state_info.state_combine(), parameters, locals, stack,
1459 state_info.shared_info(), outer_state); 1534 state_info.shared_info(), outer_state);
1460 } 1535 }
1461 1536
1462 1537
1463 } // namespace compiler 1538 } // namespace compiler
1464 } // namespace internal 1539 } // namespace internal
1465 } // namespace v8 1540 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698