• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/bailout-reason.h"
12  #include "src/hydrogen.h"
13  #include "src/safepoint-table.h"
14  #include "src/zone-allocator.h"
15  
16  namespace v8 {
17  namespace internal {
18  
19  #define LITHIUM_OPERAND_LIST(V)               \
20    V(ConstantOperand, CONSTANT_OPERAND,  128)  \
21    V(StackSlot,       STACK_SLOT,        128)  \
22    V(DoubleStackSlot, DOUBLE_STACK_SLOT, 128)  \
23    V(Register,        REGISTER,          16)   \
24    V(DoubleRegister,  DOUBLE_REGISTER,   16)
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  
LOperand()38    LOperand() : value_(KindField::encode(INVALID)) { }
39  
kind()40    Kind kind() const { return KindField::decode(value_); }
index()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
Equals(LOperand * other)48    bool Equals(LOperand* other) const { return value_ == other->value_; }
49  
50    void PrintTo(StringStream* stream);
ConvertTo(Kind kind,int index)51    void ConvertTo(Kind kind, int index) {
52      if (kind == REGISTER) DCHECK(index >= 0);
53      value_ = KindField::encode(kind);
54      value_ |= index << kKindFieldWidth;
55      DCHECK(this->index() == index);
56    }
57  
58    // Calls SetUpCache()/TearDownCache() for each subclass.
59    static void SetUpCaches();
60    static void TearDownCaches();
61  
62   protected:
63    static const int kKindFieldWidth = 3;
64    class KindField : public BitField<Kind, 0, kKindFieldWidth> { };
65  
LOperand(Kind kind,int index)66    LOperand(Kind kind, int index) { ConvertTo(kind, index); }
67  
68    unsigned value_;
69  };
70  
71  
72  class LUnallocated : public LOperand {
73   public:
74    enum BasicPolicy {
75      FIXED_SLOT,
76      EXTENDED_POLICY
77    };
78  
79    enum ExtendedPolicy {
80      NONE,
81      ANY,
82      FIXED_REGISTER,
83      FIXED_DOUBLE_REGISTER,
84      MUST_HAVE_REGISTER,
85      MUST_HAVE_DOUBLE_REGISTER,
86      WRITABLE_REGISTER,
87      SAME_AS_FIRST_INPUT
88    };
89  
90    // Lifetime of operand inside the instruction.
91    enum Lifetime {
92      // USED_AT_START operand is guaranteed to be live only at
93      // instruction start. Register allocator is free to assign the same register
94      // to some other operand used inside instruction (i.e. temporary or
95      // output).
96      USED_AT_START,
97  
98      // USED_AT_END operand is treated as live until the end of
99      // instruction. This means that register allocator will not reuse it's
100      // register for any other operand inside instruction.
101      USED_AT_END
102    };
103  
LUnallocated(ExtendedPolicy policy)104    explicit LUnallocated(ExtendedPolicy policy) : LOperand(UNALLOCATED, 0) {
105      value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
106      value_ |= ExtendedPolicyField::encode(policy);
107      value_ |= LifetimeField::encode(USED_AT_END);
108    }
109  
LUnallocated(BasicPolicy policy,int index)110    LUnallocated(BasicPolicy policy, int index) : LOperand(UNALLOCATED, 0) {
111      DCHECK(policy == FIXED_SLOT);
112      value_ |= BasicPolicyField::encode(policy);
113      value_ |= index << FixedSlotIndexField::kShift;
114      DCHECK(this->fixed_slot_index() == index);
115    }
116  
LUnallocated(ExtendedPolicy policy,int index)117    LUnallocated(ExtendedPolicy policy, int index) : LOperand(UNALLOCATED, 0) {
118      DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER);
119      value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
120      value_ |= ExtendedPolicyField::encode(policy);
121      value_ |= LifetimeField::encode(USED_AT_END);
122      value_ |= FixedRegisterField::encode(index);
123    }
124  
LUnallocated(ExtendedPolicy policy,Lifetime lifetime)125    LUnallocated(ExtendedPolicy policy, Lifetime lifetime)
126        : LOperand(UNALLOCATED, 0) {
127      value_ |= BasicPolicyField::encode(EXTENDED_POLICY);
128      value_ |= ExtendedPolicyField::encode(policy);
129      value_ |= LifetimeField::encode(lifetime);
130    }
131  
CopyUnconstrained(Zone * zone)132    LUnallocated* CopyUnconstrained(Zone* zone) {
133      LUnallocated* result = new(zone) LUnallocated(ANY);
134      result->set_virtual_register(virtual_register());
135      return result;
136    }
137  
cast(LOperand * op)138    static LUnallocated* cast(LOperand* op) {
139      DCHECK(op->IsUnallocated());
140      return reinterpret_cast<LUnallocated*>(op);
141    }
142  
143    // The encoding used for LUnallocated operands depends on the policy that is
144    // stored within the operand. The FIXED_SLOT policy uses a compact encoding
145    // because it accommodates a larger pay-load.
146    //
147    // For FIXED_SLOT policy:
148    //     +------------------------------------------+
149    //     |       slot_index      |  vreg  | 0 | 001 |
150    //     +------------------------------------------+
151    //
152    // For all other (extended) policies:
153    //     +------------------------------------------+
154    //     |  reg_index  | L | PPP |  vreg  | 1 | 001 |    L ... Lifetime
155    //     +------------------------------------------+    P ... Policy
156    //
157    // The slot index is a signed value which requires us to decode it manually
158    // instead of using the BitField utility class.
159  
160    // The superclass has a KindField.
161    STATIC_ASSERT(kKindFieldWidth == 3);
162  
163    // BitFields for all unallocated operands.
164    class BasicPolicyField     : public BitField<BasicPolicy,     3,  1> {};
165    class VirtualRegisterField : public BitField<unsigned,        4, 18> {};
166  
167    // BitFields specific to BasicPolicy::FIXED_SLOT.
168    class FixedSlotIndexField  : public BitField<int,            22, 10> {};
169  
170    // BitFields specific to BasicPolicy::EXTENDED_POLICY.
171    class ExtendedPolicyField  : public BitField<ExtendedPolicy, 22,  3> {};
172    class LifetimeField        : public BitField<Lifetime,       25,  1> {};
173    class FixedRegisterField   : public BitField<int,            26,  6> {};
174  
175    static const int kMaxVirtualRegisters = VirtualRegisterField::kMax + 1;
176    static const int kFixedSlotIndexWidth = FixedSlotIndexField::kSize;
177    static const int kMaxFixedSlotIndex = (1 << (kFixedSlotIndexWidth - 1)) - 1;
178    static const int kMinFixedSlotIndex = -(1 << (kFixedSlotIndexWidth - 1));
179  
180    // Predicates for the operand policy.
HasAnyPolicy()181    bool HasAnyPolicy() const {
182      return basic_policy() == EXTENDED_POLICY &&
183          extended_policy() == ANY;
184    }
HasFixedPolicy()185    bool HasFixedPolicy() const {
186      return basic_policy() == FIXED_SLOT ||
187          extended_policy() == FIXED_REGISTER ||
188          extended_policy() == FIXED_DOUBLE_REGISTER;
189    }
HasRegisterPolicy()190    bool HasRegisterPolicy() const {
191      return basic_policy() == EXTENDED_POLICY && (
192          extended_policy() == WRITABLE_REGISTER ||
193          extended_policy() == MUST_HAVE_REGISTER);
194    }
HasDoubleRegisterPolicy()195    bool HasDoubleRegisterPolicy() const {
196      return basic_policy() == EXTENDED_POLICY &&
197          extended_policy() == MUST_HAVE_DOUBLE_REGISTER;
198    }
HasSameAsInputPolicy()199    bool HasSameAsInputPolicy() const {
200      return basic_policy() == EXTENDED_POLICY &&
201          extended_policy() == SAME_AS_FIRST_INPUT;
202    }
HasFixedSlotPolicy()203    bool HasFixedSlotPolicy() const {
204      return basic_policy() == FIXED_SLOT;
205    }
HasFixedRegisterPolicy()206    bool HasFixedRegisterPolicy() const {
207      return basic_policy() == EXTENDED_POLICY &&
208          extended_policy() == FIXED_REGISTER;
209    }
HasFixedDoubleRegisterPolicy()210    bool HasFixedDoubleRegisterPolicy() const {
211      return basic_policy() == EXTENDED_POLICY &&
212          extended_policy() == FIXED_DOUBLE_REGISTER;
213    }
HasWritableRegisterPolicy()214    bool HasWritableRegisterPolicy() const {
215      return basic_policy() == EXTENDED_POLICY &&
216          extended_policy() == WRITABLE_REGISTER;
217    }
218  
219    // [basic_policy]: Distinguish between FIXED_SLOT and all other policies.
basic_policy()220    BasicPolicy basic_policy() const {
221      return BasicPolicyField::decode(value_);
222    }
223  
224    // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
extended_policy()225    ExtendedPolicy extended_policy() const {
226      DCHECK(basic_policy() == EXTENDED_POLICY);
227      return ExtendedPolicyField::decode(value_);
228    }
229  
230    // [fixed_slot_index]: Only for FIXED_SLOT.
fixed_slot_index()231    int fixed_slot_index() const {
232      DCHECK(HasFixedSlotPolicy());
233      return static_cast<int>(value_) >> FixedSlotIndexField::kShift;
234    }
235  
236    // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER.
fixed_register_index()237    int fixed_register_index() const {
238      DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy());
239      return FixedRegisterField::decode(value_);
240    }
241  
242    // [virtual_register]: The virtual register ID for this operand.
virtual_register()243    int virtual_register() const {
244      return VirtualRegisterField::decode(value_);
245    }
set_virtual_register(unsigned id)246    void set_virtual_register(unsigned id) {
247      value_ = VirtualRegisterField::update(value_, id);
248    }
249  
250    // [lifetime]: Only for non-FIXED_SLOT.
IsUsedAtStart()251    bool IsUsedAtStart() {
252      DCHECK(basic_policy() == EXTENDED_POLICY);
253      return LifetimeField::decode(value_) == USED_AT_START;
254    }
255  };
256  
257  
258  class LMoveOperands FINAL BASE_EMBEDDED {
259   public:
LMoveOperands(LOperand * source,LOperand * destination)260    LMoveOperands(LOperand* source, LOperand* destination)
261        : source_(source), destination_(destination) {
262    }
263  
source()264    LOperand* source() const { return source_; }
set_source(LOperand * operand)265    void set_source(LOperand* operand) { source_ = operand; }
266  
destination()267    LOperand* destination() const { return destination_; }
set_destination(LOperand * operand)268    void set_destination(LOperand* operand) { destination_ = operand; }
269  
270    // The gap resolver marks moves as "in-progress" by clearing the
271    // destination (but not the source).
IsPending()272    bool IsPending() const {
273      return destination_ == NULL && source_ != NULL;
274    }
275  
276    // True if this move a move into the given destination operand.
Blocks(LOperand * operand)277    bool Blocks(LOperand* operand) const {
278      return !IsEliminated() && source()->Equals(operand);
279    }
280  
281    // A move is redundant if it's been eliminated, if its source and
282    // destination are the same, or if its destination is unneeded or constant.
IsRedundant()283    bool IsRedundant() const {
284      return IsEliminated() || source_->Equals(destination_) || IsIgnored() ||
285             (destination_ != NULL && destination_->IsConstantOperand());
286    }
287  
IsIgnored()288    bool IsIgnored() const {
289      return destination_ != NULL && destination_->IsIgnored();
290    }
291  
292    // We clear both operands to indicate move that's been eliminated.
Eliminate()293    void Eliminate() { source_ = destination_ = NULL; }
IsEliminated()294    bool IsEliminated() const {
295      DCHECK(source_ != NULL || destination_ == NULL);
296      return source_ == NULL;
297    }
298  
299   private:
300    LOperand* source_;
301    LOperand* destination_;
302  };
303  
304  
305  template<LOperand::Kind kOperandKind, int kNumCachedOperands>
306  class LSubKindOperand FINAL : public LOperand {
307   public:
Create(int index,Zone * zone)308    static LSubKindOperand* Create(int index, Zone* zone) {
309      DCHECK(index >= 0);
310      if (index < kNumCachedOperands) return &cache[index];
311      return new(zone) LSubKindOperand(index);
312    }
313  
cast(LOperand * op)314    static LSubKindOperand* cast(LOperand* op) {
315      DCHECK(op->kind() == kOperandKind);
316      return reinterpret_cast<LSubKindOperand*>(op);
317    }
318  
319    static void SetUpCache();
320    static void TearDownCache();
321  
322   private:
323    static LSubKindOperand* cache;
324  
LSubKindOperand()325    LSubKindOperand() : LOperand() { }
LSubKindOperand(int index)326    explicit LSubKindOperand(int index) : LOperand(kOperandKind, index) { }
327  };
328  
329  
330  #define LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS(name, type, number)   \
331  typedef LSubKindOperand<LOperand::type, number> L##name;
LITHIUM_OPERAND_LIST(LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS)332  LITHIUM_OPERAND_LIST(LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS)
333  #undef LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS
334  
335  
336  class LParallelMove FINAL : public ZoneObject {
337   public:
338    explicit LParallelMove(Zone* zone) : move_operands_(4, zone) { }
339  
340    void AddMove(LOperand* from, LOperand* to, Zone* zone) {
341      move_operands_.Add(LMoveOperands(from, to), zone);
342    }
343  
344    bool IsRedundant() const;
345  
346    ZoneList<LMoveOperands>* move_operands() { return &move_operands_; }
347  
348    void PrintDataTo(StringStream* stream) const;
349  
350   private:
351    ZoneList<LMoveOperands> move_operands_;
352  };
353  
354  
355  class LPointerMap FINAL : public ZoneObject {
356   public:
LPointerMap(Zone * zone)357    explicit LPointerMap(Zone* zone)
358        : pointer_operands_(8, zone),
359          untagged_operands_(0, zone),
360          lithium_position_(-1) { }
361  
GetNormalizedOperands()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    }
lithium_position()369    int lithium_position() const { return lithium_position_; }
370  
set_lithium_position(int pos)371    void set_lithium_position(int pos) {
372      DCHECK(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 FINAL : public ZoneObject {
389   public:
LEnvironment(Handle<JSFunction> closure,FrameType frame_type,BailoutId ast_id,int parameter_count,int argument_count,int value_count,LEnvironment * outer,HEnterInlined * entry,Zone * zone)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  
closure()417    Handle<JSFunction> closure() const { return closure_; }
frame_type()418    FrameType frame_type() const { return frame_type_; }
arguments_stack_height()419    int arguments_stack_height() const { return arguments_stack_height_; }
deoptimization_index()420    int deoptimization_index() const { return deoptimization_index_; }
translation_index()421    int translation_index() const { return translation_index_; }
ast_id()422    BailoutId ast_id() const { return ast_id_; }
translation_size()423    int translation_size() const { return translation_size_; }
parameter_count()424    int parameter_count() const { return parameter_count_; }
pc_offset()425    int pc_offset() const { return pc_offset_; }
values()426    const ZoneList<LOperand*>* values() const { return &values_; }
outer()427    LEnvironment* outer() const { return outer_; }
entry()428    HEnterInlined* entry() { return entry_; }
zone()429    Zone* zone() const { return zone_; }
430  
has_been_used()431    bool has_been_used() const { return has_been_used_; }
set_has_been_used()432    void set_has_been_used() { has_been_used_ = true; }
433  
AddValue(LOperand * operand,Representation representation,bool is_uint32)434    void AddValue(LOperand* operand,
435                  Representation representation,
436                  bool is_uint32) {
437      values_.Add(operand, zone());
438      if (representation.IsSmiOrTagged()) {
439        DCHECK(!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  
HasTaggedValueAt(int index)448    bool HasTaggedValueAt(int index) const {
449      return is_tagged_.Contains(index);
450    }
451  
HasUint32ValueAt(int index)452    bool HasUint32ValueAt(int index) const {
453      return is_uint32_.Contains(index);
454    }
455  
AddNewObject(int length,bool is_arguments)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  
AddDuplicateObject(int dupe_of)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  
ObjectDuplicateOfAt(int index)469    int ObjectDuplicateOfAt(int index) {
470      DCHECK(ObjectIsDuplicateAt(index));
471      return LengthOrDupeField::decode(object_mapping_[index]);
472    }
473  
ObjectLengthAt(int index)474    int ObjectLengthAt(int index) {
475      DCHECK(!ObjectIsDuplicateAt(index));
476      return LengthOrDupeField::decode(object_mapping_[index]);
477    }
478  
ObjectIsArgumentsAt(int index)479    bool ObjectIsArgumentsAt(int index) {
480      DCHECK(!ObjectIsDuplicateAt(index));
481      return IsArgumentsField::decode(object_mapping_[index]);
482    }
483  
ObjectIsDuplicateAt(int index)484    bool ObjectIsDuplicateAt(int index) {
485      return IsDuplicateField::decode(object_mapping_[index]);
486    }
487  
Register(int deoptimization_index,int translation_index,int pc_offset)488    void Register(int deoptimization_index,
489                  int translation_index,
490                  int pc_offset) {
491      DCHECK(!HasBeenRegistered());
492      deoptimization_index_ = deoptimization_index;
493      translation_index_ = translation_index;
494      pc_offset_ = pc_offset;
495    }
HasBeenRegistered()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.
materialization_marker()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 FINAL BASE_EMBEDDED {
539   public:
ShallowIterator(LEnvironment * env)540    explicit ShallowIterator(LEnvironment* env)
541        : env_(env),
542          limit_(env != NULL ? env->values()->length() : 0),
543          current_(0) {
544      SkipUninteresting();
545    }
546  
Done()547    bool Done() { return current_ >= limit_; }
548  
Current()549    LOperand* Current() {
550      DCHECK(!Done());
551      DCHECK(env_->values()->at(current_) != NULL);
552      return env_->values()->at(current_);
553    }
554  
Advance()555    void Advance() {
556      DCHECK(!Done());
557      ++current_;
558      SkipUninteresting();
559    }
560  
env()561    LEnvironment* env() { return env_; }
562  
563   private:
ShouldSkip(LOperand * op)564    bool ShouldSkip(LOperand* op) {
565      return op == NULL || op->IsConstantOperand();
566    }
567  
568    // Skip until something interesting, beginning with and including current_.
SkipUninteresting()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 FINAL BASE_EMBEDDED {
583   public:
DeepIterator(LEnvironment * env)584    explicit DeepIterator(LEnvironment* env)
585        : current_iterator_(env) {
586      SkipUninteresting();
587    }
588  
Done()589    bool Done() { return current_iterator_.Done(); }
590  
Current()591    LOperand* Current() {
592      DCHECK(!current_iterator_.Done());
593      DCHECK(current_iterator_.Current() != NULL);
594      return current_iterator_.Current();
595    }
596  
Advance()597    void Advance() {
598      current_iterator_.Advance();
599      SkipUninteresting();
600    }
601  
602   private:
SkipUninteresting()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;
spill_slot_count()630    int spill_slot_count() const { return spill_slot_count_; }
info()631    CompilationInfo* info() const { return info_; }
graph()632    HGraph* graph() const { return graph_; }
isolate()633    Isolate* isolate() const { return graph_->isolate(); }
instructions()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();
pointer_maps()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  
inlined_closures()645    const ZoneList<Handle<JSFunction> >* inlined_closures() const {
646      return &inlined_closures_;
647    }
648  
AddInlinedClosure(Handle<JSFunction> closure)649    void AddInlinedClosure(Handle<JSFunction> closure) {
650      inlined_closures_.Add(closure, zone());
651    }
652  
AddDeprecationDependency(Handle<Map> map)653    void AddDeprecationDependency(Handle<Map> map) {
654      DCHECK(!map->is_deprecated());
655      if (!map->CanBeDeprecated()) return;
656      DCHECK(!info_->IsStub());
657      deprecation_dependencies_.insert(map);
658    }
659  
AddStabilityDependency(Handle<Map> map)660    void AddStabilityDependency(Handle<Map> map) {
661      DCHECK(map->is_stable());
662      if (!map->CanTransition()) return;
663      DCHECK(!info_->IsStub());
664      stability_dependencies_.insert(map);
665    }
666  
zone()667    Zone* zone() const { return info_->zone(); }
668  
669    Handle<Code> Codegen();
670  
671    void set_allocated_double_registers(BitVector* allocated_registers);
allocated_double_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:
LChunkBuilderBase(CompilationInfo * info,HGraph * graph)701    explicit LChunkBuilderBase(CompilationInfo* info, HGraph* graph)
702        : argument_count_(0),
703          chunk_(NULL),
704          info_(info),
705          graph_(graph),
706          status_(UNUSED),
707          zone_(graph->zone()) {}
708  
~LChunkBuilderBase()709    virtual ~LChunkBuilderBase() { }
710  
711    void Abort(BailoutReason reason);
712    void Retry(BailoutReason reason);
713  
714   protected:
715    enum Status { UNUSED, BUILDING, DONE, ABORTED };
716  
chunk()717    LPlatformChunk* chunk() const { return chunk_; }
info()718    CompilationInfo* info() const { return info_; }
graph()719    HGraph* graph() const { return graph_; }
argument_count()720    int argument_count() const { return argument_count_; }
isolate()721    Isolate* isolate() const { return graph_->isolate(); }
heap()722    Heap* heap() const { return isolate()->heap(); }
723  
is_unused()724    bool is_unused() const { return status_ == UNUSED; }
is_building()725    bool is_building() const { return status_ == BUILDING; }
is_done()726    bool is_done() const { return status_ == DONE; }
is_aborted()727    bool is_aborted() const { return status_ == ABORTED; }
728  
729    // An input operand in register, stack slot or a constant operand.
730    // Will not be moved to a register even if one is freely available.
731    virtual MUST_USE_RESULT LOperand* UseAny(HValue* value) = 0;
732  
733    LEnvironment* CreateEnvironment(HEnvironment* hydrogen_env,
734                                    int* argument_index_accumulator,
735                                    ZoneList<HValue*>* objects_to_materialize);
736    void AddObjectToMaterialize(HValue* value,
737                                ZoneList<HValue*>* objects_to_materialize,
738                                LEnvironment* result);
739  
zone()740    Zone* zone() const { return zone_; }
741  
742    int argument_count_;
743    LPlatformChunk* chunk_;
744    CompilationInfo* info_;
745    HGraph* const graph_;
746    Status status_;
747  
748   private:
749    Zone* zone_;
750  };
751  
752  
753  int StackSlotOffset(int index);
754  
755  enum NumberUntagDMode {
756    NUMBER_CANDIDATE_IS_SMI,
757    NUMBER_CANDIDATE_IS_ANY_TAGGED
758  };
759  
760  
761  class LPhase : public CompilationPhase {
762   public:
LPhase(const char * name,LChunk * chunk)763    LPhase(const char* name, LChunk* chunk)
764        : CompilationPhase(name, chunk->info()),
765          chunk_(chunk) { }
766    ~LPhase();
767  
768   private:
769    LChunk* chunk_;
770  
771    DISALLOW_COPY_AND_ASSIGN(LPhase);
772  };
773  
774  
775  // A register-allocator view of a Lithium instruction. It contains the id of
776  // the output operand and a list of input operand uses.
777  
778  enum RegisterKind {
779    UNALLOCATED_REGISTERS,
780    GENERAL_REGISTERS,
781    DOUBLE_REGISTERS
782  };
783  
784  // Iterator for non-null temp operands.
785  class TempIterator BASE_EMBEDDED {
786   public:
787    inline explicit TempIterator(LInstruction* instr);
788    inline bool Done();
789    inline LOperand* Current();
790    inline void Advance();
791  
792   private:
793    inline void SkipUninteresting();
794    LInstruction* instr_;
795    int limit_;
796    int current_;
797  };
798  
799  
800  // Iterator for non-constant input operands.
801  class InputIterator BASE_EMBEDDED {
802   public:
803    inline explicit InputIterator(LInstruction* instr);
804    inline bool Done();
805    inline LOperand* Current();
806    inline void Advance();
807  
808   private:
809    inline void SkipUninteresting();
810    LInstruction* instr_;
811    int limit_;
812    int current_;
813  };
814  
815  
816  class UseIterator BASE_EMBEDDED {
817   public:
818    inline explicit UseIterator(LInstruction* instr);
819    inline bool Done();
820    inline LOperand* Current();
821    inline void Advance();
822  
823   private:
824    InputIterator input_iterator_;
825    DeepIterator env_iterator_;
826  };
827  
828  class LInstruction;
829  class LCodeGen;
830  } }  // namespace v8::internal
831  
832  #endif  // V8_LITHIUM_H_
833