blob: f6e67291179d0cefc560e1535dcf3590440c28fe [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Block6ded16b2010-05-10 14:33:55 +01002// 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"
Ben Murdochb0fe1622011-05-05 13:52:32 +010032#include "zone.h"
33#include "zone-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +010034
35namespace v8 {
36namespace internal {
37
Ben Murdochb0fe1622011-05-05 13:52:32 +010038// Unknown
39// | |
40// | \--------------|
41// Primitive Non-primitive
42// | \--------| |
43// Number String |
44// / | | |
45// Double Integer32 | /
46// | | / /
47// | Smi / /
48// | | / /
49// | | / /
50// Uninitialized.--/
Steve Block6ded16b2010-05-10 14:33:55 +010051
52class TypeInfo {
53 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +010054 TypeInfo() : type_(kUninitialized) { }
Steve Block6ded16b2010-05-10 14:33:55 +010055
Ben Murdochb0fe1622011-05-05 13:52:32 +010056 static TypeInfo Unknown() { return TypeInfo(kUnknown); }
Steve Block6ded16b2010-05-10 14:33:55 +010057 // We know it's a primitive type.
Ben Murdochb0fe1622011-05-05 13:52:32 +010058 static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
Steve Block6ded16b2010-05-10 14:33:55 +010059 // We know it's a number of some sort.
Ben Murdochb0fe1622011-05-05 13:52:32 +010060 static TypeInfo Number() { return TypeInfo(kNumber); }
61 // We know it's a signed 32 bit integer.
62 static TypeInfo Integer32() { return TypeInfo(kInteger32); }
Steve Block6ded16b2010-05-10 14:33:55 +010063 // We know it's a Smi.
Ben Murdochb0fe1622011-05-05 13:52:32 +010064 static TypeInfo Smi() { return TypeInfo(kSmi); }
Steve Block6ded16b2010-05-10 14:33:55 +010065 // We know it's a heap number.
Ben Murdochb0fe1622011-05-05 13:52:32 +010066 static TypeInfo Double() { return TypeInfo(kDouble); }
Steve Block6ded16b2010-05-10 14:33:55 +010067 // We know it's a string.
Ben Murdochb0fe1622011-05-05 13:52:32 +010068 static TypeInfo String() { return TypeInfo(kString); }
69 // We know it's a non-primitive (object) type.
70 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
Steve Block6ded16b2010-05-10 14:33:55 +010071 // We haven't started collecting info yet.
Ben Murdochb0fe1622011-05-05 13:52:32 +010072 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
Steve Block6ded16b2010-05-10 14:33:55 +010073
74 // Return compact representation. Very sensitive to enum values below!
Ben Murdochb0fe1622011-05-05 13:52:32 +010075 // Compacting drops information about primitive types and strings types.
Steve Block6ded16b2010-05-10 14:33:55 +010076 // We use the compact representation when we only care about number types.
77 int ThreeBitRepresentation() {
Ben Murdochb0fe1622011-05-05 13:52:32 +010078 ASSERT(type_ != kUninitialized);
Steve Block6ded16b2010-05-10 14:33:55 +010079 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) {
Steve Block8defd9f2010-07-08 12:39:36 +010088 Type t = static_cast<Type>(three_bit_representation > 4 ?
Steve Block6ded16b2010-05-10 14:33:55 +010089 three_bit_representation + 2 :
90 three_bit_representation);
Ben Murdochb0fe1622011-05-05 13:52:32 +010091 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);
Steve Block6ded16b2010-05-10 14:33:55 +010097 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);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100106 ASSERT(t == kUnknown ||
107 t == kPrimitive ||
108 t == kNumber ||
109 t == kInteger32 ||
110 t == kSmi ||
111 t == kDouble ||
112 t == kString ||
113 t == kNonPrimitive);
Steve Block6ded16b2010-05-10 14:33:55 +0100114 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
Steve Block1e0659c2011-05-24 12:43:12 +0100123 // 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
Ben Murdochb0fe1622011-05-05 13:52:32 +0100126 // as it is not an Integer32.
Steve Block6ded16b2010-05-10 14:33:55 +0100127 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;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100131 if (value >= kMinInt && value <= kMaxInt &&
132 value == static_cast<int32_t>(value)) {
133 return true;
Steve Block6ded16b2010-05-10 14:33:55 +0100134 }
135 return false;
136 }
137
138 static TypeInfo TypeFromValue(Handle<Object> value);
139
Ben Murdochb0fe1622011-05-05 13:52:32 +0100140 bool Equals(const TypeInfo& other) {
141 return type_ == other.type_;
142 }
143
Steve Block6ded16b2010-05-10 14:33:55 +0100144 inline bool IsUnknown() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100145 ASSERT(type_ != kUninitialized);
146 return type_ == kUnknown;
147 }
148
149 inline bool IsPrimitive() {
150 ASSERT(type_ != kUninitialized);
151 return ((type_ & kPrimitive) == kPrimitive);
Steve Block6ded16b2010-05-10 14:33:55 +0100152 }
153
154 inline bool IsNumber() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100155 ASSERT(type_ != kUninitialized);
156 return ((type_ & kNumber) == kNumber);
Steve Block6ded16b2010-05-10 14:33:55 +0100157 }
158
159 inline bool IsSmi() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100160 ASSERT(type_ != kUninitialized);
161 return ((type_ & kSmi) == kSmi);
Steve Block6ded16b2010-05-10 14:33:55 +0100162 }
163
164 inline bool IsInteger32() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100165 ASSERT(type_ != kUninitialized);
166 return ((type_ & kInteger32) == kInteger32);
Steve Block6ded16b2010-05-10 14:33:55 +0100167 }
168
169 inline bool IsDouble() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100170 ASSERT(type_ != kUninitialized);
171 return ((type_ & kDouble) == kDouble);
Steve Block6ded16b2010-05-10 14:33:55 +0100172 }
173
174 inline bool IsString() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100175 ASSERT(type_ != kUninitialized);
176 return ((type_ & kString) == kString);
177 }
178
179 inline bool IsNonPrimitive() {
180 ASSERT(type_ != kUninitialized);
181 return ((type_ & kNonPrimitive) == kNonPrimitive);
Steve Block6ded16b2010-05-10 14:33:55 +0100182 }
183
184 inline bool IsUninitialized() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185 return type_ == kUninitialized;
Steve Block6ded16b2010-05-10 14:33:55 +0100186 }
187
188 const char* ToString() {
189 switch (type_) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100190 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";
Steve Block6ded16b2010-05-10 14:33:55 +0100199 }
200 UNREACHABLE();
201 return "Unreachable code";
202 }
203
204 private:
Steve Block6ded16b2010-05-10 14:33:55 +0100205 enum Type {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100206 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
Steve Block6ded16b2010-05-10 14:33:55 +0100215 };
216 explicit inline TypeInfo(Type t) : type_(t) { }
217
218 Type type_;
219};
220
221
Ben Murdochb8e0da22011-05-16 14:20:40 +0100222enum StringStubFeedback {
223 DEFAULT_STRING_STUB = 0,
224 STRING_INDEX_OUT_OF_BOUNDS = 1
225};
226
227
Ben Murdochb0fe1622011-05-05 13:52:32 +0100228// Forward declarations.
229class Assignment;
230class BinaryOperation;
231class Call;
232class CompareOperation;
233class CompilationInfo;
234class Property;
235class CaseClause;
Steve Block6ded16b2010-05-10 14:33:55 +0100236
Ben Murdochb0fe1622011-05-05 13:52:32 +0100237class TypeFeedbackOracle BASE_EMBEDDED {
238 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100239 TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
Steve Block6ded16b2010-05-10 14:33:55 +0100240
Ben Murdochb0fe1622011-05-05 13:52:32 +0100241 bool LoadIsMonomorphic(Property* expr);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 bool StoreIsMonomorphic(Expression* expr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100243 bool CallIsMonomorphic(Call* expr);
Steve Block6ded16b2010-05-10 14:33:55 +0100244
Ben Murdochb0fe1622011-05-05 13:52:32 +0100245 Handle<Map> LoadMonomorphicReceiverType(Property* expr);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100246 Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
Steve Block6ded16b2010-05-10 14:33:55 +0100247
Ben Murdochb0fe1622011-05-05 13:52:32 +0100248 ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
249 ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
250 ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
Steve Block6ded16b2010-05-10 14:33:55 +0100251
Steve Block44f0eee2011-05-26 01:26:41 +0100252 ExternalArrayType GetKeyedLoadExternalArrayType(Property* expr);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100253 ExternalArrayType GetKeyedStoreExternalArrayType(Expression* expr);
Steve Block44f0eee2011-05-26 01:26:41 +0100254
Ben Murdochb8e0da22011-05-16 14:20:40 +0100255 CheckType GetCallCheckType(Call* expr);
256 Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
257
Ben Murdochb0fe1622011-05-05 13:52:32 +0100258 bool LoadIsBuiltin(Property* expr, Builtins::Name id);
Steve Block6ded16b2010-05-10 14:33:55 +0100259
Ben Murdochb0fe1622011-05-05 13:52:32 +0100260 // Get type information for arithmetic operations and compares.
Steve Block1e0659c2011-05-24 12:43:12 +0100261 TypeInfo BinaryType(BinaryOperation* expr);
262 TypeInfo CompareType(CompareOperation* expr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100263 TypeInfo SwitchType(CaseClause* clause);
Steve Block6ded16b2010-05-10 14:33:55 +0100264
Ben Murdochb0fe1622011-05-05 13:52:32 +0100265 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100266 ZoneMapList* CollectReceiverTypes(int position,
267 Handle<String> name,
268 Code::Flags flags);
Steve Block6ded16b2010-05-10 14:33:55 +0100269
Ben Murdoch8b112d22011-06-08 16:22:53 +0100270 void SetInfo(int position, Object* target);
271
Ben Murdochb0fe1622011-05-05 13:52:32 +0100272 void PopulateMap(Handle<Code> code);
Steve Block6ded16b2010-05-10 14:33:55 +0100273
Ben Murdochb0fe1622011-05-05 13:52:32 +0100274 void CollectPositions(Code* code,
275 List<int>* code_positions,
276 List<int>* source_positions);
Steve Block6ded16b2010-05-10 14:33:55 +0100277
Steve Block44f0eee2011-05-26 01:26:41 +0100278 // Returns an element from the backing store. Returns undefined if
279 // there is no information.
280 Handle<Object> GetInfo(int pos);
281
Ben Murdochb8e0da22011-05-16 14:20:40 +0100282 Handle<Context> global_context_;
Steve Block44f0eee2011-05-26 01:26:41 +0100283 Handle<NumberDictionary> dictionary_;
Steve Block6ded16b2010-05-10 14:33:55 +0100284
Ben Murdochb0fe1622011-05-05 13:52:32 +0100285 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
286};
Steve Block6ded16b2010-05-10 14:33:55 +0100287
288} } // namespace v8::internal
289
290#endif // V8_TYPE_INFO_H_