Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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_TYPE_INFO_H_
     29 #define V8_TYPE_INFO_H_
     30 
     31 #include "globals.h"
     32 #include "zone.h"
     33 #include "zone-inl.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 //         Unknown
     39 //           |   |
     40 //           |   \--------------|
     41 //      Primitive             Non-primitive
     42 //           |   \--------|     |
     43 //         Number      String   |
     44 //         /    |         |     |
     45 //    Double  Integer32   |    /
     46 //        |      |       /    /
     47 //        |     Smi     /    /
     48 //        |      |     /    /
     49 //        |      |    /    /
     50 //        Uninitialized.--/
     51 
     52 class TypeInfo {
     53  public:
     54   TypeInfo() : type_(kUninitialized) { }
     55 
     56   static TypeInfo Unknown() { return TypeInfo(kUnknown); }
     57   // We know it's a primitive type.
     58   static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
     59   // We know it's a number of some sort.
     60   static TypeInfo Number() { return TypeInfo(kNumber); }
     61   // We know it's a signed 32 bit integer.
     62   static TypeInfo Integer32() { return TypeInfo(kInteger32); }
     63   // We know it's a Smi.
     64   static TypeInfo Smi() { return TypeInfo(kSmi); }
     65   // We know it's a heap number.
     66   static TypeInfo Double() { return TypeInfo(kDouble); }
     67   // We know it's a string.
     68   static TypeInfo String() { return TypeInfo(kString); }
     69   // We know it's a non-primitive (object) type.
     70   static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
     71   // We haven't started collecting info yet.
     72   static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
     73 
     74   // Return compact representation.  Very sensitive to enum values below!
     75   // Compacting drops information about primitive types and strings types.
     76   // We use the compact representation when we only care about number types.
     77   int ThreeBitRepresentation() {
     78     ASSERT(type_ != kUninitialized);
     79     int answer = type_ & 0xf;
     80     answer = answer > 6 ? answer - 2 : answer;
     81     ASSERT(answer >= 0);
     82     ASSERT(answer <= 7);
     83     return answer;
     84   }
     85 
     86   // Decode compact representation.  Very sensitive to enum values below!
     87   static TypeInfo ExpandedRepresentation(int three_bit_representation) {
     88     Type t = static_cast<Type>(three_bit_representation > 4 ?
     89                                three_bit_representation + 2 :
     90                                three_bit_representation);
     91     t = (t == kUnknown) ? t : static_cast<Type>(t | kPrimitive);
     92     ASSERT(t == kUnknown ||
     93            t == kNumber ||
     94            t == kInteger32 ||
     95            t == kSmi ||
     96            t == kDouble);
     97     return TypeInfo(t);
     98   }
     99 
    100   int ToInt() {
    101     return type_;
    102   }
    103 
    104   static TypeInfo FromInt(int bit_representation) {
    105     Type t = static_cast<Type>(bit_representation);
    106     ASSERT(t == kUnknown ||
    107            t == kPrimitive ||
    108            t == kNumber ||
    109            t == kInteger32 ||
    110            t == kSmi ||
    111            t == kDouble ||
    112            t == kString ||
    113            t == kNonPrimitive);
    114     return TypeInfo(t);
    115   }
    116 
    117   // Return the weakest (least precise) common type.
    118   static TypeInfo Combine(TypeInfo a, TypeInfo b) {
    119     return TypeInfo(static_cast<Type>(a.type_ & b.type_));
    120   }
    121 
    122 
    123   // Integer32 is an integer that can be represented as a signed
    124   // 32-bit integer. It has to be
    125   // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
    126   // as it is not an Integer32.
    127   static inline bool IsInt32Double(double value) {
    128     const DoubleRepresentation minus_zero(-0.0);
    129     DoubleRepresentation rep(value);
    130     if (rep.bits == minus_zero.bits) return false;
    131     if (value >= kMinInt && value <= kMaxInt &&
    132         value == static_cast<int32_t>(value)) {
    133       return true;
    134     }
    135     return false;
    136   }
    137 
    138   static TypeInfo TypeFromValue(Handle<Object> value);
    139 
    140   bool Equals(const TypeInfo& other) {
    141     return type_ == other.type_;
    142   }
    143 
    144   inline bool IsUnknown() {
    145     ASSERT(type_ != kUninitialized);
    146     return type_ == kUnknown;
    147   }
    148 
    149   inline bool IsPrimitive() {
    150     ASSERT(type_ != kUninitialized);
    151     return ((type_ & kPrimitive) == kPrimitive);
    152   }
    153 
    154   inline bool IsNumber() {
    155     ASSERT(type_ != kUninitialized);
    156     return ((type_ & kNumber) == kNumber);
    157   }
    158 
    159   inline bool IsSmi() {
    160     ASSERT(type_ != kUninitialized);
    161     return ((type_ & kSmi) == kSmi);
    162   }
    163 
    164   inline bool IsInteger32() {
    165     ASSERT(type_ != kUninitialized);
    166     return ((type_ & kInteger32) == kInteger32);
    167   }
    168 
    169   inline bool IsDouble() {
    170     ASSERT(type_ != kUninitialized);
    171     return ((type_ & kDouble) == kDouble);
    172   }
    173 
    174   inline bool IsString() {
    175     ASSERT(type_ != kUninitialized);
    176     return ((type_ & kString) == kString);
    177   }
    178 
    179   inline bool IsNonPrimitive() {
    180     ASSERT(type_ != kUninitialized);
    181     return ((type_ & kNonPrimitive) == kNonPrimitive);
    182   }
    183 
    184   inline bool IsUninitialized() {
    185     return type_ == kUninitialized;
    186   }
    187 
    188   const char* ToString() {
    189     switch (type_) {
    190       case kUnknown: return "Unknown";
    191       case kPrimitive: return "Primitive";
    192       case kNumber: return "Number";
    193       case kInteger32: return "Integer32";
    194       case kSmi: return "Smi";
    195       case kDouble: return "Double";
    196       case kString: return "String";
    197       case kNonPrimitive: return "Object";
    198       case kUninitialized: return "Uninitialized";
    199     }
    200     UNREACHABLE();
    201     return "Unreachable code";
    202   }
    203 
    204  private:
    205   enum Type {
    206     kUnknown = 0,          // 0000000
    207     kPrimitive = 0x10,     // 0010000
    208     kNumber = 0x11,        // 0010001
    209     kInteger32 = 0x13,     // 0010011
    210     kSmi = 0x17,           // 0010111
    211     kDouble = 0x19,        // 0011001
    212     kString = 0x30,        // 0110000
    213     kNonPrimitive = 0x40,  // 1000000
    214     kUninitialized = 0x7f  // 1111111
    215   };
    216   explicit inline TypeInfo(Type t) : type_(t) { }
    217 
    218   Type type_;
    219 };
    220 
    221 
    222 enum StringStubFeedback {
    223   DEFAULT_STRING_STUB = 0,
    224   STRING_INDEX_OUT_OF_BOUNDS = 1
    225 };
    226 
    227 
    228 // Forward declarations.
    229 class Assignment;
    230 class BinaryOperation;
    231 class Call;
    232 class CompareOperation;
    233 class CompilationInfo;
    234 class Property;
    235 class CaseClause;
    236 
    237 class TypeFeedbackOracle BASE_EMBEDDED {
    238  public:
    239   TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
    240 
    241   bool LoadIsMonomorphic(Property* expr);
    242   bool StoreIsMonomorphic(Expression* expr);
    243   bool CallIsMonomorphic(Call* expr);
    244 
    245   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
    246   Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
    247 
    248   ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
    249   ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
    250   ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
    251 
    252   ExternalArrayType GetKeyedLoadExternalArrayType(Property* expr);
    253   ExternalArrayType GetKeyedStoreExternalArrayType(Expression* expr);
    254 
    255   CheckType GetCallCheckType(Call* expr);
    256   Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
    257 
    258   bool LoadIsBuiltin(Property* expr, Builtins::Name id);
    259 
    260   // Get type information for arithmetic operations and compares.
    261   TypeInfo BinaryType(BinaryOperation* expr);
    262   TypeInfo CompareType(CompareOperation* expr);
    263   TypeInfo SwitchType(CaseClause* clause);
    264 
    265  private:
    266   ZoneMapList* CollectReceiverTypes(int position,
    267                                     Handle<String> name,
    268                                     Code::Flags flags);
    269 
    270   void SetInfo(int position, Object* target);
    271 
    272   void PopulateMap(Handle<Code> code);
    273 
    274   void CollectPositions(Code* code,
    275                         List<int>* code_positions,
    276                         List<int>* source_positions);
    277 
    278   // Returns an element from the backing store. Returns undefined if
    279   // there is no information.
    280   Handle<Object> GetInfo(int pos);
    281 
    282   Handle<Context> global_context_;
    283   Handle<NumberDictionary> dictionary_;
    284 
    285   DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
    286 };
    287 
    288 } }  // namespace v8::internal
    289 
    290 #endif  // V8_TYPE_INFO_H_
    291