The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.
Please select the desired protocol below to get the URL.
This URL has Read-Only access.
main_repo / deps / v8 / src / types.cc @ f230a1cf
History | View | Annotate | Download (17.5 KB)
1 |
// Copyright 2013 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 |
#include "types.h" |
29 |
#include "string-stream.h" |
30 |
|
31 |
namespace v8 {
|
32 |
namespace internal {
|
33 |
|
34 |
int Type::NumClasses() {
|
35 |
if (is_class()) {
|
36 |
return 1; |
37 |
} else if (is_union()) { |
38 |
Handle<Unioned> unioned = as_union(); |
39 |
int result = 0; |
40 |
for (int i = 0; i < unioned->length(); ++i) { |
41 |
if (union_get(unioned, i)->is_class()) ++result;
|
42 |
} |
43 |
return result;
|
44 |
} else {
|
45 |
return 0; |
46 |
} |
47 |
} |
48 |
|
49 |
|
50 |
int Type::NumConstants() {
|
51 |
if (is_constant()) {
|
52 |
return 1; |
53 |
} else if (is_union()) { |
54 |
Handle<Unioned> unioned = as_union(); |
55 |
int result = 0; |
56 |
for (int i = 0; i < unioned->length(); ++i) { |
57 |
if (union_get(unioned, i)->is_constant()) ++result;
|
58 |
} |
59 |
return result;
|
60 |
} else {
|
61 |
return 0; |
62 |
} |
63 |
} |
64 |
|
65 |
|
66 |
template<class T> |
67 |
Handle<Type> Type::Iterator<T>::get_type() { |
68 |
ASSERT(!Done()); |
69 |
return type_->is_union() ? union_get(type_->as_union(), index_) : type_;
|
70 |
} |
71 |
|
72 |
template<>
|
73 |
Handle<Map> Type::Iterator<Map>::Current() { |
74 |
return get_type()->as_class();
|
75 |
} |
76 |
|
77 |
template<>
|
78 |
Handle<v8::internal::Object> Type::Iterator<v8::internal::Object>::Current() { |
79 |
return get_type()->as_constant();
|
80 |
} |
81 |
|
82 |
|
83 |
template<>
|
84 |
bool Type::Iterator<Map>::matches(Handle<Type> type) {
|
85 |
return type->is_class();
|
86 |
} |
87 |
|
88 |
template<>
|
89 |
bool Type::Iterator<v8::internal::Object>::matches(Handle<Type> type) {
|
90 |
return type->is_constant();
|
91 |
} |
92 |
|
93 |
|
94 |
template<class T> |
95 |
void Type::Iterator<T>::Advance() {
|
96 |
++index_; |
97 |
if (type_->is_union()) {
|
98 |
Handle<Unioned> unioned = type_->as_union(); |
99 |
for (; index_ < unioned->length(); ++index_) {
|
100 |
if (matches(union_get(unioned, index_))) return; |
101 |
} |
102 |
} else if (index_ == 0 && matches(type_)) { |
103 |
return;
|
104 |
} |
105 |
index_ = -1;
|
106 |
} |
107 |
|
108 |
template class Type::Iterator<Map>; |
109 |
template class Type::Iterator<v8::internal::Object>; |
110 |
|
111 |
|
112 |
// Get the smallest bitset subsuming this type.
|
113 |
int Type::LubBitset() {
|
114 |
if (this->is_bitset()) { |
115 |
return this->as_bitset(); |
116 |
} else if (this->is_union()) { |
117 |
Handle<Unioned> unioned = this->as_union();
|
118 |
int bitset = kNone;
|
119 |
for (int i = 0; i < unioned->length(); ++i) { |
120 |
bitset |= union_get(unioned, i)->LubBitset(); |
121 |
} |
122 |
return bitset;
|
123 |
} else {
|
124 |
Map* map = NULL;
|
125 |
if (this->is_class()) { |
126 |
map = *this->as_class();
|
127 |
} else {
|
128 |
Handle<v8::internal::Object> value = this->as_constant();
|
129 |
if (value->IsSmi()) return kSmi; |
130 |
map = HeapObject::cast(*value)->map(); |
131 |
if (map->instance_type() == HEAP_NUMBER_TYPE) {
|
132 |
int32_t i; |
133 |
uint32_t u; |
134 |
if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32; |
135 |
if (value->ToUint32(&u)) return kUnsigned32; |
136 |
return kDouble;
|
137 |
} |
138 |
if (map->instance_type() == ODDBALL_TYPE) {
|
139 |
if (value->IsUndefined()) return kUndefined; |
140 |
if (value->IsNull()) return kNull; |
141 |
if (value->IsTrue() || value->IsFalse()) return kBoolean; |
142 |
if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone? |
143 |
UNREACHABLE(); |
144 |
} |
145 |
} |
146 |
switch (map->instance_type()) {
|
147 |
case STRING_TYPE:
|
148 |
case ASCII_STRING_TYPE:
|
149 |
case CONS_STRING_TYPE:
|
150 |
case CONS_ASCII_STRING_TYPE:
|
151 |
case SLICED_STRING_TYPE:
|
152 |
case SLICED_ASCII_STRING_TYPE:
|
153 |
case EXTERNAL_STRING_TYPE:
|
154 |
case EXTERNAL_ASCII_STRING_TYPE:
|
155 |
case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
|
156 |
case SHORT_EXTERNAL_STRING_TYPE:
|
157 |
case SHORT_EXTERNAL_ASCII_STRING_TYPE:
|
158 |
case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
|
159 |
case INTERNALIZED_STRING_TYPE:
|
160 |
case ASCII_INTERNALIZED_STRING_TYPE:
|
161 |
case CONS_INTERNALIZED_STRING_TYPE:
|
162 |
case CONS_ASCII_INTERNALIZED_STRING_TYPE:
|
163 |
case EXTERNAL_INTERNALIZED_STRING_TYPE:
|
164 |
case EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE:
|
165 |
case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
|
166 |
case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE:
|
167 |
case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE:
|
168 |
case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
|
169 |
return kString;
|
170 |
case SYMBOL_TYPE:
|
171 |
return kSymbol;
|
172 |
case ODDBALL_TYPE:
|
173 |
return kOddball;
|
174 |
case HEAP_NUMBER_TYPE:
|
175 |
return kDouble;
|
176 |
case JS_VALUE_TYPE:
|
177 |
case JS_DATE_TYPE:
|
178 |
case JS_OBJECT_TYPE:
|
179 |
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
|
180 |
case JS_GENERATOR_OBJECT_TYPE:
|
181 |
case JS_MODULE_TYPE:
|
182 |
case JS_GLOBAL_OBJECT_TYPE:
|
183 |
case JS_BUILTINS_OBJECT_TYPE:
|
184 |
case JS_GLOBAL_PROXY_TYPE:
|
185 |
case JS_ARRAY_BUFFER_TYPE:
|
186 |
case JS_TYPED_ARRAY_TYPE:
|
187 |
case JS_DATA_VIEW_TYPE:
|
188 |
case JS_SET_TYPE:
|
189 |
case JS_MAP_TYPE:
|
190 |
case JS_WEAK_MAP_TYPE:
|
191 |
case JS_WEAK_SET_TYPE:
|
192 |
if (map->is_undetectable()) return kUndetectable; |
193 |
return kOtherObject;
|
194 |
case JS_ARRAY_TYPE:
|
195 |
return kArray;
|
196 |
case JS_FUNCTION_TYPE:
|
197 |
return kFunction;
|
198 |
case JS_REGEXP_TYPE:
|
199 |
return kRegExp;
|
200 |
case JS_PROXY_TYPE:
|
201 |
case JS_FUNCTION_PROXY_TYPE:
|
202 |
return kProxy;
|
203 |
case MAP_TYPE:
|
204 |
// When compiling stub templates, the meta map is used as a place holder
|
205 |
// for the actual map with which the template is later instantiated.
|
206 |
// We treat it as a kind of type variable whose upper bound is Any.
|
207 |
// TODO(rossberg): for caching of CompareNilIC stubs to work correctly,
|
208 |
// we must exclude Undetectable here. This makes no sense, really,
|
209 |
// because it means that the template isn't actually parametric.
|
210 |
// Also, it doesn't apply elsewhere. 8-(
|
211 |
// We ought to find a cleaner solution for compiling stubs parameterised
|
212 |
// over type or class variables, esp ones with bounds...
|
213 |
return kDetectable;
|
214 |
case DECLARED_ACCESSOR_INFO_TYPE:
|
215 |
case EXECUTABLE_ACCESSOR_INFO_TYPE:
|
216 |
case ACCESSOR_PAIR_TYPE:
|
217 |
case FIXED_ARRAY_TYPE:
|
218 |
return kInternal;
|
219 |
default:
|
220 |
UNREACHABLE(); |
221 |
return kNone;
|
222 |
} |
223 |
} |
224 |
} |
225 |
|
226 |
|
227 |
// Get the largest bitset subsumed by this type.
|
228 |
int Type::GlbBitset() {
|
229 |
if (this->is_bitset()) { |
230 |
return this->as_bitset(); |
231 |
} else if (this->is_union()) { |
232 |
// All but the first are non-bitsets and thus would yield kNone anyway.
|
233 |
return union_get(this->as_union(), 0)->GlbBitset(); |
234 |
} else {
|
235 |
return kNone;
|
236 |
} |
237 |
} |
238 |
|
239 |
|
240 |
// Check this <= that.
|
241 |
bool Type::SlowIs(Type* that) {
|
242 |
// Fast path for bitsets.
|
243 |
if (this->is_none()) return true; |
244 |
if (that->is_bitset()) {
|
245 |
return (this->LubBitset() | that->as_bitset()) == that->as_bitset(); |
246 |
} |
247 |
|
248 |
if (that->is_class()) {
|
249 |
return this->is_class() && *this->as_class() == *that->as_class(); |
250 |
} |
251 |
if (that->is_constant()) {
|
252 |
return this->is_constant() && *this->as_constant() == *that->as_constant(); |
253 |
} |
254 |
|
255 |
// (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
|
256 |
if (this->is_union()) { |
257 |
Handle<Unioned> unioned = this->as_union();
|
258 |
for (int i = 0; i < unioned->length(); ++i) { |
259 |
Handle<Type> this_i = union_get(unioned, i); |
260 |
if (!this_i->Is(that)) return false; |
261 |
} |
262 |
return true; |
263 |
} |
264 |
|
265 |
// T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn)
|
266 |
// (iff T is not a union)
|
267 |
ASSERT(!this->is_union());
|
268 |
if (that->is_union()) {
|
269 |
Handle<Unioned> unioned = that->as_union(); |
270 |
for (int i = 0; i < unioned->length(); ++i) { |
271 |
Handle<Type> that_i = union_get(unioned, i); |
272 |
if (this->Is(that_i)) return true; |
273 |
if (this->is_bitset()) break; // Fast fail, no other field is a bitset. |
274 |
} |
275 |
return false; |
276 |
} |
277 |
|
278 |
return false; |
279 |
} |
280 |
|
281 |
|
282 |
// Check this overlaps that.
|
283 |
bool Type::Maybe(Type* that) {
|
284 |
// Fast path for bitsets.
|
285 |
if (this->is_bitset()) { |
286 |
return (this->as_bitset() & that->LubBitset()) != 0; |
287 |
} |
288 |
if (that->is_bitset()) {
|
289 |
return (this->LubBitset() & that->as_bitset()) != 0; |
290 |
} |
291 |
|
292 |
// (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
|
293 |
if (this->is_union()) { |
294 |
Handle<Unioned> unioned = this->as_union();
|
295 |
for (int i = 0; i < unioned->length(); ++i) { |
296 |
Handle<Type> this_i = union_get(unioned, i); |
297 |
if (this_i->Maybe(that)) return true; |
298 |
} |
299 |
return false; |
300 |
} |
301 |
|
302 |
// T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn)
|
303 |
if (that->is_union()) {
|
304 |
Handle<Unioned> unioned = that->as_union(); |
305 |
for (int i = 0; i < unioned->length(); ++i) { |
306 |
Handle<Type> that_i = union_get(unioned, i); |
307 |
if (this->Maybe(that_i)) return true; |
308 |
} |
309 |
return false; |
310 |
} |
311 |
|
312 |
ASSERT(!that->is_union()); |
313 |
if (this->is_class()) { |
314 |
return that->is_class() && *this->as_class() == *that->as_class(); |
315 |
} |
316 |
if (this->is_constant()) { |
317 |
return that->is_constant() && *this->as_constant() == *that->as_constant(); |
318 |
} |
319 |
|
320 |
return false; |
321 |
} |
322 |
|
323 |
|
324 |
bool Type::InUnion(Handle<Unioned> unioned, int current_size) { |
325 |
ASSERT(!this->is_union());
|
326 |
for (int i = 0; i < current_size; ++i) { |
327 |
Handle<Type> type = union_get(unioned, i); |
328 |
if (this->Is(type)) return true; |
329 |
} |
330 |
return false; |
331 |
} |
332 |
|
333 |
|
334 |
// Get non-bitsets from this which are not subsumed by union, store at unioned,
|
335 |
// starting at index. Returns updated index.
|
336 |
int Type::ExtendUnion(Handle<Unioned> result, int current_size) { |
337 |
int old_size = current_size;
|
338 |
if (this->is_class() || this->is_constant()) { |
339 |
if (!this->InUnion(result, old_size)) result->set(current_size++, this); |
340 |
} else if (this->is_union()) { |
341 |
Handle<Unioned> unioned = this->as_union();
|
342 |
for (int i = 0; i < unioned->length(); ++i) { |
343 |
Handle<Type> type = union_get(unioned, i); |
344 |
ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0)))); |
345 |
if (type->is_bitset()) continue; |
346 |
if (!type->InUnion(result, old_size)) result->set(current_size++, *type);
|
347 |
} |
348 |
} |
349 |
return current_size;
|
350 |
} |
351 |
|
352 |
|
353 |
// Union is O(1) on simple bit unions, but O(n*m) on structured unions.
|
354 |
// TODO(rossberg): Should we use object sets somehow? Is it worth it?
|
355 |
Type* Type::Union(Handle<Type> type1, Handle<Type> type2) { |
356 |
// Fast case: bit sets.
|
357 |
if (type1->is_bitset() && type2->is_bitset()) {
|
358 |
return from_bitset(type1->as_bitset() | type2->as_bitset());
|
359 |
} |
360 |
|
361 |
// Fast case: top or bottom types.
|
362 |
if (type1->SameValue(Type::Any())) return *type1; |
363 |
if (type2->SameValue(Type::Any())) return *type2; |
364 |
if (type1->SameValue(Type::None())) return *type2; |
365 |
if (type2->SameValue(Type::None())) return *type1; |
366 |
|
367 |
// Semi-fast case: Unioned objects are neither involved nor produced.
|
368 |
if (!(type1->is_union() || type2->is_union())) {
|
369 |
if (type1->Is(type2)) return *type2; |
370 |
if (type2->Is(type1)) return *type1; |
371 |
} |
372 |
|
373 |
// Slow case: may need to produce a Unioned object.
|
374 |
Isolate* isolate = NULL;
|
375 |
int size = type1->is_bitset() || type2->is_bitset() ? 1 : 0; |
376 |
if (!type1->is_bitset()) {
|
377 |
isolate = HeapObject::cast(*type1)->GetIsolate(); |
378 |
size += (type1->is_union() ? type1->as_union()->length() : 1);
|
379 |
} |
380 |
if (!type2->is_bitset()) {
|
381 |
isolate = HeapObject::cast(*type2)->GetIsolate(); |
382 |
size += (type2->is_union() ? type2->as_union()->length() : 1);
|
383 |
} |
384 |
ASSERT(isolate != NULL);
|
385 |
ASSERT(size >= 2);
|
386 |
Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size); |
387 |
size = 0;
|
388 |
|
389 |
int bitset = type1->GlbBitset() | type2->GlbBitset();
|
390 |
if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
|
391 |
size = type1->ExtendUnion(unioned, size); |
392 |
size = type2->ExtendUnion(unioned, size); |
393 |
|
394 |
if (size == 1) { |
395 |
return *union_get(unioned, 0); |
396 |
} else if (size == unioned->length()) { |
397 |
return from_handle(unioned);
|
398 |
} |
399 |
|
400 |
// There was an overlap. Copy to smaller union.
|
401 |
Handle<Unioned> result = isolate->factory()->NewFixedArray(size); |
402 |
for (int i = 0; i < size; ++i) result->set(i, unioned->get(i)); |
403 |
return from_handle(result);
|
404 |
} |
405 |
|
406 |
|
407 |
// Get non-bitsets from this which are also in that, store at unioned,
|
408 |
// starting at index. Returns updated index.
|
409 |
int Type::ExtendIntersection(
|
410 |
Handle<Unioned> result, Handle<Type> that, int current_size) {
|
411 |
int old_size = current_size;
|
412 |
if (this->is_class() || this->is_constant()) { |
413 |
if (this->Is(that) && !this->InUnion(result, old_size)) |
414 |
result->set(current_size++, this);
|
415 |
} else if (this->is_union()) { |
416 |
Handle<Unioned> unioned = this->as_union();
|
417 |
for (int i = 0; i < unioned->length(); ++i) { |
418 |
Handle<Type> type = union_get(unioned, i); |
419 |
ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0)))); |
420 |
if (type->is_bitset()) continue; |
421 |
if (type->Is(that) && !type->InUnion(result, old_size))
|
422 |
result->set(current_size++, *type); |
423 |
} |
424 |
} |
425 |
return current_size;
|
426 |
} |
427 |
|
428 |
|
429 |
// Intersection is O(1) on simple bit unions, but O(n*m) on structured unions.
|
430 |
// TODO(rossberg): Should we use object sets somehow? Is it worth it?
|
431 |
Type* Type::Intersect(Handle<Type> type1, Handle<Type> type2) { |
432 |
// Fast case: bit sets.
|
433 |
if (type1->is_bitset() && type2->is_bitset()) {
|
434 |
return from_bitset(type1->as_bitset() & type2->as_bitset());
|
435 |
} |
436 |
|
437 |
// Fast case: top or bottom types.
|
438 |
if (type1->SameValue(Type::None())) return *type1; |
439 |
if (type2->SameValue(Type::None())) return *type2; |
440 |
if (type1->SameValue(Type::Any())) return *type2; |
441 |
if (type2->SameValue(Type::Any())) return *type1; |
442 |
|
443 |
// Semi-fast case: Unioned objects are neither involved nor produced.
|
444 |
if (!(type1->is_union() || type2->is_union())) {
|
445 |
if (type1->Is(type2)) return *type1; |
446 |
if (type2->Is(type1)) return *type2; |
447 |
} |
448 |
|
449 |
// Slow case: may need to produce a Unioned object.
|
450 |
Isolate* isolate = NULL;
|
451 |
int size = 0; |
452 |
if (!type1->is_bitset()) {
|
453 |
isolate = HeapObject::cast(*type1)->GetIsolate(); |
454 |
size = (type1->is_union() ? type1->as_union()->length() : 2);
|
455 |
} |
456 |
if (!type2->is_bitset()) {
|
457 |
isolate = HeapObject::cast(*type2)->GetIsolate(); |
458 |
int size2 = (type2->is_union() ? type2->as_union()->length() : 2); |
459 |
size = (size == 0 ? size2 : Min(size, size2));
|
460 |
} |
461 |
ASSERT(isolate != NULL);
|
462 |
ASSERT(size >= 2);
|
463 |
Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size); |
464 |
size = 0;
|
465 |
|
466 |
int bitset = type1->GlbBitset() & type2->GlbBitset();
|
467 |
if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
|
468 |
size = type1->ExtendIntersection(unioned, type2, size); |
469 |
size = type2->ExtendIntersection(unioned, type1, size); |
470 |
|
471 |
if (size == 0) { |
472 |
return None();
|
473 |
} else if (size == 1) { |
474 |
return *union_get(unioned, 0); |
475 |
} else if (size == unioned->length()) { |
476 |
return from_handle(unioned);
|
477 |
} |
478 |
|
479 |
// There were dropped cases. Copy to smaller union.
|
480 |
Handle<Unioned> result = isolate->factory()->NewFixedArray(size); |
481 |
for (int i = 0; i < size; ++i) result->set(i, unioned->get(i)); |
482 |
return from_handle(result);
|
483 |
} |
484 |
|
485 |
|
486 |
Type* Type::Optional(Handle<Type> type) { |
487 |
return type->is_bitset()
|
488 |
? from_bitset(type->as_bitset() | kUndefined) |
489 |
: Union(type, Undefined()->handle_via_isolate_of(*type)); |
490 |
} |
491 |
|
492 |
|
493 |
Representation Representation::FromType(Handle<Type> type) { |
494 |
if (type->Is(Type::None())) return Representation::None(); |
495 |
if (type->Is(Type::Smi())) return Representation::Smi(); |
496 |
if (type->Is(Type::Signed32())) return Representation::Integer32(); |
497 |
if (type->Is(Type::Number())) return Representation::Double(); |
498 |
return Representation::Tagged();
|
499 |
} |
500 |
|
501 |
|
502 |
#ifdef OBJECT_PRINT
|
503 |
void Type::TypePrint() {
|
504 |
TypePrint(stdout); |
505 |
PrintF(stdout, "\n");
|
506 |
Flush(stdout); |
507 |
} |
508 |
|
509 |
|
510 |
void Type::TypePrint(FILE* out) {
|
511 |
if (is_bitset()) {
|
512 |
int val = as_bitset();
|
513 |
const char* composed_name = GetComposedName(val); |
514 |
if (composed_name != NULL) { |
515 |
PrintF(out, "%s", composed_name);
|
516 |
return;
|
517 |
} |
518 |
bool first_entry = true; |
519 |
PrintF(out, "{");
|
520 |
for (unsigned i = 0; i < sizeof(val)*8; ++i) { |
521 |
int mask = (1 << i); |
522 |
if ((val & mask) != 0) { |
523 |
if (!first_entry) PrintF(out, ","); |
524 |
first_entry = false;
|
525 |
PrintF(out, "%s", GetPrimitiveName(mask));
|
526 |
} |
527 |
} |
528 |
PrintF(out, "}");
|
529 |
} else if (is_constant()) { |
530 |
PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant())); |
531 |
from_bitset(LubBitset())->TypePrint(out); |
532 |
PrintF(")");
|
533 |
} else if (is_class()) { |
534 |
PrintF(out, "Class(%p < ", static_cast<void*>(*as_class())); |
535 |
from_bitset(LubBitset())->TypePrint(out); |
536 |
PrintF(")");
|
537 |
} else if (is_union()) { |
538 |
PrintF(out, "{");
|
539 |
Handle<Unioned> unioned = as_union(); |
540 |
for (int i = 0; i < unioned->length(); ++i) { |
541 |
Handle<Type> type_i = union_get(unioned, i); |
542 |
if (i > 0) PrintF(out, ","); |
543 |
type_i->TypePrint(out); |
544 |
} |
545 |
PrintF(out, "}");
|
546 |
} |
547 |
} |
548 |
#endif
|
549 |
|
550 |
|
551 |
} } // namespace v8::internal
|