Home | History | Annotate | Download | only in src
      1 // Copyright 2009 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_FRAME_ELEMENT_H_
     29 #define V8_FRAME_ELEMENT_H_
     30 
     31 #include "number-info.h"
     32 #include "macro-assembler.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 // -------------------------------------------------------------------------
     38 // Virtual frame elements
     39 //
     40 // The internal elements of the virtual frames.  There are several kinds of
     41 // elements:
     42 //   * Invalid: elements that are uninitialized or not actually part
     43 //     of the virtual frame.  They should not be read.
     44 //   * Memory: an element that resides in the actual frame.  Its address is
     45 //     given by its position in the virtual frame.
     46 //   * Register: an element that resides in a register.
     47 //   * Constant: an element whose value is known at compile time.
     48 
     49 class FrameElement BASE_EMBEDDED {
     50  public:
     51   enum SyncFlag {
     52     NOT_SYNCED,
     53     SYNCED
     54   };
     55 
     56   inline NumberInfo::Type number_info() {
     57     // Copied elements do not have number info. Instead
     58     // we have to inspect their backing element in the frame.
     59     ASSERT(!is_copy());
     60     if (!is_constant()) return NumberInfoField::decode(value_);
     61     Handle<Object> value = handle();
     62     if (value->IsSmi()) return NumberInfo::kSmi;
     63     if (value->IsHeapNumber()) return NumberInfo::kHeapNumber;
     64     return NumberInfo::kUnknown;
     65   }
     66 
     67   inline void set_number_info(NumberInfo::Type info) {
     68     // Copied elements do not have number info. Instead
     69     // we have to inspect their backing element in the frame.
     70     ASSERT(!is_copy());
     71     value_ = value_ & ~NumberInfoField::mask();
     72     value_ = value_ | NumberInfoField::encode(info);
     73   }
     74 
     75   // The default constructor creates an invalid frame element.
     76   FrameElement() {
     77     value_ = TypeField::encode(INVALID)
     78         | CopiedField::encode(false)
     79         | SyncedField::encode(false)
     80         | NumberInfoField::encode(NumberInfo::kUninitialized)
     81         | DataField::encode(0);
     82   }
     83 
     84   // Factory function to construct an invalid frame element.
     85   static FrameElement InvalidElement() {
     86     FrameElement result;
     87     return result;
     88   }
     89 
     90   // Factory function to construct an in-memory frame element.
     91   static FrameElement MemoryElement(NumberInfo::Type info) {
     92     FrameElement result(MEMORY, no_reg, SYNCED, info);
     93     return result;
     94   }
     95 
     96   // Factory function to construct an in-register frame element.
     97   static FrameElement RegisterElement(Register reg,
     98                                       SyncFlag is_synced,
     99                                       NumberInfo::Type info) {
    100     return FrameElement(REGISTER, reg, is_synced, info);
    101   }
    102 
    103   // Factory function to construct a frame element whose value is known at
    104   // compile time.
    105   static FrameElement ConstantElement(Handle<Object> value,
    106                                       SyncFlag is_synced) {
    107     FrameElement result(value, is_synced);
    108     return result;
    109   }
    110 
    111   // Static indirection table for handles to constants.  If a frame
    112   // element represents a constant, the data contains an index into
    113   // this table of handles to the actual constants.
    114   typedef ZoneList<Handle<Object> > ZoneObjectList;
    115 
    116   static ZoneObjectList* ConstantList();
    117 
    118   // Clear the constants indirection table.
    119   static void ClearConstantList() {
    120     ConstantList()->Clear();
    121   }
    122 
    123   bool is_synced() const { return SyncedField::decode(value_); }
    124 
    125   void set_sync() {
    126     ASSERT(type() != MEMORY);
    127     value_ = value_ | SyncedField::encode(true);
    128   }
    129 
    130   void clear_sync() {
    131     ASSERT(type() != MEMORY);
    132     value_ = value_ & ~SyncedField::mask();
    133   }
    134 
    135   bool is_valid() const { return type() != INVALID; }
    136   bool is_memory() const { return type() == MEMORY; }
    137   bool is_register() const { return type() == REGISTER; }
    138   bool is_constant() const { return type() == CONSTANT; }
    139   bool is_copy() const { return type() == COPY; }
    140 
    141   bool is_copied() const { return CopiedField::decode(value_); }
    142   void set_copied() { value_ = value_ | CopiedField::encode(true); }
    143   void clear_copied() { value_ = value_ & ~CopiedField::mask(); }
    144 
    145   Register reg() const {
    146     ASSERT(is_register());
    147     uint32_t reg = DataField::decode(value_);
    148     Register result;
    149     result.code_ = reg;
    150     return result;
    151   }
    152 
    153   Handle<Object> handle() const {
    154     ASSERT(is_constant());
    155     return ConstantList()->at(DataField::decode(value_));
    156   }
    157 
    158   int index() const {
    159     ASSERT(is_copy());
    160     return DataField::decode(value_);
    161   }
    162 
    163   bool Equals(FrameElement other) {
    164     uint32_t masked_difference = (value_ ^ other.value_) & ~CopiedField::mask();
    165     if (!masked_difference) {
    166       // The elements are equal if they agree exactly except on copied field.
    167       return true;
    168     } else {
    169       // If two constants have the same value, and agree otherwise, return true.
    170        return !(masked_difference & ~DataField::mask()) &&
    171               is_constant() &&
    172               handle().is_identical_to(other.handle());
    173     }
    174   }
    175 
    176   // Test if two FrameElements refer to the same memory or register location.
    177   bool SameLocation(FrameElement* other) {
    178     if (type() == other->type()) {
    179       if (value_ == other->value_) return true;
    180       if (is_constant() && handle().is_identical_to(other->handle())) {
    181         return true;
    182       }
    183     }
    184     return false;
    185   }
    186 
    187   // Given a pair of non-null frame element pointers, return one of them
    188   // as an entry frame candidate or null if they are incompatible.
    189   FrameElement* Combine(FrameElement* other) {
    190     // If either is invalid, the result is.
    191     if (!is_valid()) return this;
    192     if (!other->is_valid()) return other;
    193 
    194     if (!SameLocation(other)) return NULL;
    195     // If either is unsynced, the result is.
    196     FrameElement* result = is_synced() ? other : this;
    197     return result;
    198   }
    199 
    200  private:
    201   enum Type {
    202     INVALID,
    203     MEMORY,
    204     REGISTER,
    205     CONSTANT,
    206     COPY
    207   };
    208 
    209   // Used to construct memory and register elements.
    210   FrameElement(Type type,
    211                Register reg,
    212                SyncFlag is_synced,
    213                NumberInfo::Type info) {
    214     value_ = TypeField::encode(type)
    215         | CopiedField::encode(false)
    216         | SyncedField::encode(is_synced != NOT_SYNCED)
    217         | NumberInfoField::encode(info)
    218         | DataField::encode(reg.code_ > 0 ? reg.code_ : 0);
    219   }
    220 
    221   // Used to construct constant elements.
    222   FrameElement(Handle<Object> value, SyncFlag is_synced) {
    223     value_ = TypeField::encode(CONSTANT)
    224         | CopiedField::encode(false)
    225         | SyncedField::encode(is_synced != NOT_SYNCED)
    226         | NumberInfoField::encode(NumberInfo::kUninitialized)
    227         | DataField::encode(ConstantList()->length());
    228     ConstantList()->Add(value);
    229   }
    230 
    231   Type type() const { return TypeField::decode(value_); }
    232   void set_type(Type type) {
    233     value_ = value_ & ~TypeField::mask();
    234     value_ = value_ | TypeField::encode(type);
    235   }
    236 
    237   void set_index(int new_index) {
    238     ASSERT(is_copy());
    239     value_ = value_ & ~DataField::mask();
    240     value_ = value_ | DataField::encode(new_index);
    241   }
    242 
    243   void set_reg(Register new_reg) {
    244     ASSERT(is_register());
    245     value_ = value_ & ~DataField::mask();
    246     value_ = value_ | DataField::encode(new_reg.code_);
    247   }
    248 
    249   // Encode type, copied, synced and data in one 32 bit integer.
    250   uint32_t value_;
    251 
    252   class TypeField: public BitField<Type, 0, 3> {};
    253   class CopiedField: public BitField<bool, 3, 1> {};
    254   class SyncedField: public BitField<bool, 4, 1> {};
    255   class NumberInfoField: public BitField<NumberInfo::Type, 5, 3> {};
    256   class DataField: public BitField<uint32_t, 8, 32 - 8> {};
    257 
    258   friend class VirtualFrame;
    259 };
    260 
    261 } }  // namespace v8::internal
    262 
    263 #endif  // V8_FRAME_ELEMENT_H_
    264