blob: 9c978cee7c37543a40f791d14a730b6879c2edd2 [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;
Ben Murdoch097c5b22016-05-18 11:27:45 +010070 inline bool IsSimd128Register() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 inline bool IsStackSlot() const;
72 inline bool IsDoubleStackSlot() const;
Ben Murdoch097c5b22016-05-18 11:27:45 +010073 inline bool IsSimd128StackSlot() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074
75 template <typename SubKindOperand>
76 static SubKindOperand* New(Zone* zone, const SubKindOperand& op) {
77 void* buffer = zone->New(sizeof(op));
78 return new (buffer) SubKindOperand(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 }
80
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 static void ReplaceWith(InstructionOperand* dest,
82 const InstructionOperand* src) {
83 *dest = *src;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 }
85
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086 bool Equals(const InstructionOperand& that) const {
87 return this->value_ == that.value_;
88 }
89
90 bool Compare(const InstructionOperand& that) const {
91 return this->value_ < that.value_;
92 }
93
94 bool EqualsCanonicalized(const InstructionOperand& that) const {
95 return this->GetCanonicalizedValue() == that.GetCanonicalizedValue();
96 }
97
98 bool CompareCanonicalized(const InstructionOperand& that) const {
99 return this->GetCanonicalizedValue() < that.GetCanonicalizedValue();
100 }
101
102 void Print(const RegisterConfiguration* config) const;
103 void Print() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104
105 protected:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 explicit InstructionOperand(Kind kind) : value_(KindField::encode(kind)) {}
107
108 inline uint64_t GetCanonicalizedValue() const;
109
110 class KindField : public BitField64<Kind, 0, 3> {};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000111
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112 uint64_t value_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113};
114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115
116typedef ZoneVector<InstructionOperand> InstructionOperandVector;
117
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400119struct PrintableInstructionOperand {
120 const RegisterConfiguration* register_configuration_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 InstructionOperand op_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122};
123
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125std::ostream& operator<<(std::ostream& os,
126 const PrintableInstructionOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128
129#define INSTRUCTION_OPERAND_CASTS(OperandType, OperandKind) \
130 \
131 static OperandType* cast(InstructionOperand* op) { \
132 DCHECK_EQ(OperandKind, op->kind()); \
133 return static_cast<OperandType*>(op); \
134 } \
135 \
136 static const OperandType* cast(const InstructionOperand* op) { \
137 DCHECK_EQ(OperandKind, op->kind()); \
138 return static_cast<const OperandType*>(op); \
139 } \
140 \
141 static OperandType cast(const InstructionOperand& op) { \
142 DCHECK_EQ(OperandKind, op.kind()); \
143 return *static_cast<const OperandType*>(&op); \
144 }
145
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146class UnallocatedOperand : public InstructionOperand {
147 public:
148 enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
149
150 enum ExtendedPolicy {
151 NONE,
152 ANY,
153 FIXED_REGISTER,
154 FIXED_DOUBLE_REGISTER,
155 MUST_HAVE_REGISTER,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 MUST_HAVE_SLOT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 SAME_AS_FIRST_INPUT
158 };
159
160 // Lifetime of operand inside the instruction.
161 enum Lifetime {
162 // USED_AT_START operand is guaranteed to be live only at
163 // instruction start. Register allocator is free to assign the same register
164 // to some other operand used inside instruction (i.e. temporary or
165 // output).
166 USED_AT_START,
167
168 // USED_AT_END operand is treated as live until the end of
169 // instruction. This means that register allocator will not reuse it's
170 // register for any other operand inside instruction.
171 USED_AT_END
172 };
173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 UnallocatedOperand(ExtendedPolicy policy, int virtual_register)
175 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
177 value_ |= ExtendedPolicyField::encode(policy);
178 value_ |= LifetimeField::encode(USED_AT_END);
179 }
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 UnallocatedOperand(BasicPolicy policy, int index, int virtual_register)
182 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 DCHECK(policy == FIXED_SLOT);
184 value_ |= BasicPolicyField::encode(policy);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 value_ |= static_cast<int64_t>(index) << FixedSlotIndexField::kShift;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 DCHECK(this->fixed_slot_index() == index);
187 }
188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189 UnallocatedOperand(ExtendedPolicy policy, int index, int virtual_register)
190 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000191 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
192 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
193 value_ |= ExtendedPolicyField::encode(policy);
194 value_ |= LifetimeField::encode(USED_AT_END);
195 value_ |= FixedRegisterField::encode(index);
196 }
197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime,
199 int virtual_register)
200 : UnallocatedOperand(virtual_register) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201 value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
202 value_ |= ExtendedPolicyField::encode(policy);
203 value_ |= LifetimeField::encode(lifetime);
204 }
205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 UnallocatedOperand(int reg_id, int slot_id, int virtual_register)
207 : UnallocatedOperand(FIXED_REGISTER, reg_id, virtual_register) {
208 value_ |= HasSecondaryStorageField::encode(true);
209 value_ |= SecondaryStorageField::encode(slot_id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 }
211
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 // Predicates for the operand policy.
213 bool HasAnyPolicy() const {
214 return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
215 }
216 bool HasFixedPolicy() const {
217 return basic_policy() == FIXED_SLOT ||
218 extended_policy() == FIXED_REGISTER ||
219 extended_policy() == FIXED_DOUBLE_REGISTER;
220 }
221 bool HasRegisterPolicy() const {
222 return basic_policy() == EXTENDED_POLICY &&
223 extended_policy() == MUST_HAVE_REGISTER;
224 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 bool HasSlotPolicy() const {
226 return basic_policy() == EXTENDED_POLICY &&
227 extended_policy() == MUST_HAVE_SLOT;
228 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 bool HasSameAsInputPolicy() const {
230 return basic_policy() == EXTENDED_POLICY &&
231 extended_policy() == SAME_AS_FIRST_INPUT;
232 }
233 bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
234 bool HasFixedRegisterPolicy() const {
235 return basic_policy() == EXTENDED_POLICY &&
236 extended_policy() == FIXED_REGISTER;
237 }
238 bool HasFixedDoubleRegisterPolicy() const {
239 return basic_policy() == EXTENDED_POLICY &&
240 extended_policy() == FIXED_DOUBLE_REGISTER;
241 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 bool HasSecondaryStorage() const {
243 return basic_policy() == EXTENDED_POLICY &&
244 extended_policy() == FIXED_REGISTER &&
245 HasSecondaryStorageField::decode(value_);
246 }
247 int GetSecondaryStorage() const {
248 DCHECK(HasSecondaryStorage());
249 return SecondaryStorageField::decode(value_);
250 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251
252 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 BasicPolicy basic_policy() const {
254 DCHECK_EQ(UNALLOCATED, kind());
255 return BasicPolicyField::decode(value_);
256 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257
258 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
259 ExtendedPolicy extended_policy() const {
260 DCHECK(basic_policy() == EXTENDED_POLICY);
261 return ExtendedPolicyField::decode(value_);
262 }
263
264 // [fixed_slot_index]: Only for FIXED_SLOT.
265 int fixed_slot_index() const {
266 DCHECK(HasFixedSlotPolicy());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 return static_cast<int>(static_cast<int64_t>(value_) >>
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268 FixedSlotIndexField::kShift);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 }
270
271 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
272 int fixed_register_index() const {
273 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
274 return FixedRegisterField::decode(value_);
275 }
276
277 // [virtual_register]: The virtual register ID for this operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 int32_t virtual_register() const {
279 DCHECK_EQ(UNALLOCATED, kind());
280 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
281 }
282
283 // TODO(dcarney): remove this.
284 void set_virtual_register(int32_t id) {
285 DCHECK_EQ(UNALLOCATED, kind());
286 value_ = VirtualRegisterField::update(value_, static_cast<uint32_t>(id));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 }
288
289 // [lifetime]: Only for non-FIXED_SLOT.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290 bool IsUsedAtStart() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 DCHECK(basic_policy() == EXTENDED_POLICY);
292 return LifetimeField::decode(value_) == USED_AT_START;
293 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294
295 INSTRUCTION_OPERAND_CASTS(UnallocatedOperand, UNALLOCATED);
296
297 // The encoding used for UnallocatedOperand operands depends on the policy
298 // that is
299 // stored within the operand. The FIXED_SLOT policy uses a compact encoding
300 // because it accommodates a larger pay-load.
301 //
302 // For FIXED_SLOT policy:
303 // +------------------------------------------------+
304 // | slot_index | 0 | virtual_register | 001 |
305 // +------------------------------------------------+
306 //
307 // For all other (extended) policies:
308 // +-----------------------------------------------------+
309 // | reg_index | L | PPP | 1 | virtual_register | 001 |
310 // +-----------------------------------------------------+
311 // L ... Lifetime
312 // P ... Policy
313 //
314 // The slot index is a signed value which requires us to decode it manually
315 // instead of using the BitField utility class.
316
317 STATIC_ASSERT(KindField::kSize == 3);
318
319 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
320
321 // BitFields for all unallocated operands.
322 class BasicPolicyField : public BitField64<BasicPolicy, 35, 1> {};
323
324 // BitFields specific to BasicPolicy::FIXED_SLOT.
325 class FixedSlotIndexField : public BitField64<int, 36, 28> {};
326
327 // BitFields specific to BasicPolicy::EXTENDED_POLICY.
328 class ExtendedPolicyField : public BitField64<ExtendedPolicy, 36, 3> {};
329 class LifetimeField : public BitField64<Lifetime, 39, 1> {};
330 class HasSecondaryStorageField : public BitField64<bool, 40, 1> {};
331 class FixedRegisterField : public BitField64<int, 41, 6> {};
332 class SecondaryStorageField : public BitField64<int, 47, 3> {};
333
334 private:
335 explicit UnallocatedOperand(int virtual_register)
336 : InstructionOperand(UNALLOCATED) {
337 value_ |=
338 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
339 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340};
341
342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343class ConstantOperand : public InstructionOperand {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 explicit ConstantOperand(int virtual_register)
346 : InstructionOperand(CONSTANT) {
347 value_ |=
348 VirtualRegisterField::encode(static_cast<uint32_t>(virtual_register));
349 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351 int32_t virtual_register() const {
352 return static_cast<int32_t>(VirtualRegisterField::decode(value_));
353 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 static ConstantOperand* New(Zone* zone, int virtual_register) {
356 return InstructionOperand::New(zone, ConstantOperand(virtual_register));
357 }
358
359 INSTRUCTION_OPERAND_CASTS(ConstantOperand, CONSTANT);
360
361 STATIC_ASSERT(KindField::kSize == 3);
362 class VirtualRegisterField : public BitField64<uint32_t, 3, 32> {};
363};
364
365
366class ImmediateOperand : public InstructionOperand {
367 public:
368 enum ImmediateType { INLINE, INDEXED };
369
370 explicit ImmediateOperand(ImmediateType type, int32_t value)
371 : InstructionOperand(IMMEDIATE) {
372 value_ |= TypeField::encode(type);
373 value_ |= static_cast<int64_t>(value) << ValueField::kShift;
374 }
375
376 ImmediateType type() const { return TypeField::decode(value_); }
377
378 int32_t inline_value() const {
379 DCHECK_EQ(INLINE, type());
380 return static_cast<int64_t>(value_) >> ValueField::kShift;
381 }
382
383 int32_t indexed_value() const {
384 DCHECK_EQ(INDEXED, type());
385 return static_cast<int64_t>(value_) >> ValueField::kShift;
386 }
387
388 static ImmediateOperand* New(Zone* zone, ImmediateType type, int32_t value) {
389 return InstructionOperand::New(zone, ImmediateOperand(type, value));
390 }
391
392 INSTRUCTION_OPERAND_CASTS(ImmediateOperand, IMMEDIATE);
393
394 STATIC_ASSERT(KindField::kSize == 3);
395 class TypeField : public BitField64<ImmediateType, 3, 1> {};
396 class ValueField : public BitField64<int32_t, 32, 32> {};
397};
398
399
400class LocationOperand : public InstructionOperand {
401 public:
402 enum LocationKind { REGISTER, STACK_SLOT };
403
404 LocationOperand(InstructionOperand::Kind operand_kind,
405 LocationOperand::LocationKind location_kind,
406 MachineRepresentation rep, int index)
407 : InstructionOperand(operand_kind) {
408 DCHECK_IMPLIES(location_kind == REGISTER, index >= 0);
409 DCHECK(IsSupportedRepresentation(rep));
410 value_ |= LocationKindField::encode(location_kind);
411 value_ |= RepresentationField::encode(rep);
412 value_ |= static_cast<int64_t>(index) << IndexField::kShift;
413 }
414
415 int index() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100416 DCHECK(IsStackSlot() || IsDoubleStackSlot() || IsSimd128StackSlot());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 return static_cast<int64_t>(value_) >> IndexField::kShift;
418 }
419
420 Register GetRegister() const {
421 DCHECK(IsRegister());
422 return Register::from_code(static_cast<int64_t>(value_) >>
423 IndexField::kShift);
424 }
425
426 DoubleRegister GetDoubleRegister() const {
427 DCHECK(IsDoubleRegister());
428 return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
429 IndexField::kShift);
430 }
431
Ben Murdoch097c5b22016-05-18 11:27:45 +0100432 Simd128Register GetSimd128Register() const {
433 DCHECK(IsSimd128Register());
434 return Simd128Register::from_code(static_cast<int64_t>(value_) >>
435 IndexField::kShift);
436 }
437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 LocationKind location_kind() const {
439 return LocationKindField::decode(value_);
440 }
441
442 MachineRepresentation representation() const {
443 return RepresentationField::decode(value_);
444 }
445
446 static bool IsSupportedRepresentation(MachineRepresentation rep) {
447 switch (rep) {
448 case MachineRepresentation::kWord32:
449 case MachineRepresentation::kWord64:
450 case MachineRepresentation::kFloat32:
451 case MachineRepresentation::kFloat64:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100452 case MachineRepresentation::kSimd128:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 case MachineRepresentation::kTagged:
454 return true;
455 case MachineRepresentation::kBit:
456 case MachineRepresentation::kWord8:
457 case MachineRepresentation::kWord16:
458 case MachineRepresentation::kNone:
459 return false;
460 }
461 UNREACHABLE();
462 return false;
463 }
464
465 static LocationOperand* cast(InstructionOperand* op) {
466 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
467 return static_cast<LocationOperand*>(op);
468 }
469
470 static const LocationOperand* cast(const InstructionOperand* op) {
471 DCHECK(ALLOCATED == op->kind() || EXPLICIT == op->kind());
472 return static_cast<const LocationOperand*>(op);
473 }
474
475 static LocationOperand cast(const InstructionOperand& op) {
476 DCHECK(ALLOCATED == op.kind() || EXPLICIT == op.kind());
477 return *static_cast<const LocationOperand*>(&op);
478 }
479
480 STATIC_ASSERT(KindField::kSize == 3);
481 class LocationKindField : public BitField64<LocationKind, 3, 2> {};
482 class RepresentationField : public BitField64<MachineRepresentation, 5, 8> {};
483 class IndexField : public BitField64<int32_t, 35, 29> {};
484};
485
486
487class ExplicitOperand : public LocationOperand {
488 public:
489 ExplicitOperand(LocationKind kind, MachineRepresentation rep, int index);
490
491 static ExplicitOperand* New(Zone* zone, LocationKind kind,
492 MachineRepresentation rep, int index) {
493 return InstructionOperand::New(zone, ExplicitOperand(kind, rep, index));
494 }
495
496 INSTRUCTION_OPERAND_CASTS(ExplicitOperand, EXPLICIT);
497};
498
499
500class AllocatedOperand : public LocationOperand {
501 public:
502 AllocatedOperand(LocationKind kind, MachineRepresentation rep, int index)
503 : LocationOperand(ALLOCATED, kind, rep, index) {}
504
505 static AllocatedOperand* New(Zone* zone, LocationKind kind,
506 MachineRepresentation rep, int index) {
507 return InstructionOperand::New(zone, AllocatedOperand(kind, rep, index));
508 }
509
510 INSTRUCTION_OPERAND_CASTS(AllocatedOperand, ALLOCATED);
511};
512
513
514#undef INSTRUCTION_OPERAND_CASTS
515
516
517bool InstructionOperand::IsAnyRegister() const {
518 return (IsAllocated() || IsExplicit()) &&
519 LocationOperand::cast(this)->location_kind() ==
520 LocationOperand::REGISTER;
521}
522
523
524bool InstructionOperand::IsRegister() const {
525 return IsAnyRegister() &&
526 !IsFloatingPoint(LocationOperand::cast(this)->representation());
527}
528
529bool InstructionOperand::IsDoubleRegister() const {
530 return IsAnyRegister() &&
531 IsFloatingPoint(LocationOperand::cast(this)->representation());
532}
533
Ben Murdoch097c5b22016-05-18 11:27:45 +0100534bool InstructionOperand::IsSimd128Register() const {
535 return IsAnyRegister() &&
536 LocationOperand::cast(this)->representation() ==
537 MachineRepresentation::kSimd128;
538}
539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540bool InstructionOperand::IsStackSlot() const {
541 return (IsAllocated() || IsExplicit()) &&
542 LocationOperand::cast(this)->location_kind() ==
543 LocationOperand::STACK_SLOT &&
544 !IsFloatingPoint(LocationOperand::cast(this)->representation());
545}
546
547bool InstructionOperand::IsDoubleStackSlot() const {
548 return (IsAllocated() || IsExplicit()) &&
549 LocationOperand::cast(this)->location_kind() ==
550 LocationOperand::STACK_SLOT &&
551 IsFloatingPoint(LocationOperand::cast(this)->representation());
552}
553
Ben Murdoch097c5b22016-05-18 11:27:45 +0100554bool InstructionOperand::IsSimd128StackSlot() const {
555 return (IsAllocated() || IsExplicit()) &&
556 LocationOperand::cast(this)->location_kind() ==
557 LocationOperand::STACK_SLOT &&
558 LocationOperand::cast(this)->representation() ==
559 MachineRepresentation::kSimd128;
560}
561
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562uint64_t InstructionOperand::GetCanonicalizedValue() const {
563 if (IsAllocated() || IsExplicit()) {
564 // TODO(dcarney): put machine type last and mask.
565 MachineRepresentation canonicalized_representation =
566 IsFloatingPoint(LocationOperand::cast(this)->representation())
567 ? MachineRepresentation::kFloat64
568 : MachineRepresentation::kNone;
569 return InstructionOperand::KindField::update(
570 LocationOperand::RepresentationField::update(
571 this->value_, canonicalized_representation),
572 LocationOperand::EXPLICIT);
573 }
574 return this->value_;
575}
576
577
578// Required for maps that don't care about machine type.
579struct CompareOperandModuloType {
580 bool operator()(const InstructionOperand& a,
581 const InstructionOperand& b) const {
582 return a.CompareCanonicalized(b);
583 }
584};
585
586
587class MoveOperands final : public ZoneObject {
588 public:
589 MoveOperands(const InstructionOperand& source,
590 const InstructionOperand& destination)
591 : source_(source), destination_(destination) {
592 DCHECK(!source.IsInvalid() && !destination.IsInvalid());
593 }
594
595 const InstructionOperand& source() const { return source_; }
596 InstructionOperand& source() { return source_; }
597 void set_source(const InstructionOperand& operand) { source_ = operand; }
598
599 const InstructionOperand& destination() const { return destination_; }
600 InstructionOperand& destination() { return destination_; }
601 void set_destination(const InstructionOperand& operand) {
602 destination_ = operand;
603 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604
605 // The gap resolver marks moves as "in-progress" by clearing the
606 // destination (but not the source).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 bool IsPending() const {
608 return destination_.IsInvalid() && !source_.IsInvalid();
609 }
610 void SetPending() { destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611
612 // True if this move a move into the given destination operand.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 bool Blocks(const InstructionOperand& operand) const {
614 return !IsEliminated() && source().EqualsCanonicalized(operand);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000615 }
616
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 // A move is redundant if it's been eliminated or if its source and
618 // destination are the same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619 bool IsRedundant() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000620 DCHECK_IMPLIES(!destination_.IsInvalid(), !destination_.IsConstant());
621 return IsEliminated() || source_.EqualsCanonicalized(destination_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 }
623
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 // We clear both operands to indicate move that's been eliminated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625 void Eliminate() { source_ = destination_ = InstructionOperand(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000626 bool IsEliminated() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
628 return source_.IsInvalid();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 }
630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 void Print(const RegisterConfiguration* config) const;
632 void Print() const;
633
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 InstructionOperand source_;
636 InstructionOperand destination_;
637
638 DISALLOW_COPY_AND_ASSIGN(MoveOperands);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000639};
640
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400641
642struct PrintableMoveOperands {
643 const RegisterConfiguration* register_configuration_;
644 const MoveOperands* move_operands_;
645};
646
647
648std::ostream& operator<<(std::ostream& os, const PrintableMoveOperands& mo);
649
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651class ParallelMove final : public ZoneVector<MoveOperands*>, public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653 explicit ParallelMove(Zone* zone) : ZoneVector<MoveOperands*>(zone) {
654 reserve(4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 }
656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 MoveOperands* AddMove(const InstructionOperand& from,
658 const InstructionOperand& to) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100659 Zone* zone = get_allocator().zone();
660 return AddMove(from, to, zone);
661 }
662
663 MoveOperands* AddMove(const InstructionOperand& from,
664 const InstructionOperand& to,
665 Zone* operand_allocation_zone) {
666 MoveOperands* move = new (operand_allocation_zone) MoveOperands(from, to);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000667 push_back(move);
668 return move;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 }
670
671 bool IsRedundant() const;
672
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 // Prepare this ParallelMove to insert move as if it happened in a subsequent
674 // ParallelMove. move->source() may be changed. The MoveOperand returned
675 // must be Eliminated.
676 MoveOperands* PrepareInsertAfter(MoveOperands* move) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677
678 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 DISALLOW_COPY_AND_ASSIGN(ParallelMove);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680};
681
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400682
683struct PrintableParallelMove {
684 const RegisterConfiguration* register_configuration_;
685 const ParallelMove* parallel_move_;
686};
687
688
689std::ostream& operator<<(std::ostream& os, const PrintableParallelMove& pm);
690
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000691
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692class ReferenceMap final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000693 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000694 explicit ReferenceMap(Zone* zone)
695 : reference_operands_(8, zone), instruction_position_(-1) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000696
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 const ZoneVector<InstructionOperand>& reference_operands() const {
698 return reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 }
700 int instruction_position() const { return instruction_position_; }
701
702 void set_instruction_position(int pos) {
703 DCHECK(instruction_position_ == -1);
704 instruction_position_ = pos;
705 }
706
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 void RecordReference(const AllocatedOperand& op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708
709 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 friend std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 ZoneVector<InstructionOperand> reference_operands_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713 int instruction_position_;
714};
715
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718class Instruction final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000719 public:
720 size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 const InstructionOperand* OutputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 DCHECK(i < OutputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 return &operands_[i];
724 }
725 InstructionOperand* OutputAt(size_t i) {
726 DCHECK(i < OutputCount());
727 return &operands_[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000728 }
729
730 bool HasOutput() const { return OutputCount() == 1; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 const InstructionOperand* Output() const { return OutputAt(0); }
732 InstructionOperand* Output() { return OutputAt(0); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733
734 size_t InputCount() const { return InputCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 const InstructionOperand* InputAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 return &operands_[OutputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 InstructionOperand* InputAt(size_t i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400740 DCHECK(i < InputCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 return &operands_[OutputCount() + i];
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400742 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000743
744 size_t TempCount() const { return TempCountField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 const InstructionOperand* TempAt(size_t i) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 DCHECK(i < TempCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 return &operands_[OutputCount() + InputCount() + i];
748 }
749 InstructionOperand* TempAt(size_t i) {
750 DCHECK(i < TempCount());
751 return &operands_[OutputCount() + InputCount() + i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 }
753
754 InstructionCode opcode() const { return opcode_; }
755 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
756 AddressingMode addressing_mode() const {
757 return AddressingModeField::decode(opcode());
758 }
759 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
760 FlagsCondition flags_condition() const {
761 return FlagsConditionField::decode(opcode());
762 }
763
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000764 static Instruction* New(Zone* zone, InstructionCode opcode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 return New(zone, opcode, 0, nullptr, 0, nullptr, 0, nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 }
767
768 static Instruction* New(Zone* zone, InstructionCode opcode,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 size_t output_count, InstructionOperand* outputs,
770 size_t input_count, InstructionOperand* inputs,
771 size_t temp_count, InstructionOperand* temps) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000772 DCHECK(opcode >= 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000773 DCHECK(output_count == 0 || outputs != nullptr);
774 DCHECK(input_count == 0 || inputs != nullptr);
775 DCHECK(temp_count == 0 || temps != nullptr);
776 size_t total_extra_ops = output_count + input_count + temp_count;
777 if (total_extra_ops != 0) total_extra_ops--;
778 int size = static_cast<int>(
779 RoundUp(sizeof(Instruction), sizeof(InstructionOperand)) +
780 total_extra_ops * sizeof(InstructionOperand));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 return new (zone->New(size)) Instruction(
782 opcode, output_count, outputs, input_count, inputs, temp_count, temps);
783 }
784
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785 Instruction* MarkAsCall() {
786 bit_field_ = IsCallField::update(bit_field_, true);
787 return this;
788 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 bool IsCall() const { return IsCallField::decode(bit_field_); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 bool NeedsReferenceMap() const { return IsCall(); }
791 bool HasReferenceMap() const { return reference_map_ != nullptr; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792
793 bool ClobbersRegisters() const { return IsCall(); }
794 bool ClobbersTemps() const { return IsCall(); }
795 bool ClobbersDoubleRegisters() const { return IsCall(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 ReferenceMap* reference_map() const { return reference_map_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000798 void set_reference_map(ReferenceMap* map) {
799 DCHECK(NeedsReferenceMap());
800 DCHECK(!reference_map_);
801 reference_map_ = map;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000802 }
803
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400804 void OverwriteWithNop() {
805 opcode_ = ArchOpcodeField::encode(kArchNop);
806 bit_field_ = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 reference_map_ = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400808 }
809
810 bool IsNop() const {
811 return arch_opcode() == kArchNop && InputCount() == 0 &&
812 OutputCount() == 0 && TempCount() == 0;
813 }
814
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 enum GapPosition {
816 START,
817 END,
818 FIRST_GAP_POSITION = START,
819 LAST_GAP_POSITION = END
820 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822 ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
823 if (parallel_moves_[pos] == nullptr) {
824 parallel_moves_[pos] = new (zone) ParallelMove(zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 return parallel_moves_[pos];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 }
828
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829 ParallelMove* GetParallelMove(GapPosition pos) {
830 return parallel_moves_[pos];
831 }
832
833 const ParallelMove* GetParallelMove(GapPosition pos) const {
834 return parallel_moves_[pos];
835 }
836
837 bool AreMovesRedundant() const;
838
839 ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
840 ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
841
842 void Print(const RegisterConfiguration* config) const;
843 void Print() const;
844
845 private:
846 explicit Instruction(InstructionCode opcode);
847
848 Instruction(InstructionCode opcode, size_t output_count,
849 InstructionOperand* outputs, size_t input_count,
850 InstructionOperand* inputs, size_t temp_count,
851 InstructionOperand* temps);
852
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 typedef BitField<size_t, 0, 8> OutputCountField;
854 typedef BitField<size_t, 8, 16> InputCountField;
855 typedef BitField<size_t, 24, 6> TempCountField;
856 typedef BitField<bool, 30, 1> IsCallField;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857
858 InstructionCode opcode_;
859 uint32_t bit_field_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 ParallelMove* parallel_moves_[2];
861 ReferenceMap* reference_map_;
862 InstructionOperand operands_[1];
863
864 DISALLOW_COPY_AND_ASSIGN(Instruction);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000865};
866
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400867
868struct PrintableInstruction {
869 const RegisterConfiguration* register_configuration_;
870 const Instruction* instr_;
871};
872std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
873
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875class RpoNumber final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 static const int kInvalidRpoNumber = -1;
878 int ToInt() const {
879 DCHECK(IsValid());
880 return index_;
881 }
882 size_t ToSize() const {
883 DCHECK(IsValid());
884 return static_cast<size_t>(index_);
885 }
886 bool IsValid() const { return index_ >= 0; }
887 static RpoNumber FromInt(int index) { return RpoNumber(index); }
888 static RpoNumber Invalid() { return RpoNumber(kInvalidRpoNumber); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890 bool IsNext(const RpoNumber other) const {
891 DCHECK(IsValid());
892 return other.index_ == this->index_ + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 }
894
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000895 // Comparison operators.
896 bool operator==(RpoNumber other) const { return index_ == other.index_; }
897 bool operator!=(RpoNumber other) const { return index_ != other.index_; }
898 bool operator>(RpoNumber other) const { return index_ > other.index_; }
899 bool operator<(RpoNumber other) const { return index_ < other.index_; }
900 bool operator<=(RpoNumber other) const { return index_ <= other.index_; }
901 bool operator>=(RpoNumber other) const { return index_ >= other.index_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902
903 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 explicit RpoNumber(int32_t index) : index_(index) {}
905 int32_t index_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906};
907
908
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909std::ostream& operator<<(std::ostream&, const RpoNumber&);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910
911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912class Constant final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400914 enum Type {
915 kInt32,
916 kInt64,
917 kFloat32,
918 kFloat64,
919 kExternalReference,
920 kHeapObject,
921 kRpoNumber
922 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924 explicit Constant(int32_t v);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925 explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400926 explicit Constant(float v) : type_(kFloat32), value_(bit_cast<int32_t>(v)) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
928 explicit Constant(ExternalReference ref)
929 : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
930 explicit Constant(Handle<HeapObject> obj)
931 : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 explicit Constant(RpoNumber rpo) : type_(kRpoNumber), value_(rpo.ToInt()) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933
934 Type type() const { return type_; }
935
936 int32_t ToInt32() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400937 DCHECK(type() == kInt32 || type() == kInt64);
938 const int32_t value = static_cast<int32_t>(value_);
939 DCHECK_EQ(value_, static_cast<int64_t>(value));
940 return value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000941 }
942
943 int64_t ToInt64() const {
944 if (type() == kInt32) return ToInt32();
945 DCHECK_EQ(kInt64, type());
946 return value_;
947 }
948
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400949 float ToFloat32() const {
950 DCHECK_EQ(kFloat32, type());
951 return bit_cast<float>(static_cast<int32_t>(value_));
952 }
953
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 double ToFloat64() const {
955 if (type() == kInt32) return ToInt32();
956 DCHECK_EQ(kFloat64, type());
957 return bit_cast<double>(value_);
958 }
959
960 ExternalReference ToExternalReference() const {
961 DCHECK_EQ(kExternalReference, type());
962 return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
963 }
964
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 RpoNumber ToRpoNumber() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400966 DCHECK_EQ(kRpoNumber, type());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967 return RpoNumber::FromInt(static_cast<int>(value_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400968 }
969
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000970 Handle<HeapObject> ToHeapObject() const {
971 DCHECK_EQ(kHeapObject, type());
972 return bit_cast<Handle<HeapObject> >(static_cast<intptr_t>(value_));
973 }
974
975 private:
976 Type type_;
977 int64_t value_;
978};
979
980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981std::ostream& operator<<(std::ostream& os, const Constant& constant);
982
983
984// Forward declarations.
985class FrameStateDescriptor;
986
987
988enum class StateValueKind { kPlain, kNested, kDuplicate };
989
990
991class StateValueDescriptor {
992 public:
993 explicit StateValueDescriptor(Zone* zone)
994 : kind_(StateValueKind::kPlain),
995 type_(MachineType::AnyTagged()),
996 id_(0),
997 fields_(zone) {}
998
999 static StateValueDescriptor Plain(Zone* zone, MachineType type) {
1000 return StateValueDescriptor(StateValueKind::kPlain, zone, type, 0);
1001 }
1002 static StateValueDescriptor Recursive(Zone* zone, size_t id) {
1003 return StateValueDescriptor(StateValueKind::kNested, zone,
1004 MachineType::AnyTagged(), id);
1005 }
1006 static StateValueDescriptor Duplicate(Zone* zone, size_t id) {
1007 return StateValueDescriptor(StateValueKind::kDuplicate, zone,
1008 MachineType::AnyTagged(), id);
1009 }
1010
1011 size_t size() { return fields_.size(); }
1012 ZoneVector<StateValueDescriptor>& fields() { return fields_; }
1013 int IsPlain() { return kind_ == StateValueKind::kPlain; }
1014 int IsNested() { return kind_ == StateValueKind::kNested; }
1015 int IsDuplicate() { return kind_ == StateValueKind::kDuplicate; }
1016 MachineType type() const { return type_; }
1017 MachineType GetOperandType(size_t index) const {
1018 return fields_[index].type_;
1019 }
1020 size_t id() const { return id_; }
1021
1022 private:
1023 StateValueDescriptor(StateValueKind kind, Zone* zone, MachineType type,
1024 size_t id)
1025 : kind_(kind), type_(type), id_(id), fields_(zone) {}
1026
1027 StateValueKind kind_;
1028 MachineType type_;
1029 size_t id_;
1030 ZoneVector<StateValueDescriptor> fields_;
1031};
1032
1033
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034class FrameStateDescriptor : public ZoneObject {
1035 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036 FrameStateDescriptor(Zone* zone, FrameStateType type, BailoutId bailout_id,
1037 OutputFrameStateCombine state_combine,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 size_t parameters_count, size_t locals_count,
1039 size_t stack_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001040 MaybeHandle<SharedFunctionInfo> shared_info,
1041 FrameStateDescriptor* outer_state = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042
1043 FrameStateType type() const { return type_; }
1044 BailoutId bailout_id() const { return bailout_id_; }
1045 OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
1046 size_t parameters_count() const { return parameters_count_; }
1047 size_t locals_count() const { return locals_count_; }
1048 size_t stack_count() const { return stack_count_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 MaybeHandle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001050 FrameStateDescriptor* outer_state() const { return outer_state_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001051 bool HasContext() const {
1052 return FrameStateFunctionInfo::IsJSFunctionType(type_);
1053 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001054
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001055 size_t GetSize(OutputFrameStateCombine combine =
1056 OutputFrameStateCombine::Ignore()) const;
1057 size_t GetTotalSize() const;
1058 size_t GetFrameCount() const;
1059 size_t GetJSFrameCount() const;
1060
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001061 MachineType GetType(size_t index) const {
1062 return values_.GetOperandType(index);
1063 }
1064 StateValueDescriptor* GetStateValueDescriptor() { return &values_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001065
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001066 private:
1067 FrameStateType type_;
1068 BailoutId bailout_id_;
1069 OutputFrameStateCombine frame_state_combine_;
1070 size_t parameters_count_;
1071 size_t locals_count_;
1072 size_t stack_count_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 StateValueDescriptor values_;
1074 MaybeHandle<SharedFunctionInfo> const shared_info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001075 FrameStateDescriptor* outer_state_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076};
1077
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078
1079typedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001080
1081
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082class PhiInstruction final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001083 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 typedef ZoneVector<InstructionOperand> Inputs;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001085
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001086 PhiInstruction(Zone* zone, int virtual_register, size_t input_count);
1087
1088 void SetInput(size_t offset, int virtual_register);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001089
1090 int virtual_register() const { return virtual_register_; }
1091 const IntVector& operands() const { return operands_; }
1092
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001093 // TODO(dcarney): this has no real business being here, since it's internal to
1094 // the register allocator, but putting it here was convenient.
1095 const InstructionOperand& output() const { return output_; }
1096 InstructionOperand& output() { return output_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001097
1098 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001099 const int virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001100 InstructionOperand output_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001101 IntVector operands_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001102};
1103
1104
1105// Analogue of BasicBlock for Instructions instead of Nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001106class InstructionBlock final : public ZoneObject {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001107 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 InstructionBlock(Zone* zone, RpoNumber rpo_number, RpoNumber loop_header,
1109 RpoNumber loop_end, bool deferred, bool handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001110
1111 // Instruction indexes (used by the register allocator).
1112 int first_instruction_index() const {
1113 DCHECK(code_start_ >= 0);
1114 DCHECK(code_end_ > 0);
1115 DCHECK(code_end_ >= code_start_);
1116 return code_start_;
1117 }
1118 int last_instruction_index() const {
1119 DCHECK(code_start_ >= 0);
1120 DCHECK(code_end_ > 0);
1121 DCHECK(code_end_ >= code_start_);
1122 return code_end_ - 1;
1123 }
1124
1125 int32_t code_start() const { return code_start_; }
1126 void set_code_start(int32_t start) { code_start_ = start; }
1127
1128 int32_t code_end() const { return code_end_; }
1129 void set_code_end(int32_t end) { code_end_ = end; }
1130
1131 bool IsDeferred() const { return deferred_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132 bool IsHandler() const { return handler_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001134 RpoNumber ao_number() const { return ao_number_; }
1135 RpoNumber rpo_number() const { return rpo_number_; }
1136 RpoNumber loop_header() const { return loop_header_; }
1137 RpoNumber loop_end() const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001138 DCHECK(IsLoopHeader());
1139 return loop_end_;
1140 }
1141 inline bool IsLoopHeader() const { return loop_end_.IsValid(); }
1142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143 typedef ZoneVector<RpoNumber> Predecessors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001144 Predecessors& predecessors() { return predecessors_; }
1145 const Predecessors& predecessors() const { return predecessors_; }
1146 size_t PredecessorCount() const { return predecessors_.size(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 size_t PredecessorIndexOf(RpoNumber rpo_number) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001148
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001149 typedef ZoneVector<RpoNumber> Successors;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001150 Successors& successors() { return successors_; }
1151 const Successors& successors() const { return successors_; }
1152 size_t SuccessorCount() const { return successors_.size(); }
1153
1154 typedef ZoneVector<PhiInstruction*> PhiInstructions;
1155 const PhiInstructions& phis() const { return phis_; }
1156 void AddPhi(PhiInstruction* phi) { phis_.push_back(phi); }
1157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 void set_ao_number(RpoNumber ao_number) { ao_number_ = ao_number; }
1159
1160 bool needs_frame() const { return needs_frame_; }
1161 void mark_needs_frame() { needs_frame_ = true; }
1162
1163 bool must_construct_frame() const { return must_construct_frame_; }
1164 void mark_must_construct_frame() { must_construct_frame_ = true; }
1165
1166 bool must_deconstruct_frame() const { return must_deconstruct_frame_; }
1167 void mark_must_deconstruct_frame() { must_deconstruct_frame_ = true; }
1168
1169 void set_last_deferred(RpoNumber last) { last_deferred_ = last; }
1170 RpoNumber last_deferred() const { return last_deferred_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001171
1172 private:
1173 Successors successors_;
1174 Predecessors predecessors_;
1175 PhiInstructions phis_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 RpoNumber ao_number_; // Assembly order number.
1177 const RpoNumber rpo_number_;
1178 const RpoNumber loop_header_;
1179 const RpoNumber loop_end_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001180 int32_t code_start_; // start index of arch-specific code.
1181 int32_t code_end_; // end index of arch-specific code.
1182 const bool deferred_; // Block contains deferred code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 const bool handler_; // Block is a handler entry point.
1184 bool needs_frame_;
1185 bool must_construct_frame_;
1186 bool must_deconstruct_frame_;
1187 RpoNumber last_deferred_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001188};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189
1190typedef ZoneDeque<Constant> ConstantDeque;
1191typedef std::map<int, Constant, std::less<int>,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 zone_allocator<std::pair<const int, Constant> > > ConstantMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001193
1194typedef ZoneDeque<Instruction*> InstructionDeque;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195typedef ZoneDeque<ReferenceMap*> ReferenceMapDeque;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001196typedef ZoneVector<InstructionBlock*> InstructionBlocks;
1197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198
1199// Forward declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001200struct PrintableInstructionSequence;
1201
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202
1203// Represents architecture-specific generated code before, during, and after
1204// register allocation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001205class InstructionSequence final : public ZoneObject {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001207 static InstructionBlocks* InstructionBlocksFor(Zone* zone,
1208 const Schedule* schedule);
1209 // Puts the deferred blocks last.
1210 static void ComputeAssemblyOrder(InstructionBlocks* blocks);
1211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001212 InstructionSequence(Isolate* isolate, Zone* zone,
1213 InstructionBlocks* instruction_blocks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 int NextVirtualRegister();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216 int VirtualRegisterCount() const { return next_virtual_register_; }
1217
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001218 const InstructionBlocks& instruction_blocks() const {
1219 return *instruction_blocks_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220 }
1221
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001222 int InstructionBlockCount() const {
1223 return static_cast<int>(instruction_blocks_->size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 }
1225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001227 return instruction_blocks_->at(rpo_number.ToSize());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001228 }
1229
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001230 int LastLoopInstructionIndex(const InstructionBlock* block) {
1231 return instruction_blocks_->at(block->loop_end().ToSize() - 1)
1232 ->last_instruction_index();
1233 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001234
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001235 const InstructionBlock* InstructionBlockAt(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001236 return instruction_blocks_->at(rpo_number.ToSize());
1237 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 InstructionBlock* GetInstructionBlock(int instruction_index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001240
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 static MachineRepresentation DefaultRepresentation() {
1242 return MachineType::PointerRepresentation();
1243 }
1244 MachineRepresentation GetRepresentation(int virtual_register) const;
1245 void MarkAsRepresentation(MachineRepresentation rep, int virtual_register);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001247 bool IsReference(int virtual_register) const {
1248 return GetRepresentation(virtual_register) ==
1249 MachineRepresentation::kTagged;
1250 }
1251 bool IsFloat(int virtual_register) const {
1252 return IsFloatingPoint(GetRepresentation(virtual_register));
1253 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001255 Instruction* GetBlockStart(RpoNumber rpo) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001256
1257 typedef InstructionDeque::const_iterator const_iterator;
1258 const_iterator begin() const { return instructions_.begin(); }
1259 const_iterator end() const { return instructions_.end(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001260 const InstructionDeque& instructions() const { return instructions_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 int LastInstructionIndex() const {
1262 return static_cast<int>(instructions().size()) - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001264
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001265 Instruction* InstructionAt(int index) const {
1266 DCHECK(index >= 0);
1267 DCHECK(index < static_cast<int>(instructions_.size()));
1268 return instructions_[index];
1269 }
1270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271 Isolate* isolate() const { return isolate_; }
1272 const ReferenceMapDeque* reference_maps() const { return &reference_maps_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001273 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001275 // Used by the instruction selector while adding instructions.
1276 int AddInstruction(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001277 void StartBlock(RpoNumber rpo);
1278 void EndBlock(RpoNumber rpo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001280 int AddConstant(int virtual_register, Constant constant) {
1281 // TODO(titzer): allow RPO numbers as constants?
1282 DCHECK(constant.type() != Constant::kRpoNumber);
1283 DCHECK(virtual_register >= 0 && virtual_register < next_virtual_register_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 DCHECK(constants_.find(virtual_register) == constants_.end());
1285 constants_.insert(std::make_pair(virtual_register, constant));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001286 return virtual_register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 }
1288 Constant GetConstant(int virtual_register) const {
1289 ConstantMap::const_iterator it = constants_.find(virtual_register);
1290 DCHECK(it != constants_.end());
1291 DCHECK_EQ(virtual_register, it->first);
1292 return it->second;
1293 }
1294
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001295 typedef ZoneVector<Constant> Immediates;
1296 Immediates& immediates() { return immediates_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298 ImmediateOperand AddImmediate(const Constant& constant) {
1299 if (constant.type() == Constant::kInt32) {
1300 return ImmediateOperand(ImmediateOperand::INLINE, constant.ToInt32());
1301 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 int index = static_cast<int>(immediates_.size());
1303 immediates_.push_back(constant);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 return ImmediateOperand(ImmediateOperand::INDEXED, index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001306
1307 Constant GetImmediate(const ImmediateOperand* op) const {
1308 switch (op->type()) {
1309 case ImmediateOperand::INLINE:
1310 return Constant(op->inline_value());
1311 case ImmediateOperand::INDEXED: {
1312 int index = op->indexed_value();
1313 DCHECK(index >= 0);
1314 DCHECK(index < static_cast<int>(immediates_.size()));
1315 return immediates_[index];
1316 }
1317 }
1318 UNREACHABLE();
1319 return Constant(static_cast<int32_t>(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001320 }
1321
1322 class StateId {
1323 public:
1324 static StateId FromInt(int id) { return StateId(id); }
1325 int ToInt() const { return id_; }
1326
1327 private:
1328 explicit StateId(int id) : id_(id) {}
1329 int id_;
1330 };
1331
1332 StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor);
1333 FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
1334 int GetFrameStateDescriptorCount();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001335 DeoptimizationVector const& frame_state_descriptors() const {
1336 return deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001337 }
1338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 RpoNumber InputRpo(Instruction* instr, size_t index);
1340
1341 bool GetSourcePosition(const Instruction* instr,
1342 SourcePosition* result) const;
1343 void SetSourcePosition(const Instruction* instr, SourcePosition value);
1344
1345 bool ContainsCall() const {
1346 for (Instruction* instr : instructions_) {
1347 if (instr->IsCall()) return true;
1348 }
1349 return false;
1350 }
1351 void Print(const RegisterConfiguration* config) const;
1352 void Print() const;
1353
Ben Murdoch097c5b22016-05-18 11:27:45 +01001354 void PrintBlock(const RegisterConfiguration* config, int block_id) const;
1355 void PrintBlock(int block_id) const;
1356
1357 void Validate();
1358
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001360 friend std::ostream& operator<<(std::ostream& os,
1361 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 typedef ZoneMap<const Instruction*, SourcePosition> SourcePositionMap;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001365 Isolate* isolate_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001366 Zone* const zone_;
1367 InstructionBlocks* const instruction_blocks_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001368 SourcePositionMap source_positions_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001369 IntVector block_starts_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001370 ConstantMap constants_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001371 Immediates immediates_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 InstructionDeque instructions_;
1373 int next_virtual_register_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 ReferenceMapDeque reference_maps_;
1375 ZoneVector<MachineRepresentation> representations_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376 DeoptimizationVector deoptimization_entries_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001377
1378 DISALLOW_COPY_AND_ASSIGN(InstructionSequence);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379};
1380
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001381
1382struct PrintableInstructionSequence {
1383 const RegisterConfiguration* register_configuration_;
1384 const InstructionSequence* sequence_;
1385};
1386
1387
1388std::ostream& operator<<(std::ostream& os,
1389 const PrintableInstructionSequence& code);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390
1391} // namespace compiler
1392} // namespace internal
1393} // namespace v8
1394
1395#endif // V8_COMPILER_INSTRUCTION_H_