Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 "allocation.h"
     32 #include "globals.h"
     33 #include "types.h"
     34 #include "zone-inl.h"
     35 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 const int kMaxKeyedPolymorphism = 4;
     40 
     41 //         Unknown
     42 //           |   \____________
     43 //           |                |
     44 //      Primitive       Non-primitive
     45 //           |   \_______     |
     46 //           |           |    |
     47 //        Number       String |
     48 //         /   \         |    |
     49 //    Double  Integer32  |   /
     50 //        |      |      /   /
     51 //        |     Smi    /   /
     52 //        |      |    / __/
     53 //        Uninitialized.
     54 
     55 class TypeInfo {
     56  public:
     57   TypeInfo() : type_(kUninitialized) { }
     58 
     59   static TypeInfo Unknown() { return TypeInfo(kUnknown); }
     60   // We know it's a primitive type.
     61   static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
     62   // We know it's a number of some sort.
     63   static TypeInfo Number() { return TypeInfo(kNumber); }
     64   // We know it's a signed 32 bit integer.
     65   static TypeInfo Integer32() { return TypeInfo(kInteger32); }
     66   // We know it's a Smi.
     67   static TypeInfo Smi() { return TypeInfo(kSmi); }
     68   // We know it's a heap number.
     69   static TypeInfo Double() { return TypeInfo(kDouble); }
     70   // We know it's a string.
     71   static TypeInfo String() { return TypeInfo(kString); }
     72   // We know it's an internalized string.
     73   static TypeInfo InternalizedString() { return TypeInfo(kInternalizedString); }
     74   // We know it's a non-primitive (object) type.
     75   static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
     76   // We haven't started collecting info yet.
     77   static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
     78 
     79   int ToInt() {
     80     return type_;
     81   }
     82 
     83   static TypeInfo FromInt(int bit_representation) {
     84     Type t = static_cast<Type>(bit_representation);
     85     ASSERT(t == kUnknown ||
     86            t == kPrimitive ||
     87            t == kNumber ||
     88            t == kInteger32 ||
     89            t == kSmi ||
     90            t == kDouble ||
     91            t == kString ||
     92            t == kNonPrimitive);
     93     return TypeInfo(t);
     94   }
     95 
     96   // Return the weakest (least precise) common type.
     97   static TypeInfo Combine(TypeInfo a, TypeInfo b) {
     98     return TypeInfo(static_cast<Type>(a.type_ & b.type_));
     99   }
    100 
    101 
    102   // Integer32 is an integer that can be represented as a signed
    103   // 32-bit integer. It has to be
    104   // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
    105   // as it is not an Integer32.
    106   static inline bool IsInt32Double(double value) {
    107     const DoubleRepresentation minus_zero(-0.0);
    108     DoubleRepresentation rep(value);
    109     if (rep.bits == minus_zero.bits) return false;
    110     if (value >= kMinInt && value <= kMaxInt &&
    111         value == static_cast<int32_t>(value)) {
    112       return true;
    113     }
    114     return false;
    115   }
    116 
    117   static TypeInfo FromValue(Handle<Object> value);
    118 
    119   bool Equals(const TypeInfo& other) {
    120     return type_ == other.type_;
    121   }
    122 
    123   inline bool IsUnknown() {
    124     ASSERT(type_ != kUninitialized);
    125     return type_ == kUnknown;
    126   }
    127 
    128   inline bool IsPrimitive() {
    129     ASSERT(type_ != kUninitialized);
    130     return ((type_ & kPrimitive) == kPrimitive);
    131   }
    132 
    133   inline bool IsNumber() {
    134     ASSERT(type_ != kUninitialized);
    135     return ((type_ & kNumber) == kNumber);
    136   }
    137 
    138   inline bool IsSmi() {
    139     ASSERT(type_ != kUninitialized);
    140     return ((type_ & kSmi) == kSmi);
    141   }
    142 
    143   inline bool IsInternalizedString() {
    144     ASSERT(type_ != kUninitialized);
    145     return ((type_ & kInternalizedString) == kInternalizedString);
    146   }
    147 
    148   inline bool IsNonInternalizedString() {
    149     ASSERT(type_ != kUninitialized);
    150     return ((type_ & kInternalizedString) == kString);
    151   }
    152 
    153   inline bool IsInteger32() {
    154     ASSERT(type_ != kUninitialized);
    155     return ((type_ & kInteger32) == kInteger32);
    156   }
    157 
    158   inline bool IsDouble() {
    159     ASSERT(type_ != kUninitialized);
    160     return ((type_ & kDouble) == kDouble);
    161   }
    162 
    163   inline bool IsString() {
    164     ASSERT(type_ != kUninitialized);
    165     return ((type_ & kString) == kString);
    166   }
    167 
    168   inline bool IsNonPrimitive() {
    169     ASSERT(type_ != kUninitialized);
    170     return ((type_ & kNonPrimitive) == kNonPrimitive);
    171   }
    172 
    173   inline bool IsUninitialized() {
    174     return type_ == kUninitialized;
    175   }
    176 
    177   const char* ToString() {
    178     switch (type_) {
    179       case kUnknown: return "Unknown";
    180       case kPrimitive: return "Primitive";
    181       case kNumber: return "Number";
    182       case kInteger32: return "Integer32";
    183       case kSmi: return "Smi";
    184       case kInternalizedString: return "InternalizedString";
    185       case kDouble: return "Double";
    186       case kString: return "String";
    187       case kNonPrimitive: return "Object";
    188       case kUninitialized: return "Uninitialized";
    189     }
    190     UNREACHABLE();
    191     return "Unreachable code";
    192   }
    193 
    194  private:
    195   enum Type {
    196     kUnknown = 0,                // 0000000
    197     kPrimitive = 0x10,           // 0010000
    198     kNumber = 0x11,              // 0010001
    199     kInteger32 = 0x13,           // 0010011
    200     kSmi = 0x17,                 // 0010111
    201     kDouble = 0x19,              // 0011001
    202     kString = 0x30,              // 0110000
    203     kInternalizedString = 0x32,  // 0110010
    204     kNonPrimitive = 0x40,        // 1000000
    205     kUninitialized = 0x7f        // 1111111
    206   };
    207 
    208   explicit inline TypeInfo(Type t) : type_(t) { }
    209 
    210   Type type_;
    211 };
    212 
    213 
    214 enum StringStubFeedback {
    215   DEFAULT_STRING_STUB = 0,
    216   STRING_INDEX_OUT_OF_BOUNDS = 1
    217 };
    218 
    219 
    220 // Forward declarations.
    221 // TODO(rossberg): these should all go away eventually.
    222 class Assignment;
    223 class Call;
    224 class CallNew;
    225 class CaseClause;
    226 class CompilationInfo;
    227 class CountOperation;
    228 class Expression;
    229 class ForInStatement;
    230 class ICStub;
    231 class Property;
    232 class SmallMapList;
    233 class ObjectLiteral;
    234 class ObjectLiteralProperty;
    235 
    236 
    237 class TypeFeedbackOracle: public ZoneObject {
    238  public:
    239   TypeFeedbackOracle(Handle<Code> code,
    240                      Handle<Context> native_context,
    241                      Isolate* isolate,
    242                      Zone* zone);
    243 
    244   bool LoadIsMonomorphicNormal(Property* expr);
    245   bool LoadIsUninitialized(Property* expr);
    246   bool LoadIsPolymorphic(Property* expr);
    247   bool StoreIsUninitialized(TypeFeedbackId ast_id);
    248   bool StoreIsMonomorphicNormal(TypeFeedbackId ast_id);
    249   bool StoreIsKeyedPolymorphic(TypeFeedbackId ast_id);
    250   bool CallIsMonomorphic(Call* expr);
    251   bool CallNewIsMonomorphic(CallNew* expr);
    252   bool ObjectLiteralStoreIsMonomorphic(ObjectLiteralProperty* prop);
    253 
    254   // TODO(1571) We can't use ForInStatement::ForInType as the return value due
    255   // to various cycles in our headers.
    256   byte ForInType(ForInStatement* expr);
    257 
    258   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
    259   Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId id);
    260 
    261   KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
    262 
    263   void LoadReceiverTypes(Property* expr,
    264                          Handle<String> name,
    265                          SmallMapList* types);
    266   void StoreReceiverTypes(Assignment* expr,
    267                           Handle<String> name,
    268                           SmallMapList* types);
    269   void CallReceiverTypes(Call* expr,
    270                          Handle<String> name,
    271                          CallKind call_kind,
    272                          SmallMapList* types);
    273   void CollectKeyedReceiverTypes(TypeFeedbackId ast_id,
    274                                  SmallMapList* types);
    275   void CollectPolymorphicStoreReceiverTypes(TypeFeedbackId ast_id,
    276                                             SmallMapList* types);
    277 
    278   static bool CanRetainOtherContext(Map* map, Context* native_context);
    279   static bool CanRetainOtherContext(JSFunction* function,
    280                                     Context* native_context);
    281 
    282   void CollectPolymorphicMaps(Handle<Code> code, SmallMapList* types);
    283 
    284   CheckType GetCallCheckType(Call* expr);
    285   Handle<JSFunction> GetCallTarget(Call* expr);
    286   Handle<JSFunction> GetCallNewTarget(CallNew* expr);
    287   Handle<Cell> GetCallNewAllocationInfoCell(CallNew* expr);
    288 
    289   Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
    290 
    291   bool LoadIsBuiltin(Property* expr, Builtins::Name id);
    292   bool LoadIsStub(Property* expr, ICStub* stub);
    293 
    294   // TODO(1571) We can't use ToBooleanStub::Types as the return value because
    295   // of various cycles in our headers. Death to tons of implementations in
    296   // headers!! :-P
    297   byte ToBooleanTypes(TypeFeedbackId id);
    298 
    299   // Get type information for arithmetic operations and compares.
    300   void BinaryType(TypeFeedbackId id,
    301                   Handle<Type>* left,
    302                   Handle<Type>* right,
    303                   Handle<Type>* result,
    304                   Maybe<int>* fixed_right_arg);
    305 
    306   void CompareType(TypeFeedbackId id,
    307                    Handle<Type>* left,
    308                    Handle<Type>* right,
    309                    Handle<Type>* combined);
    310 
    311   Handle<Type> ClauseType(TypeFeedbackId id);
    312 
    313   TypeInfo IncrementType(CountOperation* expr);
    314 
    315   Zone* zone() const { return zone_; }
    316   Isolate* isolate() const { return isolate_; }
    317 
    318  private:
    319   void CollectReceiverTypes(TypeFeedbackId ast_id,
    320                             Handle<String> name,
    321                             Code::Flags flags,
    322                             SmallMapList* types);
    323 
    324   void SetInfo(TypeFeedbackId ast_id, Object* target);
    325 
    326   void BuildDictionary(Handle<Code> code);
    327   void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
    328   void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
    329   void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
    330                           byte* old_start,
    331                           byte* new_start);
    332   void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
    333   void ProcessTypeFeedbackCells(Handle<Code> code);
    334 
    335   // Returns an element from the backing store. Returns undefined if
    336   // there is no information.
    337   Handle<Object> GetInfo(TypeFeedbackId ast_id);
    338 
    339   // Return the cell that contains type feedback.
    340   Handle<Cell> GetInfoCell(TypeFeedbackId ast_id);
    341 
    342  private:
    343   Handle<Context> native_context_;
    344   Isolate* isolate_;
    345   Zone* zone_;
    346   Handle<UnseededNumberDictionary> dictionary_;
    347 
    348   DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
    349 };
    350 
    351 } }  // namespace v8::internal
    352 
    353 #endif  // V8_TYPE_INFO_H_
    354