The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / type-info.h @ f230a1cf

History | View | Annotate | Download (11.5 KB)

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 LoadIsPreMonomorphic(Property* expr);
247
  bool LoadIsPolymorphic(Property* expr);
248
  bool StoreIsUninitialized(TypeFeedbackId ast_id);
249
  bool StoreIsMonomorphicNormal(TypeFeedbackId ast_id);
250
  bool StoreIsPreMonomorphic(TypeFeedbackId ast_id);
251
  bool StoreIsKeyedPolymorphic(TypeFeedbackId ast_id);
252
  bool CallIsMonomorphic(Call* expr);
253
  bool CallNewIsMonomorphic(CallNew* expr);
254
  bool ObjectLiteralStoreIsMonomorphic(ObjectLiteralProperty* prop);
255

    
256
  // TODO(1571) We can't use ForInStatement::ForInType as the return value due
257
  // to various cycles in our headers.
258
  byte ForInType(ForInStatement* expr);
259

    
260
  Handle<Map> LoadMonomorphicReceiverType(Property* expr);
261
  Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId id);
262

    
263
  KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
264

    
265
  void LoadReceiverTypes(Property* expr,
266
                         Handle<String> name,
267
                         SmallMapList* types);
268
  void StoreReceiverTypes(Assignment* expr,
269
                          Handle<String> name,
270
                          SmallMapList* types);
271
  void CallReceiverTypes(Call* expr,
272
                         Handle<String> name,
273
                         CallKind call_kind,
274
                         SmallMapList* types);
275
  void CollectKeyedReceiverTypes(TypeFeedbackId ast_id,
276
                                 SmallMapList* types);
277
  void CollectPolymorphicStoreReceiverTypes(TypeFeedbackId ast_id,
278
                                            SmallMapList* types);
279

    
280
  static bool CanRetainOtherContext(Map* map, Context* native_context);
281
  static bool CanRetainOtherContext(JSFunction* function,
282
                                    Context* native_context);
283

    
284
  void CollectPolymorphicMaps(Handle<Code> code, SmallMapList* types);
285

    
286
  CheckType GetCallCheckType(Call* expr);
287
  Handle<JSFunction> GetCallTarget(Call* expr);
288
  Handle<JSFunction> GetCallNewTarget(CallNew* expr);
289
  Handle<Cell> GetCallNewAllocationInfoCell(CallNew* expr);
290

    
291
  Handle<Map> GetObjectLiteralStoreMap(ObjectLiteralProperty* prop);
292

    
293
  bool LoadIsBuiltin(Property* expr, Builtins::Name id);
294
  bool LoadIsStub(Property* expr, ICStub* stub);
295

    
296
  // TODO(1571) We can't use ToBooleanStub::Types as the return value because
297
  // of various cycles in our headers. Death to tons of implementations in
298
  // headers!! :-P
299
  byte ToBooleanTypes(TypeFeedbackId id);
300

    
301
  // Get type information for arithmetic operations and compares.
302
  void BinaryType(TypeFeedbackId id,
303
                  Handle<Type>* left,
304
                  Handle<Type>* right,
305
                  Handle<Type>* result,
306
                  Maybe<int>* fixed_right_arg,
307
                  Token::Value operation);
308

    
309
  void CompareType(TypeFeedbackId id,
310
                   Handle<Type>* left,
311
                   Handle<Type>* right,
312
                   Handle<Type>* combined);
313

    
314
  Handle<Type> ClauseType(TypeFeedbackId id);
315

    
316
  Handle<Type> IncrementType(CountOperation* expr);
317

    
318
  Zone* zone() const { return zone_; }
319
  Isolate* isolate() const { return isolate_; }
320

    
321
 private:
322
  void CollectReceiverTypes(TypeFeedbackId ast_id,
323
                            Handle<String> name,
324
                            Code::Flags flags,
325
                            SmallMapList* types);
326

    
327
  void SetInfo(TypeFeedbackId ast_id, Object* target);
328

    
329
  void BuildDictionary(Handle<Code> code);
330
  void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
331
  void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
332
  void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
333
                          byte* old_start,
334
                          byte* new_start);
335
  void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
336
  void ProcessTypeFeedbackCells(Handle<Code> code);
337

    
338
  // Returns an element from the backing store. Returns undefined if
339
  // there is no information.
340
  Handle<Object> GetInfo(TypeFeedbackId ast_id);
341

    
342
  // Return the cell that contains type feedback.
343
  Handle<Cell> GetInfoCell(TypeFeedbackId ast_id);
344

    
345
 private:
346
  Handle<Context> native_context_;
347
  Isolate* isolate_;
348
  Zone* zone_;
349
  Handle<UnseededNumberDictionary> dictionary_;
350

    
351
  DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
352
};
353

    
354
} }  // namespace v8::internal
355

    
356
#endif  // V8_TYPE_INFO_H_