1086aeeaae12517475c22695a200be45495516549Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
29fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Redistribution and use in source and binary forms, with or without
39fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// modification, are permitted provided that the following conditions are
49fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// met:
59fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//
69fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//     * Redistributions of source code must retain the above copyright
79fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//       notice, this list of conditions and the following disclaimer.
89fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//     * Redistributions in binary form must reproduce the above
99fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//       copyright notice, this list of conditions and the following
109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//       disclaimer in the documentation and/or other materials provided
119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//       with the distribution.
129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//     * Neither the name of Google Inc. nor the names of its
139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//       contributors may be used to endorse or promote products derived
149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//       from this software without specific prior written permission.
159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block//
169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
28086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifndef V8_LITHIUM_H_
29086aeeaae12517475c22695a200be45495516549Ben Murdoch#define V8_LITHIUM_H_
309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
31b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "hydrogen.h"
32b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#include "safepoint-table.h"
339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
34086aeeaae12517475c22695a200be45495516549Ben Murdochnamespace v8 {
35086aeeaae12517475c22695a200be45495516549Ben Murdochnamespace internal {
369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LOperand: public ZoneObject {
381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum Kind {
401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    INVALID,
411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    UNALLOCATED,
421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CONSTANT_OPERAND,
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    STACK_SLOT,
441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DOUBLE_STACK_SLOT,
451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    REGISTER,
461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DOUBLE_REGISTER,
471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ARGUMENT
481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LOperand() : value_(KindField::encode(INVALID)) { }
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Kind kind() const { return KindField::decode(value_); }
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int index() const { return static_cast<int>(value_) >> kKindFieldWidth; }
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsConstantOperand() const { return kind() == CONSTANT_OPERAND; }
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsStackSlot() const { return kind() == STACK_SLOT; }
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsDoubleStackSlot() const { return kind() == DOUBLE_STACK_SLOT; }
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsRegister() const { return kind() == REGISTER; }
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; }
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsArgument() const { return kind() == ARGUMENT; }
601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsUnallocated() const { return kind() == UNALLOCATED; }
611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool Equals(LOperand* other) const { return value_ == other->value_; }
621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int VirtualRegister();
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void PrintTo(StringStream* stream);
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void ConvertTo(Kind kind, int index) {
661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ = KindField::encode(kind);
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ |= index << kKindFieldWidth;
681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(this->index() == index);
691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block protected:
721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kKindFieldWidth = 3;
731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LOperand(Kind kind, int index) { ConvertTo(kind, index); }
761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned value_;
781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LUnallocated: public LOperand {
821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum Policy {
841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    NONE,
851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ANY,
861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    FIXED_REGISTER,
871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    FIXED_DOUBLE_REGISTER,
881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    FIXED_SLOT,
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    MUST_HAVE_REGISTER,
901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    WRITABLE_REGISTER,
911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    SAME_AS_FIRST_INPUT,
921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    IGNORE
931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Lifetime of operand inside the instruction.
961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum Lifetime {
971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // USED_AT_START operand is guaranteed to be live only at
981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // instruction start. Register allocator is free to assign the same register
991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // to some other operand used inside instruction (i.e. temporary or
1001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // output).
1011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    USED_AT_START,
1021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // USED_AT_END operand is treated as live until the end of
1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // instruction. This means that register allocator will not reuse it's
1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // register for any other operand inside instruction.
1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    USED_AT_END
1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) {
1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Initialize(policy, 0, USED_AT_END);
1111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) {
1141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Initialize(policy, fixed_index, USED_AT_END);
1151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) {
1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Initialize(policy, 0, lifetime);
1191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The superclass has a KindField.  Some policies have a signed fixed
1221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // index in the upper bits.
1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kPolicyWidth = 4;
1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kLifetimeWidth = 1;
1251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kVirtualRegisterWidth = 17;
1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kPolicyShift = kKindFieldWidth;
1281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
1291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth;
1301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kFixedIndexShift =
1311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      kVirtualRegisterShift + kVirtualRegisterWidth;
1321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { };
1341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class LifetimeField
1361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> {
1371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
1381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  class VirtualRegisterField
1401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : public BitField<unsigned,
1411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        kVirtualRegisterShift,
1421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        kVirtualRegisterWidth> {
1431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
1441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1);
1467d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  static const int kMaxFixedIndex = 63;
1477d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  static const int kMinFixedIndex = -64;
1481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool HasIgnorePolicy() const { return policy() == IGNORE; }
1501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool HasNoPolicy() const { return policy() == NONE; }
1511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool HasAnyPolicy() const {
1521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return policy() == ANY;
1531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool HasFixedPolicy() const {
1551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return policy() == FIXED_REGISTER ||
1561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        policy() == FIXED_DOUBLE_REGISTER ||
1571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        policy() == FIXED_SLOT;
1581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool HasRegisterPolicy() const {
1601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER;
1611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool HasSameAsInputPolicy() const {
1631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return policy() == SAME_AS_FIRST_INPUT;
1641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Policy policy() const { return PolicyField::decode(value_); }
1661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void set_policy(Policy policy) {
1671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ &= ~PolicyField::mask();
1681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ |= PolicyField::encode(policy);
1691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int fixed_index() const {
1711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return static_cast<int>(value_) >> kFixedIndexShift;
1721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned virtual_register() const {
1751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return VirtualRegisterField::decode(value_);
1761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void set_virtual_register(unsigned id) {
1791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ &= ~VirtualRegisterField::mask();
1801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ |= VirtualRegisterField::encode(id);
1811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LUnallocated* CopyUnconstrained() {
1841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    LUnallocated* result = new LUnallocated(ANY);
1851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    result->set_virtual_register(virtual_register());
1861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return result;
1871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LUnallocated* cast(LOperand* op) {
1901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsUnallocated());
1911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LUnallocated*>(op);
1921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsUsedAtStart() {
1951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return LifetimeField::decode(value_) == USED_AT_START;
1961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
1991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Initialize(Policy policy, int fixed_index, Lifetime lifetime) {
2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ |= PolicyField::encode(policy);
2011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ |= LifetimeField::encode(lifetime);
2021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value_ |= fixed_index << kFixedIndexShift;
2031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(this->fixed_index() == fixed_index);
2041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
2061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LMoveOperands BASE_EMBEDDED {
2091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LMoveOperands(LOperand* source, LOperand* destination)
2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : source_(source), destination_(destination) {
2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LOperand* source() const { return source_; }
2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void set_source(LOperand* operand) { source_ = operand; }
2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LOperand* destination() const { return destination_; }
2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void set_destination(LOperand* operand) { destination_ = operand; }
2191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The gap resolver marks moves as "in-progress" by clearing the
2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // destination (but not the source).
2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsPending() const {
2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return destination_ == NULL && source_ != NULL;
2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // True if this move a move into the given destination operand.
2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool Blocks(LOperand* operand) const {
2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return !IsEliminated() && source()->Equals(operand);
2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // A move is redundant if it's been eliminated, if its source and
2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // destination are the same, or if its destination is unneeded.
2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsRedundant() const {
2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return IsEliminated() || source_->Equals(destination_) || IsIgnored();
2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsIgnored() const {
2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return destination_ != NULL &&
2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        destination_->IsUnallocated() &&
2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        LUnallocated::cast(destination_)->HasIgnorePolicy();
2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We clear both operands to indicate move that's been eliminated.
2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Eliminate() { source_ = destination_ = NULL; }
2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsEliminated() const {
2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(source_ != NULL || destination_ == NULL);
2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return source_ == NULL;
2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LOperand* source_;
2521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LOperand* destination_;
2531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
2541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LConstantOperand: public LOperand {
2571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
2581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LConstantOperand* Create(int index) {
2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(index >= 0);
2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < kNumCachedOperands) return &cache[index];
2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return new LConstantOperand(index);
2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LConstantOperand* cast(LOperand* op) {
2651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsConstantOperand());
2661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LConstantOperand*>(op);
2671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void SetupCache();
2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
2721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kNumCachedOperands = 128;
2731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LConstantOperand cache[];
2741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LConstantOperand() : LOperand() { }
2761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { }
2771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LArgument: public LOperand {
2811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LArgument(int index) : LOperand(ARGUMENT, index) { }
2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LArgument* cast(LOperand* op) {
2851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsArgument());
2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LArgument*>(op);
2871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
2891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LStackSlot: public LOperand {
2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LStackSlot* Create(int index) {
2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(index >= 0);
2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < kNumCachedOperands) return &cache[index];
2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return new LStackSlot(index);
2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LStackSlot* cast(LOperand* op) {
3001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsStackSlot());
3011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LStackSlot*>(op);
3021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void SetupCache();
3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kNumCachedOperands = 128;
3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LStackSlot cache[];
3091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LStackSlot() : LOperand() { }
3111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { }
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LDoubleStackSlot: public LOperand {
3161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
3171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LDoubleStackSlot* Create(int index) {
3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(index >= 0);
3191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < kNumCachedOperands) return &cache[index];
3201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return new LDoubleStackSlot(index);
3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LDoubleStackSlot* cast(LOperand* op) {
3241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsStackSlot());
3251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LDoubleStackSlot*>(op);
3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void SetupCache();
3291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
3311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kNumCachedOperands = 128;
3321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LDoubleStackSlot cache[];
3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LDoubleStackSlot() : LOperand() { }
3351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { }
3361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
3371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LRegister: public LOperand {
3401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
3411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LRegister* Create(int index) {
3421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(index >= 0);
3431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < kNumCachedOperands) return &cache[index];
3441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return new LRegister(index);
3451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LRegister* cast(LOperand* op) {
3481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsRegister());
3491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LRegister*>(op);
3501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void SetupCache();
3531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
3551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kNumCachedOperands = 16;
3561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LRegister cache[];
3571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LRegister() : LOperand() { }
3591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LRegister(int index) : LOperand(REGISTER, index) { }
3601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
3611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass LDoubleRegister: public LOperand {
3641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
3651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LDoubleRegister* Create(int index) {
3661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(index >= 0);
3671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (index < kNumCachedOperands) return &cache[index];
3681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return new LDoubleRegister(index);
3691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LDoubleRegister* cast(LOperand* op) {
3721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(op->IsDoubleRegister());
3731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<LDoubleRegister*>(op);
3741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static void SetupCache();
3771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
3791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const int kNumCachedOperands = 16;
3801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static LDoubleRegister cache[];
3811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LDoubleRegister() : LOperand() { }
3831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { }
3841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
3851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
3861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass LParallelMove : public ZoneObject {
388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LParallelMove() : move_operands_(4) { }
390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void AddMove(LOperand* from, LOperand* to) {
392b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    move_operands_.Add(LMoveOperands(from, to));
393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool IsRedundant() const;
396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
397b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const ZoneList<LMoveOperands>* move_operands() const {
398b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return &move_operands_;
399b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
4009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void PrintDataTo(StringStream* stream) const;
402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<LMoveOperands> move_operands_;
405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass LPointerMap: public ZoneObject {
409086aeeaae12517475c22695a200be45495516549Ben Murdoch public:
410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  explicit LPointerMap(int position)
411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : pointer_operands_(8), position_(position), lithium_position_(-1) { }
412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const ZoneList<LOperand*>* operands() const { return &pointer_operands_; }
414b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int position() const { return position_; }
415b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int lithium_position() const { return lithium_position_; }
416b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
417b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void set_lithium_position(int pos) {
418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(lithium_position_ == -1);
419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    lithium_position_ = pos;
420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
421b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
422b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void RecordPointer(LOperand* op);
423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void PrintTo(StringStream* stream);
4249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
425086aeeaae12517475c22695a200be45495516549Ben Murdoch private:
426b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<LOperand*> pointer_operands_;
427b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int position_;
428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int lithium_position_;
429086aeeaae12517475c22695a200be45495516549Ben Murdoch};
430086aeeaae12517475c22695a200be45495516549Ben Murdoch
431086aeeaae12517475c22695a200be45495516549Ben Murdoch
432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass LEnvironment: public ZoneObject {
433b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LEnvironment(Handle<JSFunction> closure,
435b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch               int ast_id,
436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch               int parameter_count,
437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch               int argument_count,
438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch               int value_count,
439b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch               LEnvironment* outer)
440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : closure_(closure),
441b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        arguments_stack_height_(argument_count),
442b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
443b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        translation_index_(-1),
444b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        ast_id_(ast_id),
445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        parameter_count_(parameter_count),
446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        values_(value_count),
447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        representations_(value_count),
448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        spilled_registers_(NULL),
449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        spilled_double_registers_(NULL),
450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        outer_(outer) {
451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<JSFunction> closure() const { return closure_; }
454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int arguments_stack_height() const { return arguments_stack_height_; }
455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int deoptimization_index() const { return deoptimization_index_; }
456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int translation_index() const { return translation_index_; }
457b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int ast_id() const { return ast_id_; }
458b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int parameter_count() const { return parameter_count_; }
459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LOperand** spilled_registers() const { return spilled_registers_; }
460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LOperand** spilled_double_registers() const {
461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return spilled_double_registers_;
462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const ZoneList<LOperand*>* values() const { return &values_; }
464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LEnvironment* outer() const { return outer_; }
465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void AddValue(LOperand* operand, Representation representation) {
467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    values_.Add(operand);
468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    representations_.Add(representation);
469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool HasTaggedValueAt(int index) const {
472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return representations_[index].IsTagged();
473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
474b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
475b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void Register(int deoptimization_index, int translation_index) {
476b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(!HasBeenRegistered());
477b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    deoptimization_index_ = deoptimization_index;
478b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    translation_index_ = translation_index;
479b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
480b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  bool HasBeenRegistered() const {
481b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return deoptimization_index_ != Safepoint::kNoDeoptimizationIndex;
482b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
483b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
484b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void SetSpilledRegisters(LOperand** registers,
485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           LOperand** double_registers) {
486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    spilled_registers_ = registers;
487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    spilled_double_registers_ = double_registers;
488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
490b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void PrintTo(StringStream* stream);
491b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
492b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Handle<JSFunction> closure_;
494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int arguments_stack_height_;
495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int deoptimization_index_;
496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int translation_index_;
497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int ast_id_;
498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int parameter_count_;
499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<LOperand*> values_;
500b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<Representation> representations_;
501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Allocation index indexed arrays of spill slot operands for registers
503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // that are also in spill slots at an OSR entry.  NULL for environments
504b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // that do not correspond to an OSR entry.
505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LOperand** spilled_registers_;
506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LOperand** spilled_double_registers_;
507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
508b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  LEnvironment* outer_;
509b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  friend class LCodegen;
511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Iterates over the non-null, non-constant operands in an environment.
5151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass ShallowIterator BASE_EMBEDDED {
5161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
5171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit ShallowIterator(LEnvironment* env)
5181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : env_(env),
5191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        limit_(env != NULL ? env->values()->length() : 0),
5201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        current_(0) {
5211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    current_ = AdvanceToNext(0);
5221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline bool HasNext() {
5251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return env_ != NULL && current_ < limit_;
5261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline LOperand* Next() {
5291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(HasNext());
5301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return env_->values()->at(current_);
5311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void Advance() {
5341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    current_ = AdvanceToNext(current_ + 1);
5351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline LEnvironment* env() { return env_; }
5381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  inline bool ShouldSkip(LOperand* op) {
541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    return op == NULL || op->IsConstantOperand() || op->IsArgument();
542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline int AdvanceToNext(int start) {
545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    while (start < limit_ && ShouldSkip(env_->values()->at(start))) {
5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      start++;
5471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
5481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return start;
5491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  LEnvironment* env_;
5521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int limit_;
5531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int current_;
5541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
5551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Iterator for non-null, non-constant operands incl. outer environments.
5581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass DeepIterator BASE_EMBEDDED {
5591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
5601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  explicit DeepIterator(LEnvironment* env)
5611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      : current_iterator_(env) { }
5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline bool HasNext() {
5641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (current_iterator_.HasNext()) return true;
5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (current_iterator_.env() == NULL) return false;
5661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    AdvanceToOuter();
5671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return current_iterator_.HasNext();
5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline LOperand* Next() {
5711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(current_iterator_.HasNext());
5721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return current_iterator_.Next();
5731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void Advance() {
5761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (current_iterator_.HasNext()) {
5771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      current_iterator_.Advance();
5781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    } else {
5791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      AdvanceToOuter();
5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  inline void AdvanceToOuter() {
5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    current_iterator_ = ShallowIterator(current_iterator_.env()->outer());
5861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ShallowIterator current_iterator_;
5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
591086aeeaae12517475c22695a200be45495516549Ben Murdoch} }  // namespace v8::internal
592086aeeaae12517475c22695a200be45495516549Ben Murdoch
593086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif  // V8_LITHIUM_H_
594