OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // modification, are permitted provided that the following conditions are | 3 // found in the LICENSE file. |
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 | 4 |
28 #ifndef V8_TYPES_H_ | 5 #ifndef V8_TYPES_H_ |
29 #define V8_TYPES_H_ | 6 #define V8_TYPES_H_ |
30 | 7 |
31 #include "v8.h" | 8 #include "handles.h" |
32 | |
33 #include "objects.h" | |
34 | 9 |
35 namespace v8 { | 10 namespace v8 { |
36 namespace internal { | 11 namespace internal { |
37 | 12 |
38 | |
39 // A simple type system for compiler-internal use. It is based entirely on | 13 // A simple type system for compiler-internal use. It is based entirely on |
40 // union types, and all subtyping hence amounts to set inclusion. Besides the | 14 // union types, and all subtyping hence amounts to set inclusion. Besides the |
41 // obvious primitive types and some predefined unions, the type language also | 15 // obvious primitive types and some predefined unions, the type language also |
42 // can express class types (a.k.a. specific maps) and singleton types (i.e., | 16 // can express class types (a.k.a. specific maps) and singleton types (i.e., |
43 // concrete constants). | 17 // concrete constants). |
44 // | 18 // |
45 // Types consist of two dimensions: semantic (value range) and representation. | 19 // Types consist of two dimensions: semantic (value range) and representation. |
46 // Both are related through subtyping. | 20 // Both are related through subtyping. |
47 // | 21 // |
48 // The following equations and inequations hold for the semantic axis: | 22 // The following equations and inequations hold for the semantic axis: |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 struct ZoneTypeConfig { | 349 struct ZoneTypeConfig { |
376 private: | 350 private: |
377 typedef i::ZoneList<void*> Tagged; | 351 typedef i::ZoneList<void*> Tagged; |
378 | 352 |
379 enum Tag { | 353 enum Tag { |
380 kClassTag, | 354 kClassTag, |
381 kConstantTag, | 355 kConstantTag, |
382 kUnionTag | 356 kUnionTag |
383 }; | 357 }; |
384 | 358 |
385 static Tagged* tagged_create(Tag tag, int size, Zone* zone) { | 359 static inline Tagged* tagged_create(Tag tag, int size, Zone* zone); |
386 Tagged* tagged = new(zone) Tagged(size + 1, zone); | 360 static inline void tagged_shrink(Tagged* tagged, int size); |
387 tagged->Add(reinterpret_cast<void*>(tag), zone); | 361 static inline Tag tagged_tag(Tagged* tagged); |
388 tagged->AddBlock(NULL, size, zone); | |
389 return tagged; | |
390 } | |
391 static void tagged_shrink(Tagged* tagged, int size) { | |
392 tagged->Rewind(size + 1); | |
393 } | |
394 static Tag tagged_tag(Tagged* tagged) { | |
395 return static_cast<Tag>(reinterpret_cast<intptr_t>(tagged->at(0))); | |
396 } | |
397 template<class T> | 362 template<class T> |
398 static T tagged_get(Tagged* tagged, int i) { | 363 static inline T tagged_get(Tagged* tagged, int i); |
399 return reinterpret_cast<T>(tagged->at(i + 1)); | |
400 } | |
401 template<class T> | 364 template<class T> |
402 static void tagged_set(Tagged* tagged, int i, T value) { | 365 static inline void tagged_set(Tagged* tagged, int i, T value); |
403 tagged->at(i + 1) = reinterpret_cast<void*>(value); | 366 static inline int tagged_length(Tagged* tagged); |
404 } | |
405 static int tagged_length(Tagged* tagged) { | |
406 return tagged->length() - 1; | |
407 } | |
408 | 367 |
409 public: | 368 public: |
410 typedef TypeImpl<ZoneTypeConfig> Type; | 369 typedef TypeImpl<ZoneTypeConfig> Type; |
411 class Base {}; | 370 class Base {}; |
412 typedef i::ZoneList<Type*> Unioned; | 371 typedef i::ZoneList<Type*> Unioned; |
413 typedef i::Zone Region; | 372 typedef i::Zone Region; |
414 template<class T> struct Handle { typedef T* type; }; | 373 template<class T> struct Handle { typedef T* type; }; |
415 | 374 |
416 static Type* handle(Type* type) { return type; } | 375 static inline Type* handle(Type* type); |
417 | 376 static inline bool is(Type* type, Tag tag); |
418 static bool is(Type* type, Tag tag) { | 377 static inline bool is_bitset(Type* type); |
419 return is_tagged(type) && tagged_tag(as_tagged(type)) == tag; | 378 static inline bool is_tagged(Type* type); |
420 } | 379 static inline bool is_class(Type* type); |
421 | 380 static inline bool is_constant(Type* type); |
422 static bool is_bitset(Type* type) { | 381 static inline bool is_union(Type* type); |
423 return reinterpret_cast<intptr_t>(type) & 1; | 382 static inline bool tagged_is_union(Tagged* tagged); |
424 } | 383 static inline int as_bitset(Type* type); |
425 static bool is_tagged(Type* type) { return !is_bitset(type); } | 384 static inline Tagged* as_tagged(Type* type); |
426 static bool is_class(Type* type) { return is(type, kClassTag); } | 385 static inline i::Handle<i::Map> as_class(Type* type); |
427 static bool is_constant(Type* type) { return is(type, kConstantTag); } | 386 static inline i::Handle<i::Object> as_constant(Type* type); |
428 static bool is_union(Type* type) { return is(type, kUnionTag); } | 387 static inline Unioned* as_union(Type* type); |
429 static bool tagged_is_union(Tagged* tagged) { | 388 static inline Unioned* tagged_as_union(Tagged* tagged); |
430 return is(from_tagged(tagged), kUnionTag); | 389 static inline Type* from_bitset(int bitset); |
431 } | 390 static inline Type* from_bitset(int bitset, Zone* zone); |
432 | 391 static inline Type* from_tagged(Tagged* tagged); |
433 static int as_bitset(Type* type) { | 392 static inline Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone); |
434 ASSERT(is_bitset(type)); | 393 static inline Type* from_constant( |
435 return static_cast<int>(reinterpret_cast<intptr_t>(type) >> 1); | 394 i::Handle<i::Object> value, int lub, Zone* zone); |
436 } | 395 static inline Type* from_union(Unioned* unioned); |
437 static Tagged* as_tagged(Type* type) { | 396 static inline Tagged* tagged_from_union(Unioned* unioned); |
438 ASSERT(is_tagged(type)); | 397 static inline Unioned* union_create(int size, Zone* zone); |
439 return reinterpret_cast<Tagged*>(type); | 398 static inline void union_shrink(Unioned* unioned, int size); |
440 } | 399 static inline Type* union_get(Unioned* unioned, int i); |
441 static i::Handle<i::Map> as_class(Type* type) { | 400 static inline void union_set(Unioned* unioned, int i, Type* type); |
442 ASSERT(is_class(type)); | 401 static inline int union_length(Unioned* unioned); |
443 return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 1)); | 402 static inline int lub_bitset(Type* type); |
444 } | |
445 static i::Handle<i::Object> as_constant(Type* type) { | |
446 ASSERT(is_constant(type)); | |
447 return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 1)); | |
448 } | |
449 static Unioned* as_union(Type* type) { | |
450 ASSERT(is_union(type)); | |
451 return tagged_as_union(as_tagged(type)); | |
452 } | |
453 static Unioned* tagged_as_union(Tagged* tagged) { | |
454 ASSERT(tagged_is_union(tagged)); | |
455 return reinterpret_cast<Unioned*>(tagged); | |
456 } | |
457 | |
458 static Type* from_bitset(int bitset) { | |
459 return reinterpret_cast<Type*>((bitset << 1) | 1); | |
460 } | |
461 static Type* from_bitset(int bitset, Zone* Zone) { | |
462 return from_bitset(bitset); | |
463 } | |
464 static Type* from_tagged(Tagged* tagged) { | |
465 return reinterpret_cast<Type*>(tagged); | |
466 } | |
467 static Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone) { | |
468 Tagged* tagged = tagged_create(kClassTag, 2, zone); | |
469 tagged_set(tagged, 0, lub); | |
470 tagged_set(tagged, 1, map.location()); | |
471 return from_tagged(tagged); | |
472 } | |
473 static Type* from_constant(i::Handle<i::Object> value, int lub, Zone* zone) { | |
474 Tagged* tagged = tagged_create(kConstantTag, 2, zone); | |
475 tagged_set(tagged, 0, lub); | |
476 tagged_set(tagged, 1, value.location()); | |
477 return from_tagged(tagged); | |
478 } | |
479 static Type* from_union(Unioned* unioned) { | |
480 return from_tagged(tagged_from_union(unioned)); | |
481 } | |
482 static Tagged* tagged_from_union(Unioned* unioned) { | |
483 return reinterpret_cast<Tagged*>(unioned); | |
484 } | |
485 | |
486 static Unioned* union_create(int size, Zone* zone) { | |
487 return tagged_as_union(tagged_create(kUnionTag, size, zone)); | |
488 } | |
489 static void union_shrink(Unioned* unioned, int size) { | |
490 tagged_shrink(tagged_from_union(unioned), size); | |
491 } | |
492 static Type* union_get(Unioned* unioned, int i) { | |
493 Type* type = tagged_get<Type*>(tagged_from_union(unioned), i); | |
494 ASSERT(!is_union(type)); | |
495 return type; | |
496 } | |
497 static void union_set(Unioned* unioned, int i, Type* type) { | |
498 ASSERT(!is_union(type)); | |
499 tagged_set(tagged_from_union(unioned), i, type); | |
500 } | |
501 static int union_length(Unioned* unioned) { | |
502 return tagged_length(tagged_from_union(unioned)); | |
503 } | |
504 static int lub_bitset(Type* type) { | |
505 ASSERT(is_class(type) || is_constant(type)); | |
506 return static_cast<int>(tagged_get<intptr_t>(as_tagged(type), 0)); | |
507 } | |
508 }; | 403 }; |
509 | 404 |
510 | 405 |
511 // Heap-allocated types are either smis for bitsets, maps for classes, boxes for | 406 // Heap-allocated types are either smis for bitsets, maps for classes, boxes for |
512 // constants, or fixed arrays for unions. | 407 // constants, or fixed arrays for unions. |
513 struct HeapTypeConfig { | 408 struct HeapTypeConfig { |
514 typedef TypeImpl<HeapTypeConfig> Type; | 409 typedef TypeImpl<HeapTypeConfig> Type; |
515 typedef i::Object Base; | 410 typedef i::Object Base; |
516 typedef i::FixedArray Unioned; | 411 typedef i::FixedArray Unioned; |
517 typedef i::Isolate Region; | 412 typedef i::Isolate Region; |
518 template<class T> struct Handle { typedef i::Handle<T> type; }; | 413 template<class T> struct Handle { typedef i::Handle<T> type; }; |
519 | 414 |
520 static i::Handle<Type> handle(Type* type) { | 415 static inline i::Handle<Type> handle(Type* type); |
521 return i::handle(type, i::HeapObject::cast(type)->GetIsolate()); | 416 static inline bool is_bitset(Type* type); |
522 } | 417 static inline bool is_class(Type* type); |
523 | 418 static inline bool is_constant(Type* type); |
524 static bool is_bitset(Type* type) { return type->IsSmi(); } | 419 static inline bool is_union(Type* type); |
525 static bool is_class(Type* type) { return type->IsMap(); } | 420 static inline int as_bitset(Type* type); |
526 static bool is_constant(Type* type) { return type->IsBox(); } | 421 static inline i::Handle<i::Map> as_class(Type* type); |
527 static bool is_union(Type* type) { return type->IsFixedArray(); } | 422 static inline i::Handle<i::Object> as_constant(Type* type); |
528 | 423 static inline i::Handle<Unioned> as_union(Type* type); |
529 static int as_bitset(Type* type) { | 424 static inline Type* from_bitset(int bitset); |
530 return Smi::cast(type)->value(); | 425 static inline i::Handle<Type> from_bitset(int bitset, Isolate* isolate); |
531 } | 426 static inline i::Handle<Type> from_class( |
532 static i::Handle<i::Map> as_class(Type* type) { | 427 i::Handle<i::Map> map, int lub, Isolate* isolate); |
533 return i::handle(i::Map::cast(type)); | 428 static inline i::Handle<Type> from_constant( |
534 } | 429 i::Handle<i::Object> value, int lub, Isolate* isolate); |
535 static i::Handle<i::Object> as_constant(Type* type) { | 430 static inline i::Handle<Type> from_union(i::Handle<Unioned> unioned); |
536 i::Box* box = i::Box::cast(type); | 431 static inline i::Handle<Unioned> union_create(int size, Isolate* isolate); |
537 return i::handle(box->value(), box->GetIsolate()); | 432 static inline void union_shrink(i::Handle<Unioned> unioned, int size); |
538 } | 433 static inline i::Handle<Type> union_get(i::Handle<Unioned> unioned, int i); |
539 static i::Handle<Unioned> as_union(Type* type) { | 434 static inline void union_set( |
540 return i::handle(i::FixedArray::cast(type)); | 435 i::Handle<Unioned> unioned, int i, i::Handle<Type> type); |
541 } | 436 static inline int union_length(i::Handle<Unioned> unioned); |
542 | 437 static inline int lub_bitset(Type* type); |
543 static Type* from_bitset(int bitset) { | |
544 return Type::cast(i::Smi::FromInt(bitset)); | |
545 } | |
546 static i::Handle<Type> from_bitset(int bitset, Isolate* isolate) { | |
547 return i::handle(from_bitset(bitset), isolate); | |
548 } | |
549 static i::Handle<Type> from_class( | |
550 i::Handle<i::Map> map, int lub, Isolate* isolate) { | |
551 return i::Handle<Type>::cast(i::Handle<Object>::cast(map)); | |
552 } | |
553 static i::Handle<Type> from_constant( | |
554 i::Handle<i::Object> value, int lub, Isolate* isolate) { | |
555 i::Handle<Box> box = isolate->factory()->NewBox(value); | |
556 return i::Handle<Type>::cast(i::Handle<Object>::cast(box)); | |
557 } | |
558 static i::Handle<Type> from_union(i::Handle<Unioned> unioned) { | |
559 return i::Handle<Type>::cast(i::Handle<Object>::cast(unioned)); | |
560 } | |
561 | |
562 static i::Handle<Unioned> union_create(int size, Isolate* isolate) { | |
563 return isolate->factory()->NewFixedArray(size); | |
564 } | |
565 static void union_shrink(i::Handle<Unioned> unioned, int size) { | |
566 unioned->Shrink(size); | |
567 } | |
568 static i::Handle<Type> union_get(i::Handle<Unioned> unioned, int i) { | |
569 Type* type = static_cast<Type*>(unioned->get(i)); | |
570 ASSERT(!is_union(type)); | |
571 return i::handle(type, unioned->GetIsolate()); | |
572 } | |
573 static void union_set( | |
574 i::Handle<Unioned> unioned, int i, i::Handle<Type> type) { | |
575 ASSERT(!is_union(*type)); | |
576 unioned->set(i, *type); | |
577 } | |
578 static int union_length(i::Handle<Unioned> unioned) { | |
579 return unioned->length(); | |
580 } | |
581 static int lub_bitset(Type* type) { | |
582 return 0; // kNone, which causes recomputation. | |
583 } | |
584 }; | 438 }; |
585 | 439 |
586 typedef TypeImpl<ZoneTypeConfig> Type; | 440 typedef TypeImpl<ZoneTypeConfig> Type; |
587 typedef TypeImpl<HeapTypeConfig> HeapType; | 441 typedef TypeImpl<HeapTypeConfig> HeapType; |
588 | 442 |
589 | 443 |
590 // A simple struct to represent a pair of lower/upper type bounds. | 444 // A simple struct to represent a pair of lower/upper type bounds. |
591 template<class Config> | 445 template<class Config> |
592 struct BoundsImpl { | 446 struct BoundsImpl { |
593 typedef TypeImpl<Config> Type; | 447 typedef TypeImpl<Config> Type; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 return BoundsImpl(lower, upper); | 490 return BoundsImpl(lower, upper); |
637 } | 491 } |
638 | 492 |
639 bool Narrows(BoundsImpl that) { | 493 bool Narrows(BoundsImpl that) { |
640 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 494 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
641 } | 495 } |
642 }; | 496 }; |
643 | 497 |
644 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 498 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
645 | 499 |
646 | |
647 } } // namespace v8::internal | 500 } } // namespace v8::internal |
648 | 501 |
649 #endif // V8_TYPES_H_ | 502 #endif // V8_TYPES_H_ |
OLD | NEW |