blob: d461331bec0fc3443eec771def8480da51a65c24 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Ben Murdoch3ef787d2012-04-12 10:51:47 +010032#include "ast.h"
Steve Block6ded16b2010-05-10 14:33:55 +010033#include "globals.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010034#include "zone-inl.h"
Steve Block6ded16b2010-05-10 14:33:55 +010035
36namespace v8 {
37namespace internal {
38
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000039const int kMaxKeyedPolymorphism = 4;
40
Ben Murdochb0fe1622011-05-05 13:52:32 +010041// Unknown
Ben Murdoch257744e2011-11-30 15:57:28 +000042// | \____________
43// | |
44// Primitive Non-primitive
45// | \_______ |
46// | | |
47// Number String |
48// / \ | |
49// Double Integer32 | /
50// | | / /
51// | Smi / /
52// | | / __/
53// Uninitialized.
Steve Block6ded16b2010-05-10 14:33:55 +010054
55class TypeInfo {
56 public:
Ben Murdochb0fe1622011-05-05 13:52:32 +010057 TypeInfo() : type_(kUninitialized) { }
Steve Block6ded16b2010-05-10 14:33:55 +010058
Ben Murdochb0fe1622011-05-05 13:52:32 +010059 static TypeInfo Unknown() { return TypeInfo(kUnknown); }
Steve Block6ded16b2010-05-10 14:33:55 +010060 // We know it's a primitive type.
Ben Murdochb0fe1622011-05-05 13:52:32 +010061 static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
Steve Block6ded16b2010-05-10 14:33:55 +010062 // We know it's a number of some sort.
Ben Murdochb0fe1622011-05-05 13:52:32 +010063 static TypeInfo Number() { return TypeInfo(kNumber); }
64 // We know it's a signed 32 bit integer.
65 static TypeInfo Integer32() { return TypeInfo(kInteger32); }
Steve Block6ded16b2010-05-10 14:33:55 +010066 // We know it's a Smi.
Ben Murdochb0fe1622011-05-05 13:52:32 +010067 static TypeInfo Smi() { return TypeInfo(kSmi); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010068 // We know it's a Symbol.
69 static TypeInfo Symbol() { return TypeInfo(kSymbol); }
Steve Block6ded16b2010-05-10 14:33:55 +010070 // We know it's a heap number.
Ben Murdochb0fe1622011-05-05 13:52:32 +010071 static TypeInfo Double() { return TypeInfo(kDouble); }
Steve Block6ded16b2010-05-10 14:33:55 +010072 // We know it's a string.
Ben Murdochb0fe1622011-05-05 13:52:32 +010073 static TypeInfo String() { return TypeInfo(kString); }
74 // We know it's a non-primitive (object) type.
75 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
Steve Block6ded16b2010-05-10 14:33:55 +010076 // We haven't started collecting info yet.
Ben Murdochb0fe1622011-05-05 13:52:32 +010077 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
Steve Block6ded16b2010-05-10 14:33:55 +010078
Steve Block6ded16b2010-05-10 14:33:55 +010079 int ToInt() {
80 return type_;
81 }
82
83 static TypeInfo FromInt(int bit_representation) {
84 Type t = static_cast<Type>(bit_representation);
Ben Murdochb0fe1622011-05-05 13:52:32 +010085 ASSERT(t == kUnknown ||
86 t == kPrimitive ||
87 t == kNumber ||
88 t == kInteger32 ||
89 t == kSmi ||
90 t == kDouble ||
91 t == kString ||
92 t == kNonPrimitive);
Steve Block6ded16b2010-05-10 14:33:55 +010093 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
Steve Block1e0659c2011-05-24 12:43:12 +0100102 // 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
Ben Murdochb0fe1622011-05-05 13:52:32 +0100105 // as it is not an Integer32.
Steve Block6ded16b2010-05-10 14:33:55 +0100106 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;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100110 if (value >= kMinInt && value <= kMaxInt &&
111 value == static_cast<int32_t>(value)) {
112 return true;
Steve Block6ded16b2010-05-10 14:33:55 +0100113 }
114 return false;
115 }
116
117 static TypeInfo TypeFromValue(Handle<Object> value);
118
Ben Murdochb0fe1622011-05-05 13:52:32 +0100119 bool Equals(const TypeInfo& other) {
120 return type_ == other.type_;
121 }
122
Steve Block6ded16b2010-05-10 14:33:55 +0100123 inline bool IsUnknown() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100124 ASSERT(type_ != kUninitialized);
125 return type_ == kUnknown;
126 }
127
128 inline bool IsPrimitive() {
129 ASSERT(type_ != kUninitialized);
130 return ((type_ & kPrimitive) == kPrimitive);
Steve Block6ded16b2010-05-10 14:33:55 +0100131 }
132
133 inline bool IsNumber() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100134 ASSERT(type_ != kUninitialized);
135 return ((type_ & kNumber) == kNumber);
Steve Block6ded16b2010-05-10 14:33:55 +0100136 }
137
138 inline bool IsSmi() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100139 ASSERT(type_ != kUninitialized);
140 return ((type_ & kSmi) == kSmi);
Steve Block6ded16b2010-05-10 14:33:55 +0100141 }
142
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100143 inline bool IsSymbol() {
144 ASSERT(type_ != kUninitialized);
145 return ((type_ & kSymbol) == kSymbol);
146 }
147
148 inline bool IsNonSymbol() {
149 ASSERT(type_ != kUninitialized);
150 return ((type_ & kSymbol) == kString);
151 }
152
Steve Block6ded16b2010-05-10 14:33:55 +0100153 inline bool IsInteger32() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100154 ASSERT(type_ != kUninitialized);
155 return ((type_ & kInteger32) == kInteger32);
Steve Block6ded16b2010-05-10 14:33:55 +0100156 }
157
158 inline bool IsDouble() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100159 ASSERT(type_ != kUninitialized);
160 return ((type_ & kDouble) == kDouble);
Steve Block6ded16b2010-05-10 14:33:55 +0100161 }
162
163 inline bool IsString() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100164 ASSERT(type_ != kUninitialized);
165 return ((type_ & kString) == kString);
166 }
167
168 inline bool IsNonPrimitive() {
169 ASSERT(type_ != kUninitialized);
170 return ((type_ & kNonPrimitive) == kNonPrimitive);
Steve Block6ded16b2010-05-10 14:33:55 +0100171 }
172
173 inline bool IsUninitialized() {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100174 return type_ == kUninitialized;
Steve Block6ded16b2010-05-10 14:33:55 +0100175 }
176
177 const char* ToString() {
178 switch (type_) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100179 case kUnknown: return "Unknown";
180 case kPrimitive: return "Primitive";
181 case kNumber: return "Number";
182 case kInteger32: return "Integer32";
183 case kSmi: return "Smi";
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100184 case kSymbol: return "Symbol";
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185 case kDouble: return "Double";
186 case kString: return "String";
187 case kNonPrimitive: return "Object";
188 case kUninitialized: return "Uninitialized";
Steve Block6ded16b2010-05-10 14:33:55 +0100189 }
190 UNREACHABLE();
191 return "Unreachable code";
192 }
193
194 private:
Steve Block6ded16b2010-05-10 14:33:55 +0100195 enum Type {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100196 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
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100203 kSymbol = 0x32, // 0110010
Ben Murdochb0fe1622011-05-05 13:52:32 +0100204 kNonPrimitive = 0x40, // 1000000
205 kUninitialized = 0x7f // 1111111
Steve Block6ded16b2010-05-10 14:33:55 +0100206 };
207 explicit inline TypeInfo(Type t) : type_(t) { }
208
209 Type type_;
210};
211
212
Ben Murdochb8e0da22011-05-16 14:20:40 +0100213enum StringStubFeedback {
214 DEFAULT_STRING_STUB = 0,
215 STRING_INDEX_OUT_OF_BOUNDS = 1
216};
217
218
Ben Murdochb0fe1622011-05-05 13:52:32 +0100219// Forward declarations.
220class Assignment;
221class BinaryOperation;
222class Call;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100223class CallNew;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224class CaseClause;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000225class CompareOperation;
226class CompilationInfo;
227class CountOperation;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100228class Expression;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000229class Property;
230class SmallMapList;
231class UnaryOperation;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100232class ForInStatement;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000233
Steve Block6ded16b2010-05-10 14:33:55 +0100234
Ben Murdochb0fe1622011-05-05 13:52:32 +0100235class TypeFeedbackOracle BASE_EMBEDDED {
236 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100237 TypeFeedbackOracle(Handle<Code> code,
238 Handle<Context> global_context,
239 Isolate* isolate);
Steve Block6ded16b2010-05-10 14:33:55 +0100240
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000241 bool LoadIsMonomorphicNormal(Property* expr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100242 bool LoadIsUninitialized(Property* expr);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000243 bool LoadIsMegamorphicWithTypeInfo(Property* expr);
244 bool StoreIsMonomorphicNormal(Expression* expr);
245 bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100246 bool CallIsMonomorphic(Call* expr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100247 bool CallNewIsMonomorphic(CallNew* expr);
248 bool ObjectLiteralStoreIsMonomorphic(ObjectLiteral::Property* prop);
249
250 bool IsForInFastCase(ForInStatement* expr);
Steve Block6ded16b2010-05-10 14:33:55 +0100251
Ben Murdochb0fe1622011-05-05 13:52:32 +0100252 Handle<Map> LoadMonomorphicReceiverType(Property* expr);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100253 Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
Steve Block6ded16b2010-05-10 14:33:55 +0100254
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000255 void LoadReceiverTypes(Property* expr,
256 Handle<String> name,
257 SmallMapList* types);
258 void StoreReceiverTypes(Assignment* expr,
259 Handle<String> name,
260 SmallMapList* types);
261 void CallReceiverTypes(Call* expr,
262 Handle<String> name,
263 CallKind call_kind,
264 SmallMapList* types);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000265 void CollectKeyedReceiverTypes(unsigned ast_id,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000266 SmallMapList* types);
Steve Block44f0eee2011-05-26 01:26:41 +0100267
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100268 static bool CanRetainOtherContext(Map* map, Context* global_context);
269 static bool CanRetainOtherContext(JSFunction* function,
270 Context* global_context);
271
Ben Murdochb8e0da22011-05-16 14:20:40 +0100272 CheckType GetCallCheckType(Call* expr);
273 Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
274
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100275 Handle<JSFunction> GetCallTarget(Call* expr);
276 Handle<JSFunction> GetCallNewTarget(CallNew* expr);
277
278 Handle<Map> GetObjectLiteralStoreMap(ObjectLiteral::Property* prop);
279
Ben Murdochb0fe1622011-05-05 13:52:32 +0100280 bool LoadIsBuiltin(Property* expr, Builtins::Name id);
Steve Block6ded16b2010-05-10 14:33:55 +0100281
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000282 // TODO(1571) We can't use ToBooleanStub::Types as the return value because
283 // of various cylces in our headers. Death to tons of implementations in
284 // headers!! :-P
285 byte ToBooleanTypes(unsigned ast_id);
286
Ben Murdochb0fe1622011-05-05 13:52:32 +0100287 // Get type information for arithmetic operations and compares.
Ben Murdoch257744e2011-11-30 15:57:28 +0000288 TypeInfo UnaryType(UnaryOperation* expr);
Steve Block1e0659c2011-05-24 12:43:12 +0100289 TypeInfo BinaryType(BinaryOperation* expr);
290 TypeInfo CompareType(CompareOperation* expr);
Ben Murdoch257744e2011-11-30 15:57:28 +0000291 bool IsSymbolCompare(CompareOperation* expr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100292 Handle<Map> GetCompareMap(CompareOperation* expr);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100293 TypeInfo SwitchType(CaseClause* clause);
Ben Murdoch257744e2011-11-30 15:57:28 +0000294 TypeInfo IncrementType(CountOperation* expr);
Steve Block6ded16b2010-05-10 14:33:55 +0100295
Ben Murdochb0fe1622011-05-05 13:52:32 +0100296 private:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000297 void CollectReceiverTypes(unsigned ast_id,
298 Handle<String> name,
299 Code::Flags flags,
300 SmallMapList* types);
Steve Block6ded16b2010-05-10 14:33:55 +0100301
Ben Murdoch257744e2011-11-30 15:57:28 +0000302 void SetInfo(unsigned ast_id, Object* target);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100303
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000304 void BuildDictionary(Handle<Code> code);
305 void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
306 void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
307 void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
308 byte* old_start,
309 byte* new_start);
310 void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100311 void ProcessTypeFeedbackCells(Handle<Code> code);
Steve Block6ded16b2010-05-10 14:33:55 +0100312
Steve Block44f0eee2011-05-26 01:26:41 +0100313 // Returns an element from the backing store. Returns undefined if
314 // there is no information.
Ben Murdoch257744e2011-11-30 15:57:28 +0000315 Handle<Object> GetInfo(unsigned ast_id);
Steve Block44f0eee2011-05-26 01:26:41 +0100316
Ben Murdochb8e0da22011-05-16 14:20:40 +0100317 Handle<Context> global_context_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100318 Isolate* isolate_;
Ben Murdochc7cc0282012-03-05 14:35:55 +0000319 Handle<UnseededNumberDictionary> dictionary_;
Steve Block6ded16b2010-05-10 14:33:55 +0100320
Ben Murdochb0fe1622011-05-05 13:52:32 +0100321 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
322};
Steve Block6ded16b2010-05-10 14:33:55 +0100323
324} } // namespace v8::internal
325
326#endif // V8_TYPE_INFO_H_