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. | |
Jarin
2015/10/26 13:37:02
Thank you, the descriptions are great!
| |
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 : LocationOperand(EXPLICIT, kind, machine_type, index) {} | |
450 | |
451 static ExplicitOperand* New(Zone* zone, LocationKind kind, | |
452 MachineType machine_type, int index) { | |
453 return InstructionOperand::New(zone, | |
454 ExplicitOperand(kind, machine_type, index)); | |
455 } | |
456 | |
457 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT); | |
458 }; | |
459 | |
460 | |
461 class AllocatedOperand : public LocationOperand { | |
462 public: | |
463 AllocatedOperand(LocationKind kind, MachineType machine_type, int index) | |
464 : LocationOperand(ALLOCATED, kind, machine_type, index) {} | |
465 | |
466 static AllocatedOperand* New(Zone* zone, LocationKind kind, | |
467 MachineType machine_type, int index) { | |
468 return InstructionOperand::New(zone, | |
469 AllocatedOperand(kind, machine_type, index)); | |
470 } | |
471 | |
472 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED); | |
473 }; | |
474 | |
475 | |
429 #undef INSTRUCTION_OPERAND_CASTS | 476 #undef INSTRUCTION_OPERAND_CASTS |
430 | 477 |
431 | 478 |
432 #define ALLOCATED_OPERAND_LIST(V) \ | 479 bool InstructionOperand::IsRegister() const { |
433 V(StackSlot, STACK_SLOT) \ | 480 return (IsAllocated() || IsExplicit()) && |
434 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ | 481 LocationOperand::cast(this)->location_kind() == |
435 V(Register, REGISTER) \ | 482 LocationOperand::REGISTER && |
436 V(DoubleRegister, DOUBLE_REGISTER) | 483 !IsFloatingPoint(LocationOperand::cast(this)->machine_type()); |
484 } | |
437 | 485 |
486 bool InstructionOperand::IsDoubleRegister() const { | |
487 return (IsAllocated() || IsExplicit()) && | |
488 LocationOperand::cast(this)->location_kind() == | |
489 LocationOperand::REGISTER && | |
490 IsFloatingPoint(LocationOperand::cast(this)->machine_type()); | |
491 } | |
438 | 492 |
439 #define ALLOCATED_OPERAND_IS(SubKind, kOperandKind) \ | 493 bool InstructionOperand::IsStackSlot() const { |
440 bool InstructionOperand::Is##SubKind() const { \ | 494 return (IsAllocated() || IsExplicit()) && |
441 return IsAllocated() && \ | 495 LocationOperand::cast(this)->location_kind() == |
442 AllocatedOperand::cast(this)->allocated_kind() == \ | 496 LocationOperand::STACK_SLOT && |
443 AllocatedOperand::kOperandKind; \ | 497 !IsFloatingPoint(LocationOperand::cast(this)->machine_type()); |
444 } | 498 } |
445 ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_IS) | |
446 #undef ALLOCATED_OPERAND_IS | |
447 | 499 |
500 bool InstructionOperand::IsDoubleStackSlot() const { | |
501 return (IsAllocated() || IsExplicit()) && | |
502 LocationOperand::cast(this)->location_kind() == | |
503 LocationOperand::STACK_SLOT && | |
504 IsFloatingPoint(LocationOperand::cast(this)->machine_type()); | |
505 } | |
448 | 506 |
449 // TODO(dcarney): these subkinds are now pretty useless, nuke. | 507 uint64_t InstructionOperand::GetCanonicalizedValue() const { |
450 #define ALLOCATED_OPERAND_CLASS(SubKind, kOperandKind) \ | 508 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. | 509 // TODO(dcarney): put machine type last and mask. |
484 return AllocatedOperand::MachineTypeField::update(this->value_, kMachNone); | 510 MachineType canonicalized_machine_type = |
511 IsFloatingPoint(LocationOperand::cast(this)->machine_type()) | |
512 ? kMachFloat64 | |
513 : kMachNone; | |
514 return InstructionOperand::KindField::update( | |
515 LocationOperand::MachineTypeField::update(this->value_, | |
516 canonicalized_machine_type), | |
517 LocationOperand::EXPLICIT); | |
485 } | 518 } |
486 return this->value_; | 519 return this->value_; |
487 } | 520 } |
488 | 521 |
489 | 522 |
490 // Required for maps that don't care about machine type. | 523 // Required for maps that don't care about machine type. |
491 struct CompareOperandModuloType { | 524 struct CompareOperandModuloType { |
492 bool operator()(const InstructionOperand& a, | 525 bool operator()(const InstructionOperand& a, |
493 const InstructionOperand& b) const { | 526 const InstructionOperand& b) const { |
494 return a.CompareModuloType(b); | 527 return a.CompareCanonicalized(b); |
495 } | 528 } |
496 }; | 529 }; |
497 | 530 |
498 | 531 |
499 class MoveOperands final : public ZoneObject { | 532 class MoveOperands final : public ZoneObject { |
500 public: | 533 public: |
501 MoveOperands(const InstructionOperand& source, | 534 MoveOperands(const InstructionOperand& source, |
502 const InstructionOperand& destination) | 535 const InstructionOperand& destination) |
503 : source_(source), destination_(destination) { | 536 : source_(source), destination_(destination) { |
504 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); | 537 DCHECK(!source.IsInvalid() && !destination.IsInvalid()); |
(...skipping 11 matching lines...) Expand all Loading... | |
516 | 549 |
517 // The gap resolver marks moves as "in-progress" by clearing the | 550 // The gap resolver marks moves as "in-progress" by clearing the |
518 // destination (but not the source). | 551 // destination (but not the source). |
519 bool IsPending() const { | 552 bool IsPending() const { |
520 return destination_.IsInvalid() && !source_.IsInvalid(); | 553 return destination_.IsInvalid() && !source_.IsInvalid(); |
521 } | 554 } |
522 void SetPending() { destination_ = InstructionOperand(); } | 555 void SetPending() { destination_ = InstructionOperand(); } |
523 | 556 |
524 // True if this move a move into the given destination operand. | 557 // True if this move a move into the given destination operand. |
525 bool Blocks(const InstructionOperand& operand) const { | 558 bool Blocks(const InstructionOperand& operand) const { |
526 return !IsEliminated() && source().EqualsModuloType(operand); | 559 return !IsEliminated() && source().EqualsCanonicalized(operand); |
527 } | 560 } |
528 | 561 |
529 // A move is redundant if it's been eliminated or if its source and | 562 // A move is redundant if it's been eliminated or if its source and |
530 // destination are the same. | 563 // destination are the same. |
531 bool IsRedundant() const { | 564 bool IsRedundant() const { |
532 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); | 565 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant()); |
533 return IsEliminated() || source_.EqualsModuloType(destination_); | 566 return IsEliminated() || source_.EqualsCanonicalized(destination_); |
534 } | 567 } |
535 | 568 |
536 // We clear both operands to indicate move that's been eliminated. | 569 // We clear both operands to indicate move that's been eliminated. |
537 void Eliminate() { source_ = destination_ = InstructionOperand(); } | 570 void Eliminate() { source_ = destination_ = InstructionOperand(); } |
538 bool IsEliminated() const { | 571 bool IsEliminated() const { |
539 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid()); | 572 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid()); |
540 return source_.IsInvalid(); | 573 return source_.IsInvalid(); |
541 } | 574 } |
542 | 575 |
543 private: | 576 private: |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1228 | 1261 |
1229 | 1262 |
1230 std::ostream& operator<<(std::ostream& os, | 1263 std::ostream& operator<<(std::ostream& os, |
1231 const PrintableInstructionSequence& code); | 1264 const PrintableInstructionSequence& code); |
1232 | 1265 |
1233 } // namespace compiler | 1266 } // namespace compiler |
1234 } // namespace internal | 1267 } // namespace internal |
1235 } // namespace v8 | 1268 } // namespace v8 |
1236 | 1269 |
1237 #endif // V8_COMPILER_INSTRUCTION_H_ | 1270 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |