blob: dee4c34c929453e16d2f081927967ba171acf0fe [file] [log] [blame]
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00001// Copyright 2011 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"
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000032#include "globals.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000033#include "zone-inl.h"
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000034
35namespace v8 {
36namespace internal {
37
whesse@chromium.org7b260152011-06-20 15:33:18 +000038const int kMaxKeyedPolymorphism = 4;
39
kasperl@chromium.orga5551262010-12-07 12:49:48 +000040// Unknown
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000041// | \____________
42// | |
43// Primitive Non-primitive
44// | \_______ |
45// | | |
46// Number String |
47// / \ | |
48// Double Integer32 | /
49// | | / /
50// | Smi / /
51// | | / __/
52// Uninitialized.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000053
54class TypeInfo {
55 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +000056 TypeInfo() : type_(kUninitialized) { }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000057
kasperl@chromium.orga5551262010-12-07 12:49:48 +000058 static TypeInfo Unknown() { return TypeInfo(kUnknown); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000059 // We know it's a primitive type.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000060 static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000061 // We know it's a number of some sort.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000062 static TypeInfo Number() { return TypeInfo(kNumber); }
63 // We know it's a signed 32 bit integer.
64 static TypeInfo Integer32() { return TypeInfo(kInteger32); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000065 // We know it's a Smi.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066 static TypeInfo Smi() { return TypeInfo(kSmi); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000067 // We know it's a heap number.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000068 static TypeInfo Double() { return TypeInfo(kDouble); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000069 // We know it's a string.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000070 static TypeInfo String() { return TypeInfo(kString); }
71 // We know it's a non-primitive (object) type.
72 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000073 // We haven't started collecting info yet.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000074 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000075
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000076 int ToInt() {
77 return type_;
78 }
79
80 static TypeInfo FromInt(int bit_representation) {
81 Type t = static_cast<Type>(bit_representation);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000082 ASSERT(t == kUnknown ||
83 t == kPrimitive ||
84 t == kNumber ||
85 t == kInteger32 ||
86 t == kSmi ||
87 t == kDouble ||
88 t == kString ||
89 t == kNonPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000090 return TypeInfo(t);
91 }
92
93 // Return the weakest (least precise) common type.
94 static TypeInfo Combine(TypeInfo a, TypeInfo b) {
95 return TypeInfo(static_cast<Type>(a.type_ & b.type_));
96 }
97
98
ricow@chromium.org83aa5492011-02-07 12:42:56 +000099 // Integer32 is an integer that can be represented as a signed
100 // 32-bit integer. It has to be
101 // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 // as it is not an Integer32.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000103 static inline bool IsInt32Double(double value) {
104 const DoubleRepresentation minus_zero(-0.0);
105 DoubleRepresentation rep(value);
106 if (rep.bits == minus_zero.bits) return false;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000107 if (value >= kMinInt && value <= kMaxInt &&
108 value == static_cast<int32_t>(value)) {
109 return true;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000110 }
111 return false;
112 }
113
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000114 static TypeInfo TypeFromValue(Handle<Object> value);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000115
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116 bool Equals(const TypeInfo& other) {
117 return type_ == other.type_;
118 }
119
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000120 inline bool IsUnknown() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 ASSERT(type_ != kUninitialized);
122 return type_ == kUnknown;
123 }
124
125 inline bool IsPrimitive() {
126 ASSERT(type_ != kUninitialized);
127 return ((type_ & kPrimitive) == kPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000128 }
129
130 inline bool IsNumber() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000131 ASSERT(type_ != kUninitialized);
132 return ((type_ & kNumber) == kNumber);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000133 }
134
135 inline bool IsSmi() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000136 ASSERT(type_ != kUninitialized);
137 return ((type_ & kSmi) == kSmi);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000138 }
139
140 inline bool IsInteger32() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000141 ASSERT(type_ != kUninitialized);
142 return ((type_ & kInteger32) == kInteger32);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000143 }
144
145 inline bool IsDouble() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000146 ASSERT(type_ != kUninitialized);
147 return ((type_ & kDouble) == kDouble);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000148 }
149
lrn@chromium.org25156de2010-04-06 13:10:27 +0000150 inline bool IsString() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000151 ASSERT(type_ != kUninitialized);
152 return ((type_ & kString) == kString);
153 }
154
155 inline bool IsNonPrimitive() {
156 ASSERT(type_ != kUninitialized);
157 return ((type_ & kNonPrimitive) == kNonPrimitive);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000158 }
159
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000160 inline bool IsUninitialized() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000161 return type_ == kUninitialized;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000162 }
163
164 const char* ToString() {
165 switch (type_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000166 case kUnknown: return "Unknown";
167 case kPrimitive: return "Primitive";
168 case kNumber: return "Number";
169 case kInteger32: return "Integer32";
170 case kSmi: return "Smi";
171 case kDouble: return "Double";
172 case kString: return "String";
173 case kNonPrimitive: return "Object";
174 case kUninitialized: return "Uninitialized";
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000175 }
176 UNREACHABLE();
177 return "Unreachable code";
178 }
179
180 private:
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000181 enum Type {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000182 kUnknown = 0, // 0000000
183 kPrimitive = 0x10, // 0010000
184 kNumber = 0x11, // 0010001
185 kInteger32 = 0x13, // 0010011
186 kSmi = 0x17, // 0010111
187 kDouble = 0x19, // 0011001
188 kString = 0x30, // 0110000
189 kNonPrimitive = 0x40, // 1000000
190 kUninitialized = 0x7f // 1111111
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000191 };
192 explicit inline TypeInfo(Type t) : type_(t) { }
193
194 Type type_;
195};
196
197
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000198enum StringStubFeedback {
199 DEFAULT_STRING_STUB = 0,
200 STRING_INDEX_OUT_OF_BOUNDS = 1
201};
202
203
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000204// Forward declarations.
205class Assignment;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000206class UnaryOperation;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000207class BinaryOperation;
208class Call;
209class CompareOperation;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000210class CountOperation;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000211class CompilationInfo;
212class Property;
213class CaseClause;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000214
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000215class TypeFeedbackOracle BASE_EMBEDDED {
216 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000217 TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000218
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000219 bool LoadIsMonomorphicNormal(Property* expr);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000220 bool LoadIsMegamorphicWithTypeInfo(Property* expr);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000221 bool StoreIsMonomorphicNormal(Expression* expr);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000222 bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000223 bool CallIsMonomorphic(Call* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000224
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000225 Handle<Map> LoadMonomorphicReceiverType(Property* expr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000226 Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000227
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000228 ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
229 ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000230 ZoneMapList* CallReceiverTypes(Call* expr,
231 Handle<String> name,
232 CallKind call_kind);
whesse@chromium.org7b260152011-06-20 15:33:18 +0000233 void CollectKeyedReceiverTypes(unsigned ast_id,
234 ZoneMapList* types);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000235
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000236 CheckType GetCallCheckType(Call* expr);
237 Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
238
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000239 bool LoadIsBuiltin(Property* expr, Builtins::Name id);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000240
ricow@chromium.org2c99e282011-07-28 09:15:17 +0000241 // TODO(1571) We can't use ToBooleanStub::Types as the return value because
242 // of various cylces in our headers. Death to tons of implementations in
243 // headers!! :-P
244 byte ToBooleanTypes(unsigned ast_id);
245
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246 // Get type information for arithmetic operations and compares.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000247 TypeInfo UnaryType(UnaryOperation* expr);
ager@chromium.org378b34e2011-01-28 08:04:38 +0000248 TypeInfo BinaryType(BinaryOperation* expr);
249 TypeInfo CompareType(CompareOperation* expr);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000250 bool IsSymbolCompare(CompareOperation* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000251 TypeInfo SwitchType(CaseClause* clause);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000252 TypeInfo IncrementType(CountOperation* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000253
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000254 private:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000255 ZoneMapList* CollectReceiverTypes(unsigned ast_id,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000256 Handle<String> name,
257 Code::Flags flags);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000258
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000259 void SetInfo(unsigned ast_id, Object* target);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000260
whesse@chromium.org7b260152011-06-20 15:33:18 +0000261 void BuildDictionary(Handle<Code> code);
262 void GetRelocInfos(Handle<Code> code, ZoneList<RelocInfo>* infos);
263 void CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos);
264 void RelocateRelocInfos(ZoneList<RelocInfo>* infos,
265 byte* old_start,
266 byte* new_start);
267 void ProcessRelocInfos(ZoneList<RelocInfo>* infos);
268 void ProcessTarget(unsigned ast_id, Code* target);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000269
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000270 // Returns an element from the backing store. Returns undefined if
271 // there is no information.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000272 Handle<Object> GetInfo(unsigned ast_id);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000273
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000274 Handle<Context> global_context_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000275 Handle<NumberDictionary> dictionary_;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000276
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000277 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
278};
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000279
280} } // namespace v8::internal
281
282#endif // V8_TYPE_INFO_H_