OLD | NEW |
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 #ifndef V8_COMPILER_INSTRUCTION_H_ | 5 #ifndef V8_COMPILER_INSTRUCTION_H_ |
6 #define V8_COMPILER_INSTRUCTION_H_ | 6 #define V8_COMPILER_INSTRUCTION_H_ |
7 | 7 |
8 #include <deque> | 8 #include <deque> |
9 #include <iosfwd> | 9 #include <iosfwd> |
10 #include <map> | 10 #include <map> |
(...skipping 13 matching lines...) Expand all Loading... |
24 namespace compiler { | 24 namespace compiler { |
25 | 25 |
26 class Schedule; | 26 class Schedule; |
27 | 27 |
28 class InstructionOperand { | 28 class InstructionOperand { |
29 public: | 29 public: |
30 static const int kInvalidVirtualRegister = -1; | 30 static const int kInvalidVirtualRegister = -1; |
31 | 31 |
32 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with | 32 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with |
33 // kInvalidVirtualRegister and some DCHECKS. | 33 // kInvalidVirtualRegister and some DCHECKS. |
34 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, ALLOCATED }; | 34 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, EXPLICIT, ALLOCATED }; |
35 | 35 |
36 InstructionOperand() : InstructionOperand(INVALID) {} | 36 InstructionOperand() : InstructionOperand(INVALID) {} |
37 | 37 |
38 Kind kind() const { return KindField::decode(value_); } | 38 Kind kind() const { return KindField::decode(value_); } |
39 | 39 |
40 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ | 40 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
41 bool Is##name() const { return kind() == type; } | 41 bool Is##name() const { return kind() == type; } |
42 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) | 42 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
| 43 // UnallocatedOperands are place-holder operands created before register |
| 44 // allocation. They later are assigned registers and become AllocatedOperands. |
43 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) | 45 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
| 46 // Constant operands participate in register allocation. They are allocated to |
| 47 // registers but have a special "spilling" behavior. When a ConstantOperand |
| 48 // value must be rematerialized, it is loaded from an immediate constant |
| 49 // rather from an unspilled slot. |
44 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) | 50 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) |
| 51 // ImmediateOperands do not participate in register allocation and are only |
| 52 // embedded directly in instructions, e.g. small integers and on some |
| 53 // platforms Objects. |
45 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) | 54 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) |
| 55 // ExplicitOperands do not participate in register allocation. They are |
| 56 // created by the instruction selector for direct access to registers and |
| 57 // stack slots, completely bypassing the register allocator. They are never |
| 58 // associated with a virtual register |
| 59 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT) |
| 60 // AllocatedOperands are registers or stack slots that are assigned by the |
| 61 // register allocator and are always associated with a virtual register. |
46 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) | 62 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED) |
47 #undef INSTRUCTION_OPERAND_PREDICATE | 63 #undef INSTRUCTION_OPERAND_PREDICATE |
48 | 64 |
49 inline bool IsRegister() const; | 65 inline bool IsRegister() const; |
50 inline bool IsDoubleRegister() const; | 66 inline bool IsDoubleRegister() const; |
51 inline bool IsStackSlot() const; | 67 inline bool IsStackSlot() const; |
52 inline bool IsDoubleStackSlot() const; | 68 inline bool IsDoubleStackSlot() const; |
53 | 69 |
54 template <typename SubKindOperand> | 70 template <typename SubKindOperand> |
55 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { | 71 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { |
56 void* buffer = zone->New(sizeof(op)); | 72 void* buffer = zone->New(sizeof(op)); |
57 return new (buffer) SubKindOperand(op); | 73 return new (buffer) SubKindOperand(op); |
58 } | 74 } |
59 | 75 |
60 static void ReplaceWith(InstructionOperand* dest, | 76 static void ReplaceWith(InstructionOperand* dest, |
61 const InstructionOperand* src) { | 77 const InstructionOperand* src) { |
62 *dest = *src; | 78 *dest = *src; |
63 } | 79 } |
64 | 80 |
65 bool Equals(const InstructionOperand& that) const { | 81 bool Equals(const InstructionOperand& that) const { |
66 return this->value_ == that.value_; | 82 return this->value_ == that.value_; |
67 } | 83 } |
68 | 84 |
69 bool Compare(const InstructionOperand& that) const { | 85 bool Compare(const InstructionOperand& that) const { |
70 return this->value_ < that.value_; | 86 return this->value_ < that.value_; |
71 } | 87 } |
72 | 88 |
73 bool EqualsModuloType(const InstructionOperand& that) const { | 89 bool EqualsCanonicalized(const InstructionOperand& that) const { |
74 return this->GetValueModuloType() == that.GetValueModuloType(); | 90 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue(); |
75 } | 91 } |
76 | 92 |
77 bool CompareModuloType(const InstructionOperand& that) const { | 93 bool CompareCanonicalized(const InstructionOperand& that) const { |
78 return this->GetValueModuloType() < that.GetValueModuloType(); | 94 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue(); |
79 } | 95 } |
80 | 96 |
81 protected: | 97 protected: |
82 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {} | 98 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {} |
83 | 99 |
84 inline uint64_t GetValueModuloType() const; | 100 inline uint64_t GetCanonicalizedValue() const; |
85 | 101 |
86 class KindField : public BitField64<Kind, 0, 3> {}; | 102 class KindField : public BitField64<Kind, 0, 3> {}; |
87 | 103 |
88 uint64_t value_; | 104 uint64_t value_; |
89 }; | 105 }; |
90 | 106 |
91 | 107 |
92 struct PrintableInstructionOperand { | 108 struct PrintableInstructionOperand { |
93 const RegisterConfiguration* register_configuration_; | 109 const RegisterConfiguration* register_configuration_; |
94 InstructionOperand op_; | 110 InstructionOperand op_; |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 } | 362 } |
347 | 363 |
348 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE); | 364 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE); |
349 | 365 |
350 STATIC_ASSERT(KindField::kSize == 3); | 366 STATIC_ASSERT(KindField::kSize == 3); |
351 class TypeField : public BitField64<ImmediateType, 3, 1> {}; | 367 class TypeField : public BitField64<ImmediateType, 3, 1> {}; |
352 class ValueField : public BitField64<int32_t, 32, 32> {}; | 368 class ValueField : public BitField64<int32_t, 32, 32> {}; |
353 }; | 369 }; |
354 | 370 |
355 | 371 |
356 class AllocatedOperand : public InstructionOperand { | 372 class LocationOperand : public InstructionOperand { |
357 public: | 373 public: |
358 // TODO(dcarney): machine_type makes this now redundant. Just need to know is | 374 enum LocationKind { REGISTER, STACK_SLOT }; |
359 // the operand is a slot or a register. | |
360 enum AllocatedKind { | |
361 STACK_SLOT, | |
362 DOUBLE_STACK_SLOT, | |
363 REGISTER, | |
364 DOUBLE_REGISTER | |
365 }; | |
366 | 375 |
367 AllocatedOperand(AllocatedKind kind, MachineType machine_type, int index) | 376 LocationOperand(InstructionOperand::Kind operand_kind, |
368 : InstructionOperand(ALLOCATED) { | 377 LocationOperand::LocationKind location_kind, |
369 DCHECK_IMPLIES(kind == REGISTER || kind == DOUBLE_REGISTER, index >= 0); | 378 MachineType machine_type, int index) |
| 379 : InstructionOperand(operand_kind) { |
| 380 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0); |
370 DCHECK(IsSupportedMachineType(machine_type)); | 381 DCHECK(IsSupportedMachineType(machine_type)); |
371 value_ |= AllocatedKindField::encode(kind); | 382 value_ |= LocationKindField::encode(location_kind); |
372 value_ |= MachineTypeField::encode(machine_type); | 383 value_ |= MachineTypeField::encode(machine_type); |
373 value_ |= static_cast<int64_t>(index) << IndexField::kShift; | 384 value_ |= static_cast<int64_t>(index) << IndexField::kShift; |
374 } | 385 } |
375 | 386 |
376 int index() const { | 387 int index() const { |
377 DCHECK(STACK_SLOT == allocated_kind() || | 388 DCHECK(IsStackSlot() || IsDoubleStackSlot()); |
378 DOUBLE_STACK_SLOT == allocated_kind()); | |
379 return static_cast<int64_t>(value_) >> IndexField::kShift; | 389 return static_cast<int64_t>(value_) >> IndexField::kShift; |
380 } | 390 } |
381 | 391 |
382 Register GetRegister() const { | 392 Register GetRegister() const { |
383 DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind()); | 393 DCHECK(IsRegister()); |
384 return Register::from_code(static_cast<int64_t>(value_) >> | 394 return Register::from_code(static_cast<int64_t>(value_) >> |
385 IndexField::kShift); | 395 IndexField::kShift); |
386 } | 396 } |
387 | 397 |
388 DoubleRegister GetDoubleRegister() const { | 398 DoubleRegister GetDoubleRegister() const { |
389 DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind()); | 399 DCHECK(IsDoubleRegister()); |
390 return DoubleRegister::from_code(static_cast<int64_t>(value_) >> | 400 return DoubleRegister::from_code(static_cast<int64_t>(value_) >> |
391 IndexField::kShift); | 401 IndexField::kShift); |
392 } | 402 } |
393 | 403 |
394 AllocatedKind allocated_kind() const { | 404 LocationKind location_kind() const { |
395 return AllocatedKindField::decode(value_); | 405 return LocationKindField::decode(value_); |
396 } | 406 } |
397 | 407 |
398 MachineType machine_type() const { return MachineTypeField::decode(value_); } | 408 MachineType machine_type() const { return MachineTypeField::decode(value_); } |
399 | 409 |
400 static AllocatedOperand* New(Zone* zone, AllocatedKind kind, | |
401 MachineType machine_type, int index) { | |
402 return InstructionOperand::New(zone, | |
403 AllocatedOperand(kind, machine_type, index)); | |
404 } | |
405 | |
406 static bool IsSupportedMachineType(MachineType machine_type) { | 410 static bool IsSupportedMachineType(MachineType machine_type) { |
407 if (RepresentationOf(machine_type) != machine_type) return false; | 411 if (RepresentationOf(machine_type) != machine_type) return false; |
408 switch (machine_type) { | 412 switch (machine_type) { |
409 case kRepWord32: | 413 case kRepWord32: |
410 case kRepWord64: | 414 case kRepWord64: |
411 case kRepFloat32: | 415 case kRepFloat32: |
412 case kRepFloat64: | 416 case kRepFloat64: |
413 case kRepTagged: | 417 case kRepTagged: |
414 return true; | 418 return true; |
415 default: | 419 default: |
416 return false; | 420 return false; |
417 } | 421 } |
418 } | 422 } |
419 | 423 |
420 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); | 424 static LocationOperand* cast(InstructionOperand* op) { |
| 425 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind()); |
| 426 return static_cast<LocationOperand*>(op); |
| 427 } |
| 428 |
| 429 static const LocationOperand* cast(const InstructionOperand* op) { |
| 430 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind()); |
| 431 return static_cast<const LocationOperand*>(op); |
| 432 } |
| 433 |
| 434 static LocationOperand cast(const InstructionOperand& op) { |
| 435 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind()); |
| 436 return *static_cast<const LocationOperand*>(&op); |
| 437 } |
421 | 438 |
422 STATIC_ASSERT(KindField::kSize == 3); | 439 STATIC_ASSERT(KindField::kSize == 3); |
423 class AllocatedKindField : public BitField64<AllocatedKind, 3, 2> {}; | 440 class LocationKindField : public BitField64<LocationKind, 3, 2> {}; |
424 class MachineTypeField : public BitField64<MachineType, 5, 16> {}; | 441 class MachineTypeField : public BitField64<MachineType, 5, 16> {}; |
425 class IndexField : public BitField64<int32_t, 35, 29> {}; | 442 class IndexField : public BitField64<int32_t, 35, 29> {}; |
426 }; | 443 }; |
427 | 444 |
428 | 445 |
| 446 class ExplicitOperand : public LocationOperand { |
| 447 public: |
| 448 ExplicitOperand(LocationKind kind, MachineType machine_type, int index); |
| 449 |
| 450 static ExplicitOperand* New(Zone* zone, LocationKind kind, |
| 451 MachineType machine_type, int index) { |
| 452 return InstructionOperand::New(zone, |
| 453 ExplicitOperand(kind, machine_type, index)); |
| 454 } |
| 455 |
| 456 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT); |
| 457 }; |
| 458 |
| 459 |
| 460 class AllocatedOperand : public LocationOperand { |
| 461 public: |
| 462 AllocatedOperand(LocationKind kind, MachineType machine_type, int index) |
| 463 : LocationOperand(ALLOCATED, kind, machine_type, index) {} |
| 464 |
| 465 static AllocatedOperand* New(Zone* zone, LocationKind kind, |
| 466 MachineType machine_type, int index) { |
| 467 return InstructionOperand::New(zone, |
| 468 AllocatedOperand(kind, machine_type, index)); |
| 469 } |
| 470 |
| 471 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); |
| 472 }; |
| 473 |
| 474 |
429 #undef INSTRUCTION_OPERAND_CASTS | 475 #undef INSTRUCTION_OPERAND_CASTS |
430 | 476 |
431 | 477 |
432 #define ALLOCATED_OPERAND_LIST(V) \ | 478 bool InstructionOperand::IsRegister() const { |
433 V(StackSlot, STACK_SLOT) \ | 479 return (IsAllocated() || IsExplicit()) && |
434 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ | 480 LocationOperand::cast(this)->location_kind() == |
435 V(Register, REGISTER) \ | 481 LocationOperand::REGISTER && |
436 V(DoubleRegister, DOUBLE_REGISTER) | 482 !IsFloatingPoint(LocationOperand::cast(this)->machine_type()); |
| 483 } |
437 | 484 |
| 485 bool InstructionOperand::IsDoubleRegister() const { |
| 486 return (IsAllocated() || IsExplicit()) && |
| 487 LocationOperand::cast(this)->location_kind() == |
| 488 LocationOperand::REGISTER && |
| 489 IsFloatingPoint(LocationOperand::cast(this)->machine_type()); |
| 490 } |
438 | 491 |
439 #define ALLOCATED_OPERAND_IS(SubKind, kOperandKind) \ | 492 bool InstructionOperand::IsStackSlot() const { |
440 bool InstructionOperand::Is##SubKind() const { \ | 493 return (IsAllocated() || IsExplicit()) && |
441 return IsAllocated() && \ | 494 LocationOperand::cast(this)->location_kind() == |
442 AllocatedOperand::cast(this)->allocated_kind() == \ | 495 LocationOperand::STACK_SLOT && |
443 AllocatedOperand::kOperandKind; \ | 496 !IsFloatingPoint(LocationOperand::cast(this)->machine_type()); |
444 } | 497 } |
445 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_IS) | |
446 #undef ALLOCATED_OPERAND_IS | |
447 | 498 |
| 499 bool InstructionOperand::IsDoubleStackSlot() const { |
| 500 return (IsAllocated() || IsExplicit()) && |
| 501 LocationOperand::cast(this)->location_kind() == |
| 502 LocationOperand::STACK_SLOT && |
| 503 IsFloatingPoint(LocationOperand::cast(this)->machine_type()); |
| 504 } |
448 | 505 |
449 // TODO(dcarney): these subkinds are now pretty useless, nuke. | 506 uint64_t InstructionOperand::GetCanonicalizedValue() const { |
450 #define ALLOCATED_OPERAND_CLASS(SubKind, kOperandKind) \ | 507 if (IsAllocated() || IsExplicit()) { |
451 class SubKind##Operand final : public AllocatedOperand { \ | |
452 public: \ | |
453 explicit SubKind##Operand(MachineType machine_type, int index) \ | |
454 : AllocatedOperand(kOperandKind, machine_type, index) {} \ | |
455 \ | |
456 static SubKind##Operand* New(Zone* zone, MachineType machine_type, \ | |
457 int index) { \ | |
458 return InstructionOperand::New(zone, \ | |
459 SubKind##Operand(machine_type, index)); \ | |
460 } \ | |
461 \ | |
462 static SubKind##Operand* cast(InstructionOperand* op) { \ | |
463 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \ | |
464 return reinterpret_cast<SubKind##Operand*>(op); \ | |
465 } \ | |
466 \ | |
467 static const SubKind##Operand* cast(const InstructionOperand* op) { \ | |
468 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op)->allocated_kind()); \ | |
469 return reinterpret_cast<const SubKind##Operand*>(op); \ | |
470 } \ | |
471 \ | |
472 static SubKind##Operand cast(const InstructionOperand& op) { \ | |
473 DCHECK_EQ(kOperandKind, AllocatedOperand::cast(op).allocated_kind()); \ | |
474 return *static_cast<const SubKind##Operand*>(&op); \ | |
475 } \ | |
476 }; | |
477 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CLASS) | |
478 #undef ALLOCATED_OPERAND_CLASS | |
479 | |
480 | |
481 uint64_t InstructionOperand::GetValueModuloType() const { | |
482 if (IsAllocated()) { | |
483 // TODO(dcarney): put machine type last and mask. | 508 // TODO(dcarney): put machine type last and mask. |
484 return AllocatedOperand::MachineTypeField::update(this->value_, kMachNone); | 509 MachineType canonicalized_machine_type = |
| 510 IsFloatingPoint(LocationOperand::cast(this)->machine_type()) |
| 511 ? kMachFloat64 |
| 512 : kMachNone; |
| 513 return InstructionOperand::KindField::update( |
| 514 LocationOperand::MachineTypeField::update(this->value_, |
| 515 canonicalized_machine_type), |
| 516 LocationOperand::EXPLICIT); |
485 } | 517 } |
486 return this->value_; | 518 return this->value_; |
487 } | 519 } |
488 | 520 |
489 | 521 |
490 // Required for maps that don't care about machine type. | 522 // Required for maps that don't care about machine type. |
491 struct CompareOperandModuloType { | 523 struct CompareOperandModuloType { |
492 bool operator()(const InstructionOperand& a, | 524 bool operator()(const InstructionOperand& a, |
493 const InstructionOperand& b) const { | 525 const InstructionOperand& b) const { |
494 return a.CompareModuloType(b); | 526 return a.CompareCanonicalized(b); |
495 } | 527 } |
496 }; | 528 }; |
497 | 529 |
498 | 530 |
499 class MoveOperands final : public ZoneObject { | 531 class MoveOperands final : public ZoneObject { |
500 public: | 532 public: |
501 MoveOperands(const InstructionOperand& source, | 533 MoveOperands(const InstructionOperand& source, |
502 const InstructionOperand& destination) | 534 const InstructionOperand& destination) |
503 : source_(source), destination_(destination) { | 535 : source_(source), destination_(destination) { |
504 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); | 536 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); |
(...skipping 11 matching lines...) Expand all Loading... |
516 | 548 |
517 // The gap resolver marks moves as "in-progress" by clearing the | 549 // The gap resolver marks moves as "in-progress" by clearing the |
518 // destination (but not the source). | 550 // destination (but not the source). |
519 bool IsPending() const { | 551 bool IsPending() const { |
520 return destination_.IsInvalid() && !source_.IsInvalid(); | 552 return destination_.IsInvalid() && !source_.IsInvalid(); |
521 } | 553 } |
522 void SetPending() { destination_ = InstructionOperand(); } | 554 void SetPending() { destination_ = InstructionOperand(); } |
523 | 555 |
524 // True if this move a move into the given destination operand. | 556 // True if this move a move into the given destination operand. |
525 bool Blocks(const InstructionOperand& operand) const { | 557 bool Blocks(const InstructionOperand& operand) const { |
526 return !IsEliminated() && source().EqualsModuloType(operand); | 558 return !IsEliminated() && source().EqualsCanonicalized(operand); |
527 } | 559 } |
528 | 560 |
529 // A move is redundant if it's been eliminated or if its source and | 561 // A move is redundant if it's been eliminated or if its source and |
530 // destination are the same. | 562 // destination are the same. |
531 bool IsRedundant() const { | 563 bool IsRedundant() const { |
532 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); | 564 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); |
533 return IsEliminated() || source_.EqualsModuloType(destination_); | 565 return IsEliminated() || source_.EqualsCanonicalized(destination_); |
534 } | 566 } |
535 | 567 |
536 // We clear both operands to indicate move that's been eliminated. | 568 // We clear both operands to indicate move that's been eliminated. |
537 void Eliminate() { source_ = destination_ = InstructionOperand(); } | 569 void Eliminate() { source_ = destination_ = InstructionOperand(); } |
538 bool IsEliminated() const { | 570 bool IsEliminated() const { |
539 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid()); | 571 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid()); |
540 return source_.IsInvalid(); | 572 return source_.IsInvalid(); |
541 } | 573 } |
542 | 574 |
543 private: | 575 private: |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 | 1260 |
1229 | 1261 |
1230 std::ostream& operator<<(std::ostream& os, | 1262 std::ostream& operator<<(std::ostream& os, |
1231 const PrintableInstructionSequence& code); | 1263 const PrintableInstructionSequence& code); |
1232 | 1264 |
1233 } // namespace compiler | 1265 } // namespace compiler |
1234 } // namespace internal | 1266 } // namespace internal |
1235 } // namespace v8 | 1267 } // namespace v8 |
1236 | 1268 |
1237 #endif // V8_COMPILER_INSTRUCTION_H_ | 1269 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |