type-info.h 9.12 KB
Newer Older
1
// Copyright 2011 the V8 project authors. All rights reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

28 29
#ifndef V8_TYPE_INFO_H_
#define V8_TYPE_INFO_H_
30

31
#include "allocation.h"
32
#include "globals.h"
33
#include "zone-inl.h"
34

35 36 37
namespace v8 {
namespace internal {

38 39
const int kMaxKeyedPolymorphism = 4;

40
//         Unknown
41 42 43 44 45 46 47 48 49 50 51 52
//           |   \____________
//           |                |
//      Primitive       Non-primitive
//           |   \_______     |
//           |           |    |
//        Number       String |
//         /   \         |    |
//    Double  Integer32  |   /
//        |      |      /   /
//        |     Smi    /   /
//        |      |    / __/
//        Uninitialized.
53

54
class TypeInfo {
55
 public:
56
  TypeInfo() : type_(kUninitialized) { }
57

58
  static TypeInfo Unknown() { return TypeInfo(kUnknown); }
59
  // We know it's a primitive type.
60
  static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
61
  // We know it's a number of some sort.
62 63 64
  static TypeInfo Number() { return TypeInfo(kNumber); }
  // We know it's a signed 32 bit integer.
  static TypeInfo Integer32() { return TypeInfo(kInteger32); }
65
  // We know it's a Smi.
66
  static TypeInfo Smi() { return TypeInfo(kSmi); }
67
  // We know it's a heap number.
68
  static TypeInfo Double() { return TypeInfo(kDouble); }
69
  // We know it's a string.
70 71 72
  static TypeInfo String() { return TypeInfo(kString); }
  // We know it's a non-primitive (object) type.
  static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
73
  // We haven't started collecting info yet.
74
  static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
75 76 77 78 79

  int ToInt() {
    return type_;
  }

80
  static TypeInfo FromInt(int bit_representation) {
81
    Type t = static_cast<Type>(bit_representation);
82 83 84 85 86 87 88 89
    ASSERT(t == kUnknown ||
           t == kPrimitive ||
           t == kNumber ||
           t == kInteger32 ||
           t == kSmi ||
           t == kDouble ||
           t == kString ||
           t == kNonPrimitive);
90
    return TypeInfo(t);
91
  }
92 93

  // Return the weakest (least precise) common type.
94 95
  static TypeInfo Combine(TypeInfo a, TypeInfo b) {
    return TypeInfo(static_cast<Type>(a.type_ & b.type_));
96 97
  }

98

99 100 101
  // Integer32 is an integer that can be represented as a signed
  // 32-bit integer. It has to be
  // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
102
  // as it is not an Integer32.
103
  static inline bool IsInt32Double(double value) {
104 105 106
    const DoubleRepresentation minus_zero(-0.0);
    DoubleRepresentation rep(value);
    if (rep.bits == minus_zero.bits) return false;
107 108 109
    if (value >= kMinInt && value <= kMaxInt &&
        value == static_cast<int32_t>(value)) {
      return true;
110 111 112 113
    }
    return false;
  }

114
  static TypeInfo TypeFromValue(Handle<Object> value);
115

116 117 118 119
  bool Equals(const TypeInfo& other) {
    return type_ == other.type_;
  }

120
  inline bool IsUnknown() {
121 122 123 124 125 126 127
    ASSERT(type_ != kUninitialized);
    return type_ == kUnknown;
  }

  inline bool IsPrimitive() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kPrimitive) == kPrimitive);
128 129 130
  }

  inline bool IsNumber() {
131 132
    ASSERT(type_ != kUninitialized);
    return ((type_ & kNumber) == kNumber);
133 134 135
  }

  inline bool IsSmi() {
136 137
    ASSERT(type_ != kUninitialized);
    return ((type_ & kSmi) == kSmi);
138 139 140
  }

  inline bool IsInteger32() {
141 142
    ASSERT(type_ != kUninitialized);
    return ((type_ & kInteger32) == kInteger32);
143 144
  }

145
  inline bool IsDouble() {
146 147
    ASSERT(type_ != kUninitialized);
    return ((type_ & kDouble) == kDouble);
148
  }
149

150
  inline bool IsString() {
151 152 153 154 155 156 157
    ASSERT(type_ != kUninitialized);
    return ((type_ & kString) == kString);
  }

  inline bool IsNonPrimitive() {
    ASSERT(type_ != kUninitialized);
    return ((type_ & kNonPrimitive) == kNonPrimitive);
158 159
  }

160
  inline bool IsUninitialized() {
161
    return type_ == kUninitialized;
162 163
  }

164 165
  const char* ToString() {
    switch (type_) {
166 167 168 169 170 171 172 173 174
      case kUnknown: return "Unknown";
      case kPrimitive: return "Primitive";
      case kNumber: return "Number";
      case kInteger32: return "Integer32";
      case kSmi: return "Smi";
      case kDouble: return "Double";
      case kString: return "String";
      case kNonPrimitive: return "Object";
      case kUninitialized: return "Uninitialized";
175 176 177 178
    }
    UNREACHABLE();
    return "Unreachable code";
  }
179 180 181

 private:
  enum Type {
182 183 184 185 186 187 188 189 190
    kUnknown = 0,          // 0000000
    kPrimitive = 0x10,     // 0010000
    kNumber = 0x11,        // 0010001
    kInteger32 = 0x13,     // 0010011
    kSmi = 0x17,           // 0010111
    kDouble = 0x19,        // 0011001
    kString = 0x30,        // 0110000
    kNonPrimitive = 0x40,  // 1000000
    kUninitialized = 0x7f  // 1111111
191
  };
192
  explicit inline TypeInfo(Type t) : type_(t) { }
193 194

  Type type_;
195 196
};

197

198 199 200 201 202 203
enum StringStubFeedback {
  DEFAULT_STRING_STUB = 0,
  STRING_INDEX_OUT_OF_BOUNDS = 1
};


204 205 206 207
// Forward declarations.
class Assignment;
class BinaryOperation;
class Call;
208
class CaseClause;
209 210
class CompareOperation;
class CompilationInfo;
211
class CountOperation;
212
class Property;
213 214 215
class SmallMapList;
class UnaryOperation;

216

217 218
class TypeFeedbackOracle BASE_EMBEDDED {
 public:
219
  TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
220

221
  bool LoadIsMonomorphicNormal(Property* expr);
222
  bool LoadIsMegamorphicWithTypeInfo(Property* expr);
223
  bool StoreIsMonomorphicNormal(Expression* expr);
224
  bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
225
  bool CallIsMonomorphic(Call* expr);
226

227
  Handle<Map> LoadMonomorphicReceiverType(Property* expr);
228
  Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
229

230 231 232 233 234 235 236 237 238 239
  void LoadReceiverTypes(Property* expr,
                         Handle<String> name,
                         SmallMapList* types);
  void StoreReceiverTypes(Assignment* expr,
                          Handle<String> name,
                          SmallMapList* types);
  void CallReceiverTypes(Call* expr,
                         Handle<String> name,
                         CallKind call_kind,
                         SmallMapList* types);
240
  void CollectKeyedReceiverTypes(unsigned ast_id,
241
                                 SmallMapList* types);
242

243 244 245
  CheckType GetCallCheckType(Call* expr);
  Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);

246
  bool LoadIsBuiltin(Property* expr, Builtins::Name id);
247

248 249 250 251 252
  // TODO(1571) We can't use ToBooleanStub::Types as the return value because
  // of various cylces in our headers. Death to tons of implementations in
  // headers!! :-P
  byte ToBooleanTypes(unsigned ast_id);

253
  // Get type information for arithmetic operations and compares.
254
  TypeInfo UnaryType(UnaryOperation* expr);
255 256
  TypeInfo BinaryType(BinaryOperation* expr);
  TypeInfo CompareType(CompareOperation* expr);
257
  bool IsSymbolCompare(CompareOperation* expr);
258
  TypeInfo SwitchType(CaseClause* clause);
259
  TypeInfo IncrementType(CountOperation* expr);
260

261
 private:
262 263 264 265
  void CollectReceiverTypes(unsigned ast_id,
                            Handle<String> name,
                            Code::Flags flags,
                            SmallMapList* types);
266

267
  void SetInfo(unsigned ast_id, Object* target);
268

269 270 271 272 273 274 275 276
  void BuildDictionary(Handle<Code> code);
  void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
  void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
  void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
                          byte* old_start,
                          byte* new_start);
  void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
  void ProcessTarget(unsigned ast_id, Code* target);
277

278 279
  // Returns an element from the backing store. Returns undefined if
  // there is no information.
280
  Handle<Object> GetInfo(unsigned ast_id);
281

282
  Handle<Context> global_context_;
283
  Handle<NumberDictionary> dictionary_;
284

285 286
  DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
};
287

288 289
} }  // namespace v8::internal

290
#endif  // V8_TYPE_INFO_H_