Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_LITHIUM_H_
      6 #define V8_LITHIUM_H_
      7 
      8 #include <set>
      9 
     10 #include "src/allocation.h"
     11 #include "src/hydrogen.h"
     12 #include "src/safepoint-table.h"
     13 #include "src/zone-allocator.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 #define LITHIUM_OPERAND_LIST(V)               \
     19   V(ConstantOperand, CONSTANT_OPERAND,  128)  \
     20   V(StackSlot,       STACK_SLOT,        128)  \
     21   V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128)  \
     22   V(Register,        REGISTER,          16)   \
     23   V(DoubleRegister,  DOUBLE_REGISTER,   16)
     24 
     25 
     26 class LOperand : public ZoneObject {
     27  public:
     28   enum Kind {
     29     INVALID,
     30     UNALLOCATED,
     31     CONSTANT_OPERAND,
     32     STACK_SLOT,
     33     DOUBLE_STACK_SLOT,
     34     REGISTER,
     35     DOUBLE_REGISTER
     36   };
     37 
     38   LOperand() : value_(KindField::encode(INVALID)) { }
     39 
     40   Kind kind() const { return KindField::decode(value_); }
     41   int index() const { return static_cast<int>(value_) >> kKindFieldWidth; }
     42 #define LITHIUM_OPERAND_PREDICATE(name, type, number) \
     43   bool Is##name() const { return kind() == type; }
     44   LITHIUM_OPERAND_LIST(LITHIUM_OPERAND_PREDICATE)
     45   LITHIUM_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0)
     46   LITHIUM_OPERAND_PREDICATE(Ignored, INVALID, 0)
     47 #undef LITHIUM_OPERAND_PREDICATE
     48   bool Equals(LOperand* other) const { return value_ == other->value_; }
     49 
     50   void PrintTo(StringStream* stream);
     51   void ConvertTo(Kind kind, int index) {
     52     value_ = KindField::encode(kind);
     53     value_ |= index << kKindFieldWidth;
     54     ASSERT(this->index() == index);
     55   }
     56 
     57   // Calls SetUpCache()/TearDownCache() for each subclass.
     58   static void SetUpCaches();
     59   static void TearDownCaches();
     60 
     61  protected:
     62   static const int kKindFieldWidth = 3;
     63   class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
     64 
     65   LOperand(Kind kind, int index) { ConvertTo(kind, index); }
     66 
     67   unsigned value_;
     68 };
     69 
     70 
     71 class LUnallocated : public LOperand {
     72  public:
     73   enum BasicPolicy {
     74     FIXED_SLOT,
     75     EXTENDED_POLICY
     76   };
     77 
     78   enum ExtendedPolicy {
     79     NONE,
     80     ANY,
     81     FIXED_REGISTER,
     82     FIXED_DOUBLE_REGISTER,
     83     MUST_HAVE_REGISTER,
     84     MUST_HAVE_DOUBLE_REGISTER,
     85     WRITABLE_REGISTER,
     86     SAME_AS_FIRST_INPUT
     87   };
     88 
     89   // Lifetime of operand inside the instruction.
     90   enum Lifetime {
     91     // USED_AT_START operand is guaranteed to be live only at
     92     // instruction start. Register allocator is free to assign the same register
     93     // to some other operand used inside instruction (i.e. temporary or
     94     // output).
     95     USED_AT_START,
     96 
     97     // USED_AT_END operand is treated as live until the end of
     98     // instruction. This means that register allocator will not reuse it's
     99     // register for any other operand inside instruction.
    100     USED_AT_END
    101   };
    102 
    103   explicit LUnallocated(ExtendedPolicy policy) : LOperand(UNALLOCATED, 0) {
    104     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
    105     value_ |= ExtendedPolicyField::encode(policy);
    106     value_ |= LifetimeField::encode(USED_AT_END);
    107   }
    108 
    109   LUnallocated(BasicPolicy policy, int index) : LOperand(UNALLOCATED, 0) {
    110     ASSERT(policy == FIXED_SLOT);
    111     value_ |= BasicPolicyField::encode(policy);
    112     value_ |= index << FixedSlotIndexField::kShift;
    113     ASSERT(this->fixed_slot_index() == index);
    114   }
    115 
    116   LUnallocated(ExtendedPolicy policy, int index) : LOperand(UNALLOCATED, 0) {
    117     ASSERT(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
    118     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
    119     value_ |= ExtendedPolicyField::encode(policy);
    120     value_ |= LifetimeField::encode(USED_AT_END);
    121     value_ |= FixedRegisterField::encode(index);
    122   }
    123 
    124   LUnallocated(ExtendedPolicy policy, Lifetime lifetime)
    125       : LOperand(UNALLOCATED, 0) {
    126     value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
    127     value_ |= ExtendedPolicyField::encode(policy);
    128     value_ |= LifetimeField::encode(lifetime);
    129   }
    130 
    131   LUnallocated* CopyUnconstrained(Zone* zone) {
    132     LUnallocated* result = new(zone) LUnallocated(ANY);
    133     result->set_virtual_register(virtual_register());
    134     return result;
    135   }
    136 
    137   static LUnallocated* cast(LOperand* op) {
    138     ASSERT(op->IsUnallocated());
    139     return reinterpret_cast<LUnallocated*>(op);
    140   }
    141 
    142   // The encoding used for LUnallocated operands depends on the policy that is
    143   // stored within the operand. The FIXED_SLOT policy uses a compact encoding
    144   // because it accommodates a larger pay-load.
    145   //
    146   // For FIXED_SLOT policy:
    147   //     +------------------------------------------+
    148   //     |       slot_index      |  vreg  | 0 | 001 |
    149   //     +------------------------------------------+
    150   //
    151   // For all other (extended) policies:
    152   //     +------------------------------------------+
    153   //     |  reg_index  | L | PPP |  vreg  | 1 | 001 |    L ... Lifetime
    154   //     +------------------------------------------+    P ... Policy
    155   //
    156   // The slot index is a signed value which requires us to decode it manually
    157   // instead of using the BitField utility class.
    158 
    159   // The superclass has a KindField.
    160   STATIC_ASSERT(kKindFieldWidth == 3);
    161 
    162   // BitFields for all unallocated operands.
    163   class BasicPolicyField     : public BitField<BasicPolicy,     3,  1> {};
    164   class VirtualRegisterField : public BitField<unsigned,        4, 18> {};
    165 
    166   // BitFields specific to BasicPolicy::FIXED_SLOT.
    167   class FixedSlotIndexField  : public BitField<int,            22, 10> {};
    168 
    169   // BitFields specific to BasicPolicy::EXTENDED_POLICY.
    170   class ExtendedPolicyField  : public BitField<ExtendedPolicy, 22,  3> {};
    171   class LifetimeField        : public BitField<Lifetime,       25,  1> {};
    172   class FixedRegisterField   : public BitField<int,            26,  6> {};
    173 
    174   static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1;
    175   static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize;
    176   static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
    177   static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
    178 
    179   // Predicates for the operand policy.
    180   bool HasAnyPolicy() const {
    181     return basic_policy() == EXTENDED_POLICY &&
    182         extended_policy() == ANY;
    183   }
    184   bool HasFixedPolicy() const {
    185     return basic_policy() == FIXED_SLOT ||
    186         extended_policy() == FIXED_REGISTER ||
    187         extended_policy() == FIXED_DOUBLE_REGISTER;
    188   }
    189   bool HasRegisterPolicy() const {
    190     return basic_policy() == EXTENDED_POLICY && (
    191         extended_policy() == WRITABLE_REGISTER ||
    192         extended_policy() == MUST_HAVE_REGISTER);
    193   }
    194   bool HasDoubleRegisterPolicy() const {
    195     return basic_policy() == EXTENDED_POLICY &&
    196         extended_policy() == MUST_HAVE_DOUBLE_REGISTER;
    197   }
    198   bool HasSameAsInputPolicy() const {
    199     return basic_policy() == EXTENDED_POLICY &&
    200         extended_policy() == SAME_AS_FIRST_INPUT;
    201   }
    202   bool HasFixedSlotPolicy() const {
    203     return basic_policy() == FIXED_SLOT;
    204   }
    205   bool HasFixedRegisterPolicy() const {
    206     return basic_policy() == EXTENDED_POLICY &&
    207         extended_policy() == FIXED_REGISTER;
    208   }
    209   bool HasFixedDoubleRegisterPolicy() const {
    210     return basic_policy() == EXTENDED_POLICY &&
    211         extended_policy() == FIXED_DOUBLE_REGISTER;
    212   }
    213   bool HasWritableRegisterPolicy() const {
    214     return basic_policy() == EXTENDED_POLICY &&
    215         extended_policy() == WRITABLE_REGISTER;
    216   }
    217 
    218   // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
    219   BasicPolicy basic_policy() const {
    220     return BasicPolicyField::decode(value_);
    221   }
    222 
    223   // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
    224   ExtendedPolicy extended_policy() const {
    225     ASSERT(basic_policy() == EXTENDED_POLICY);
    226     return ExtendedPolicyField::decode(value_);
    227   }
    228 
    229   // [fixed_slot_index]: Only for FIXED_SLOT.
    230   int fixed_slot_index() const {
    231     ASSERT(HasFixedSlotPolicy());
    232     return static_cast<int>(value_) >> FixedSlotIndexField::kShift;
    233   }
    234 
    235   // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
    236   int fixed_register_index() const {
    237     ASSERT(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
    238     return FixedRegisterField::decode(value_);
    239   }
    240 
    241   // [virtual_register]: The virtual register ID for this operand.
    242   int virtual_register() const {
    243     return VirtualRegisterField::decode(value_);
    244   }
    245   void set_virtual_register(unsigned id) {
    246     value_ = VirtualRegisterField::update(value_, id);
    247   }
    248 
    249   // [lifetime]: Only for non-FIXED_SLOT.
    250   bool IsUsedAtStart() {
    251     ASSERT(basic_policy() == EXTENDED_POLICY);
    252     return LifetimeField::decode(value_) == USED_AT_START;
    253   }
    254 };
    255 
    256 
    257 class LMoveOperands V8_FINAL BASE_EMBEDDED {
    258  public:
    259   LMoveOperands(LOperand* source, LOperand* destination)
    260       : source_(source), destination_(destination) {
    261   }
    262 
    263   LOperand* source() const { return source_; }
    264   void set_source(LOperand* operand) { source_ = operand; }
    265 
    266   LOperand* destination() const { return destination_; }
    267   void set_destination(LOperand* operand) { destination_ = operand; }
    268 
    269   // The gap resolver marks moves as "in-progress" by clearing the
    270   // destination (but not the source).
    271   bool IsPending() const {
    272     return destination_ == NULL && source_ != NULL;
    273   }
    274 
    275   // True if this move a move into the given destination operand.
    276   bool Blocks(LOperand* operand) const {
    277     return !IsEliminated() && source()->Equals(operand);
    278   }
    279 
    280   // A move is redundant if it's been eliminated, if its source and
    281   // destination are the same, or if its destination is unneeded.
    282   bool IsRedundant() const {
    283     return IsEliminated() || source_->Equals(destination_) || IsIgnored();
    284   }
    285 
    286   bool IsIgnored() const {
    287     return destination_ != NULL && destination_->IsIgnored();
    288   }
    289 
    290   // We clear both operands to indicate move that's been eliminated.
    291   void Eliminate() { source_ = destination_ = NULL; }
    292   bool IsEliminated() const {
    293     ASSERT(source_ != NULL || destination_ == NULL);
    294     return source_ == NULL;
    295   }
    296 
    297  private:
    298   LOperand* source_;
    299   LOperand* destination_;
    300 };
    301 
    302 
    303 template<LOperand::Kind kOperandKind, int kNumCachedOperands>
    304 class LSubKindOperand V8_FINAL : public LOperand {
    305  public:
    306   static LSubKindOperand* Create(int index, Zone* zone) {
    307     ASSERT(index >= 0);
    308     if (index < kNumCachedOperands) return &cache[index];
    309     return new(zone) LSubKindOperand(index);
    310   }
    311 
    312   static LSubKindOperand* cast(LOperand* op) {
    313     ASSERT(op->kind() == kOperandKind);
    314     return reinterpret_cast<LSubKindOperand*>(op);
    315   }
    316 
    317   static void SetUpCache();
    318   static void TearDownCache();
    319 
    320  private:
    321   static LSubKindOperand* cache;
    322 
    323   LSubKindOperand() : LOperand() { }
    324   explicit LSubKindOperand(int index) : LOperand(kOperandKind, index) { }
    325 };
    326 
    327 
    328 #define LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number)   \
    329 typedef LSubKindOperand<LOperand::type, number> L##name;
    330 LITHIUM_OPERAND_LIST(LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS)
    331 #undef LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS
    332 
    333 
    334 class LParallelMove V8_FINAL : public ZoneObject {
    335  public:
    336   explicit LParallelMove(Zone* zone) : move_operands_(4, zone) { }
    337 
    338   void AddMove(LOperand* from, LOperand* to, Zone* zone) {
    339     move_operands_.Add(LMoveOperands(from, to), zone);
    340   }
    341 
    342   bool IsRedundant() const;
    343 
    344   const ZoneList<LMoveOperands>* move_operands() const {
    345     return &move_operands_;
    346   }
    347 
    348   void PrintDataTo(StringStream* stream) const;
    349 
    350  private:
    351   ZoneList<LMoveOperands> move_operands_;
    352 };
    353 
    354 
    355 class LPointerMap V8_FINAL : public ZoneObject {
    356  public:
    357   explicit LPointerMap(Zone* zone)
    358       : pointer_operands_(8, zone),
    359         untagged_operands_(0, zone),
    360         lithium_position_(-1) { }
    361 
    362   const ZoneList<LOperand*>* GetNormalizedOperands() {
    363     for (int i = 0; i < untagged_operands_.length(); ++i) {
    364       RemovePointer(untagged_operands_[i]);
    365     }
    366     untagged_operands_.Clear();
    367     return &pointer_operands_;
    368   }
    369   int lithium_position() const { return lithium_position_; }
    370 
    371   void set_lithium_position(int pos) {
    372     ASSERT(lithium_position_ == -1);
    373     lithium_position_ = pos;
    374   }
    375 
    376   void RecordPointer(LOperand* op, Zone* zone);
    377   void RemovePointer(LOperand* op);
    378   void RecordUntagged(LOperand* op, Zone* zone);
    379   void PrintTo(StringStream* stream);
    380 
    381  private:
    382   ZoneList<LOperand*> pointer_operands_;
    383   ZoneList<LOperand*> untagged_operands_;
    384   int lithium_position_;
    385 };
    386 
    387 
    388 class LEnvironment V8_FINAL : public ZoneObject {
    389  public:
    390   LEnvironment(Handle<JSFunction> closure,
    391                FrameType frame_type,
    392                BailoutId ast_id,
    393                int parameter_count,
    394                int argument_count,
    395                int value_count,
    396                LEnvironment* outer,
    397                HEnterInlined* entry,
    398                Zone* zone)
    399       : closure_(closure),
    400         frame_type_(frame_type),
    401         arguments_stack_height_(argument_count),
    402         deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
    403         translation_index_(-1),
    404         ast_id_(ast_id),
    405         translation_size_(value_count),
    406         parameter_count_(parameter_count),
    407         pc_offset_(-1),
    408         values_(value_count, zone),
    409         is_tagged_(value_count, zone),
    410         is_uint32_(value_count, zone),
    411         object_mapping_(0, zone),
    412         outer_(outer),
    413         entry_(entry),
    414         zone_(zone),
    415         has_been_used_(false) { }
    416 
    417   Handle<JSFunction> closure() const { return closure_; }
    418   FrameType frame_type() const { return frame_type_; }
    419   int arguments_stack_height() const { return arguments_stack_height_; }
    420   int deoptimization_index() const { return deoptimization_index_; }
    421   int translation_index() const { return translation_index_; }
    422   BailoutId ast_id() const { return ast_id_; }
    423   int translation_size() const { return translation_size_; }
    424   int parameter_count() const { return parameter_count_; }
    425   int pc_offset() const { return pc_offset_; }
    426   const ZoneList<LOperand*>* values() const { return &values_; }
    427   LEnvironment* outer() const { return outer_; }
    428   HEnterInlined* entry() { return entry_; }
    429   Zone* zone() const { return zone_; }
    430 
    431   bool has_been_used() const { return has_been_used_; }
    432   void set_has_been_used() { has_been_used_ = true; }
    433 
    434   void AddValue(LOperand* operand,
    435                 Representation representation,
    436                 bool is_uint32) {
    437     values_.Add(operand, zone());
    438     if (representation.IsSmiOrTagged()) {
    439       ASSERT(!is_uint32);
    440       is_tagged_.Add(values_.length() - 1, zone());
    441     }
    442 
    443     if (is_uint32) {
    444       is_uint32_.Add(values_.length() - 1, zone());
    445     }
    446   }
    447 
    448   bool HasTaggedValueAt(int index) const {
    449     return is_tagged_.Contains(index);
    450   }
    451 
    452   bool HasUint32ValueAt(int index) const {
    453     return is_uint32_.Contains(index);
    454   }
    455 
    456   void AddNewObject(int length, bool is_arguments) {
    457     uint32_t encoded = LengthOrDupeField::encode(length) |
    458                        IsArgumentsField::encode(is_arguments) |
    459                        IsDuplicateField::encode(false);
    460     object_mapping_.Add(encoded, zone());
    461   }
    462 
    463   void AddDuplicateObject(int dupe_of) {
    464     uint32_t encoded = LengthOrDupeField::encode(dupe_of) |
    465                        IsDuplicateField::encode(true);
    466     object_mapping_.Add(encoded, zone());
    467   }
    468 
    469   int ObjectDuplicateOfAt(int index) {
    470     ASSERT(ObjectIsDuplicateAt(index));
    471     return LengthOrDupeField::decode(object_mapping_[index]);
    472   }
    473 
    474   int ObjectLengthAt(int index) {
    475     ASSERT(!ObjectIsDuplicateAt(index));
    476     return LengthOrDupeField::decode(object_mapping_[index]);
    477   }
    478 
    479   bool ObjectIsArgumentsAt(int index) {
    480     ASSERT(!ObjectIsDuplicateAt(index));
    481     return IsArgumentsField::decode(object_mapping_[index]);
    482   }
    483 
    484   bool ObjectIsDuplicateAt(int index) {
    485     return IsDuplicateField::decode(object_mapping_[index]);
    486   }
    487 
    488   void Register(int deoptimization_index,
    489                 int translation_index,
    490                 int pc_offset) {
    491     ASSERT(!HasBeenRegistered());
    492     deoptimization_index_ = deoptimization_index;
    493     translation_index_ = translation_index;
    494     pc_offset_ = pc_offset;
    495   }
    496   bool HasBeenRegistered() const {
    497     return deoptimization_index_ != Safepoint::kNoDeoptimizationIndex;
    498   }
    499 
    500   void PrintTo(StringStream* stream);
    501 
    502   // Marker value indicating a de-materialized object.
    503   static LOperand* materialization_marker() { return NULL; }
    504 
    505   // Encoding used for the object_mapping map below.
    506   class LengthOrDupeField : public BitField<int,   0, 30> { };
    507   class IsArgumentsField  : public BitField<bool, 30,  1> { };
    508   class IsDuplicateField  : public BitField<bool, 31,  1> { };
    509 
    510  private:
    511   Handle<JSFunction> closure_;
    512   FrameType frame_type_;
    513   int arguments_stack_height_;
    514   int deoptimization_index_;
    515   int translation_index_;
    516   BailoutId ast_id_;
    517   int translation_size_;
    518   int parameter_count_;
    519   int pc_offset_;
    520 
    521   // Value array: [parameters] [locals] [expression stack] [de-materialized].
    522   //              |>--------- translation_size ---------<|
    523   ZoneList<LOperand*> values_;
    524   GrowableBitVector is_tagged_;
    525   GrowableBitVector is_uint32_;
    526 
    527   // Map with encoded information about materialization_marker operands.
    528   ZoneList<uint32_t> object_mapping_;
    529 
    530   LEnvironment* outer_;
    531   HEnterInlined* entry_;
    532   Zone* zone_;
    533   bool has_been_used_;
    534 };
    535 
    536 
    537 // Iterates over the non-null, non-constant operands in an environment.
    538 class ShallowIterator V8_FINAL BASE_EMBEDDED {
    539  public:
    540   explicit ShallowIterator(LEnvironment* env)
    541       : env_(env),
    542         limit_(env != NULL ? env->values()->length() : 0),
    543         current_(0) {
    544     SkipUninteresting();
    545   }
    546 
    547   bool Done() { return current_ >= limit_; }
    548 
    549   LOperand* Current() {
    550     ASSERT(!Done());
    551     ASSERT(env_->values()->at(current_) != NULL);
    552     return env_->values()->at(current_);
    553   }
    554 
    555   void Advance() {
    556     ASSERT(!Done());
    557     ++current_;
    558     SkipUninteresting();
    559   }
    560 
    561   LEnvironment* env() { return env_; }
    562 
    563  private:
    564   bool ShouldSkip(LOperand* op) {
    565     return op == NULL || op->IsConstantOperand();
    566   }
    567 
    568   // Skip until something interesting, beginning with and including current_.
    569   void SkipUninteresting() {
    570     while (current_ < limit_ && ShouldSkip(env_->values()->at(current_))) {
    571       ++current_;
    572     }
    573   }
    574 
    575   LEnvironment* env_;
    576   int limit_;
    577   int current_;
    578 };
    579 
    580 
    581 // Iterator for non-null, non-constant operands incl. outer environments.
    582 class DeepIterator V8_FINAL BASE_EMBEDDED {
    583  public:
    584   explicit DeepIterator(LEnvironment* env)
    585       : current_iterator_(env) {
    586     SkipUninteresting();
    587   }
    588 
    589   bool Done() { return current_iterator_.Done(); }
    590 
    591   LOperand* Current() {
    592     ASSERT(!current_iterator_.Done());
    593     ASSERT(current_iterator_.Current() != NULL);
    594     return current_iterator_.Current();
    595   }
    596 
    597   void Advance() {
    598     current_iterator_.Advance();
    599     SkipUninteresting();
    600   }
    601 
    602  private:
    603   void SkipUninteresting() {
    604     while (current_iterator_.env() != NULL && current_iterator_.Done()) {
    605       current_iterator_ = ShallowIterator(current_iterator_.env()->outer());
    606     }
    607   }
    608 
    609   ShallowIterator current_iterator_;
    610 };
    611 
    612 
    613 class LPlatformChunk;
    614 class LGap;
    615 class LLabel;
    616 
    617 // Superclass providing data and behavior common to all the
    618 // arch-specific LPlatformChunk classes.
    619 class LChunk : public ZoneObject {
    620  public:
    621   static LChunk* NewChunk(HGraph* graph);
    622 
    623   void AddInstruction(LInstruction* instruction, HBasicBlock* block);
    624   LConstantOperand* DefineConstantOperand(HConstant* constant);
    625   HConstant* LookupConstant(LConstantOperand* operand) const;
    626   Representation LookupLiteralRepresentation(LConstantOperand* operand) const;
    627 
    628   int ParameterAt(int index);
    629   int GetParameterStackSlot(int index) const;
    630   int spill_slot_count() const { return spill_slot_count_; }
    631   CompilationInfo* info() const { return info_; }
    632   HGraph* graph() const { return graph_; }
    633   Isolate* isolate() const { return graph_->isolate(); }
    634   const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
    635   void AddGapMove(int index, LOperand* from, LOperand* to);
    636   LGap* GetGapAt(int index) const;
    637   bool IsGapAt(int index) const;
    638   int NearestGapPos(int index) const;
    639   void MarkEmptyBlocks();
    640   const ZoneList<LPointerMap*>* pointer_maps() const { return &pointer_maps_; }
    641   LLabel* GetLabel(int block_id) const;
    642   int LookupDestination(int block_id) const;
    643   Label* GetAssemblyLabel(int block_id) const;
    644 
    645   const ZoneList<Handle<JSFunction> >* inlined_closures() const {
    646     return &inlined_closures_;
    647   }
    648 
    649   void AddInlinedClosure(Handle<JSFunction> closure) {
    650     inlined_closures_.Add(closure, zone());
    651   }
    652 
    653   void AddDeprecationDependency(Handle<Map> map) {
    654     ASSERT(!map->is_deprecated());
    655     if (!map->CanBeDeprecated()) return;
    656     ASSERT(!info_->IsStub());
    657     deprecation_dependencies_.insert(map);
    658   }
    659 
    660   void AddStabilityDependency(Handle<Map> map) {
    661     ASSERT(map->is_stable());
    662     if (!map->CanTransition()) return;
    663     ASSERT(!info_->IsStub());
    664     stability_dependencies_.insert(map);
    665   }
    666 
    667   Zone* zone() const { return info_->zone(); }
    668 
    669   Handle<Code> Codegen();
    670 
    671   void set_allocated_double_registers(BitVector* allocated_registers);
    672   BitVector* allocated_double_registers() {
    673     return allocated_double_registers_;
    674   }
    675 
    676  protected:
    677   LChunk(CompilationInfo* info, HGraph* graph);
    678 
    679   int spill_slot_count_;
    680 
    681  private:
    682   typedef std::less<Handle<Map> > MapLess;
    683   typedef zone_allocator<Handle<Map> > MapAllocator;
    684   typedef std::set<Handle<Map>, MapLess, MapAllocator> MapSet;
    685 
    686   void CommitDependencies(Handle<Code> code) const;
    687 
    688   CompilationInfo* info_;
    689   HGraph* const graph_;
    690   BitVector* allocated_double_registers_;
    691   ZoneList<LInstruction*> instructions_;
    692   ZoneList<LPointerMap*> pointer_maps_;
    693   ZoneList<Handle<JSFunction> > inlined_closures_;
    694   MapSet deprecation_dependencies_;
    695   MapSet stability_dependencies_;
    696 };
    697 
    698 
    699 class LChunkBuilderBase BASE_EMBEDDED {
    700  public:
    701   explicit LChunkBuilderBase(Zone* zone)
    702       : argument_count_(0),
    703         zone_(zone) { }
    704 
    705   virtual ~LChunkBuilderBase() { }
    706 
    707  protected:
    708   // An input operand in register, stack slot or a constant operand.
    709   // Will not be moved to a register even if one is freely available.
    710   virtual MUST_USE_RESULT LOperand* UseAny(HValue* value) = 0;
    711 
    712   LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
    713                                   int* argument_index_accumulator,
    714                                   ZoneList<HValue*>* objects_to_materialize);
    715   void AddObjectToMaterialize(HValue* value,
    716                               ZoneList<HValue*>* objects_to_materialize,
    717                               LEnvironment* result);
    718 
    719   Zone* zone() const { return zone_; }
    720 
    721   int argument_count_;
    722 
    723  private:
    724   Zone* zone_;
    725 };
    726 
    727 
    728 int StackSlotOffset(int index);
    729 
    730 enum NumberUntagDMode {
    731   NUMBER_CANDIDATE_IS_SMI,
    732   NUMBER_CANDIDATE_IS_ANY_TAGGED
    733 };
    734 
    735 
    736 class LPhase : public CompilationPhase {
    737  public:
    738   LPhase(const char* name, LChunk* chunk)
    739       : CompilationPhase(name, chunk->info()),
    740         chunk_(chunk) { }
    741   ~LPhase();
    742 
    743  private:
    744   LChunk* chunk_;
    745 
    746   DISALLOW_COPY_AND_ASSIGN(LPhase);
    747 };
    748 
    749 
    750 } }  // namespace v8::internal
    751 
    752 #endif  // V8_LITHIUM_H_
    753