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

Side by Side Diff: src/compiler/instruction.h

Issue 889843003: [turbofan] Don't allocate UnallocatedOperands in Zone memory during instruction selection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « src/compiler/ia32/instruction-selector-ia32.cc ('k') | src/compiler/instruction.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #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 17 matching lines...) Expand all
28 const InstructionCode kSourcePositionInstruction = -2; 28 const InstructionCode kSourcePositionInstruction = -2;
29 29
30 #define INSTRUCTION_OPERAND_LIST(V) \ 30 #define INSTRUCTION_OPERAND_LIST(V) \
31 V(Constant, CONSTANT, 0) \ 31 V(Constant, CONSTANT, 0) \
32 V(Immediate, IMMEDIATE, 0) \ 32 V(Immediate, IMMEDIATE, 0) \
33 V(StackSlot, STACK_SLOT, 128) \ 33 V(StackSlot, STACK_SLOT, 128) \
34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \ 34 V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128) \
35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \ 35 V(Register, REGISTER, RegisterConfiguration::kMaxGeneralRegisters) \
36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters) 36 V(DoubleRegister, DOUBLE_REGISTER, RegisterConfiguration::kMaxDoubleRegisters)
37 37
38 class InstructionOperand : public ZoneObject { 38 class InstructionOperand {
39 public: 39 public:
40 static const int kInvalidVirtualRegister = -1; 40 static const int kInvalidVirtualRegister = -1;
41 41
42 enum Kind { 42 enum Kind {
43 INVALID, 43 INVALID,
44 UNALLOCATED, 44 UNALLOCATED,
45 CONSTANT, 45 CONSTANT,
46 IMMEDIATE, 46 IMMEDIATE,
47 STACK_SLOT, 47 STACK_SLOT,
48 DOUBLE_STACK_SLOT, 48 DOUBLE_STACK_SLOT,
49 REGISTER, 49 REGISTER,
50 DOUBLE_REGISTER 50 DOUBLE_REGISTER
51 }; 51 };
52 52
53 InstructionOperand() : virtual_register_(kInvalidVirtualRegister) {
54 ConvertTo(INVALID, 0);
55 }
56
53 InstructionOperand(Kind kind, int index) 57 InstructionOperand(Kind kind, int index)
54 : virtual_register_(kInvalidVirtualRegister) { 58 : virtual_register_(kInvalidVirtualRegister) {
55 DCHECK(kind != INVALID); 59 DCHECK(kind != INVALID);
56 ConvertTo(kind, index); 60 ConvertTo(kind, index);
57 } 61 }
58 62
59 Kind kind() const { return KindField::decode(value_); } 63 Kind kind() const { return KindField::decode(value_); }
60 int index() const { return static_cast<int>(value_) >> KindField::kSize; } 64 int index() const { return static_cast<int>(value_) >> KindField::kSize; }
61 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \ 65 #define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \
62 bool Is##name() const { return kind() == type; } 66 bool Is##name() const { return kind() == type; }
63 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) 67 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
64 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) 68 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0)
69 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID, 0)
65 #undef INSTRUCTION_OPERAND_PREDICATE 70 #undef INSTRUCTION_OPERAND_PREDICATE
66 bool Equals(const InstructionOperand* other) const { 71 bool Equals(const InstructionOperand* other) const {
67 return value_ == other->value_; 72 return value_ == other->value_;
68 } 73 }
69 74
70 void ConvertTo(Kind kind, int index) { 75 void ConvertTo(Kind kind, int index) {
71 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); 76 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
72 value_ = KindField::encode(kind); 77 value_ = KindField::encode(kind);
73 value_ |= bit_cast<unsigned>(index << KindField::kSize); 78 value_ |= bit_cast<unsigned>(index << KindField::kSize);
74 DCHECK(this->index() == index); 79 DCHECK(this->index() == index);
75 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister; 80 if (kind != UNALLOCATED) virtual_register_ = kInvalidVirtualRegister;
76 } 81 }
77 82
78 // Calls SetUpCache()/TearDownCache() for each subclass. 83 // Calls SetUpCache()/TearDownCache() for each subclass.
79 static void SetUpCaches(); 84 static void SetUpCaches();
80 static void TearDownCaches(); 85 static void TearDownCaches();
81 86
87 // TODO(dcarney): get rid of these
88 void* operator new(size_t, void* location) { return location; }
89 void* operator new(size_t size, Zone* zone) {
90 return zone->New(static_cast<int>(size));
91 }
92
82 protected: 93 protected:
83 InstructionOperand(Kind kind, int index, int virtual_register) 94 InstructionOperand(Kind kind, int index, int virtual_register)
84 : virtual_register_(virtual_register) { 95 : virtual_register_(virtual_register) {
85 ConvertTo(kind, index); 96 ConvertTo(kind, index);
86 } 97 }
87 typedef BitField<Kind, 0, 3> KindField; 98 typedef BitField<Kind, 0, 3> KindField;
88 99
89 uint32_t value_; 100 uint32_t value_;
90 // TODO(dcarney): this should really be unsigned. 101 // TODO(dcarney): this should really be unsigned.
91 int32_t virtual_register_; 102 int32_t virtual_register_;
92 }; 103 };
93 104
94 typedef ZoneVector<InstructionOperand*> InstructionOperandVector;
95
96 struct PrintableInstructionOperand { 105 struct PrintableInstructionOperand {
97 const RegisterConfiguration* register_configuration_; 106 const RegisterConfiguration* register_configuration_;
98 const InstructionOperand* op_; 107 const InstructionOperand* op_;
99 }; 108 };
100 109
101 std::ostream& operator<<(std::ostream& os, 110 std::ostream& operator<<(std::ostream& os,
102 const PrintableInstructionOperand& op); 111 const PrintableInstructionOperand& op);
103 112
104 class UnallocatedOperand : public InstructionOperand { 113 class UnallocatedOperand : public InstructionOperand {
105 public: 114 public:
(...skipping 18 matching lines...) Expand all
124 133
125 // USED_AT_END operand is treated as live until the end of 134 // USED_AT_END operand is treated as live until the end of
126 // instruction. This means that register allocator will not reuse it's 135 // instruction. This means that register allocator will not reuse it's
127 // register for any other operand inside instruction. 136 // register for any other operand inside instruction.
128 USED_AT_END 137 USED_AT_END
129 }; 138 };
130 139
131 // TODO(dcarney): remove this. 140 // TODO(dcarney): remove this.
132 static const int kInvalidVirtualRegister = -1; 141 static const int kInvalidVirtualRegister = -1;
133 142
134 // This is only for array initialization.
135 UnallocatedOperand()
136 : InstructionOperand(INVALID, 0, kInvalidVirtualRegister) {}
137
138 UnallocatedOperand(ExtendedPolicy policy, int virtual_register) 143 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
139 : InstructionOperand(UNALLOCATED, 0, virtual_register) { 144 : InstructionOperand(UNALLOCATED, 0, virtual_register) {
140 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); 145 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
141 value_ |= ExtendedPolicyField::encode(policy); 146 value_ |= ExtendedPolicyField::encode(policy);
142 value_ |= LifetimeField::encode(USED_AT_END); 147 value_ |= LifetimeField::encode(USED_AT_END);
143 } 148 }
144 149
145 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register) 150 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
146 : InstructionOperand(UNALLOCATED, 0, virtual_register) { 151 : InstructionOperand(UNALLOCATED, 0, virtual_register) {
147 DCHECK(policy == FIXED_SLOT); 152 DCHECK(policy == FIXED_SLOT);
(...skipping 26 matching lines...) Expand all
174 static const UnallocatedOperand* cast(const InstructionOperand* op) { 179 static const UnallocatedOperand* cast(const InstructionOperand* op) {
175 DCHECK(op->IsUnallocated()); 180 DCHECK(op->IsUnallocated());
176 return static_cast<const UnallocatedOperand*>(op); 181 return static_cast<const UnallocatedOperand*>(op);
177 } 182 }
178 183
179 static UnallocatedOperand* cast(InstructionOperand* op) { 184 static UnallocatedOperand* cast(InstructionOperand* op) {
180 DCHECK(op->IsUnallocated()); 185 DCHECK(op->IsUnallocated());
181 return static_cast<UnallocatedOperand*>(op); 186 return static_cast<UnallocatedOperand*>(op);
182 } 187 }
183 188
189 static UnallocatedOperand cast(const InstructionOperand& op) {
190 DCHECK(op.IsUnallocated());
191 return *static_cast<const UnallocatedOperand*>(&op);
192 }
193
184 // The encoding used for UnallocatedOperand operands depends on the policy 194 // The encoding used for UnallocatedOperand operands depends on the policy
185 // that is 195 // that is
186 // stored within the operand. The FIXED_SLOT policy uses a compact encoding 196 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
187 // because it accommodates a larger pay-load. 197 // because it accommodates a larger pay-load.
188 // 198 //
189 // For FIXED_SLOT policy: 199 // For FIXED_SLOT policy:
190 // +-----------------------------+ 200 // +-----------------------------+
191 // | slot_index | 0 | 001 | 201 // | slot_index | 0 | 001 |
192 // +-----------------------------+ 202 // +-----------------------------+
193 // 203 //
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 const MoveOperands* move_operands_; 344 const MoveOperands* move_operands_;
335 }; 345 };
336 346
337 347
338 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo); 348 std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
339 349
340 350
341 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands> 351 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
342 class SubKindOperand FINAL : public InstructionOperand { 352 class SubKindOperand FINAL : public InstructionOperand {
343 public: 353 public:
354 explicit SubKindOperand(int index)
355 : InstructionOperand(kOperandKind, index) {}
356
344 static SubKindOperand* Create(int index, Zone* zone) { 357 static SubKindOperand* Create(int index, Zone* zone) {
345 DCHECK(index >= 0); 358 DCHECK(index >= 0);
346 if (index < kNumCachedOperands) return &cache[index]; 359 if (index < kNumCachedOperands) return &cache[index];
347 return new (zone) SubKindOperand(index); 360 return new (zone) SubKindOperand(index);
348 } 361 }
349 362
350 static SubKindOperand* cast(InstructionOperand* op) { 363 static SubKindOperand* cast(InstructionOperand* op) {
351 DCHECK(op->kind() == kOperandKind); 364 DCHECK(op->kind() == kOperandKind);
352 return reinterpret_cast<SubKindOperand*>(op); 365 return reinterpret_cast<SubKindOperand*>(op);
353 } 366 }
354 367
355 static const SubKindOperand* cast(const InstructionOperand* op) { 368 static const SubKindOperand* cast(const InstructionOperand* op) {
356 DCHECK(op->kind() == kOperandKind); 369 DCHECK(op->kind() == kOperandKind);
357 return reinterpret_cast<const SubKindOperand*>(op); 370 return reinterpret_cast<const SubKindOperand*>(op);
358 } 371 }
359 372
373 static SubKindOperand cast(const InstructionOperand& op) {
374 DCHECK(op.kind() == kOperandKind);
375 return *static_cast<const SubKindOperand*>(&op);
376 }
377
360 static void SetUpCache(); 378 static void SetUpCache();
361 static void TearDownCache(); 379 static void TearDownCache();
362 380
363 private: 381 private:
364 static SubKindOperand* cache; 382 static SubKindOperand* cache;
365 383
366 SubKindOperand() : InstructionOperand(kOperandKind, 0) {} // For the caches. 384 SubKindOperand() : InstructionOperand(kOperandKind, 0) {} // For the caches.
367 explicit SubKindOperand(int index)
368 : InstructionOperand(kOperandKind, index) {}
369 }; 385 };
370 386
371 387
372 #define INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number) \ 388 #define INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number) \
373 typedef SubKindOperand<InstructionOperand::type, number> name##Operand; 389 typedef SubKindOperand<InstructionOperand::type, number> name##Operand;
374 INSTRUCTION_OPERAND_LIST(INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS) 390 INSTRUCTION_OPERAND_LIST(INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS)
375 #undef INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS 391 #undef INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS
376 392
377 393
378 class ParallelMove FINAL : public ZoneObject { 394 class ParallelMove FINAL : public ZoneObject {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 FlagsCondition flags_condition() const { 501 FlagsCondition flags_condition() const {
486 return FlagsConditionField::decode(opcode()); 502 return FlagsConditionField::decode(opcode());
487 } 503 }
488 504
489 // TODO(titzer): make control and call into flags. 505 // TODO(titzer): make control and call into flags.
490 static Instruction* New(Zone* zone, InstructionCode opcode) { 506 static Instruction* New(Zone* zone, InstructionCode opcode) {
491 return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL); 507 return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL);
492 } 508 }
493 509
494 static Instruction* New(Zone* zone, InstructionCode opcode, 510 static Instruction* New(Zone* zone, InstructionCode opcode,
495 size_t output_count, InstructionOperand** outputs, 511 size_t output_count, InstructionOperand* outputs,
496 size_t input_count, InstructionOperand** inputs, 512 size_t input_count, InstructionOperand* inputs,
497 size_t temp_count, InstructionOperand** temps) { 513 size_t temp_count, InstructionOperand* temps) {
498 DCHECK(opcode >= 0); 514 DCHECK(opcode >= 0);
499 DCHECK(output_count == 0 || outputs != NULL); 515 DCHECK(output_count == 0 || outputs != NULL);
500 DCHECK(input_count == 0 || inputs != NULL); 516 DCHECK(input_count == 0 || inputs != NULL);
501 DCHECK(temp_count == 0 || temps != NULL); 517 DCHECK(temp_count == 0 || temps != NULL);
502 size_t total_extra_ops = output_count + input_count + temp_count; 518 size_t total_extra_ops = output_count + input_count + temp_count;
503 if (total_extra_ops != 0) total_extra_ops--; 519 if (total_extra_ops != 0) total_extra_ops--;
504 int size = static_cast<int>( 520 int size = static_cast<int>(
505 RoundUp(sizeof(Instruction), sizeof(UnallocatedOperand)) + 521 RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
506 total_extra_ops * sizeof(UnallocatedOperand)); 522 total_extra_ops * sizeof(InstructionOperand));
507 return new (zone->New(size)) Instruction( 523 return new (zone->New(size)) Instruction(
508 opcode, output_count, outputs, input_count, inputs, temp_count, temps); 524 opcode, output_count, outputs, input_count, inputs, temp_count, temps);
509 } 525 }
510 526
511 // TODO(titzer): another holdover from lithium days; register allocator 527 // TODO(titzer): another holdover from lithium days; register allocator
512 // should not need to know about control instructions. 528 // should not need to know about control instructions.
513 Instruction* MarkAsControl() { 529 Instruction* MarkAsControl() {
514 bit_field_ = IsControlField::update(bit_field_, true); 530 bit_field_ = IsControlField::update(bit_field_, true);
515 return this; 531 return this;
516 } 532 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 } 568 }
553 569
554 bool IsNop() const { 570 bool IsNop() const {
555 return arch_opcode() == kArchNop && InputCount() == 0 && 571 return arch_opcode() == kArchNop && InputCount() == 0 &&
556 OutputCount() == 0 && TempCount() == 0; 572 OutputCount() == 0 && TempCount() == 0;
557 } 573 }
558 574
559 protected: 575 protected:
560 explicit Instruction(InstructionCode opcode); 576 explicit Instruction(InstructionCode opcode);
561 Instruction(InstructionCode opcode, size_t output_count, 577 Instruction(InstructionCode opcode, size_t output_count,
562 InstructionOperand** outputs, size_t input_count, 578 InstructionOperand* outputs, size_t input_count,
563 InstructionOperand** inputs, size_t temp_count, 579 InstructionOperand* inputs, size_t temp_count,
564 InstructionOperand** temps); 580 InstructionOperand* temps);
565 581
566 protected: 582 protected:
567 typedef BitField<size_t, 0, 8> OutputCountField; 583 typedef BitField<size_t, 0, 8> OutputCountField;
568 typedef BitField<size_t, 8, 16> InputCountField; 584 typedef BitField<size_t, 8, 16> InputCountField;
569 typedef BitField<size_t, 24, 6> TempCountField; 585 typedef BitField<size_t, 24, 6> TempCountField;
570 typedef BitField<bool, 30, 1> IsCallField; 586 typedef BitField<bool, 30, 1> IsCallField;
571 typedef BitField<bool, 31, 1> IsControlField; 587 typedef BitField<bool, 31, 1> IsControlField;
572 588
573 InstructionCode opcode_; 589 InstructionCode opcode_;
574 uint32_t bit_field_; 590 uint32_t bit_field_;
575 PointerMap* pointer_map_; 591 PointerMap* pointer_map_;
576 UnallocatedOperand operands_[1]; 592 InstructionOperand operands_[1];
577 }; 593 };
578 594
579 595
580 struct PrintableInstruction { 596 struct PrintableInstruction {
581 const RegisterConfiguration* register_configuration_; 597 const RegisterConfiguration* register_configuration_;
582 const Instruction* instr_; 598 const Instruction* instr_;
583 }; 599 };
584 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); 600 std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
585 601
586 602
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 1084
1069 1085
1070 std::ostream& operator<<(std::ostream& os, 1086 std::ostream& operator<<(std::ostream& os,
1071 const PrintableInstructionSequence& code); 1087 const PrintableInstructionSequence& code);
1072 1088
1073 } // namespace compiler 1089 } // namespace compiler
1074 } // namespace internal 1090 } // namespace internal
1075 } // namespace v8 1091 } // namespace v8
1076 1092
1077 #endif // V8_COMPILER_INSTRUCTION_H_ 1093 #endif // V8_COMPILER_INSTRUCTION_H_
OLDNEW
« no previous file with comments | « src/compiler/ia32/instruction-selector-ia32.cc ('k') | src/compiler/instruction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698