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
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.
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.
28
#ifndef V8_TYPE_INFO_H_
29
#define V8_TYPE_INFO_H_
31
#include "allocation.h"
39
const int kMaxKeyedPolymorphism = 4;
44
// Primitive Non-primitive
49
// Double Integer32 | /
57
TypeInfo() : type_(kUninitialized) { }
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 Symbol.
69
static TypeInfo Symbol() { return TypeInfo(kSymbol); }
70
// We know it's a heap number.
71
static TypeInfo Double() { return TypeInfo(kDouble); }
72
// We know it's a string.
73
static TypeInfo String() { return TypeInfo(kString); }
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); }
83
static TypeInfo FromInt(int bit_representation) {
84
Type t = static_cast<Type>(bit_representation);
85
ASSERT(t == kUnknown ||
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_));
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)) {
117
static TypeInfo TypeFromValue(Handle<Object> value);
119
bool Equals(const TypeInfo& other) {
120
return type_ == other.type_;
123
inline bool IsUnknown() {
124
ASSERT(type_ != kUninitialized);
125
return type_ == kUnknown;
128
inline bool IsPrimitive() {
129
ASSERT(type_ != kUninitialized);
130
return ((type_ & kPrimitive) == kPrimitive);
133
inline bool IsNumber() {
134
ASSERT(type_ != kUninitialized);
135
return ((type_ & kNumber) == kNumber);
138
inline bool IsSmi() {
139
ASSERT(type_ != kUninitialized);
140
return ((type_ & kSmi) == kSmi);
143
inline bool IsSymbol() {
144
ASSERT(type_ != kUninitialized);
145
return ((type_ & kSymbol) == kSymbol);
148
inline bool IsNonSymbol() {
149
ASSERT(type_ != kUninitialized);
150
return ((type_ & kSymbol) == kString);
153
inline bool IsInteger32() {
154
ASSERT(type_ != kUninitialized);
155
return ((type_ & kInteger32) == kInteger32);
158
inline bool IsDouble() {
159
ASSERT(type_ != kUninitialized);
160
return ((type_ & kDouble) == kDouble);
163
inline bool IsString() {
164
ASSERT(type_ != kUninitialized);
165
return ((type_ & kString) == kString);
168
inline bool IsNonPrimitive() {
169
ASSERT(type_ != kUninitialized);
170
return ((type_ & kNonPrimitive) == kNonPrimitive);
173
inline bool IsUninitialized() {
174
return type_ == kUninitialized;
177
const char* ToString() {
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 kSymbol: return "Symbol";
185
case kDouble: return "Double";
186
case kString: return "String";
187
case kNonPrimitive: return "Object";
188
case kUninitialized: return "Uninitialized";
191
return "Unreachable code";
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
kSymbol = 0x32, // 0110010
204
kNonPrimitive = 0x40, // 1000000
205
kUninitialized = 0x7f // 1111111
207
explicit inline TypeInfo(Type t) : type_(t) { }
213
enum StringStubFeedback {
214
DEFAULT_STRING_STUB = 0,
215
STRING_INDEX_OUT_OF_BOUNDS = 1
219
// Forward declarations.
221
class BinaryOperation;
225
class CompareOperation;
226
class CompilationInfo;
227
class CountOperation;
231
class UnaryOperation;
232
class ForInStatement;
235
class TypeFeedbackOracle: public ZoneObject {
237
TypeFeedbackOracle(Handle<Code> code,
238
Handle<Context> global_context,
242
bool LoadIsMonomorphicNormal(Property* expr);
243
bool LoadIsUninitialized(Property* expr);
244
bool LoadIsMegamorphicWithTypeInfo(Property* expr);
245
bool StoreIsMonomorphicNormal(Expression* expr);
246
bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
247
bool CallIsMonomorphic(Call* expr);
248
bool CallNewIsMonomorphic(CallNew* expr);
249
bool ObjectLiteralStoreIsMonomorphic(ObjectLiteral::Property* prop);
251
bool IsForInFastCase(ForInStatement* expr);
253
Handle<Map> LoadMonomorphicReceiverType(Property* expr);
254
Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
256
void LoadReceiverTypes(Property* expr,
258
SmallMapList* types);
259
void StoreReceiverTypes(Assignment* expr,
261
SmallMapList* types);
262
void CallReceiverTypes(Call* expr,
265
SmallMapList* types);
266
void CollectKeyedReceiverTypes(unsigned ast_id,
267
SmallMapList* types);
269
static bool CanRetainOtherContext(Map* map, Context* global_context);
270
static bool CanRetainOtherContext(JSFunction* function,
271
Context* global_context);
273
CheckType GetCallCheckType(Call* expr);
274
Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
276
Handle<JSFunction> GetCallTarget(Call* expr);
277
Handle<JSFunction> GetCallNewTarget(CallNew* expr);
279
Handle<Map> GetObjectLiteralStoreMap(ObjectLiteral::Property* prop);
281
bool LoadIsBuiltin(Property* expr, Builtins::Name id);
283
// TODO(1571) We can't use ToBooleanStub::Types as the return value because
284
// of various cylces in our headers. Death to tons of implementations in
286
byte ToBooleanTypes(unsigned ast_id);
288
// Get type information for arithmetic operations and compares.
289
TypeInfo UnaryType(UnaryOperation* expr);
290
TypeInfo BinaryType(BinaryOperation* expr);
291
TypeInfo CompareType(CompareOperation* expr);
292
bool IsSymbolCompare(CompareOperation* expr);
293
Handle<Map> GetCompareMap(CompareOperation* expr);
294
TypeInfo SwitchType(CaseClause* clause);
295
TypeInfo IncrementType(CountOperation* expr);
297
Zone* zone() const { return zone_; }
300
void CollectReceiverTypes(unsigned ast_id,
303
SmallMapList* types);
305
void SetInfo(unsigned ast_id, Object* target);
307
void BuildDictionary(Handle<Code> code);
308
void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
309
void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
310
void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
313
void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
314
void ProcessTypeFeedbackCells(Handle<Code> code);
316
// Returns an element from the backing store. Returns undefined if
317
// there is no information.
318
Handle<Object> GetInfo(unsigned ast_id);
320
Handle<Context> global_context_;
322
Handle<UnseededNumberDictionary> dictionary_;
325
DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
328
} } // namespace v8::internal
330
#endif // V8_TYPE_INFO_H_