blob: f588e561126aa994fcf51227b3c865d04313f2ec [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"
32
33namespace v8 {
34namespace internal {
35
36// Unknown
37// |
38// PrimitiveType
39// | \--------|
40// Number String
41// / | |
42// Double Integer32 |
43// | | /
44// | Smi /
45// | / /
46// Uninitialized.
47
48class TypeInfo {
49 public:
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000050 TypeInfo() : type_(kUnknownType) { }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000051
52 static inline TypeInfo Unknown();
53 // We know it's a primitive type.
54 static inline TypeInfo Primitive();
55 // We know it's a number of some sort.
56 static inline TypeInfo Number();
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000057 // We know it's signed 32 bit integer.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000058 static inline TypeInfo Integer32();
59 // We know it's a Smi.
60 static inline TypeInfo Smi();
61 // We know it's a heap number.
62 static inline TypeInfo Double();
63 // We know it's a string.
64 static inline TypeInfo String();
65 // We haven't started collecting info yet.
66 static inline TypeInfo Uninitialized();
67
68 // Return compact representation. Very sensitive to enum values below!
69 // Compacting drops information about primtive types and strings types.
70 // We use the compact representation when we only care about number types.
71 int ThreeBitRepresentation() {
72 ASSERT(type_ != kUninitializedType);
73 int answer = type_ & 0xf;
74 answer = answer > 6 ? answer - 2 : answer;
75 ASSERT(answer >= 0);
76 ASSERT(answer <= 7);
77 return answer;
78 }
79
80 // Decode compact representation. Very sensitive to enum values below!
81 static TypeInfo ExpandedRepresentation(int three_bit_representation) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000082 Type t = static_cast<Type>(three_bit_representation > 4 ?
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +000083 three_bit_representation + 2 :
84 three_bit_representation);
85 t = (t == kUnknownType) ? t : static_cast<Type>(t | kPrimitiveType);
86 ASSERT(t == kUnknownType ||
87 t == kNumberType ||
88 t == kInteger32Type ||
89 t == kSmiType ||
90 t == kDoubleType);
91 return TypeInfo(t);
92 }
93
94 int ToInt() {
95 return type_;
96 }
97
98 static TypeInfo FromInt(int bit_representation) {
99 Type t = static_cast<Type>(bit_representation);
100 ASSERT(t == kUnknownType ||
101 t == kPrimitiveType ||
102 t == kNumberType ||
103 t == kInteger32Type ||
104 t == kSmiType ||
105 t == kDoubleType ||
106 t == kStringType);
107 return TypeInfo(t);
108 }
109
110 // Return the weakest (least precise) common type.
111 static TypeInfo Combine(TypeInfo a, TypeInfo b) {
112 return TypeInfo(static_cast<Type>(a.type_ & b.type_));
113 }
114
115
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000116 // Integer32 is an integer that can be represented as a signed
117 // 32-bit integer. It has to be in the range [-2^31, 2^31 - 1].
118 // We also have to check for negative 0 as it is not an Integer32.
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000119 static inline bool IsInt32Double(double value) {
120 const DoubleRepresentation minus_zero(-0.0);
121 DoubleRepresentation rep(value);
122 if (rep.bits == minus_zero.bits) return false;
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000123 if (value >= kMinInt && value <= kMaxInt) {
124 if (value == static_cast<int32_t>(value)) return true;
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000125 }
126 return false;
127 }
128
ricow@chromium.orgaa1b6162010-03-29 07:44:58 +0000129 static TypeInfo TypeFromValue(Handle<Object> value);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000130
131 inline bool IsUnknown() {
132 return type_ == kUnknownType;
133 }
134
135 inline bool IsNumber() {
136 ASSERT(type_ != kUninitializedType);
137 return ((type_ & kNumberType) == kNumberType);
138 }
139
140 inline bool IsSmi() {
141 ASSERT(type_ != kUninitializedType);
142 return ((type_ & kSmiType) == kSmiType);
143 }
144
145 inline bool IsInteger32() {
146 ASSERT(type_ != kUninitializedType);
147 return ((type_ & kInteger32Type) == kInteger32Type);
148 }
149
150 inline bool IsDouble() {
151 ASSERT(type_ != kUninitializedType);
152 return ((type_ & kDoubleType) == kDoubleType);
153 }
154
lrn@chromium.org25156de2010-04-06 13:10:27 +0000155 inline bool IsString() {
156 ASSERT(type_ != kUninitializedType);
157 return ((type_ & kStringType) == kStringType);
158 }
159
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +0000160 inline bool IsUninitialized() {
161 return type_ == kUninitializedType;
162 }
163
164 const char* ToString() {
165 switch (type_) {
166 case kUnknownType: return "UnknownType";
167 case kPrimitiveType: return "PrimitiveType";
168 case kNumberType: return "NumberType";
169 case kInteger32Type: return "Integer32Type";
170 case kSmiType: return "SmiType";
171 case kDoubleType: return "DoubleType";
172 case kStringType: return "StringType";
173 case kUninitializedType:
174 UNREACHABLE();
175 return "UninitializedType";
176 }
177 UNREACHABLE();
178 return "Unreachable code";
179 }
180
181 private:
182 // We use 6 bits to represent the types.
183 enum Type {
184 kUnknownType = 0, // 000000
185 kPrimitiveType = 0x10, // 010000
186 kNumberType = 0x11, // 010001
187 kInteger32Type = 0x13, // 010011
188 kSmiType = 0x17, // 010111
189 kDoubleType = 0x19, // 011001
190 kStringType = 0x30, // 110000
191 kUninitializedType = 0x3f // 111111
192 };
193 explicit inline TypeInfo(Type t) : type_(t) { }
194
195 Type type_;
196};
197
198
199TypeInfo TypeInfo::Unknown() {
200 return TypeInfo(kUnknownType);
201}
202
203
204TypeInfo TypeInfo::Primitive() {
205 return TypeInfo(kPrimitiveType);
206}
207
208
209TypeInfo TypeInfo::Number() {
210 return TypeInfo(kNumberType);
211}
212
213
214TypeInfo TypeInfo::Integer32() {
215 return TypeInfo(kInteger32Type);
216}
217
218
219TypeInfo TypeInfo::Smi() {
220 return TypeInfo(kSmiType);
221}
222
223
224TypeInfo TypeInfo::Double() {
225 return TypeInfo(kDoubleType);
226}
227
228
229TypeInfo TypeInfo::String() {
230 return TypeInfo(kStringType);
231}
232
233
234TypeInfo TypeInfo::Uninitialized() {
235 return TypeInfo(kUninitializedType);
236}
237
238} } // namespace v8::internal
239
240#endif // V8_TYPE_INFO_H_