blob: 74910cd1a7c817565c953775607269e1197a9a57 [file] [log] [blame]
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001// Copyright 2012 the V8 project authors. All rights reserved.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00002// 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
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +000032#include "ast.h"
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000033#include "globals.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "zone-inl.h"
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000035
36namespace v8 {
37namespace internal {
38
whesse@chromium.org7b260152011-06-20 15:33:18 +000039const int kMaxKeyedPolymorphism = 4;
40
kasperl@chromium.orga5551262010-12-07 12:49:48 +000041// Unknown
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000042// | \____________
43// | |
44// Primitive Non-primitive
45// | \_______ |
46// | | |
47// Number String |
48// / \ | |
49// Double Integer32 | /
50// | | / /
51// | Smi / /
52// | | / __/
53// Uninitialized.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000054
55class TypeInfo {
56 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +000057 TypeInfo() : type_(kUninitialized) { }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000058
kasperl@chromium.orga5551262010-12-07 12:49:48 +000059 static TypeInfo Unknown() { return TypeInfo(kUnknown); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000060 // We know it's a primitive type.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000061 static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000062 // We know it's a number of some sort.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000063 static TypeInfo Number() { return TypeInfo(kNumber); }
64 // We know it's a signed 32 bit integer.
65 static TypeInfo Integer32() { return TypeInfo(kInteger32); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000066 // We know it's a Smi.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000067 static TypeInfo Smi() { return TypeInfo(kSmi); }
erikcorry0ad885c2011-11-21 13:51:57 +000068 // We know it's a Symbol.
69 static TypeInfo Symbol() { return TypeInfo(kSymbol); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000070 // We know it's a heap number.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000071 static TypeInfo Double() { return TypeInfo(kDouble); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000072 // We know it's a string.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000073 static TypeInfo String() { return TypeInfo(kString); }
74 // We know it's a non-primitive (object) type.
75 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000076 // We haven't started collecting info yet.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000077 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000078
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000079 int ToInt() {
80 return type_;
81 }
82
83 static TypeInfo FromInt(int bit_representation) {
84 Type t = static_cast<Type>(bit_representation);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000085 ASSERT(t == kUnknown ||
86 t == kPrimitive ||
87 t == kNumber ||
88 t == kInteger32 ||
89 t == kSmi ||
90 t == kDouble ||
91 t == kString ||
92 t == kNonPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000093 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
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000102 // 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000105 // as it is not an Integer32.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000106 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;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000110 if (value >= kMinInt && value <= kMaxInt &&
111 value == static_cast<int32_t>(value)) {
112 return true;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000113 }
114 return false;
115 }
116
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000117 static TypeInfo TypeFromValue(Handle<Object> value);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000118
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000119 bool Equals(const TypeInfo& other) {
120 return type_ == other.type_;
121 }
122
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000123 inline bool IsUnknown() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124 ASSERT(type_ != kUninitialized);
125 return type_ == kUnknown;
126 }
127
128 inline bool IsPrimitive() {
129 ASSERT(type_ != kUninitialized);
130 return ((type_ & kPrimitive) == kPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000131 }
132
133 inline bool IsNumber() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000134 ASSERT(type_ != kUninitialized);
135 return ((type_ & kNumber) == kNumber);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000136 }
137
138 inline bool IsSmi() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000139 ASSERT(type_ != kUninitialized);
140 return ((type_ & kSmi) == kSmi);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000141 }
142
erikcorry0ad885c2011-11-21 13:51:57 +0000143 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
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000153 inline bool IsInteger32() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000154 ASSERT(type_ != kUninitialized);
155 return ((type_ & kInteger32) == kInteger32);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000156 }
157
158 inline bool IsDouble() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000159 ASSERT(type_ != kUninitialized);
160 return ((type_ & kDouble) == kDouble);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000161 }
162
lrn@chromium.org25156de2010-04-06 13:10:27 +0000163 inline bool IsString() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000164 ASSERT(type_ != kUninitialized);
165 return ((type_ & kString) == kString);
166 }
167
168 inline bool IsNonPrimitive() {
169 ASSERT(type_ != kUninitialized);
170 return ((type_ & kNonPrimitive) == kNonPrimitive);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000171 }
172
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000173 inline bool IsUninitialized() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000174 return type_ == kUninitialized;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000175 }
176
177 const char* ToString() {
178 switch (type_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000179 case kUnknown: return "Unknown";
180 case kPrimitive: return "Primitive";
181 case kNumber: return "Number";
182 case kInteger32: return "Integer32";
183 case kSmi: return "Smi";
erikcorry0ad885c2011-11-21 13:51:57 +0000184 case kSymbol: return "Symbol";
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000185 case kDouble: return "Double";
186 case kString: return "String";
187 case kNonPrimitive: return "Object";
188 case kUninitialized: return "Uninitialized";
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000189 }
190 UNREACHABLE();
191 return "Unreachable code";
192 }
193
194 private:
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000195 enum Type {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000196 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
erikcorry0ad885c2011-11-21 13:51:57 +0000203 kSymbol = 0x32, // 0110010
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000204 kNonPrimitive = 0x40, // 1000000
205 kUninitialized = 0x7f // 1111111
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000206 };
207 explicit inline TypeInfo(Type t) : type_(t) { }
208
209 Type type_;
210};
211
212
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000213enum StringStubFeedback {
214 DEFAULT_STRING_STUB = 0,
215 STRING_INDEX_OUT_OF_BOUNDS = 1
216};
217
218
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000219// Forward declarations.
220class Assignment;
221class BinaryOperation;
222class Call;
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000223class CallNew;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000224class CaseClause;
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000225class CompareOperation;
226class CompilationInfo;
227class CountOperation;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000228class Expression;
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000229class Property;
230class SmallMapList;
231class UnaryOperation;
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000232class ForInStatement;
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000233
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000234
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000235class TypeFeedbackOracle BASE_EMBEDDED {
236 public:
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000237 TypeFeedbackOracle(Handle<Code> code,
238 Handle<Context> global_context,
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000239 Isolate* isolate,
240 Zone* zone);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000241
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000242 bool LoadIsMonomorphicNormal(Property* expr);
jkummerow@chromium.org531dfe82012-03-20 13:01:16 +0000243 bool LoadIsUninitialized(Property* expr);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000244 bool LoadIsMegamorphicWithTypeInfo(Property* expr);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000245 bool StoreIsMonomorphicNormal(Expression* expr);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000246 bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000247 bool CallIsMonomorphic(Call* expr);
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000248 bool CallNewIsMonomorphic(CallNew* expr);
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000249 bool ObjectLiteralStoreIsMonomorphic(ObjectLiteral::Property* prop);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000250
ulan@chromium.org9a21ec42012-03-06 08:42:24 +0000251 bool IsForInFastCase(ForInStatement* expr);
252
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000253 Handle<Map> LoadMonomorphicReceiverType(Property* expr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000254 Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000255
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000256 void LoadReceiverTypes(Property* expr,
257 Handle<String> name,
258 SmallMapList* types);
259 void StoreReceiverTypes(Assignment* expr,
260 Handle<String> name,
261 SmallMapList* types);
262 void CallReceiverTypes(Call* expr,
263 Handle<String> name,
264 CallKind call_kind,
265 SmallMapList* types);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000266 void CollectKeyedReceiverTypes(unsigned ast_id,
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000267 SmallMapList* types);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000268
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000269 static bool CanRetainOtherContext(Map* map, Context* global_context);
270 static bool CanRetainOtherContext(JSFunction* function,
271 Context* global_context);
272
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000273 CheckType GetCallCheckType(Call* expr);
274 Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
275
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000276 Handle<JSFunction> GetCallTarget(Call* expr);
ulan@chromium.org967e2702012-02-28 09:49:15 +0000277 Handle<JSFunction> GetCallNewTarget(CallNew* expr);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000278
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000279 Handle<Map> GetObjectLiteralStoreMap(ObjectLiteral::Property* prop);
280
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000281 bool LoadIsBuiltin(Property* expr, Builtins::Name id);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000282
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000283 // 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
285 // headers!! :-P
286 byte ToBooleanTypes(unsigned ast_id);
287
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000288 // Get type information for arithmetic operations and compares.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000289 TypeInfo UnaryType(UnaryOperation* expr);
ager@chromium.org378b34e2011-01-28 08:04:38 +0000290 TypeInfo BinaryType(BinaryOperation* expr);
291 TypeInfo CompareType(CompareOperation* expr);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000292 bool IsSymbolCompare(CompareOperation* expr);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000293 Handle<Map> GetCompareMap(CompareOperation* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000294 TypeInfo SwitchType(CaseClause* clause);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000295 TypeInfo IncrementType(CountOperation* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000296
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000297 Zone* zone() const { return zone_; }
298
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000299 private:
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000300 void CollectReceiverTypes(unsigned ast_id,
301 Handle<String> name,
302 Code::Flags flags,
303 SmallMapList* types);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000304
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000305 void SetInfo(unsigned ast_id, Object* target);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000306
whesse@chromium.org7b260152011-06-20 15:33:18 +0000307 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,
311 byte* old_start,
312 byte* new_start);
313 void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000314 void ProcessTypeFeedbackCells(Handle<Code> code);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000315
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000316 // Returns an element from the backing store. Returns undefined if
317 // there is no information.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000318 Handle<Object> GetInfo(unsigned ast_id);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000319
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000320 Handle<Context> global_context_;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000321 Isolate* isolate_;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000322 Handle<UnseededNumberDictionary> dictionary_;
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000323 Zone* zone_;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000324
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
326};
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000327
328} } // namespace v8::internal
329
330#endif // V8_TYPE_INFO_H_