LCOV - code coverage report
Current view: top level - src/crankshaft - lithium.h (source / functions) Hit Total Coverage
Test: app.info Lines: 114 114 100.0 %
Date: 2017-04-26 Functions: 17 19 89.5 %

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

Generated by: LCOV version 1.10