blob: 715ea278518d18a62917714940026fae21a68edd [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.h"
34#include "zone-inl.h"
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000035
36namespace v8 {
37namespace internal {
38
kasperl@chromium.orga5551262010-12-07 12:49:48 +000039// Unknown
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000040// | \____________
41// | |
42// Primitive Non-primitive
43// | \_______ |
44// | | |
45// Number String |
46// / \ | |
47// Double Integer32 | /
48// | | / /
49// | Smi / /
50// | | / __/
51// Uninitialized.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000052
53class TypeInfo {
54 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +000055 TypeInfo() : type_(kUninitialized) { }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000056
kasperl@chromium.orga5551262010-12-07 12:49:48 +000057 static TypeInfo Unknown() { return TypeInfo(kUnknown); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000058 // We know it's a primitive type.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000059 static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000060 // We know it's a number of some sort.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000061 static TypeInfo Number() { return TypeInfo(kNumber); }
62 // We know it's a signed 32 bit integer.
63 static TypeInfo Integer32() { return TypeInfo(kInteger32); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000064 // We know it's a Smi.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000065 static TypeInfo Smi() { return TypeInfo(kSmi); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000066 // We know it's a heap number.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000067 static TypeInfo Double() { return TypeInfo(kDouble); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000068 // We know it's a string.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000069 static TypeInfo String() { return TypeInfo(kString); }
70 // We know it's a non-primitive (object) type.
71 static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000072 // We haven't started collecting info yet.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000073 static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000074
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000075 int ToInt() {
76 return type_;
77 }
78
79 static TypeInfo FromInt(int bit_representation) {
80 Type t = static_cast<Type>(bit_representation);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000081 ASSERT(t == kUnknown ||
82 t == kPrimitive ||
83 t == kNumber ||
84 t == kInteger32 ||
85 t == kSmi ||
86 t == kDouble ||
87 t == kString ||
88 t == kNonPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000089 return TypeInfo(t);
90 }
91
92 // Return the weakest (least precise) common type.
93 static TypeInfo Combine(TypeInfo a, TypeInfo b) {
94 return TypeInfo(static_cast<Type>(a.type_ & b.type_));
95 }
96
97
ricow@chromium.org83aa5492011-02-07 12:42:56 +000098 // Integer32 is an integer that can be represented as a signed
99 // 32-bit integer. It has to be
100 // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000101 // as it is not an Integer32.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000102 static inline bool IsInt32Double(double value) {
103 const DoubleRepresentation minus_zero(-0.0);
104 DoubleRepresentation rep(value);
105 if (rep.bits == minus_zero.bits) return false;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000106 if (value >= kMinInt && value <= kMaxInt &&
107 value == static_cast<int32_t>(value)) {
108 return true;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000109 }
110 return false;
111 }
112
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000113 static TypeInfo TypeFromValue(Handle<Object> value);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000114
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 bool Equals(const TypeInfo& other) {
116 return type_ == other.type_;
117 }
118
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000119 inline bool IsUnknown() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120 ASSERT(type_ != kUninitialized);
121 return type_ == kUnknown;
122 }
123
124 inline bool IsPrimitive() {
125 ASSERT(type_ != kUninitialized);
126 return ((type_ & kPrimitive) == kPrimitive);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000127 }
128
129 inline bool IsNumber() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000130 ASSERT(type_ != kUninitialized);
131 return ((type_ & kNumber) == kNumber);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000132 }
133
134 inline bool IsSmi() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135 ASSERT(type_ != kUninitialized);
136 return ((type_ & kSmi) == kSmi);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000137 }
138
139 inline bool IsInteger32() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000140 ASSERT(type_ != kUninitialized);
141 return ((type_ & kInteger32) == kInteger32);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000142 }
143
144 inline bool IsDouble() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000145 ASSERT(type_ != kUninitialized);
146 return ((type_ & kDouble) == kDouble);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000147 }
148
lrn@chromium.org25156de2010-04-06 13:10:27 +0000149 inline bool IsString() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000150 ASSERT(type_ != kUninitialized);
151 return ((type_ & kString) == kString);
152 }
153
154 inline bool IsNonPrimitive() {
155 ASSERT(type_ != kUninitialized);
156 return ((type_ & kNonPrimitive) == kNonPrimitive);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000157 }
158
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000159 inline bool IsUninitialized() {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000160 return type_ == kUninitialized;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000161 }
162
163 const char* ToString() {
164 switch (type_) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000165 case kUnknown: return "Unknown";
166 case kPrimitive: return "Primitive";
167 case kNumber: return "Number";
168 case kInteger32: return "Integer32";
169 case kSmi: return "Smi";
170 case kDouble: return "Double";
171 case kString: return "String";
172 case kNonPrimitive: return "Object";
173 case kUninitialized: return "Uninitialized";
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000174 }
175 UNREACHABLE();
176 return "Unreachable code";
177 }
178
179 private:
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000180 enum Type {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000181 kUnknown = 0, // 0000000
182 kPrimitive = 0x10, // 0010000
183 kNumber = 0x11, // 0010001
184 kInteger32 = 0x13, // 0010011
185 kSmi = 0x17, // 0010111
186 kDouble = 0x19, // 0011001
187 kString = 0x30, // 0110000
188 kNonPrimitive = 0x40, // 1000000
189 kUninitialized = 0x7f // 1111111
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000190 };
191 explicit inline TypeInfo(Type t) : type_(t) { }
192
193 Type type_;
194};
195
196
erik.corry@gmail.com0511e242011-01-19 11:11:08 +0000197enum StringStubFeedback {
198 DEFAULT_STRING_STUB = 0,
199 STRING_INDEX_OUT_OF_BOUNDS = 1
200};
201
202
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000203// Forward declarations.
204class Assignment;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000205class UnaryOperation;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000206class BinaryOperation;
207class Call;
208class CompareOperation;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000209class CountOperation;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000210class CompilationInfo;
211class Property;
212class CaseClause;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000213
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000214class TypeFeedbackOracle BASE_EMBEDDED {
215 public:
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000216 TypeFeedbackOracle(Handle<Code> code, Handle<Context> global_context);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000217
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000218 bool LoadIsMonomorphicNormal(Property* expr);
219 bool StoreIsMonomorphicNormal(Expression* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000220 bool CallIsMonomorphic(Call* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000221
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000222 Handle<Map> LoadMonomorphicReceiverType(Property* expr);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000223 Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000224
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000225 ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
226 ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000227 ZoneMapList* CallReceiverTypes(Call* expr,
228 Handle<String> name,
229 CallKind call_kind);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000230
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000231 CheckType GetCallCheckType(Call* expr);
232 Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
233
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000234 bool LoadIsBuiltin(Property* expr, Builtins::Name id);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000235
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000236 // Get type information for arithmetic operations and compares.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000237 TypeInfo UnaryType(UnaryOperation* expr);
ager@chromium.org378b34e2011-01-28 08:04:38 +0000238 TypeInfo BinaryType(BinaryOperation* expr);
239 TypeInfo CompareType(CompareOperation* expr);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000240 bool IsSymbolCompare(CompareOperation* expr);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000241 TypeInfo SwitchType(CaseClause* clause);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000242 TypeInfo IncrementType(CountOperation* expr);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000243
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000244 private:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000245 ZoneMapList* CollectReceiverTypes(unsigned ast_id,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000246 Handle<String> name,
247 Code::Flags flags);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000248
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000249 void SetInfo(unsigned ast_id, Object* target);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000250
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000251 void PopulateMap(Handle<Code> code);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000252
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000253 void CollectIds(Code* code,
254 List<int>* code_positions,
255 List<unsigned>* ast_ids);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000256
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000257 // Returns an element from the backing store. Returns undefined if
258 // there is no information.
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000259 Handle<Object> GetInfo(unsigned ast_id);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000260
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000261 Handle<Context> global_context_;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +0000262 Handle<NumberDictionary> dictionary_;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000263
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000264 DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle);
265};
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000266
267} } // namespace v8::internal
268
269#endif // V8_TYPE_INFO_H_