blob: 34ff58452ff3261ec9ce03c2964b7a81a3c2c30a [file] [log] [blame]
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00001// Copyright 2010 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
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"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000032#include "zone.h"
33#include "zone-inl.h"
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000034
35namespace v8 {
36namespace internal {
37
kasperl@chromium.orga5551262010-12-07 12:49:48 +000038// Unknown
39// | |
40// | \--------------|
41// Primitive Non-primitive
42// | \--------| |
43// Number String |
44// / | | |
45// Double Integer32 | /
46// | | / /
47// | Smi / /
48// | | / /
49// | | / /
50// Uninitialized.--/
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000051
52class TypeInfo {
53 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +000054 TypeInfo() : type_(kUninitialized) { }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000055
kasperl@chromium.orga5551262010-12-07 12:49:48 +000056 static TypeInfo Unknown() { return TypeInfo(kUnknown); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000057 // We know it's a primitive type.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000058 static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000059 // We know it's a number of some sort.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000060 static TypeInfo Number() { return TypeInfo(kNumber); }
61 // We know it's a signed 32 bit integer.
62 static TypeInfo Integer32() { return TypeInfo(kInteger32); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000063 // We know it's a Smi.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000064 static TypeInfo Smi() { return TypeInfo(kSmi); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000065 // We know it's a heap number.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000066 static TypeInfo Double() { return TypeInfo(kDouble); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000067 // We know it's a string.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000068 static TypeInfo String() { return TypeInfo(kString); }
69 // We know it's a non-primitive (object) type.
70 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000071 // We haven't started collecting info yet.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000072 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000073
74 // Return compact representation. Very sensitive to enum values below!
kasperl@chromium.orga5551262010-12-07 12:49:48 +000075 // Compacting drops information about primitive types and strings types.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000076 // We use the compact representation when we only care about number types.
77 int ThreeBitRepresentation() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000078 ASSERT(type_ != kUninitialized);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000079 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) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000088 Type t = static_cast<Type>(three_bit_representation > 4 ?
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000089 three_bit_representation + 2 :
90 three_bit_representation);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000091 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);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000097 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);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000106 ASSERT(t == kUnknown ||
107 t == kPrimitive ||
108 t == kNumber ||
109 t == kInteger32 ||
110 t == kSmi ||
111 t == kDouble ||
112 t == kString ||
113 t == kNonPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000114 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
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000123 // 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000126 // as it is not an Integer32.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000127 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;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000131 if (value >= kMinInt && value <= kMaxInt &&
132 value == static_cast<int32_t>(value)) {
133 return true;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000134 }
135 return false;
136 }
137
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000138 static TypeInfo TypeFromValue(Handle<Object> value);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000139
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140 bool Equals(const TypeInfo& other) {
141 return type_ == other.type_;
142 }
143
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000144 inline bool IsUnknown() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000145 ASSERT(type_ != kUninitialized);
146 return type_ == kUnknown;
147 }
148
149 inline bool IsPrimitive() {
150 ASSERT(type_ != kUninitialized);
151 return ((type_ & kPrimitive) == kPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000152 }
153
154 inline bool IsNumber() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000155 ASSERT(type_ != kUninitialized);
156 return ((type_ & kNumber) == kNumber);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000157 }
158
159 inline bool IsSmi() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000160 ASSERT(type_ != kUninitialized);
161 return ((type_ & kSmi) == kSmi);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000162 }
163
164 inline bool IsInteger32() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000165 ASSERT(type_ != kUninitialized);
166 return ((type_ & kInteger32) == kInteger32);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000167 }
168
169 inline bool IsDouble() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000170 ASSERT(type_ != kUninitialized);
171 return ((type_ & kDouble) == kDouble);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000172 }
173
lrn@chromium.org25156de2010-04-06 13:10:27 +0000174 inline bool IsString() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000175 ASSERT(type_ != kUninitialized);
176 return ((type_ & kString) == kString);
177 }
178
179 inline bool IsNonPrimitive() {
180 ASSERT(type_ != kUninitialized);
181 return ((type_ & kNonPrimitive) == kNonPrimitive);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000182 }
183
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000184 inline bool IsUninitialized() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000185 return type_ == kUninitialized;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000186 }
187
188 const char* ToString() {
189 switch (type_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000190 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";
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000199 }
200 UNREACHABLE();
201 return "Unreachable code";
202 }
203
204 private:
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000205 enum Type {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000206 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
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000215 };
216 explicit inline TypeInfo(Type t) : type_(t) { }
217
218 Type type_;
219};
220
221
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000222enum StringStubFeedback {
223 DEFAULT_STRING_STUB = 0,
224 STRING_INDEX_OUT_OF_BOUNDS = 1
225};
226
227
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000228// Forward declarations.
229class Assignment;
230class BinaryOperation;
231class Call;
232class CompareOperation;
233class CompilationInfo;
234class Property;
235class CaseClause;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000236
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000237class TypeFeedbackOracle BASE_EMBEDDED {
238 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000239 TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000240
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000241 bool LoadIsMonomorphic(Property* expr);
242 bool StoreIsMonomorphic(Assignment* expr);
243 bool CallIsMonomorphic(Call* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000244
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000245 Handle<Map> LoadMonomorphicReceiverType(Property* expr);
246 Handle<Map> StoreMonomorphicReceiverType(Assignment* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000247
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000248 ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
249 ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
250 ZoneMapList* CallReceiverTypes(Call* expr, Handle<String> name);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000251
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000252 CheckType GetCallCheckType(Call* expr);
253 Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
254
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000255 bool LoadIsBuiltin(Property* expr, Builtins::Name id);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000256
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000257 // Get type information for arithmetic operations and compares.
ager@chromium.org378b34e2011-01-28 08:04:38 +0000258 TypeInfo BinaryType(BinaryOperation* expr);
259 TypeInfo CompareType(CompareOperation* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000260 TypeInfo SwitchType(CaseClause* clause);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000261
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000262 private:
263 void Initialize(Handle<Code> code);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000264
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000265 ZoneMapList* CollectReceiverTypes(int position,
266 Handle<String> name,
267 Code::Flags flags);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000268
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000269 void PopulateMap(Handle<Code> code);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000270
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000271 void CollectPositions(Code* code,
272 List<int>* code_positions,
273 List<int>* source_positions);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000274
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000275 Handle<Context> global_context_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000276 Handle<JSObject> map_;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000277
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000278 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
279};
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000280
281} } // namespace v8::internal
282
283#endif // V8_TYPE_INFO_H_