blob: 8a6a0ae92a9481f513dec2fff10cc84c08b6c060 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_INSTRUCTION_H_
6#define V8_COMPILER_INSTRUCTION_H_
7
8#include <deque>
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009#include <iosfwd>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include <map>
11#include <set>
12
13#include "src/compiler/common-operator.h"
14#include "src/compiler/frame.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/compiler/instruction-codes.h"
16#include "src/compiler/opcodes.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017#include "src/compiler/source-position.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/macro-assembler.h"
19#include "src/register-configuration.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/zone-allocator.h"
21
22namespace v8 {
23namespace internal {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024namespace compiler {
25
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026// Forward declarations.
27class Schedule;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028
Ben Murdochb8a8cc12014-11-26 15:28:44 +000029
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030class InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 static const int kInvalidVirtualRegister = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034 // TODO(dcarney): recover bit. INVALID can be represented as UNALLOCATED with
35 // kInvalidVirtualRegister and some DCHECKS.
36 enum Kind { INVALID, UNALLOCATED, CONSTANT, IMMEDIATE, EXPLICIT, ALLOCATED };
37
38 InstructionOperand() : InstructionOperand(INVALID) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039
40 Kind kind() const { return KindField::decode(value_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041
42#define INSTRUCTION_OPERAND_PREDICATE(name, type) \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043 bool Is##name() const { return kind() == type; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 INSTRUCTION_OPERAND_PREDICATE(Invalid, INVALID)
45 // UnallocatedOperands are place-holder operands created before register
46 // allocation. They later are assigned registers and become AllocatedOperands.
47 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED)
48 // Constant operands participate in register allocation. They are allocated to
49 // registers but have a special "spilling" behavior. When a ConstantOperand
50 // value must be rematerialized, it is loaded from an immediate constant
51 // rather from an unspilled slot.
52 INSTRUCTION_OPERAND_PREDICATE(Constant, CONSTANT)
53 // ImmediateOperands do not participate in register allocation and are only
54 // embedded directly in instructions, e.g. small integers and on some
55 // platforms Objects.
56 INSTRUCTION_OPERAND_PREDICATE(Immediate, IMMEDIATE)
57 // ExplicitOperands do not participate in register allocation. They are
58 // created by the instruction selector for direct access to registers and
59 // stack slots, completely bypassing the register allocator. They are never
60 // associated with a virtual register
61 INSTRUCTION_OPERAND_PREDICATE(Explicit, EXPLICIT)
62 // AllocatedOperands are registers or stack slots that are assigned by the
63 // register allocator and are always associated with a virtual register.
64 INSTRUCTION_OPERAND_PREDICATE(Allocated, ALLOCATED)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065#undef INSTRUCTION_OPERAND_PREDICATE
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066
67 inline bool IsAnyRegister() const;
68 inline bool IsRegister() const;
69 inline bool IsDoubleRegister() const;
70 inline bool IsStackSlot() const;
71 inline bool IsDoubleStackSlot() const;
72
73 template <typename SubKindOperand>
74 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
75 void* buffer = zone->New(sizeof(op));
76 return new (buffer) SubKindOperand(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077 }
78
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000079 static void ReplaceWith(InstructionOperand* dest,
80 const InstructionOperand* src) {
81 *dest = *src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 }
83
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 bool Equals(const InstructionOperand& that) const {
85 return this->value_ == that.value_;
86 }
87
88 bool Compare(const InstructionOperand& that) const {
89 return this->value_ < that.value_;
90 }
91
92 bool EqualsCanonicalized(const InstructionOperand& that) const {
93 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
94 }
95
96 bool CompareCanonicalized(const InstructionOperand& that) const {
97 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
98 }
99
100 void Print(const RegisterConfiguration* config) const;
101 void Print() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102
103 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
105
106 inline uint64_t GetCanonicalizedValue() const;
107
108 class KindField : public BitField64<Kind, 0, 3> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400110 uint64_t value_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111};
112
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113
114typedef ZoneVector<InstructionOperand> InstructionOperandVector;
115
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400117struct PrintableInstructionOperand {
118 const RegisterConfiguration* register_configuration_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 InstructionOperand op_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400120};
121
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123std::ostream& operator<<(std::ostream& os,
124 const PrintableInstructionOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126
127#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \
128 \
129 static OperandType* cast(InstructionOperand* op) { \
130 DCHECK_EQ(OperandKind, op->kind()); \
131 return static_cast<OperandType*>(op); \
132 } \
133 \
134 static const OperandType* cast(const InstructionOperand* op) { \
135 DCHECK_EQ(OperandKind, op->kind()); \
136 return static_cast<const OperandType*>(op); \
137 } \
138 \
139 static OperandType cast(const InstructionOperand& op) { \
140 DCHECK_EQ(OperandKind, op.kind()); \
141 return *static_cast<const OperandType*>(&op); \
142 }
143
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144class UnallocatedOperand : public InstructionOperand {
145 public:
146 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
147
148 enum ExtendedPolicy {
149 NONE,
150 ANY,
151 FIXED_REGISTER,
152 FIXED_DOUBLE_REGISTER,
153 MUST_HAVE_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 MUST_HAVE_SLOT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155 SAME_AS_FIRST_INPUT
156 };
157
158 // Lifetime of operand inside the instruction.
159 enum Lifetime {
160 // USED_AT_START operand is guaranteed to be live only at
161 // instruction start. Register allocator is free to assign the same register
162 // to some other operand used inside instruction (i.e. temporary or
163 // output).
164 USED_AT_START,
165
166 // USED_AT_END operand is treated as live until the end of
167 // instruction. This means that register allocator will not reuse it's
168 // register for any other operand inside instruction.
169 USED_AT_END
170 };
171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
173 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
175 value_ |= ExtendedPolicyField::encode(policy);
176 value_ |= LifetimeField::encode(USED_AT_END);
177 }
178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
180 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 DCHECK(policy == FIXED_SLOT);
182 value_ |= BasicPolicyField::encode(policy);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400183 value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 DCHECK(this->fixed_slot_index() == index);
185 }
186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
188 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
190 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
191 value_ |= ExtendedPolicyField::encode(policy);
192 value_ |= LifetimeField::encode(USED_AT_END);
193 value_ |= FixedRegisterField::encode(index);
194 }
195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
197 int virtual_register)
198 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
200 value_ |= ExtendedPolicyField::encode(policy);
201 value_ |= LifetimeField::encode(lifetime);
202 }
203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
205 : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
206 value_ |= HasSecondaryStorageField::encode(true);
207 value_ |= SecondaryStorageField::encode(slot_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 }
209
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 // Predicates for the operand policy.
211 bool HasAnyPolicy() const {
212 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
213 }
214 bool HasFixedPolicy() const {
215 return basic_policy() == FIXED_SLOT ||
216 extended_policy() == FIXED_REGISTER ||
217 extended_policy() == FIXED_DOUBLE_REGISTER;
218 }
219 bool HasRegisterPolicy() const {
220 return basic_policy() == EXTENDED_POLICY &&
221 extended_policy() == MUST_HAVE_REGISTER;
222 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223 bool HasSlotPolicy() const {
224 return basic_policy() == EXTENDED_POLICY &&
225 extended_policy() == MUST_HAVE_SLOT;
226 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 bool HasSameAsInputPolicy() const {
228 return basic_policy() == EXTENDED_POLICY &&
229 extended_policy() == SAME_AS_FIRST_INPUT;
230 }
231 bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
232 bool HasFixedRegisterPolicy() const {
233 return basic_policy() == EXTENDED_POLICY &&
234 extended_policy() == FIXED_REGISTER;
235 }
236 bool HasFixedDoubleRegisterPolicy() const {
237 return basic_policy() == EXTENDED_POLICY &&
238 extended_policy() == FIXED_DOUBLE_REGISTER;
239 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 bool HasSecondaryStorage() const {
241 return basic_policy() == EXTENDED_POLICY &&
242 extended_policy() == FIXED_REGISTER &&
243 HasSecondaryStorageField::decode(value_);
244 }
245 int GetSecondaryStorage() const {
246 DCHECK(HasSecondaryStorage());
247 return SecondaryStorageField::decode(value_);
248 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249
250 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 BasicPolicy basic_policy() const {
252 DCHECK_EQ(UNALLOCATED, kind());
253 return BasicPolicyField::decode(value_);
254 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255
256 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
257 ExtendedPolicy extended_policy() const {
258 DCHECK(basic_policy() == EXTENDED_POLICY);
259 return ExtendedPolicyField::decode(value_);
260 }
261
262 // [fixed_slot_index]: Only for FIXED_SLOT.
263 int fixed_slot_index() const {
264 DCHECK(HasFixedSlotPolicy());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 return static_cast<int>(static_cast<int64_t>(value_) >>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400266 FixedSlotIndexField::kShift);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 }
268
269 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
270 int fixed_register_index() const {
271 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
272 return FixedRegisterField::decode(value_);
273 }
274
275 // [virtual_register]: The virtual register ID for this operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 int32_t virtual_register() const {
277 DCHECK_EQ(UNALLOCATED, kind());
278 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
279 }
280
281 // TODO(dcarney): remove this.
282 void set_virtual_register(int32_t id) {
283 DCHECK_EQ(UNALLOCATED, kind());
284 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 }
286
287 // [lifetime]: Only for non-FIXED_SLOT.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400288 bool IsUsedAtStart() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 DCHECK(basic_policy() == EXTENDED_POLICY);
290 return LifetimeField::decode(value_) == USED_AT_START;
291 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292
293 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
294
295 // The encoding used for UnallocatedOperand operands depends on the policy
296 // that is
297 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
298 // because it accommodates a larger pay-load.
299 //
300 // For FIXED_SLOT policy:
301 // +------------------------------------------------+
302 // | slot_index | 0 | virtual_register | 001 |
303 // +------------------------------------------------+
304 //
305 // For all other (extended) policies:
306 // +-----------------------------------------------------+
307 // | reg_index | L | PPP | 1 | virtual_register | 001 |
308 // +-----------------------------------------------------+
309 // L ... Lifetime
310 // P ... Policy
311 //
312 // The slot index is a signed value which requires us to decode it manually
313 // instead of using the BitField utility class.
314
315 STATIC_ASSERT(KindField::kSize == 3);
316
317 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
318
319 // BitFields for all unallocated operands.
320 class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
321
322 // BitFields specific to BasicPolicy::FIXED_SLOT.
323 class FixedSlotIndexField : public BitField64<int, 36, 28> {};
324
325 // BitFields specific to BasicPolicy::EXTENDED_POLICY.
326 class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
327 class LifetimeField : public BitField64<Lifetime, 39, 1> {};
328 class HasSecondaryStorageField : public BitField64<bool, 40, 1> {};
329 class FixedRegisterField : public BitField64<int, 41, 6> {};
330 class SecondaryStorageField : public BitField64<int, 47, 3> {};
331
332 private:
333 explicit UnallocatedOperand(int virtual_register)
334 : InstructionOperand(UNALLOCATED) {
335 value_ |=
336 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
337 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338};
339
340
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341class ConstantOperand : public InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 explicit ConstantOperand(int virtual_register)
344 : InstructionOperand(CONSTANT) {
345 value_ |=
346 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
347 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349 int32_t virtual_register() const {
350 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
351 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 static ConstantOperand* New(Zone* zone, int virtual_register) {
354 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
355 }
356
357 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
358
359 STATIC_ASSERT(KindField::kSize == 3);
360 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
361};
362
363
364class ImmediateOperand : public InstructionOperand {
365 public:
366 enum ImmediateType { INLINE, INDEXED };
367
368 explicit ImmediateOperand(ImmediateType type, int32_t value)
369 : InstructionOperand(IMMEDIATE) {
370 value_ |= TypeField::encode(type);
371 value_ |= static_cast<int64_t>(value) << ValueField::kShift;
372 }
373
374 ImmediateType type() const { return TypeField::decode(value_); }
375
376 int32_t inline_value() const {
377 DCHECK_EQ(INLINE, type());
378 return static_cast<int64_t>(value_) >> ValueField::kShift;
379 }
380
381 int32_t indexed_value() const {
382 DCHECK_EQ(INDEXED, type());
383 return static_cast<int64_t>(value_) >> ValueField::kShift;
384 }
385
386 static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
387 return InstructionOperand::New(zone, ImmediateOperand(type, value));
388 }
389
390 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
391
392 STATIC_ASSERT(KindField::kSize == 3);
393 class TypeField : public BitField64<ImmediateType, 3, 1> {};
394 class ValueField : public BitField64<int32_t, 32, 32> {};
395};
396
397
398class LocationOperand : public InstructionOperand {
399 public:
400 enum LocationKind { REGISTER, STACK_SLOT };
401
402 LocationOperand(InstructionOperand::Kind operand_kind,
403 LocationOperand::LocationKind location_kind,
404 MachineRepresentation rep, int index)
405 : InstructionOperand(operand_kind) {
406 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
407 DCHECK(IsSupportedRepresentation(rep));
408 value_ |= LocationKindField::encode(location_kind);
409 value_ |= RepresentationField::encode(rep);
410 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
411 }
412
413 int index() const {
414 DCHECK(IsStackSlot() || IsDoubleStackSlot());
415 return static_cast<int64_t>(value_) >> IndexField::kShift;
416 }
417
418 Register GetRegister() const {
419 DCHECK(IsRegister());
420 return Register::from_code(static_cast<int64_t>(value_) >>
421 IndexField::kShift);
422 }
423
424 DoubleRegister GetDoubleRegister() const {
425 DCHECK(IsDoubleRegister());
426 return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
427 IndexField::kShift);
428 }
429
430 LocationKind location_kind() const {
431 return LocationKindField::decode(value_);
432 }
433
434 MachineRepresentation representation() const {
435 return RepresentationField::decode(value_);
436 }
437
438 static bool IsSupportedRepresentation(MachineRepresentation rep) {
439 switch (rep) {
440 case MachineRepresentation::kWord32:
441 case MachineRepresentation::kWord64:
442 case MachineRepresentation::kFloat32:
443 case MachineRepresentation::kFloat64:
444 case MachineRepresentation::kTagged:
445 return true;
446 case MachineRepresentation::kBit:
447 case MachineRepresentation::kWord8:
448 case MachineRepresentation::kWord16:
449 case MachineRepresentation::kNone:
450 return false;
451 }
452 UNREACHABLE();
453 return false;
454 }
455
456 static LocationOperand* cast(InstructionOperand* op) {
457 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
458 return static_cast<LocationOperand*>(op);
459 }
460
461 static const LocationOperand* cast(const InstructionOperand* op) {
462 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
463 return static_cast<const LocationOperand*>(op);
464 }
465
466 static LocationOperand cast(const InstructionOperand& op) {
467 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind());
468 return *static_cast<const LocationOperand*>(&op);
469 }
470
471 STATIC_ASSERT(KindField::kSize == 3);
472 class LocationKindField : public BitField64<LocationKind, 3, 2> {};
473 class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
474 class IndexField : public BitField64<int32_t, 35, 29> {};
475};
476
477
478class ExplicitOperand : public LocationOperand {
479 public:
480 ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
481
482 static ExplicitOperand* New(Zone* zone, LocationKind kind,
483 MachineRepresentation rep, int index) {
484 return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
485 }
486
487 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT);
488};
489
490
491class AllocatedOperand : public LocationOperand {
492 public:
493 AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
494 : LocationOperand(ALLOCATED, kind, rep, index) {}
495
496 static AllocatedOperand* New(Zone* zone, LocationKind kind,
497 MachineRepresentation rep, int index) {
498 return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
499 }
500
501 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
502};
503
504
505#undef INSTRUCTION_OPERAND_CASTS
506
507
508bool InstructionOperand::IsAnyRegister() const {
509 return (IsAllocated() || IsExplicit()) &&
510 LocationOperand::cast(this)->location_kind() ==
511 LocationOperand::REGISTER;
512}
513
514
515bool InstructionOperand::IsRegister() const {
516 return IsAnyRegister() &&
517 !IsFloatingPoint(LocationOperand::cast(this)->representation());
518}
519
520bool InstructionOperand::IsDoubleRegister() const {
521 return IsAnyRegister() &&
522 IsFloatingPoint(LocationOperand::cast(this)->representation());
523}
524
525bool InstructionOperand::IsStackSlot() const {
526 return (IsAllocated() || IsExplicit()) &&
527 LocationOperand::cast(this)->location_kind() ==
528 LocationOperand::STACK_SLOT &&
529 !IsFloatingPoint(LocationOperand::cast(this)->representation());
530}
531
532bool InstructionOperand::IsDoubleStackSlot() const {
533 return (IsAllocated() || IsExplicit()) &&
534 LocationOperand::cast(this)->location_kind() ==
535 LocationOperand::STACK_SLOT &&
536 IsFloatingPoint(LocationOperand::cast(this)->representation());
537}
538
539uint64_t InstructionOperand::GetCanonicalizedValue() const {
540 if (IsAllocated() || IsExplicit()) {
541 // TODO(dcarney): put machine type last and mask.
542 MachineRepresentation canonicalized_representation =
543 IsFloatingPoint(LocationOperand::cast(this)->representation())
544 ? MachineRepresentation::kFloat64
545 : MachineRepresentation::kNone;
546 return InstructionOperand::KindField::update(
547 LocationOperand::RepresentationField::update(
548 this->value_, canonicalized_representation),
549 LocationOperand::EXPLICIT);
550 }
551 return this->value_;
552}
553
554
555// Required for maps that don't care about machine type.
556struct CompareOperandModuloType {
557 bool operator()(const InstructionOperand& a,
558 const InstructionOperand& b) const {
559 return a.CompareCanonicalized(b);
560 }
561};
562
563
564class MoveOperands final : public ZoneObject {
565 public:
566 MoveOperands(const InstructionOperand& source,
567 const InstructionOperand& destination)
568 : source_(source), destination_(destination) {
569 DCHECK(!source.IsInvalid() && !destination.IsInvalid());
570 }
571
572 const InstructionOperand& source() const { return source_; }
573 InstructionOperand& source() { return source_; }
574 void set_source(const InstructionOperand& operand) { source_ = operand; }
575
576 const InstructionOperand& destination() const { return destination_; }
577 InstructionOperand& destination() { return destination_; }
578 void set_destination(const InstructionOperand& operand) {
579 destination_ = operand;
580 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000581
582 // The gap resolver marks moves as "in-progress" by clearing the
583 // destination (but not the source).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 bool IsPending() const {
585 return destination_.IsInvalid() && !source_.IsInvalid();
586 }
587 void SetPending() { destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588
589 // True if this move a move into the given destination operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590 bool Blocks(const InstructionOperand& operand) const {
591 return !IsEliminated() && source().EqualsCanonicalized(operand);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 }
593
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000594 // A move is redundant if it's been eliminated or if its source and
595 // destination are the same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596 bool IsRedundant() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
598 return IsEliminated() || source_.EqualsCanonicalized(destination_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000599 }
600
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 // We clear both operands to indicate move that's been eliminated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 void Eliminate() { source_ = destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 bool IsEliminated() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
605 return source_.IsInvalid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606 }
607
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 void Print(const RegisterConfiguration* config) const;
609 void Print() const;
610
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 InstructionOperand source_;
613 InstructionOperand destination_;
614
615 DISALLOW_COPY_AND_ASSIGN(MoveOperands);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616};
617
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400618
619struct PrintableMoveOperands {
620 const RegisterConfiguration* register_configuration_;
621 const MoveOperands* move_operands_;
622};
623
624
625std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
626
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628class ParallelMove final : public ZoneVector<MoveOperands*>, public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {
631 reserve(4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 }
633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000634 MoveOperands* AddMove(const InstructionOperand& from,
635 const InstructionOperand& to) {
636 auto zone = get_allocator().zone();
637 auto move = new (zone) MoveOperands(from, to);
638 push_back(move);
639 return move;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 }
641
642 bool IsRedundant() const;
643
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 // Prepare this ParallelMove to insert move as if it happened in a subsequent
645 // ParallelMove. move->source() may be changed. The MoveOperand returned
646 // must be Eliminated.
647 MoveOperands* PrepareInsertAfter(MoveOperands* move) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648
649 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000650 DISALLOW_COPY_AND_ASSIGN(ParallelMove);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651};
652
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400653
654struct PrintableParallelMove {
655 const RegisterConfiguration* register_configuration_;
656 const ParallelMove* parallel_move_;
657};
658
659
660std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
661
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663class ReferenceMap final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000664 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000665 explicit ReferenceMap(Zone* zone)
666 : reference_operands_(8, zone), instruction_position_(-1) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 const ZoneVector<InstructionOperand>& reference_operands() const {
669 return reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670 }
671 int instruction_position() const { return instruction_position_; }
672
673 void set_instruction_position(int pos) {
674 DCHECK(instruction_position_ == -1);
675 instruction_position_ = pos;
676 }
677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000678 void RecordReference(const AllocatedOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679
680 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681 friend std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 ZoneVector<InstructionOperand> reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 int instruction_position_;
685};
686
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000687std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689class Instruction final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 public:
691 size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 const InstructionOperand* OutputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000693 DCHECK(i < OutputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000694 return &operands_[i];
695 }
696 InstructionOperand* OutputAt(size_t i) {
697 DCHECK(i < OutputCount());
698 return &operands_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 }
700
701 bool HasOutput() const { return OutputCount() == 1; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 const InstructionOperand* Output() const { return OutputAt(0); }
703 InstructionOperand* Output() { return OutputAt(0); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704
705 size_t InputCount() const { return InputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 const InstructionOperand* InputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 return &operands_[OutputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 InstructionOperand* InputAt(size_t i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400711 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 return &operands_[OutputCount() + i];
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400713 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714
715 size_t TempCount() const { return TempCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 const InstructionOperand* TempAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 DCHECK(i < TempCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 return &operands_[OutputCount() + InputCount() + i];
719 }
720 InstructionOperand* TempAt(size_t i) {
721 DCHECK(i < TempCount());
722 return &operands_[OutputCount() + InputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 }
724
725 InstructionCode opcode() const { return opcode_; }
726 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
727 AddressingMode addressing_mode() const {
728 return AddressingModeField::decode(opcode());
729 }
730 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
731 FlagsCondition flags_condition() const {
732 return FlagsConditionField::decode(opcode());
733 }
734
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 // TODO(titzer): make call into a flags.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736 static Instruction* New(Zone* zone, InstructionCode opcode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 }
739
740 static Instruction* New(Zone* zone, InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 size_t output_count, InstructionOperand* outputs,
742 size_t input_count, InstructionOperand* inputs,
743 size_t temp_count, InstructionOperand* temps) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 DCHECK(opcode >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 DCHECK(output_count == 0 || outputs != nullptr);
746 DCHECK(input_count == 0 || inputs != nullptr);
747 DCHECK(temp_count == 0 || temps != nullptr);
748 size_t total_extra_ops = output_count + input_count + temp_count;
749 if (total_extra_ops != 0) total_extra_ops--;
750 int size = static_cast<int>(
751 RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
752 total_extra_ops * sizeof(InstructionOperand));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 return new (zone->New(size)) Instruction(
754 opcode, output_count, outputs, input_count, inputs, temp_count, temps);
755 }
756
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757 Instruction* MarkAsCall() {
758 bit_field_ = IsCallField::update(bit_field_, true);
759 return this;
760 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 bool IsCall() const { return IsCallField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 bool NeedsReferenceMap() const { return IsCall(); }
763 bool HasReferenceMap() const { return reference_map_ != nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000764
765 bool ClobbersRegisters() const { return IsCall(); }
766 bool ClobbersTemps() const { return IsCall(); }
767 bool ClobbersDoubleRegisters() const { return IsCall(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 ReferenceMap* reference_map() const { return reference_map_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 void set_reference_map(ReferenceMap* map) {
771 DCHECK(NeedsReferenceMap());
772 DCHECK(!reference_map_);
773 reference_map_ = map;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000774 }
775
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400776 void OverwriteWithNop() {
777 opcode_ = ArchOpcodeField::encode(kArchNop);
778 bit_field_ = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779 reference_map_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400780 }
781
782 bool IsNop() const {
783 return arch_opcode() == kArchNop && InputCount() == 0 &&
784 OutputCount() == 0 && TempCount() == 0;
785 }
786
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000787 enum GapPosition {
788 START,
789 END,
790 FIRST_GAP_POSITION = START,
791 LAST_GAP_POSITION = END
792 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000793
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
795 if (parallel_moves_[pos] == nullptr) {
796 parallel_moves_[pos] = new (zone) ParallelMove(zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798 return parallel_moves_[pos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799 }
800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000801 ParallelMove* GetParallelMove(GapPosition pos) {
802 return parallel_moves_[pos];
803 }
804
805 const ParallelMove* GetParallelMove(GapPosition pos) const {
806 return parallel_moves_[pos];
807 }
808
809 bool AreMovesRedundant() const;
810
811 ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
812 ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
813
814 void Print(const RegisterConfiguration* config) const;
815 void Print() const;
816
817 private:
818 explicit Instruction(InstructionCode opcode);
819
820 Instruction(InstructionCode opcode, size_t output_count,
821 InstructionOperand* outputs, size_t input_count,
822 InstructionOperand* inputs, size_t temp_count,
823 InstructionOperand* temps);
824
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 typedef BitField<size_t, 0, 8> OutputCountField;
826 typedef BitField<size_t, 8, 16> InputCountField;
827 typedef BitField<size_t, 24, 6> TempCountField;
828 typedef BitField<bool, 30, 1> IsCallField;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000829
830 InstructionCode opcode_;
831 uint32_t bit_field_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000832 ParallelMove* parallel_moves_[2];
833 ReferenceMap* reference_map_;
834 InstructionOperand operands_[1];
835
836 DISALLOW_COPY_AND_ASSIGN(Instruction);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837};
838
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400839
840struct PrintableInstruction {
841 const RegisterConfiguration* register_configuration_;
842 const Instruction* instr_;
843};
844std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
845
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000847class RpoNumber final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 static const int kInvalidRpoNumber = -1;
850 int ToInt() const {
851 DCHECK(IsValid());
852 return index_;
853 }
854 size_t ToSize() const {
855 DCHECK(IsValid());
856 return static_cast<size_t>(index_);
857 }
858 bool IsValid() const { return index_ >= 0; }
859 static RpoNumber FromInt(int index) { return RpoNumber(index); }
860 static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 bool IsNext(const RpoNumber other) const {
863 DCHECK(IsValid());
864 return other.index_ == this->index_ + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000865 }
866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867 // Comparison operators.
868 bool operator==(RpoNumber other) const { return index_ == other.index_; }
869 bool operator!=(RpoNumber other) const { return index_ != other.index_; }
870 bool operator>(RpoNumber other) const { return index_ > other.index_; }
871 bool operator<(RpoNumber other) const { return index_ < other.index_; }
872 bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
873 bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874
875 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 explicit RpoNumber(int32_t index) : index_(index) {}
877 int32_t index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878};
879
880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881std::ostream& operator<<(std::ostream&, const RpoNumber&);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882
883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884class Constant final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400886 enum Type {
887 kInt32,
888 kInt64,
889 kFloat32,
890 kFloat64,
891 kExternalReference,
892 kHeapObject,
893 kRpoNumber
894 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 explicit Constant(int32_t v);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000897 explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400898 explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000899 explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
900 explicit Constant(ExternalReference ref)
901 : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
902 explicit Constant(Handle<HeapObject> obj)
903 : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905
906 Type type() const { return type_; }
907
908 int32_t ToInt32() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400909 DCHECK(type() == kInt32 || type() == kInt64);
910 const int32_t value = static_cast<int32_t>(value_);
911 DCHECK_EQ(value_, static_cast<int64_t>(value));
912 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 }
914
915 int64_t ToInt64() const {
916 if (type() == kInt32) return ToInt32();
917 DCHECK_EQ(kInt64, type());
918 return value_;
919 }
920
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 float ToFloat32() const {
922 DCHECK_EQ(kFloat32, type());
923 return bit_cast<float>(static_cast<int32_t>(value_));
924 }
925
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926 double ToFloat64() const {
927 if (type() == kInt32) return ToInt32();
928 DCHECK_EQ(kFloat64, type());
929 return bit_cast<double>(value_);
930 }
931
932 ExternalReference ToExternalReference() const {
933 DCHECK_EQ(kExternalReference, type());
934 return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
935 }
936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 RpoNumber ToRpoNumber() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400938 DCHECK_EQ(kRpoNumber, type());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939 return RpoNumber::FromInt(static_cast<int>(value_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400940 }
941
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000942 Handle<HeapObject> ToHeapObject() const {
943 DCHECK_EQ(kHeapObject, type());
944 return bit_cast<Handle<HeapObject> >(static_cast<intptr_t>(value_));
945 }
946
947 private:
948 Type type_;
949 int64_t value_;
950};
951
952
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000953std::ostream& operator<<(std::ostream& os, const Constant& constant);
954
955
956// Forward declarations.
957class FrameStateDescriptor;
958
959
960enum class StateValueKind { kPlain, kNested, kDuplicate };
961
962
963class StateValueDescriptor {
964 public:
965 explicit StateValueDescriptor(Zone* zone)
966 : kind_(StateValueKind::kPlain),
967 type_(MachineType::AnyTagged()),
968 id_(0),
969 fields_(zone) {}
970
971 static StateValueDescriptor Plain(Zone* zone, MachineType type) {
972 return StateValueDescriptor(StateValueKind::kPlain, zone, type, 0);
973 }
974 static StateValueDescriptor Recursive(Zone* zone, size_t id) {
975 return StateValueDescriptor(StateValueKind::kNested, zone,
976 MachineType::AnyTagged(), id);
977 }
978 static StateValueDescriptor Duplicate(Zone* zone, size_t id) {
979 return StateValueDescriptor(StateValueKind::kDuplicate, zone,
980 MachineType::AnyTagged(), id);
981 }
982
983 size_t size() { return fields_.size(); }
984 ZoneVector<StateValueDescriptor>& fields() { return fields_; }
985 int IsPlain() { return kind_ == StateValueKind::kPlain; }
986 int IsNested() { return kind_ == StateValueKind::kNested; }
987 int IsDuplicate() { return kind_ == StateValueKind::kDuplicate; }
988 MachineType type() const { return type_; }
989 MachineType GetOperandType(size_t index) const {
990 return fields_[index].type_;
991 }
992 size_t id() const { return id_; }
993
994 private:
995 StateValueDescriptor(StateValueKind kind, Zone* zone, MachineType type,
996 size_t id)
997 : kind_(kind), type_(type), id_(id), fields_(zone) {}
998
999 StateValueKind kind_;
1000 MachineType type_;
1001 size_t id_;
1002 ZoneVector<StateValueDescriptor> fields_;
1003};
1004
1005
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006class FrameStateDescriptor : public ZoneObject {
1007 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
1009 OutputFrameStateCombine state_combine,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 size_t parameters_count, size_t locals_count,
1011 size_t stack_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001012 MaybeHandle<SharedFunctionInfo> shared_info,
1013 FrameStateDescriptor* outer_state = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014
1015 FrameStateType type() const { return type_; }
1016 BailoutId bailout_id() const { return bailout_id_; }
1017 OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
1018 size_t parameters_count() const { return parameters_count_; }
1019 size_t locals_count() const { return locals_count_; }
1020 size_t stack_count() const { return stack_count_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 FrameStateDescriptor* outer_state() const { return outer_state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001023 bool HasContext() const {
1024 return FrameStateFunctionInfo::IsJSFunctionType(type_);
1025 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001027 size_t GetSize(OutputFrameStateCombine combine =
1028 OutputFrameStateCombine::Ignore()) const;
1029 size_t GetTotalSize() const;
1030 size_t GetFrameCount() const;
1031 size_t GetJSFrameCount() const;
1032
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001033 MachineType GetType(size_t index) const {
1034 return values_.GetOperandType(index);
1035 }
1036 StateValueDescriptor* GetStateValueDescriptor() { return &values_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001037
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 private:
1039 FrameStateType type_;
1040 BailoutId bailout_id_;
1041 OutputFrameStateCombine frame_state_combine_;
1042 size_t parameters_count_;
1043 size_t locals_count_;
1044 size_t stack_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 StateValueDescriptor values_;
1046 MaybeHandle<SharedFunctionInfo> const shared_info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047 FrameStateDescriptor* outer_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048};
1049
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050
1051typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001052
1053
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054class PhiInstruction final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001055 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001056 typedef ZoneVector<InstructionOperand> Inputs;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001057
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001058 PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
1059
1060 void SetInput(size_t offset, int virtual_register);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001061
1062 int virtual_register() const { return virtual_register_; }
1063 const IntVector& operands() const { return operands_; }
1064
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 // TODO(dcarney): this has no real business being here, since it's internal to
1066 // the register allocator, but putting it here was convenient.
1067 const InstructionOperand& output() const { return output_; }
1068 InstructionOperand& output() { return output_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001069
1070 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001071 const int virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 InstructionOperand output_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001073 IntVector operands_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001074};
1075
1076
1077// Analogue of BasicBlock for Instructions instead of Nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078class InstructionBlock final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001079 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
1081 RpoNumber loop_end, bool deferred, bool handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001082
1083 // Instruction indexes (used by the register allocator).
1084 int first_instruction_index() const {
1085 DCHECK(code_start_ >= 0);
1086 DCHECK(code_end_ > 0);
1087 DCHECK(code_end_ >= code_start_);
1088 return code_start_;
1089 }
1090 int last_instruction_index() const {
1091 DCHECK(code_start_ >= 0);
1092 DCHECK(code_end_ > 0);
1093 DCHECK(code_end_ >= code_start_);
1094 return code_end_ - 1;
1095 }
1096
1097 int32_t code_start() const { return code_start_; }
1098 void set_code_start(int32_t start) { code_start_ = start; }
1099
1100 int32_t code_end() const { return code_end_; }
1101 void set_code_end(int32_t end) { code_end_ = end; }
1102
1103 bool IsDeferred() const { return deferred_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001104 bool IsHandler() const { return handler_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106 RpoNumber ao_number() const { return ao_number_; }
1107 RpoNumber rpo_number() const { return rpo_number_; }
1108 RpoNumber loop_header() const { return loop_header_; }
1109 RpoNumber loop_end() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001110 DCHECK(IsLoopHeader());
1111 return loop_end_;
1112 }
1113 inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
1114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001115 typedef ZoneVector<RpoNumber> Predecessors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001116 Predecessors& predecessors() { return predecessors_; }
1117 const Predecessors& predecessors() const { return predecessors_; }
1118 size_t PredecessorCount() const { return predecessors_.size(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 size_t PredecessorIndexOf(RpoNumber rpo_number) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001120
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 typedef ZoneVector<RpoNumber> Successors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001122 Successors& successors() { return successors_; }
1123 const Successors& successors() const { return successors_; }
1124 size_t SuccessorCount() const { return successors_.size(); }
1125
1126 typedef ZoneVector<PhiInstruction*> PhiInstructions;
1127 const PhiInstructions& phis() const { return phis_; }
1128 void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
1129
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001130 void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
1131
1132 bool needs_frame() const { return needs_frame_; }
1133 void mark_needs_frame() { needs_frame_ = true; }
1134
1135 bool must_construct_frame() const { return must_construct_frame_; }
1136 void mark_must_construct_frame() { must_construct_frame_ = true; }
1137
1138 bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
1139 void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
1140
1141 void set_last_deferred(RpoNumber last) { last_deferred_ = last; }
1142 RpoNumber last_deferred() const { return last_deferred_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001143
1144 private:
1145 Successors successors_;
1146 Predecessors predecessors_;
1147 PhiInstructions phis_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148 RpoNumber ao_number_; // Assembly order number.
1149 const RpoNumber rpo_number_;
1150 const RpoNumber loop_header_;
1151 const RpoNumber loop_end_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001152 int32_t code_start_; // start index of arch-specific code.
1153 int32_t code_end_; // end index of arch-specific code.
1154 const bool deferred_; // Block contains deferred code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155 const bool handler_; // Block is a handler entry point.
1156 bool needs_frame_;
1157 bool must_construct_frame_;
1158 bool must_deconstruct_frame_;
1159 RpoNumber last_deferred_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001160};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161
1162typedef ZoneDeque<Constant> ConstantDeque;
1163typedef std::map<int, Constant, std::less<int>,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 zone_allocator<std::pair<const int, Constant> > > ConstantMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165
1166typedef ZoneDeque<Instruction*> InstructionDeque;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001167typedef ZoneDeque<ReferenceMap*> ReferenceMapDeque;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001168typedef ZoneVector<InstructionBlock*> InstructionBlocks;
1169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001170
1171// Forward declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001172struct PrintableInstructionSequence;
1173
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174
1175// Represents architecture-specific generated code before, during, and after
1176// register allocation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001177class InstructionSequence final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001178 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001179 static InstructionBlocks* InstructionBlocksFor(Zone* zone,
1180 const Schedule* schedule);
1181 // Puts the deferred blocks last.
1182 static void ComputeAssemblyOrder(InstructionBlocks* blocks);
1183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001184 InstructionSequence(Isolate* isolate, Zone* zone,
1185 InstructionBlocks* instruction_blocks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 int NextVirtualRegister();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001188 int VirtualRegisterCount() const { return next_virtual_register_; }
1189
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001190 const InstructionBlocks& instruction_blocks() const {
1191 return *instruction_blocks_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 }
1193
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001194 int InstructionBlockCount() const {
1195 return static_cast<int>(instruction_blocks_->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 }
1197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001199 return instruction_blocks_->at(rpo_number.ToSize());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001200 }
1201
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001202 int LastLoopInstructionIndex(const InstructionBlock* block) {
1203 return instruction_blocks_->at(block->loop_end().ToSize() - 1)
1204 ->last_instruction_index();
1205 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001207 const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001208 return instruction_blocks_->at(rpo_number.ToSize());
1209 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001211 InstructionBlock* GetInstructionBlock(int instruction_index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 static MachineRepresentation DefaultRepresentation() {
1214 return MachineType::PointerRepresentation();
1215 }
1216 MachineRepresentation GetRepresentation(int virtual_register) const;
1217 void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 bool IsReference(int virtual_register) const {
1220 return GetRepresentation(virtual_register) ==
1221 MachineRepresentation::kTagged;
1222 }
1223 bool IsFloat(int virtual_register) const {
1224 return IsFloatingPoint(GetRepresentation(virtual_register));
1225 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001227 Instruction* GetBlockStart(RpoNumber rpo) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001228
1229 typedef InstructionDeque::const_iterator const_iterator;
1230 const_iterator begin() const { return instructions_.begin(); }
1231 const_iterator end() const { return instructions_.end(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001232 const InstructionDeque& instructions() const { return instructions_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001233 int LastInstructionIndex() const {
1234 return static_cast<int>(instructions().size()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 Instruction* InstructionAt(int index) const {
1238 DCHECK(index >= 0);
1239 DCHECK(index < static_cast<int>(instructions_.size()));
1240 return instructions_[index];
1241 }
1242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001243 Isolate* isolate() const { return isolate_; }
1244 const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001245 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001247 // Used by the instruction selector while adding instructions.
1248 int AddInstruction(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 void StartBlock(RpoNumber rpo);
1250 void EndBlock(RpoNumber rpo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001251
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001252 int AddConstant(int virtual_register, Constant constant) {
1253 // TODO(titzer): allow RPO numbers as constants?
1254 DCHECK(constant.type() != Constant::kRpoNumber);
1255 DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256 DCHECK(constants_.find(virtual_register) == constants_.end());
1257 constants_.insert(std::make_pair(virtual_register, constant));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258 return virtual_register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 }
1260 Constant GetConstant(int virtual_register) const {
1261 ConstantMap::const_iterator it = constants_.find(virtual_register);
1262 DCHECK(it != constants_.end());
1263 DCHECK_EQ(virtual_register, it->first);
1264 return it->second;
1265 }
1266
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001267 typedef ZoneVector<Constant> Immediates;
1268 Immediates& immediates() { return immediates_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 ImmediateOperand AddImmediate(const Constant& constant) {
1271 if (constant.type() == Constant::kInt32) {
1272 return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
1273 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274 int index = static_cast<int>(immediates_.size());
1275 immediates_.push_back(constant);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 return ImmediateOperand(ImmediateOperand::INDEXED, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001277 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278
1279 Constant GetImmediate(const ImmediateOperand* op) const {
1280 switch (op->type()) {
1281 case ImmediateOperand::INLINE:
1282 return Constant(op->inline_value());
1283 case ImmediateOperand::INDEXED: {
1284 int index = op->indexed_value();
1285 DCHECK(index >= 0);
1286 DCHECK(index < static_cast<int>(immediates_.size()));
1287 return immediates_[index];
1288 }
1289 }
1290 UNREACHABLE();
1291 return Constant(static_cast<int32_t>(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 }
1293
1294 class StateId {
1295 public:
1296 static StateId FromInt(int id) { return StateId(id); }
1297 int ToInt() const { return id_; }
1298
1299 private:
1300 explicit StateId(int id) : id_(id) {}
1301 int id_;
1302 };
1303
1304 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor);
1305 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
1306 int GetFrameStateDescriptorCount();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001307 DeoptimizationVector const& frame_state_descriptors() const {
1308 return deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 }
1310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001311 RpoNumber InputRpo(Instruction* instr, size_t index);
1312
1313 bool GetSourcePosition(const Instruction* instr,
1314 SourcePosition* result) const;
1315 void SetSourcePosition(const Instruction* instr, SourcePosition value);
1316
1317 bool ContainsCall() const {
1318 for (Instruction* instr : instructions_) {
1319 if (instr->IsCall()) return true;
1320 }
1321 return false;
1322 }
1323 void Print(const RegisterConfiguration* config) const;
1324 void Print() const;
1325
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001326 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001327 friend std::ostream& operator<<(std::ostream& os,
1328 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 typedef ZoneMap<const Instruction*, SourcePosition> SourcePositionMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001332 Isolate* isolate_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001333 Zone* const zone_;
1334 InstructionBlocks* const instruction_blocks_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001335 SourcePositionMap source_positions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001336 IntVector block_starts_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001337 ConstantMap constants_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001338 Immediates immediates_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001339 InstructionDeque instructions_;
1340 int next_virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001341 ReferenceMapDeque reference_maps_;
1342 ZoneVector<MachineRepresentation> representations_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001343 DeoptimizationVector deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001344
1345 DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346};
1347
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001348
1349struct PrintableInstructionSequence {
1350 const RegisterConfiguration* register_configuration_;
1351 const InstructionSequence* sequence_;
1352};
1353
1354
1355std::ostream& operator<<(std::ostream& os,
1356 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001357
1358} // namespace compiler
1359} // namespace internal
1360} // namespace v8
1361
1362#endif // V8_COMPILER_INSTRUCTION_H_