• 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/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 
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     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 
LOperand(Kind kind,int index)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 
LUnallocated(ExtendedPolicy policy)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 
LUnallocated(BasicPolicy policy,int index)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 
LUnallocated(ExtendedPolicy policy,int index)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 
LUnallocated(ExtendedPolicy policy,Lifetime lifetime)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 
CopyUnconstrained(Zone * zone)131   LUnallocated* CopyUnconstrained(Zone* zone) {
132     LUnallocated* result = new(zone) LUnallocated(ANY);
133     result->set_virtual_register(virtual_register());
134     return result;
135   }
136 
cast(LOperand * op)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.
HasAnyPolicy()180   bool HasAnyPolicy() const {
181     return basic_policy() == EXTENDED_POLICY &&
182         extended_policy() == ANY;
183   }
HasFixedPolicy()184   bool HasFixedPolicy() const {
185     return basic_policy() == FIXED_SLOT ||
186         extended_policy() == FIXED_REGISTER ||
187         extended_policy() == FIXED_DOUBLE_REGISTER;
188   }
HasRegisterPolicy()189   bool HasRegisterPolicy() const {
190     return basic_policy() == EXTENDED_POLICY && (
191         extended_policy() == WRITABLE_REGISTER ||
192         extended_policy() == MUST_HAVE_REGISTER);
193   }
HasDoubleRegisterPolicy()194   bool HasDoubleRegisterPolicy() const {
195     return basic_policy() == EXTENDED_POLICY &&
196         extended_policy() == MUST_HAVE_DOUBLE_REGISTER;
197   }
HasSameAsInputPolicy()198   bool HasSameAsInputPolicy() const {
199     return basic_policy() == EXTENDED_POLICY &&
200         extended_policy() == SAME_AS_FIRST_INPUT;
201   }
HasFixedSlotPolicy()202   bool HasFixedSlotPolicy() const {
203     return basic_policy() == FIXED_SLOT;
204   }
HasFixedRegisterPolicy()205   bool HasFixedRegisterPolicy() const {
206     return basic_policy() == EXTENDED_POLICY &&
207         extended_policy() == FIXED_REGISTER;
208   }
HasFixedDoubleRegisterPolicy()209   bool HasFixedDoubleRegisterPolicy() const {
210     return basic_policy() == EXTENDED_POLICY &&
211         extended_policy() == FIXED_DOUBLE_REGISTER;
212   }
HasWritableRegisterPolicy()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.
basic_policy()219   BasicPolicy basic_policy() const {
220     return BasicPolicyField::decode(value_);
221   }
222 
223   // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy.
extended_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.
fixed_slot_index()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.
fixed_register_index()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.
virtual_register()242   int virtual_register() const {
243     return VirtualRegisterField::decode(value_);
244   }
set_virtual_register(unsigned id)245   void set_virtual_register(unsigned id) {
246     value_ = VirtualRegisterField::update(value_, id);
247   }
248 
249   // [lifetime]: Only for non-FIXED_SLOT.
IsUsedAtStart()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:
LMoveOperands(LOperand * source,LOperand * destination)259   LMoveOperands(LOperand* source, LOperand* destination)
260       : source_(source), destination_(destination) {
261   }
262 
source()263   LOperand* source() const { return source_; }
set_source(LOperand * operand)264   void set_source(LOperand* operand) { source_ = operand; }
265 
destination()266   LOperand* destination() const { return destination_; }
set_destination(LOperand * operand)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).
IsPending()271   bool IsPending() const {
272     return destination_ == NULL && source_ != NULL;
273   }
274 
275   // True if this move a move into the given destination operand.
Blocks(LOperand * 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.
IsRedundant()282   bool IsRedundant() const {
283     return IsEliminated() || source_->Equals(destination_) || IsIgnored();
284   }
285 
IsIgnored()286   bool IsIgnored() const {
287     return destination_ != NULL && destination_->IsIgnored();
288   }
289 
290   // We clear both operands to indicate move that's been eliminated.
Eliminate()291   void Eliminate() { source_ = destination_ = NULL; }
IsEliminated()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:
Create(int index,Zone * zone)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 
cast(LOperand * op)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 
LSubKindOperand()323   LSubKindOperand() : LOperand() { }
LSubKindOperand(int index)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;
LITHIUM_OPERAND_LIST(LITHIUM_TYPEDEF_SUBKIND_OPERAND_CLASS)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:
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     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:
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       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 
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     ASSERT(ObjectIsDuplicateAt(index));
471     return LengthOrDupeField::decode(object_mapping_[index]);
472   }
473 
ObjectLengthAt(int index)474   int ObjectLengthAt(int index) {
475     ASSERT(!ObjectIsDuplicateAt(index));
476     return LengthOrDupeField::decode(object_mapping_[index]);
477   }
478 
ObjectIsArgumentsAt(int index)479   bool ObjectIsArgumentsAt(int index) {
480     ASSERT(!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     ASSERT(!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 V8_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     ASSERT(!Done());
551     ASSERT(env_->values()->at(current_) != NULL);
552     return env_->values()->at(current_);
553   }
554 
Advance()555   void Advance() {
556     ASSERT(!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 V8_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     ASSERT(!current_iterator_.Done());
593     ASSERT(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     ASSERT(!map->is_deprecated());
655     if (!map->CanBeDeprecated()) return;
656     ASSERT(!info_->IsStub());
657     deprecation_dependencies_.insert(map);
658   }
659 
AddStabilityDependency(Handle<Map> map)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 
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(Zone * zone)701   explicit LChunkBuilderBase(Zone* zone)
702       : argument_count_(0),
703         zone_(zone) { }
704 
~LChunkBuilderBase()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 
zone()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:
LPhase(const char * name,LChunk * chunk)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