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> |
11 #include <set> | 11 #include <set> |
12 | 12 |
13 #include "src/compiler/common-operator.h" | 13 #include "src/compiler/common-operator.h" |
14 #include "src/compiler/frame.h" | 14 #include "src/compiler/frame.h" |
15 #include "src/compiler/instruction-codes.h" | 15 #include "src/compiler/instruction-codes.h" |
16 #include "src/compiler/opcodes.h" | 16 #include "src/compiler/opcodes.h" |
17 #include "src/compiler/register-configuration.h" | 17 #include "src/compiler/register-configuration.h" |
18 #include "src/compiler/source-position.h" | 18 #include "src/compiler/source-position.h" |
19 #include "src/zone-allocator.h" | 19 #include "src/zone-allocator.h" |
20 | 20 |
21 namespace v8 { | 21 namespace v8 { |
22 namespace internal { | 22 namespace internal { |
23 namespace compiler { | 23 namespace compiler { |
24 | 24 |
25 class Schedule; | 25 class Schedule; |
26 | 26 |
27 // A couple of reserved opcodes are used for internal use. | 27 // A couple of reserved opcodes are used for internal use. |
28 const InstructionCode kSourcePositionInstruction = -1; | 28 const InstructionCode kSourcePositionInstruction = -1; |
29 | 29 |
30 #define INSTRUCTION_OPERAND_LIST(V) \ | 30 #define ALLOCATED_OPERAND_LIST(V) \ |
31 V(Constant, CONSTANT) \ | |
32 V(Immediate, IMMEDIATE) \ | |
33 V(StackSlot, STACK_SLOT) \ | 31 V(StackSlot, STACK_SLOT) \ |
34 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ | 32 V(DoubleStackSlot, DOUBLE_STACK_SLOT) \ |
35 V(Register, REGISTER) \ | 33 V(Register, REGISTER) \ |
36 V(DoubleRegister, DOUBLE_REGISTER) | 34 V(DoubleRegister, DOUBLE_REGISTER) |
37 | 35 |
38 class InstructionOperand { | 36 class InstructionOperand { |
39 public: | 37 public: |
40 static const int kInvalidVirtualRegister = -1; | 38 static const int kInvalidVirtualRegister = -1; |
41 | 39 |
42 enum Kind { | 40 enum Kind { |
43 INVALID, | 41 INVALID, |
44 UNALLOCATED, | 42 UNALLOCATED, |
45 CONSTANT, | 43 CONSTANT, |
46 IMMEDIATE, | 44 IMMEDIATE, |
47 STACK_SLOT, | 45 STACK_SLOT, |
48 DOUBLE_STACK_SLOT, | 46 DOUBLE_STACK_SLOT, |
49 REGISTER, | 47 REGISTER, |
50 DOUBLE_REGISTER | 48 DOUBLE_REGISTER |
51 }; | 49 }; |
52 | 50 |
53 InstructionOperand() { ConvertTo(INVALID, 0, kInvalidVirtualRegister); } | 51 InstructionOperand() |
54 | 52 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {} |
55 InstructionOperand(Kind kind, int index) { | |
56 DCHECK(kind != UNALLOCATED && kind != INVALID); | |
57 ConvertTo(kind, index, kInvalidVirtualRegister); | |
58 } | |
59 | |
60 static InstructionOperand* New(Zone* zone, Kind kind, int index) { | |
61 return New(zone, InstructionOperand(kind, index)); | |
62 } | |
63 | 53 |
64 Kind kind() const { return KindField::decode(value_); } | 54 Kind kind() const { return KindField::decode(value_); } |
65 // TODO(dcarney): move this to subkind operand. | 55 |
66 int index() const { | |
67 DCHECK(kind() != UNALLOCATED && kind() != INVALID); | |
68 return static_cast<int64_t>(value_) >> IndexField::kShift; | |
69 } | |
70 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ | 56 #define INSTRUCTION_OPERAND_PREDICATE(name, type) \ |
71 bool Is##name() const { return kind() == type; } | 57 bool Is##name() const { return kind() == type; } |
72 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) | 58 ALLOCATED_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
| 59 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT) |
| 60 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE) |
73 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) | 61 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED) |
74 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) | 62 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID) |
75 #undef INSTRUCTION_OPERAND_PREDICATE | 63 #undef INSTRUCTION_OPERAND_PREDICATE |
| 64 |
76 bool Equals(const InstructionOperand* other) const { | 65 bool Equals(const InstructionOperand* other) const { |
77 return value_ == other->value_; | 66 return value_ == other->value_; |
78 } | 67 } |
79 | 68 |
80 void ConvertTo(Kind kind, int index) { | |
81 DCHECK(kind != UNALLOCATED && kind != INVALID); | |
82 ConvertTo(kind, index, kInvalidVirtualRegister); | |
83 } | |
84 | |
85 // Useful for map/set keys. | 69 // Useful for map/set keys. |
86 bool operator<(const InstructionOperand& op) const { | 70 bool operator<(const InstructionOperand& op) const { |
87 return value_ < op.value_; | 71 return value_ < op.value_; |
88 } | 72 } |
89 | 73 |
90 protected: | |
91 template <typename SubKindOperand> | 74 template <typename SubKindOperand> |
92 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { | 75 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) { |
93 void* buffer = zone->New(sizeof(op)); | 76 void* buffer = zone->New(sizeof(op)); |
94 return new (buffer) SubKindOperand(op); | 77 return new (buffer) SubKindOperand(op); |
95 } | 78 } |
96 | 79 |
97 InstructionOperand(Kind kind, int index, int virtual_register) { | 80 static void ReplaceWith(InstructionOperand* dest, |
98 ConvertTo(kind, index, virtual_register); | 81 const InstructionOperand* src) { |
| 82 *dest = *src; |
99 } | 83 } |
100 | 84 |
101 void ConvertTo(Kind kind, int index, int virtual_register) { | 85 protected: |
| 86 InstructionOperand(Kind kind, int index, int virtual_register) { |
102 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); | 87 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
103 if (kind != UNALLOCATED) { | 88 if (kind != UNALLOCATED && kind != CONSTANT) { |
104 DCHECK(virtual_register == kInvalidVirtualRegister); | 89 DCHECK(virtual_register == kInvalidVirtualRegister); |
105 } | 90 } |
106 value_ = KindField::encode(kind); | 91 value_ = KindField::encode(kind); |
107 value_ |= | 92 value_ |= |
108 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register)); | 93 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register)); |
109 value_ |= static_cast<int64_t>(index) << IndexField::kShift; | 94 value_ |= static_cast<int64_t>(index) << IndexField::kShift; |
110 DCHECK(((kind == UNALLOCATED || kind == INVALID) && index == 0) || | |
111 this->index() == index); | |
112 } | 95 } |
113 | 96 |
114 typedef BitField64<Kind, 0, 3> KindField; | 97 typedef BitField64<Kind, 0, 3> KindField; |
115 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField; | 98 typedef BitField64<uint32_t, 3, 32> VirtualRegisterField; |
116 typedef BitField64<int32_t, 35, 29> IndexField; | 99 typedef BitField64<int32_t, 35, 29> IndexField; |
117 | 100 |
118 uint64_t value_; | 101 uint64_t value_; |
119 }; | 102 }; |
120 | 103 |
121 struct PrintableInstructionOperand { | 104 struct PrintableInstructionOperand { |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 } | 293 } |
311 | 294 |
312 // [lifetime]: Only for non-FIXED_SLOT. | 295 // [lifetime]: Only for non-FIXED_SLOT. |
313 bool IsUsedAtStart() const { | 296 bool IsUsedAtStart() const { |
314 DCHECK(basic_policy() == EXTENDED_POLICY); | 297 DCHECK(basic_policy() == EXTENDED_POLICY); |
315 return LifetimeField::decode(value_) == USED_AT_START; | 298 return LifetimeField::decode(value_) == USED_AT_START; |
316 } | 299 } |
317 }; | 300 }; |
318 | 301 |
319 | 302 |
| 303 class ConstantOperand : public InstructionOperand { |
| 304 public: |
| 305 explicit ConstantOperand(int virtual_register) |
| 306 : InstructionOperand(CONSTANT, 0, virtual_register) {} |
| 307 |
| 308 int32_t virtual_register() const { |
| 309 return static_cast<int32_t>(VirtualRegisterField::decode(value_)); |
| 310 } |
| 311 |
| 312 static ConstantOperand* New(Zone* zone, int virtual_register) { |
| 313 return InstructionOperand::New(zone, ConstantOperand(virtual_register)); |
| 314 } |
| 315 |
| 316 static ConstantOperand* cast(InstructionOperand* op) { |
| 317 DCHECK(op->kind() == CONSTANT); |
| 318 return static_cast<ConstantOperand*>(op); |
| 319 } |
| 320 |
| 321 static const ConstantOperand* cast(const InstructionOperand* op) { |
| 322 DCHECK(op->kind() == CONSTANT); |
| 323 return static_cast<const ConstantOperand*>(op); |
| 324 } |
| 325 |
| 326 static ConstantOperand cast(const InstructionOperand& op) { |
| 327 DCHECK(op.kind() == CONSTANT); |
| 328 return *static_cast<const ConstantOperand*>(&op); |
| 329 } |
| 330 }; |
| 331 |
| 332 |
| 333 class ImmediateOperand : public InstructionOperand { |
| 334 public: |
| 335 explicit ImmediateOperand(int index) |
| 336 : InstructionOperand(IMMEDIATE, index, kInvalidVirtualRegister) {} |
| 337 |
| 338 int index() const { |
| 339 return static_cast<int64_t>(value_) >> IndexField::kShift; |
| 340 } |
| 341 |
| 342 static ImmediateOperand* New(Zone* zone, int index) { |
| 343 return InstructionOperand::New(zone, ImmediateOperand(index)); |
| 344 } |
| 345 |
| 346 static ImmediateOperand* cast(InstructionOperand* op) { |
| 347 DCHECK(op->kind() == IMMEDIATE); |
| 348 return static_cast<ImmediateOperand*>(op); |
| 349 } |
| 350 |
| 351 static const ImmediateOperand* cast(const InstructionOperand* op) { |
| 352 DCHECK(op->kind() == IMMEDIATE); |
| 353 return static_cast<const ImmediateOperand*>(op); |
| 354 } |
| 355 |
| 356 static ImmediateOperand cast(const InstructionOperand& op) { |
| 357 DCHECK(op.kind() == IMMEDIATE); |
| 358 return *static_cast<const ImmediateOperand*>(&op); |
| 359 } |
| 360 }; |
| 361 |
| 362 |
| 363 class AllocatedOperand : public InstructionOperand { |
| 364 #define ALLOCATED_OPERAND_CHECK(Name, Kind) || kind == Kind |
| 365 #define CHECK_ALLOCATED_KIND() \ |
| 366 DCHECK(false ALLOCATED_OPERAND_LIST(ALLOCATED_OPERAND_CHECK)); \ |
| 367 USE(kind); |
| 368 |
| 369 public: |
| 370 int index() const { |
| 371 return static_cast<int64_t>(value_) >> IndexField::kShift; |
| 372 } |
| 373 |
| 374 AllocatedOperand(Kind kind, int index) |
| 375 : InstructionOperand(kind, index, kInvalidVirtualRegister) { |
| 376 CHECK_ALLOCATED_KIND(); |
| 377 } |
| 378 |
| 379 static AllocatedOperand* New(Zone* zone, Kind kind, int index) { |
| 380 return InstructionOperand::New(zone, AllocatedOperand(kind, index)); |
| 381 } |
| 382 |
| 383 static AllocatedOperand* cast(InstructionOperand* op) { |
| 384 Kind kind = op->kind(); |
| 385 CHECK_ALLOCATED_KIND(); |
| 386 return static_cast<AllocatedOperand*>(op); |
| 387 } |
| 388 |
| 389 static const AllocatedOperand* cast(const InstructionOperand* op) { |
| 390 Kind kind = op->kind(); |
| 391 CHECK_ALLOCATED_KIND(); |
| 392 return static_cast<const AllocatedOperand*>(op); |
| 393 } |
| 394 |
| 395 static AllocatedOperand cast(const InstructionOperand& op) { |
| 396 Kind kind = op.kind(); |
| 397 CHECK_ALLOCATED_KIND(); |
| 398 return *static_cast<const AllocatedOperand*>(&op); |
| 399 } |
| 400 |
| 401 #undef CHECK_ALLOCATED_KIND |
| 402 #undef ALLOCATED_OPERAND_CAST_CHECK |
| 403 }; |
| 404 |
| 405 |
| 406 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ |
| 407 class SubKind##Operand FINAL : public AllocatedOperand { \ |
| 408 public: \ |
| 409 explicit SubKind##Operand(int index) \ |
| 410 : AllocatedOperand(kOperandKind, index) {} \ |
| 411 \ |
| 412 static SubKind##Operand* New(Zone* zone, int index) { \ |
| 413 return InstructionOperand::New(zone, SubKind##Operand(index)); \ |
| 414 } \ |
| 415 \ |
| 416 static SubKind##Operand* cast(InstructionOperand* op) { \ |
| 417 DCHECK(op->kind() == kOperandKind); \ |
| 418 return reinterpret_cast<SubKind##Operand*>(op); \ |
| 419 } \ |
| 420 \ |
| 421 static const SubKind##Operand* cast(const InstructionOperand* op) { \ |
| 422 DCHECK(op->kind() == kOperandKind); \ |
| 423 return reinterpret_cast<const SubKind##Operand*>(op); \ |
| 424 } \ |
| 425 \ |
| 426 static SubKind##Operand cast(const InstructionOperand& op) { \ |
| 427 DCHECK(op.kind() == kOperandKind); \ |
| 428 return *static_cast<const SubKind##Operand*>(&op); \ |
| 429 } \ |
| 430 }; |
| 431 ALLOCATED_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) |
| 432 #undef INSTRUCTION_SUBKIND_OPERAND_CLASS |
| 433 |
| 434 |
320 class MoveOperands FINAL { | 435 class MoveOperands FINAL { |
321 public: | 436 public: |
322 MoveOperands(InstructionOperand* source, InstructionOperand* destination) | 437 MoveOperands(InstructionOperand* source, InstructionOperand* destination) |
323 : source_(source), destination_(destination) {} | 438 : source_(source), destination_(destination) {} |
324 | 439 |
325 InstructionOperand* source() const { return source_; } | 440 InstructionOperand* source() const { return source_; } |
326 void set_source(InstructionOperand* operand) { source_ = operand; } | 441 void set_source(InstructionOperand* operand) { source_ = operand; } |
327 | 442 |
328 InstructionOperand* destination() const { return destination_; } | 443 InstructionOperand* destination() const { return destination_; } |
329 void set_destination(InstructionOperand* operand) { destination_ = operand; } | 444 void set_destination(InstructionOperand* operand) { destination_ = operand; } |
330 | 445 |
331 // The gap resolver marks moves as "in-progress" by clearing the | 446 // The gap resolver marks moves as "in-progress" by clearing the |
332 // destination (but not the source). | 447 // destination (but not the source). |
333 bool IsPending() const { return destination_ == NULL && source_ != NULL; } | 448 bool IsPending() const { return destination_ == NULL && source_ != NULL; } |
334 | 449 |
335 // True if this move a move into the given destination operand. | 450 // True if this move a move into the given destination operand. |
336 bool Blocks(InstructionOperand* operand) const { | 451 bool Blocks(InstructionOperand* operand) const { |
337 return !IsEliminated() && source()->Equals(operand); | 452 return !IsEliminated() && source()->Equals(operand); |
338 } | 453 } |
339 | 454 |
340 // A move is redundant if it's been eliminated, if its source and | 455 // A move is redundant if it's been eliminated or if its source and |
341 // destination are the same, or if its destination is constant. | 456 // destination are the same. |
342 bool IsRedundant() const { | 457 bool IsRedundant() const { |
343 return IsEliminated() || source_->Equals(destination_) || | 458 DCHECK_IMPLIES(destination_ != nullptr, !destination_->IsConstant()); |
344 (destination_ != NULL && destination_->IsConstant()); | 459 return IsEliminated() || source_->Equals(destination_); |
345 } | 460 } |
346 | 461 |
347 // We clear both operands to indicate move that's been eliminated. | 462 // We clear both operands to indicate move that's been eliminated. |
348 void Eliminate() { source_ = destination_ = NULL; } | 463 void Eliminate() { source_ = destination_ = NULL; } |
349 bool IsEliminated() const { | 464 bool IsEliminated() const { |
350 DCHECK(source_ != NULL || destination_ == NULL); | 465 DCHECK(source_ != NULL || destination_ == NULL); |
351 return source_ == NULL; | 466 return source_ == NULL; |
352 } | 467 } |
353 | 468 |
354 private: | 469 private: |
355 InstructionOperand* source_; | 470 InstructionOperand* source_; |
356 InstructionOperand* destination_; | 471 InstructionOperand* destination_; |
357 }; | 472 }; |
358 | 473 |
359 | 474 |
360 struct PrintableMoveOperands { | 475 struct PrintableMoveOperands { |
361 const RegisterConfiguration* register_configuration_; | 476 const RegisterConfiguration* register_configuration_; |
362 const MoveOperands* move_operands_; | 477 const MoveOperands* move_operands_; |
363 }; | 478 }; |
364 | 479 |
365 | 480 |
366 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); | 481 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); |
367 | 482 |
368 | 483 |
369 #define INSTRUCTION_SUBKIND_OPERAND_CLASS(SubKind, kOperandKind) \ | |
370 class SubKind##Operand FINAL : public InstructionOperand { \ | |
371 public: \ | |
372 explicit SubKind##Operand(int index) \ | |
373 : InstructionOperand(kOperandKind, index) {} \ | |
374 \ | |
375 static SubKind##Operand* New(int index, Zone* zone) { \ | |
376 return InstructionOperand::New(zone, SubKind##Operand(index)); \ | |
377 } \ | |
378 \ | |
379 static SubKind##Operand* cast(InstructionOperand* op) { \ | |
380 DCHECK(op->kind() == kOperandKind); \ | |
381 return reinterpret_cast<SubKind##Operand*>(op); \ | |
382 } \ | |
383 \ | |
384 static const SubKind##Operand* cast(const InstructionOperand* op) { \ | |
385 DCHECK(op->kind() == kOperandKind); \ | |
386 return reinterpret_cast<const SubKind##Operand*>(op); \ | |
387 } \ | |
388 \ | |
389 static SubKind##Operand cast(const InstructionOperand& op) { \ | |
390 DCHECK(op.kind() == kOperandKind); \ | |
391 return *static_cast<const SubKind##Operand*>(&op); \ | |
392 } \ | |
393 }; | |
394 INSTRUCTION_OPERAND_LIST(INSTRUCTION_SUBKIND_OPERAND_CLASS) | |
395 #undef INSTRUCTION_SUBKIND_OPERAND_CLASS | |
396 | |
397 | |
398 class ParallelMove FINAL : public ZoneObject { | 484 class ParallelMove FINAL : public ZoneObject { |
399 public: | 485 public: |
400 explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {} | 486 explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {} |
401 | 487 |
402 void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) { | 488 void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) { |
403 move_operands_.Add(MoveOperands(from, to), zone); | 489 move_operands_.Add(MoveOperands(from, to), zone); |
404 } | 490 } |
405 | 491 |
406 bool IsRedundant() const; | 492 bool IsRedundant() const; |
407 | 493 |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 | 1095 |
1010 private: | 1096 private: |
1011 explicit StateId(int id) : id_(id) {} | 1097 explicit StateId(int id) : id_(id) {} |
1012 int id_; | 1098 int id_; |
1013 }; | 1099 }; |
1014 | 1100 |
1015 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor); | 1101 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor); |
1016 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id); | 1102 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id); |
1017 int GetFrameStateDescriptorCount(); | 1103 int GetFrameStateDescriptorCount(); |
1018 | 1104 |
1019 RpoNumber InputRpo(Instruction* instr, size_t index) { | 1105 RpoNumber InputRpo(Instruction* instr, size_t index); |
1020 InstructionOperand* operand = instr->InputAt(index); | |
1021 Constant constant = operand->IsImmediate() ? GetImmediate(operand->index()) | |
1022 : GetConstant(operand->index()); | |
1023 return constant.ToRpoNumber(); | |
1024 } | |
1025 | 1106 |
1026 private: | 1107 private: |
1027 friend std::ostream& operator<<(std::ostream& os, | 1108 friend std::ostream& operator<<(std::ostream& os, |
1028 const PrintableInstructionSequence& code); | 1109 const PrintableInstructionSequence& code); |
1029 | 1110 |
1030 typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet; | 1111 typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet; |
1031 | 1112 |
1032 Isolate* isolate_; | 1113 Isolate* isolate_; |
1033 Zone* const zone_; | 1114 Zone* const zone_; |
1034 InstructionBlocks* const instruction_blocks_; | 1115 InstructionBlocks* const instruction_blocks_; |
(...skipping 18 matching lines...) Expand all Loading... |
1053 | 1134 |
1054 | 1135 |
1055 std::ostream& operator<<(std::ostream& os, | 1136 std::ostream& operator<<(std::ostream& os, |
1056 const PrintableInstructionSequence& code); | 1137 const PrintableInstructionSequence& code); |
1057 | 1138 |
1058 } // namespace compiler | 1139 } // namespace compiler |
1059 } // namespace internal | 1140 } // namespace internal |
1060 } // namespace v8 | 1141 } // namespace v8 |
1061 | 1142 |
1062 #endif // V8_COMPILER_INSTRUCTION_H_ | 1143 #endif // V8_COMPILER_INSTRUCTION_H_ |
OLD | NEW |