17d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Copyright 2014 the V8 project authors. All rights reserved.
27d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Use of this source code is governed by a BSD-style license that can be
37d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// found in the LICENSE file.
47d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
57d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#ifndef V8_COMPILER_INSTRUCTION_H_
67d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define V8_COMPILER_INSTRUCTION_H_
77d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
87d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include <deque>
97d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include <map>
107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include <set>
117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/common-operator.h"
137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/frame.h"
147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/graph.h"
157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/instruction-codes.h"
167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/opcodes.h"
177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/compiler/schedule.h"
18b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org// TODO(titzer): don't include the macro-assembler?
19b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org#include "src/macro-assembler.h"
207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/zone-allocator.h"
217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace v8 {
237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace internal {
247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Forward declarations.
267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass OStream;
277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgnamespace compiler {
297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Forward declarations.
317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass Linkage;
327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// A couple of reserved opcodes are used for internal use.
347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgconst InstructionCode kGapInstruction = -1;
357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgconst InstructionCode kBlockStartInstruction = -2;
367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgconst InstructionCode kSourcePositionInstruction = -3;
377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define INSTRUCTION_OPERAND_LIST(V)              \
407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(Constant, CONSTANT, 128)                     \
417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(Immediate, IMMEDIATE, 128)                   \
427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(StackSlot, STACK_SLOT, 128)                  \
437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128)     \
447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(Register, REGISTER, Register::kNumRegisters) \
457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  V(DoubleRegister, DOUBLE_REGISTER, DoubleRegister::kMaxNumRegisters)
467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass InstructionOperand : public ZoneObject {
487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  enum Kind {
507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    INVALID,
517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    UNALLOCATED,
527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    CONSTANT,
537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    IMMEDIATE,
547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    STACK_SLOT,
557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    DOUBLE_STACK_SLOT,
567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    REGISTER,
577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    DOUBLE_REGISTER
587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  };
597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand() : value_(KindField::encode(INVALID)) {}
617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand(Kind kind, int index) { ConvertTo(kind, index); }
627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Kind kind() const { return KindField::decode(value_); }
647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int index() const { return static_cast<int>(value_) >> KindField::kSize; }
657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define INSTRUCTION_OPERAND_PREDICATE(name, type, number) \
667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool Is##name() const { return kind() == type; }
677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE)
687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0)
697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  INSTRUCTION_OPERAND_PREDICATE(Ignored, INVALID, 0)
707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#undef INSTRUCTION_OPERAND_PREDICATE
717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool Equals(InstructionOperand* other) const {
727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return value_ == other->value_;
737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void ConvertTo(Kind kind, int index) {
76e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0);
777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ = KindField::encode(kind);
787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= index << KindField::kSize;
79e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(this->index() == index);
807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Calls SetUpCache()/TearDownCache() for each subclass.
837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static void SetUpCaches();
847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static void TearDownCaches();
857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org protected:
877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef BitField<Kind, 0, 3> KindField;
887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  unsigned value_;
907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
92fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgtypedef ZoneVector<InstructionOperand*> InstructionOperandVector;
93a8702c210b949f35c64d8e4aa01bb6d525086c85machenbach@chromium.org
947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const InstructionOperand& op);
957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass UnallocatedOperand : public InstructionOperand {
977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  enum BasicPolicy { FIXED_SLOT, EXTENDED_POLICY };
997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  enum ExtendedPolicy {
1017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    NONE,
1027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    ANY,
1037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    FIXED_REGISTER,
1047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    FIXED_DOUBLE_REGISTER,
1057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    MUST_HAVE_REGISTER,
1067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    SAME_AS_FIRST_INPUT
1077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  };
1087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Lifetime of operand inside the instruction.
1107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  enum Lifetime {
1117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // USED_AT_START operand is guaranteed to be live only at
1127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // instruction start. Register allocator is free to assign the same register
1137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // to some other operand used inside instruction (i.e. temporary or
1147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // output).
1157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    USED_AT_START,
1167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // USED_AT_END operand is treated as live until the end of
1187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // instruction. This means that register allocator will not reuse it's
1197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    // register for any other operand inside instruction.
1207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    USED_AT_END
1217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  };
1227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit UnallocatedOperand(ExtendedPolicy policy)
1247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : InstructionOperand(UNALLOCATED, 0) {
1257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
1267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= ExtendedPolicyField::encode(policy);
1277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= LifetimeField::encode(USED_AT_END);
1287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  UnallocatedOperand(BasicPolicy policy, int index)
1317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : InstructionOperand(UNALLOCATED, 0) {
132e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(policy == FIXED_SLOT);
1337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= BasicPolicyField::encode(policy);
1347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= index << FixedSlotIndexField::kShift;
135e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(this->fixed_slot_index() == index);
1367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  UnallocatedOperand(ExtendedPolicy policy, int index)
1397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : InstructionOperand(UNALLOCATED, 0) {
140e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
1417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
1427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= ExtendedPolicyField::encode(policy);
1437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= LifetimeField::encode(USED_AT_END);
1447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= FixedRegisterField::encode(index);
1457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime)
1487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : InstructionOperand(UNALLOCATED, 0) {
1497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
1507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= ExtendedPolicyField::encode(policy);
1517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ |= LifetimeField::encode(lifetime);
1527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  UnallocatedOperand* CopyUnconstrained(Zone* zone) {
1557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    UnallocatedOperand* result = new (zone) UnallocatedOperand(ANY);
1567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    result->set_virtual_register(virtual_register());
1577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return result;
1587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const UnallocatedOperand* cast(const InstructionOperand* op) {
161e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(op->IsUnallocated());
1627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<const UnallocatedOperand*>(op);
1637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static UnallocatedOperand* cast(InstructionOperand* op) {
166e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(op->IsUnallocated());
1677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<UnallocatedOperand*>(op);
1687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
1697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // The encoding used for UnallocatedOperand operands depends on the policy
1717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // that is
1727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // stored within the operand. The FIXED_SLOT policy uses a compact encoding
1737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // because it accommodates a larger pay-load.
1747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //
1757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // For FIXED_SLOT policy:
1767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //     +------------------------------------------+
1777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //     |       slot_index      |  vreg  | 0 | 001 |
1787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //     +------------------------------------------+
1797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //
1807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // For all other (extended) policies:
1817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //     +------------------------------------------+
1827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //     |  reg_index  | L | PPP |  vreg  | 1 | 001 |    L ... Lifetime
1837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //     +------------------------------------------+    P ... Policy
1847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  //
1857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // The slot index is a signed value which requires us to decode it manually
1867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // instead of using the BitField utility class.
1877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // The superclass has a KindField.
1897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  STATIC_ASSERT(KindField::kSize == 3);
1907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // BitFields for all unallocated operands.
1927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  class BasicPolicyField : public BitField<BasicPolicy, 3, 1> {};
1937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  class VirtualRegisterField : public BitField<unsigned, 4, 18> {};
1947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // BitFields specific to BasicPolicy::FIXED_SLOT.
1967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  class FixedSlotIndexField : public BitField<int, 22, 10> {};
1977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
1987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // BitFields specific to BasicPolicy::EXTENDED_POLICY.
1997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  class ExtendedPolicyField : public BitField<ExtendedPolicy, 22, 3> {};
2007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  class LifetimeField : public BitField<Lifetime, 25, 1> {};
2017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  class FixedRegisterField : public BitField<int, 26, 6> {};
2027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1;
2047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize;
2057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
2067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
2077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Predicates for the operand policy.
2097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasAnyPolicy() const {
2107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return basic_policy() == EXTENDED_POLICY && extended_policy() == ANY;
2117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasFixedPolicy() const {
2137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return basic_policy() == FIXED_SLOT ||
2147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           extended_policy() == FIXED_REGISTER ||
2157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           extended_policy() == FIXED_DOUBLE_REGISTER;
2167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasRegisterPolicy() const {
2187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return basic_policy() == EXTENDED_POLICY &&
2197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           extended_policy() == MUST_HAVE_REGISTER;
2207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasSameAsInputPolicy() const {
2227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return basic_policy() == EXTENDED_POLICY &&
2237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           extended_policy() == SAME_AS_FIRST_INPUT;
2247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasFixedSlotPolicy() const { return basic_policy() == FIXED_SLOT; }
2267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasFixedRegisterPolicy() const {
2277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return basic_policy() == EXTENDED_POLICY &&
2287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           extended_policy() == FIXED_REGISTER;
2297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasFixedDoubleRegisterPolicy() const {
2317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return basic_policy() == EXTENDED_POLICY &&
2327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           extended_policy() == FIXED_DOUBLE_REGISTER;
2337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
2367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); }
2377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
2397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ExtendedPolicy extended_policy() const {
240e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(basic_policy() == EXTENDED_POLICY);
2417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return ExtendedPolicyField::decode(value_);
2427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // [fixed_slot_index]: Only for FIXED_SLOT.
2457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int fixed_slot_index() const {
246e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(HasFixedSlotPolicy());
2477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<int>(value_) >> FixedSlotIndexField::kShift;
2487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
2517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int fixed_register_index() const {
252e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
2537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return FixedRegisterField::decode(value_);
2547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // [virtual_register]: The virtual register ID for this operand.
2577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int virtual_register() const { return VirtualRegisterField::decode(value_); }
2587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void set_virtual_register(unsigned id) {
2597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    value_ = VirtualRegisterField::update(value_, id);
2607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // [lifetime]: Only for non-FIXED_SLOT.
2637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsUsedAtStart() {
264e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(basic_policy() == EXTENDED_POLICY);
2657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return LifetimeField::decode(value_) == USED_AT_START;
2667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
2687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
270ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass MoveOperands FINAL {
2717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
2727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  MoveOperands(InstructionOperand* source, InstructionOperand* destination)
2737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : source_(source), destination_(destination) {}
2747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* source() const { return source_; }
2767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void set_source(InstructionOperand* operand) { source_ = operand; }
2777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* destination() const { return destination_; }
2797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void set_destination(InstructionOperand* operand) { destination_ = operand; }
2807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // The gap resolver marks moves as "in-progress" by clearing the
2827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // destination (but not the source).
2837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsPending() const { return destination_ == NULL && source_ != NULL; }
2847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // True if this move a move into the given destination operand.
2867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool Blocks(InstructionOperand* operand) const {
2877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return !IsEliminated() && source()->Equals(operand);
2887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // A move is redundant if it's been eliminated, if its source and
2917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // destination are the same, or if its destination is unneeded or constant.
2927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsRedundant() const {
2937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return IsEliminated() || source_->Equals(destination_) || IsIgnored() ||
2947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org           (destination_ != NULL && destination_->IsConstant());
2957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
2967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
2977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsIgnored() const {
2987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return destination_ != NULL && destination_->IsIgnored();
2997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // We clear both operands to indicate move that's been eliminated.
3027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void Eliminate() { source_ = destination_ = NULL; }
3037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsEliminated() const {
304e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(source_ != NULL || destination_ == NULL);
3057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return source_ == NULL;
3067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
3097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* source_;
3107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* destination_;
3117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
3127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const MoveOperands& mo);
3147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtemplate <InstructionOperand::Kind kOperandKind, int kNumCachedOperands>
316ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass SubKindOperand FINAL : public InstructionOperand {
3177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
3187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static SubKindOperand* Create(int index, Zone* zone) {
319e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index >= 0);
3207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (index < kNumCachedOperands) return &cache[index];
3217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return new (zone) SubKindOperand(index);
3227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static SubKindOperand* cast(InstructionOperand* op) {
325e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(op->kind() == kOperandKind);
3267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return reinterpret_cast<SubKindOperand*>(op);
3277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static void SetUpCache();
3307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static void TearDownCache();
3317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
3337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static SubKindOperand* cache;
3347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  SubKindOperand() : InstructionOperand() {}
3367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit SubKindOperand(int index)
3377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : InstructionOperand(kOperandKind, index) {}
3387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
3397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#define INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number) \
3427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef SubKindOperand<InstructionOperand::type, number> name##Operand;
3437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgINSTRUCTION_OPERAND_LIST(INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS)
3447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#undef INSTRUCTION_TYPEDEF_SUBKIND_OPERAND_CLASS
3457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
347ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass ParallelMove FINAL : public ZoneObject {
3487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
3497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit ParallelMove(Zone* zone) : move_operands_(4, zone) {}
3507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void AddMove(InstructionOperand* from, InstructionOperand* to, Zone* zone) {
3527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    move_operands_.Add(MoveOperands(from, to), zone);
3537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsRedundant() const;
3567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ZoneList<MoveOperands>* move_operands() { return &move_operands_; }
3587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  const ZoneList<MoveOperands>* move_operands() const {
3597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return &move_operands_;
3607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
3637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ZoneList<MoveOperands> move_operands_;
3647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
3657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const ParallelMove& pm);
3677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
368ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass PointerMap FINAL : public ZoneObject {
3697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
3707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit PointerMap(Zone* zone)
3717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : pointer_operands_(8, zone),
3727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        untagged_operands_(0, zone),
3737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        instruction_position_(-1) {}
3747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  const ZoneList<InstructionOperand*>* GetNormalizedOperands() {
3767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (int i = 0; i < untagged_operands_.length(); ++i) {
3777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      RemovePointer(untagged_operands_[i]);
3787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
3797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    untagged_operands_.Clear();
3807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return &pointer_operands_;
3817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int instruction_position() const { return instruction_position_; }
3837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void set_instruction_position(int pos) {
385e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instruction_position_ == -1);
3867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    instruction_position_ = pos;
3877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
3887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void RecordPointer(InstructionOperand* op, Zone* zone);
3907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void RemovePointer(InstructionOperand* op);
3917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void RecordUntagged(InstructionOperand* op, Zone* zone);
3927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
3947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  friend OStream& operator<<(OStream& os, const PointerMap& pm);
3957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
3967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ZoneList<InstructionOperand*> pointer_operands_;
3977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ZoneList<InstructionOperand*> untagged_operands_;
3987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int instruction_position_;
3997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
4007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const PointerMap& pm);
4027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): s/PointerMap/ReferenceMap/
4047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass Instruction : public ZoneObject {
4057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
4067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  size_t OutputCount() const { return OutputCountField::decode(bit_field_); }
4077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* OutputAt(size_t i) const {
408e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(i < OutputCount());
4097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return operands_[i];
4107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4126474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  bool HasOutput() const { return OutputCount() == 1; }
4136474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org  InstructionOperand* Output() const { return OutputAt(0); }
4146474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org
4157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  size_t InputCount() const { return InputCountField::decode(bit_field_); }
4167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* InputAt(size_t i) const {
417e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(i < InputCount());
4187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return operands_[OutputCount() + i];
4197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  size_t TempCount() const { return TempCountField::decode(bit_field_); }
4227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* TempAt(size_t i) const {
423e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(i < TempCount());
4247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return operands_[OutputCount() + InputCount() + i];
4257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode() const { return opcode_; }
4287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); }
4297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  AddressingMode addressing_mode() const {
4307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return AddressingModeField::decode(opcode());
4317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); }
4337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  FlagsCondition flags_condition() const {
4347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return FlagsConditionField::decode(opcode());
4357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(titzer): make control and call into flags.
4387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static Instruction* New(Zone* zone, InstructionCode opcode) {
4397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL);
4407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static Instruction* New(Zone* zone, InstructionCode opcode,
4437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                          size_t output_count, InstructionOperand** outputs,
4447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                          size_t input_count, InstructionOperand** inputs,
4457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                          size_t temp_count, InstructionOperand** temps) {
446e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(opcode >= 0);
447e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(output_count == 0 || outputs != NULL);
448e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(input_count == 0 || inputs != NULL);
449e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(temp_count == 0 || temps != NULL);
4507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    InstructionOperand* none = NULL;
4517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    USE(none);
4527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int size = static_cast<int>(RoundUp(sizeof(Instruction), kPointerSize) +
4537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                (output_count + input_count + temp_count - 1) *
4547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                                    sizeof(none));
4557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return new (zone->New(size)) Instruction(
4567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        opcode, output_count, outputs, input_count, inputs, temp_count, temps);
4577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // TODO(titzer): another holdover from lithium days; register allocator
4607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // should not need to know about control instructions.
4617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction* MarkAsControl() {
4627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    bit_field_ = IsControlField::update(bit_field_, true);
4637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return this;
4647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction* MarkAsCall() {
4667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    bit_field_ = IsCallField::update(bit_field_, true);
4677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return this;
4687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsControl() const { return IsControlField::decode(bit_field_); }
4707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsCall() const { return IsCallField::decode(bit_field_); }
4717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool NeedsPointerMap() const { return IsCall(); }
4727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool HasPointerMap() const { return pointer_map_ != NULL; }
4737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsGapMoves() const {
4757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return opcode() == kGapInstruction || opcode() == kBlockStartInstruction;
4767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsBlockStart() const { return opcode() == kBlockStartInstruction; }
4787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsSourcePosition() const {
4797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return opcode() == kSourcePositionInstruction;
4807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool ClobbersRegisters() const { return IsCall(); }
4837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool ClobbersTemps() const { return IsCall(); }
4847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool ClobbersDoubleRegisters() const { return IsCall(); }
4857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  PointerMap* pointer_map() const { return pointer_map_; }
4867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void set_pointer_map(PointerMap* map) {
488e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(NeedsPointerMap());
489e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(NULL, pointer_map_);
4907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    pointer_map_ = map;
4917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
4927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Placement new operator so that we can smash instructions into
4947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // zone-allocated memory.
4957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void* operator new(size_t, void* location) { return location; }
4967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void operator delete(void* pointer, void* location) { UNREACHABLE(); }
4987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
4997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org protected:
5007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Instruction(InstructionCode opcode)
5017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : opcode_(opcode),
5027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
5037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   TempCountField::encode(0) | IsCallField::encode(false) |
5047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   IsControlField::encode(false)),
5057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        pointer_map_(NULL) {}
5067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction(InstructionCode opcode, size_t output_count,
5087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org              InstructionOperand** outputs, size_t input_count,
5097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org              InstructionOperand** inputs, size_t temp_count,
5107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org              InstructionOperand** temps)
5117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : opcode_(opcode),
5127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        bit_field_(OutputCountField::encode(output_count) |
5137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   InputCountField::encode(input_count) |
5147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   TempCountField::encode(temp_count) |
5157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   IsCallField::encode(false) | IsControlField::encode(false)),
5167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        pointer_map_(NULL) {
5177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (size_t i = 0; i < output_count; ++i) {
5187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      operands_[i] = outputs[i];
5197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
5207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (size_t i = 0; i < input_count; ++i) {
5217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      operands_[output_count + i] = inputs[i];
5227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
5237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    for (size_t i = 0; i < temp_count; ++i) {
5247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      operands_[output_count + input_count + i] = temps[i];
5257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
5267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org protected:
5297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef BitField<size_t, 0, 8> OutputCountField;
5307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef BitField<size_t, 8, 16> InputCountField;
5317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef BitField<size_t, 24, 6> TempCountField;
5327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef BitField<bool, 30, 1> IsCallField;
5337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef BitField<bool, 31, 1> IsControlField;
5347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionCode opcode_;
5367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  uint32_t bit_field_;
5377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  PointerMap* pointer_map_;
5387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionOperand* operands_[1];
5397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
5407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const Instruction& instr);
5427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Represents moves inserted before an instruction due to register allocation.
5447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): squash GapInstruction back into Instruction, since essentially
5457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// every instruction can possibly have moves inserted before it.
5467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgclass GapInstruction : public Instruction {
5477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
5487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  enum InnerPosition {
5497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    BEFORE,
5507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    START,
5517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    END,
5527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    AFTER,
5537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    FIRST_INNER_POSITION = BEFORE,
5547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    LAST_INNER_POSITION = AFTER
5557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  };
5567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
5587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (parallel_moves_[pos] == NULL) {
5597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      parallel_moves_[pos] = new (zone) ParallelMove(zone);
5607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    }
5617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return parallel_moves_[pos];
5627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ParallelMove* GetParallelMove(InnerPosition pos) {
5657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return parallel_moves_[pos];
5667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static GapInstruction* New(Zone* zone) {
5697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    void* buffer = zone->New(sizeof(GapInstruction));
5707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return new (buffer) GapInstruction(kGapInstruction);
5717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static GapInstruction* cast(Instruction* instr) {
574e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->IsGapMoves());
5757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<GapInstruction*>(instr);
5767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const GapInstruction* cast(const Instruction* instr) {
579e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->IsGapMoves());
5807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<const GapInstruction*>(instr);
5817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5827d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5837d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org protected:
5847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit GapInstruction(InstructionCode opcode) : Instruction(opcode) {
5857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    parallel_moves_[BEFORE] = NULL;
5867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    parallel_moves_[START] = NULL;
5877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    parallel_moves_[END] = NULL;
5887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    parallel_moves_[AFTER] = NULL;
5897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
5907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
5927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  friend OStream& operator<<(OStream& os, const Instruction& instr);
5937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
5947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
5957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
5977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// This special kind of gap move instruction represents the beginning of a
5987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// block of code.
5997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): move code_start and code_end from BasicBlock to here.
600ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass BlockStartInstruction FINAL : public GapInstruction {
6017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
6027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* block() const { return block_; }
6037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label* label() { return &label_; }
6047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static BlockStartInstruction* New(Zone* zone, BasicBlock* block) {
6067d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    void* buffer = zone->New(sizeof(BlockStartInstruction));
6077d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return new (buffer) BlockStartInstruction(block);
6087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6097d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static BlockStartInstruction* cast(Instruction* instr) {
611e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->IsBlockStart());
6127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<BlockStartInstruction*>(instr);
6137d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
6167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit BlockStartInstruction(BasicBlock* block)
6177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : GapInstruction(kBlockStartInstruction), block_(block) {}
6187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* block_;
6207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label label_;
6217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
6227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
624ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass SourcePositionInstruction FINAL : public Instruction {
6257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
6267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static SourcePositionInstruction* New(Zone* zone, SourcePosition position) {
6277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    void* buffer = zone->New(sizeof(SourcePositionInstruction));
6287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return new (buffer) SourcePositionInstruction(position);
6297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  SourcePosition source_position() const { return source_position_; }
6327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static SourcePositionInstruction* cast(Instruction* instr) {
634e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->IsSourcePosition());
6357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<SourcePositionInstruction*>(instr);
6367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  static const SourcePositionInstruction* cast(const Instruction* instr) {
639e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->IsSourcePosition());
6407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<const SourcePositionInstruction*>(instr);
6417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
6447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit SourcePositionInstruction(SourcePosition source_position)
6457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : Instruction(kSourcePositionInstruction),
6467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        source_position_(source_position) {
647e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!source_position_.IsInvalid());
648e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!source_position_.IsUnknown());
6497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  SourcePosition source_position_;
6527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
6537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
655ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass Constant FINAL {
6567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
6577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  enum Type { kInt32, kInt64, kFloat64, kExternalReference, kHeapObject };
6587d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6597d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Constant(int32_t v) : type_(kInt32), value_(v) {}
6607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Constant(int64_t v) : type_(kInt64), value_(v) {}
661e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  explicit Constant(double v) : type_(kFloat64), value_(bit_cast<int64_t>(v)) {}
6627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Constant(ExternalReference ref)
663e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      : type_(kExternalReference), value_(bit_cast<intptr_t>(ref)) {}
6647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  explicit Constant(Handle<HeapObject> obj)
665e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org      : type_(kHeapObject), value_(bit_cast<intptr_t>(obj)) {}
6667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type type() const { return type_; }
6687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int32_t ToInt32() const {
670e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(kInt32, type());
6717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<int32_t>(value_);
6727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int64_t ToInt64() const {
6757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (type() == kInt32) return ToInt32();
676e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(kInt64, type());
6777d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return value_;
6787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  double ToFloat64() const {
6817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    if (type() == kInt32) return ToInt32();
682e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(kFloat64, type());
683e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    return bit_cast<double>(value_);
6847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ExternalReference ToExternalReference() const {
687e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(kExternalReference, type());
688e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    return bit_cast<ExternalReference>(static_cast<intptr_t>(value_));
6897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Handle<HeapObject> ToHeapObject() const {
692e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(kHeapObject, type());
693e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    return bit_cast<Handle<HeapObject> >(static_cast<intptr_t>(value_));
6947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
6957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
6967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
6977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Type type_;
6987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int64_t value_;
6997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
7007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7019d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
7029d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.orgclass FrameStateDescriptor : public ZoneObject {
7039d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org public:
704ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  FrameStateDescriptor(const FrameStateCallInfo& state_info,
705a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                       size_t parameters_count, size_t locals_count,
706a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                       size_t stack_count,
7079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org                       FrameStateDescriptor* outer_state = NULL)
708a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      : type_(state_info.type()),
709a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        bailout_id_(state_info.bailout_id()),
710ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org        frame_state_combine_(state_info.state_combine()),
7119d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org        parameters_count_(parameters_count),
7129d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org        locals_count_(locals_count),
7139aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org        stack_count_(stack_count),
714a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        outer_state_(outer_state),
715a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        jsfunction_(state_info.jsfunction()) {}
7169d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
717a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  FrameStateType type() const { return type_; }
7189d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  BailoutId bailout_id() const { return bailout_id_; }
719ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  OutputFrameStateCombine state_combine() const { return frame_state_combine_; }
720a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t parameters_count() const { return parameters_count_; }
721a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t locals_count() const { return locals_count_; }
722a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t stack_count() const { return stack_count_; }
723a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  FrameStateDescriptor* outer_state() const { return outer_state_; }
724a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  MaybeHandle<JSFunction> jsfunction() const { return jsfunction_; }
7259d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
726a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t size() const {
727ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    return parameters_count_ + locals_count_ + stack_count_ +
728a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org           (HasContext() ? 1 : 0);
729ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  }
7309d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
731a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t GetTotalSize() const {
732a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    size_t total_size = 0;
733a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    for (const FrameStateDescriptor* iter = this; iter != NULL;
7349aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org         iter = iter->outer_state_) {
7359aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org      total_size += iter->size();
7369aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    }
7379aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    return total_size;
7389aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  }
7399aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org
740a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t GetHeight(OutputFrameStateCombine override) const {
741a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    size_t height = size() - parameters_count();
742a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    switch (override) {
743a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      case kPushOutput:
744a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        ++height;
745a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        break;
746a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      case kIgnoreOutput:
747a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        break;
748a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    }
749a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    return height;
750a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  }
751a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
752a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t GetFrameCount() const {
753a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    size_t count = 0;
754a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    for (const FrameStateDescriptor* iter = this; iter != NULL;
7559aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org         iter = iter->outer_state_) {
7569aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org      ++count;
7579aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    }
7589aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    return count;
7599aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  }
7609aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org
761a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t GetJSFrameCount() const {
762a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    size_t count = 0;
763a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    for (const FrameStateDescriptor* iter = this; iter != NULL;
764a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org         iter = iter->outer_state_) {
765a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      if (iter->type_ == JS_FRAME) {
766a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org        ++count;
767a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      }
768a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    }
769a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    return count;
770a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  }
771a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
772a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  bool HasContext() const { return type_ == JS_FRAME; }
773a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
7749d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org private:
775a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  FrameStateType type_;
7769d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org  BailoutId bailout_id_;
777ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  OutputFrameStateCombine frame_state_combine_;
778a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t parameters_count_;
779a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t locals_count_;
780a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  size_t stack_count_;
7819aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  FrameStateDescriptor* outer_state_;
782a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  MaybeHandle<JSFunction> jsfunction_;
7839d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org};
7849d72b8dd94263d9f500f18255d67f0c7b8c3527amachenbach@chromium.org
7857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const Constant& constant);
7867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
787fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgtypedef ZoneDeque<Constant> ConstantDeque;
7887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgtypedef std::map<int, Constant, std::less<int>,
7897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                 zone_allocator<std::pair<int, Constant> > > ConstantMap;
7907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
791fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgtypedef ZoneDeque<Instruction*> InstructionDeque;
792fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgtypedef ZoneDeque<PointerMap*> PointerMapDeque;
793fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgtypedef ZoneVector<FrameStateDescriptor*> DeoptimizationVector;
7947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
7957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// Represents architecture-specific generated code before, during, and after
7967d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// register allocation.
7977d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org// TODO(titzer): s/IsDouble/IsFloat64/
798ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass InstructionSequence FINAL {
7997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org public:
8007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionSequence(Linkage* linkage, Graph* graph, Schedule* schedule)
8017d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org      : graph_(graph),
8027d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        linkage_(linkage),
8037d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        schedule_(schedule),
8047d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        constants_(ConstantMap::key_compare(),
8057d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                   ConstantMap::allocator_type(zone())),
806fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        immediates_(zone()),
807fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        instructions_(zone()),
8087d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        next_virtual_register_(graph->NodeCount()),
809fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        pointer_maps_(zone()),
8107d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        doubles_(std::less<int>(), VirtualRegisterSet::allocator_type(zone())),
8117d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org        references_(std::less<int>(),
8127d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org                    VirtualRegisterSet::allocator_type(zone())),
813fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org        deoptimization_entries_(zone()) {}
8147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int NextVirtualRegister() { return next_virtual_register_++; }
8167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int VirtualRegisterCount() const { return next_virtual_register_; }
8177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int ValueCount() const { return graph_->NodeCount(); }
8197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int BasicBlockCount() const {
8217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return static_cast<int>(schedule_->rpo_order()->size());
8227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* BlockAt(int rpo_number) const {
8257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return (*schedule_->rpo_order())[rpo_number];
8267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* GetContainingLoop(BasicBlock* block) {
8297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return block->loop_header_;
8307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int GetLoopEnd(BasicBlock* block) const { return block->loop_end_; }
8337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BasicBlock* GetBasicBlock(int instruction_index);
8357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int GetVirtualRegister(Node* node) const { return node->id(); }
8377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsReference(int virtual_register) const;
8397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsDouble(int virtual_register) const;
8407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8417d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void MarkAsReference(int virtual_register);
8427d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void MarkAsDouble(int virtual_register);
8437d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8447d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to);
8457d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8467d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Label* GetLabel(BasicBlock* block);
8477d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  BlockStartInstruction* GetBlockStart(BasicBlock* block);
8487d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8497d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef InstructionDeque::const_iterator const_iterator;
8507d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  const_iterator begin() const { return instructions_.begin(); }
8517d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  const_iterator end() const { return instructions_.end(); }
8527d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8537d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  GapInstruction* GapAt(int index) const {
8547d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return GapInstruction::cast(InstructionAt(index));
8557d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8567d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  bool IsGapAt(int index) const { return InstructionAt(index)->IsGapMoves(); }
8577d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Instruction* InstructionAt(int index) const {
858e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index >= 0);
859e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index < static_cast<int>(instructions_.size()));
8607d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return instructions_[index];
8617d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8627d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8637d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Frame* frame() { return &frame_; }
8647d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Graph* graph() const { return graph_; }
8657d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Isolate* isolate() const { return zone()->isolate(); }
8667d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Linkage* linkage() const { return linkage_; }
8677d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Schedule* schedule() const { return schedule_; }
8687d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  const PointerMapDeque* pointer_maps() const { return &pointer_maps_; }
8697d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Zone* zone() const { return graph_->zone(); }
8707d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8717d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  // Used by the code generator while adding instructions.
8727d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int AddInstruction(Instruction* instr, BasicBlock* block);
8737d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void StartBlock(BasicBlock* block);
8747d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void EndBlock(BasicBlock* block);
8757d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8767d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  void AddConstant(int virtual_register, Constant constant) {
877e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(constants_.find(virtual_register) == constants_.end());
8787d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    constants_.insert(std::make_pair(virtual_register, constant));
8797d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8807d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Constant GetConstant(int virtual_register) const {
8817d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    ConstantMap::const_iterator it = constants_.find(virtual_register);
882e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(it != constants_.end());
883e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_EQ(virtual_register, it->first);
8847d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return it->second;
8857d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8867d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8877d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef ConstantDeque Immediates;
8887d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  const Immediates& immediates() const { return immediates_; }
8897d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
8907d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int AddImmediate(Constant constant) {
8917d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    int index = static_cast<int>(immediates_.size());
8927d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    immediates_.push_back(constant);
8937d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return index;
8947d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
8957d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Constant GetImmediate(int index) const {
896e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index >= 0);
897e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(index < static_cast<int>(immediates_.size()));
8987d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org    return immediates_[index];
8997d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  }
9007d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
901ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class StateId {
902ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org   public:
903ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    static StateId FromInt(int id) { return StateId(id); }
904ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    int ToInt() const { return id_; }
905ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org
906ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org   private:
907ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    explicit StateId(int id) : id_(id) {}
908ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    int id_;
909ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  };
910ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org
911ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  StateId AddFrameStateDescriptor(FrameStateDescriptor* descriptor);
912ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  FrameStateDescriptor* GetFrameStateDescriptor(StateId deoptimization_id);
913ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  int GetFrameStateDescriptorCount();
9147d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9157d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org private:
9167d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  friend OStream& operator<<(OStream& os, const InstructionSequence& code);
9177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9187d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  typedef std::set<int, std::less<int>, ZoneIntAllocator> VirtualRegisterSet;
9197d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9207d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Graph* graph_;
9217d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Linkage* linkage_;
9227d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Schedule* schedule_;
9237d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ConstantMap constants_;
9247d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  ConstantDeque immediates_;
9257d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  InstructionDeque instructions_;
9267d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  int next_virtual_register_;
9277d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  PointerMapDeque pointer_maps_;
9287d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VirtualRegisterSet doubles_;
9297d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  VirtualRegisterSet references_;
9307d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  Frame frame_;
9317d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org  DeoptimizationVector deoptimization_entries_;
9327d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org};
9337d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9347d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.orgOStream& operator<<(OStream& os, const InstructionSequence& code);
9357d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9367d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace compiler
9377d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace internal
9387d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org}  // namespace v8
9397d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org
9407d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#endif  // V8_COMPILER_INSTRUCTION_H_
941