Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 } else if (this->IsClass()) { | 143 } else if (this->IsClass()) { |
| 144 return LubBitset(*this->AsClass()); | 144 return LubBitset(*this->AsClass()); |
| 145 } else { | 145 } else { |
| 146 return LubBitset(*this->AsConstant()); | 146 return LubBitset(*this->AsConstant()); |
| 147 } | 147 } |
| 148 } | 148 } |
| 149 | 149 |
| 150 | 150 |
| 151 template<class Config> | 151 template<class Config> |
| 152 int TypeImpl<Config>::LubBitset(i::Object* value) { | 152 int TypeImpl<Config>::LubBitset(i::Object* value) { |
| 153 if (value->IsSmi()) return kSmi; | 153 if (value->IsSmi()) return kSignedSmall & kTaggedInt; |
| 154 i::Map* map = i::HeapObject::cast(value)->map(); | 154 i::Map* map = i::HeapObject::cast(value)->map(); |
| 155 if (map->instance_type() == HEAP_NUMBER_TYPE) { | 155 if (map->instance_type() == HEAP_NUMBER_TYPE) { |
| 156 int32_t i; | 156 int32_t i; |
| 157 uint32_t u; | 157 uint32_t u; |
| 158 if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32; | 158 return kTaggedPtr & ( |
|
Michael Starzinger
2014/03/04 11:59:58
High-level comment: This assumes HeapNumber object
rossberg
2014/03/04 13:53:11
Good point. As discussed off-line, I think we shou
| |
| 159 if (value->ToUint32(&u)) return kUnsigned32; | 159 value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) : |
| 160 return kDouble; | 160 value->ToUint32(&u) ? kUnsigned32 : kFloat); |
| 161 } | 161 } |
| 162 if (map->instance_type() == ODDBALL_TYPE) { | 162 if (map->instance_type() == ODDBALL_TYPE) { |
| 163 if (value->IsUndefined()) return kUndefined; | 163 if (value->IsUndefined()) return kUndefined; |
| 164 if (value->IsNull()) return kNull; | 164 if (value->IsNull()) return kNull; |
| 165 if (value->IsBoolean()) return kBoolean; | 165 if (value->IsBoolean()) return kBoolean; |
| 166 if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone? | 166 if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone? |
| 167 if (value->IsUninitialized()) return kNone; | 167 if (value->IsUninitialized()) return kNone; |
| 168 UNREACHABLE(); | 168 UNREACHABLE(); |
| 169 } | 169 } |
| 170 return LubBitset(map); | 170 return LubBitset(map); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 195 case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: | 195 case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: |
| 196 case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: | 196 case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE: |
| 197 case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE: | 197 case SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE: |
| 198 case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: | 198 case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE: |
| 199 return kString; | 199 return kString; |
| 200 case SYMBOL_TYPE: | 200 case SYMBOL_TYPE: |
| 201 return kSymbol; | 201 return kSymbol; |
| 202 case ODDBALL_TYPE: | 202 case ODDBALL_TYPE: |
| 203 return kOddball; | 203 return kOddball; |
| 204 case HEAP_NUMBER_TYPE: | 204 case HEAP_NUMBER_TYPE: |
| 205 return kDouble; | 205 return kFloat & kTaggedPtr; |
| 206 case JS_VALUE_TYPE: | 206 case JS_VALUE_TYPE: |
| 207 case JS_DATE_TYPE: | 207 case JS_DATE_TYPE: |
| 208 case JS_OBJECT_TYPE: | 208 case JS_OBJECT_TYPE: |
| 209 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 209 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 210 case JS_GENERATOR_OBJECT_TYPE: | 210 case JS_GENERATOR_OBJECT_TYPE: |
| 211 case JS_MODULE_TYPE: | 211 case JS_MODULE_TYPE: |
| 212 case JS_GLOBAL_OBJECT_TYPE: | 212 case JS_GLOBAL_OBJECT_TYPE: |
| 213 case JS_BUILTINS_OBJECT_TYPE: | 213 case JS_BUILTINS_OBJECT_TYPE: |
| 214 case JS_GLOBAL_PROXY_TYPE: | 214 case JS_GLOBAL_PROXY_TYPE: |
| 215 case JS_ARRAY_BUFFER_TYPE: | 215 case JS_ARRAY_BUFFER_TYPE: |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 238 // we must exclude Undetectable here. This makes no sense, really, | 238 // we must exclude Undetectable here. This makes no sense, really, |
| 239 // because it means that the template isn't actually parametric. | 239 // because it means that the template isn't actually parametric. |
| 240 // Also, it doesn't apply elsewhere. 8-( | 240 // Also, it doesn't apply elsewhere. 8-( |
| 241 // We ought to find a cleaner solution for compiling stubs parameterised | 241 // We ought to find a cleaner solution for compiling stubs parameterised |
| 242 // over type or class variables, esp ones with bounds... | 242 // over type or class variables, esp ones with bounds... |
| 243 return kDetectable; | 243 return kDetectable; |
| 244 case DECLARED_ACCESSOR_INFO_TYPE: | 244 case DECLARED_ACCESSOR_INFO_TYPE: |
| 245 case EXECUTABLE_ACCESSOR_INFO_TYPE: | 245 case EXECUTABLE_ACCESSOR_INFO_TYPE: |
| 246 case ACCESSOR_PAIR_TYPE: | 246 case ACCESSOR_PAIR_TYPE: |
| 247 case FIXED_ARRAY_TYPE: | 247 case FIXED_ARRAY_TYPE: |
| 248 return kInternal; | 248 return kInternal & kTaggedPtr; |
| 249 default: | 249 default: |
| 250 UNREACHABLE(); | 250 UNREACHABLE(); |
| 251 return kNone; | 251 return kNone; |
| 252 } | 252 } |
| 253 } | 253 } |
| 254 | 254 |
| 255 | 255 |
| 256 // Get the largest bitset subsumed by this type. | 256 // Get the largest bitset subsumed by this type. |
| 257 template<class Config> | 257 template<class Config> |
| 258 int TypeImpl<Config>::GlbBitset() { | 258 int TypeImpl<Config>::GlbBitset() { |
| 259 if (this->IsBitset()) { | 259 if (this->IsBitset()) { |
| 260 return this->AsBitset(); | 260 return this->AsBitset(); |
| 261 } else if (this->IsUnion()) { | 261 } else if (this->IsUnion()) { |
| 262 // All but the first are non-bitsets and thus would yield kNone anyway. | 262 // All but the first are non-bitsets and thus would yield kNone anyway. |
| 263 return Config::union_get(this->AsUnion(), 0)->GlbBitset(); | 263 return Config::union_get(this->AsUnion(), 0)->GlbBitset(); |
| 264 } else { | 264 } else { |
| 265 return kNone; | 265 return kNone; |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 | 269 |
| 270 // Most precise _current_ type of a value (usually its class). | 270 // Most precise _current_ type of a value (usually its class). |
| 271 template<class Config> | 271 template<class Config> |
| 272 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently( | 272 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently( |
| 273 i::Handle<i::Object> value, Region* region) { | 273 i::Handle<i::Object> value, Region* region) { |
| 274 if (value->IsSmi()) return Smi(region); | 274 if (value->IsSmi()) return SignedSmall(region); |
|
Michael Starzinger
2014/03/04 11:59:58
Shouldn't this be tagged?
rossberg
2014/03/04 13:53:11
Good catch.
| |
| 275 i::Map* map = i::HeapObject::cast(*value)->map(); | 275 i::Map* map = i::HeapObject::cast(*value)->map(); |
| 276 if (map->instance_type() == HEAP_NUMBER_TYPE || | 276 if (map->instance_type() == HEAP_NUMBER_TYPE || |
| 277 map->instance_type() == ODDBALL_TYPE) { | 277 map->instance_type() == ODDBALL_TYPE) { |
| 278 return Of(value, region); | 278 return Of(value, region); |
| 279 } | 279 } |
| 280 return Class(i::handle(map), region); | 280 return Class(i::handle(map), region); |
| 281 } | 281 } |
| 282 | 282 |
| 283 | 283 |
| 284 // Check this <= that. | 284 // Check this <= that. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 this->AsConstant()->IsHeapObject() && | 331 this->AsConstant()->IsHeapObject() && |
| 332 i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass()); | 332 i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass()); |
| 333 } | 333 } |
| 334 | 334 |
| 335 | 335 |
| 336 // Check this overlaps that. | 336 // Check this overlaps that. |
| 337 template<class Config> | 337 template<class Config> |
| 338 bool TypeImpl<Config>::Maybe(TypeImpl* that) { | 338 bool TypeImpl<Config>::Maybe(TypeImpl* that) { |
| 339 // Fast path for bitsets. | 339 // Fast path for bitsets. |
| 340 if (this->IsBitset()) { | 340 if (this->IsBitset()) { |
| 341 return (this->AsBitset() & that->LubBitset()) != 0; | 341 return IsInhabited(this->AsBitset() & that->LubBitset()); |
| 342 } | 342 } |
| 343 if (that->IsBitset()) { | 343 if (that->IsBitset()) { |
| 344 return (this->LubBitset() & that->AsBitset()) != 0; | 344 return IsInhabited(this->LubBitset() & that->AsBitset()); |
| 345 } | 345 } |
| 346 | 346 |
| 347 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) | 347 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) |
| 348 if (this->IsUnion()) { | 348 if (this->IsUnion()) { |
| 349 UnionedHandle unioned = this->AsUnion(); | 349 UnionedHandle unioned = this->AsUnion(); |
| 350 for (int i = 0; i < Config::union_length(unioned); ++i) { | 350 for (int i = 0; i < Config::union_length(unioned); ++i) { |
| 351 TypeHandle this_i = Config::union_get(unioned, i); | 351 TypeHandle this_i = Config::union_get(unioned, i); |
| 352 if (this_i->Maybe(that)) return true; | 352 if (this_i->Maybe(that)) return true; |
| 353 } | 353 } |
| 354 return false; | 354 return false; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 561 Convert<OtherType>(OtherType::UnionGet(unioned, i), region)); | 561 Convert<OtherType>(OtherType::UnionGet(unioned, i), region)); |
| 562 } | 562 } |
| 563 return Config::from_union(new_unioned); | 563 return Config::from_union(new_unioned); |
| 564 } | 564 } |
| 565 } | 565 } |
| 566 | 566 |
| 567 | 567 |
| 568 // TODO(rossberg): this does not belong here. | 568 // TODO(rossberg): this does not belong here. |
| 569 Representation Representation::FromType(Type* type) { | 569 Representation Representation::FromType(Type* type) { |
| 570 if (type->Is(Type::None())) return Representation::None(); | 570 if (type->Is(Type::None())) return Representation::None(); |
| 571 if (type->Is(Type::Smi())) return Representation::Smi(); | 571 if (type->Is(Type::SignedSmall())) return Representation::Smi(); |
| 572 if (type->Is(Type::Signed32())) return Representation::Integer32(); | 572 if (type->Is(Type::Signed32())) return Representation::Integer32(); |
| 573 if (type->Is(Type::Number())) return Representation::Double(); | 573 if (type->Is(Type::Number())) return Representation::Double(); |
| 574 return Representation::Tagged(); | 574 return Representation::Tagged(); |
| 575 } | 575 } |
| 576 | 576 |
| 577 | 577 |
| 578 #ifdef OBJECT_PRINT | 578 #ifdef OBJECT_PRINT |
| 579 template<class Config> | 579 template<class Config> |
| 580 void TypeImpl<Config>::TypePrint() { | 580 void TypeImpl<Config>::TypePrint(PrintDim dim) { |
| 581 TypePrint(stdout); | 581 TypePrint(stdout, dim); |
| 582 PrintF(stdout, "\n"); | 582 PrintF(stdout, "\n"); |
| 583 Flush(stdout); | 583 Flush(stdout); |
| 584 } | 584 } |
| 585 | 585 |
| 586 | 586 |
| 587 template<class Config> | 587 template<class Config> |
| 588 const char* TypeImpl<Config>::bitset_name(int bitset) { | 588 const char* TypeImpl<Config>::bitset_name(int bitset) { |
| 589 switch (bitset) { | 589 switch (bitset) { |
| 590 #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type; | 590 #define PRINT_COMPOSED_TYPE(type, value) \ |
| 591 BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) | 591 case k##type & kSemantic: return #type; |
| 592 SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) | |
| 592 #undef PRINT_COMPOSED_TYPE | 593 #undef PRINT_COMPOSED_TYPE |
| 594 | |
| 595 #define PRINT_COMPOSED_TYPE(type, value) \ | |
| 596 case k##type & kRepresentation: return #type; | |
| 597 REPRESENTATION_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) | |
| 598 #undef PRINT_COMPOSED_TYPE | |
| 599 | |
| 593 default: | 600 default: |
| 594 return NULL; | 601 return NULL; |
| 595 } | 602 } |
| 596 } | 603 } |
| 597 | 604 |
| 598 | 605 |
| 599 template<class Config> | 606 template<class Config> |
| 600 void TypeImpl<Config>::TypePrint(FILE* out) { | 607 void TypeImpl<Config>::BitsetTypePrint(FILE* out, int bitset) { |
| 608 const char* name = bitset_name(bitset); | |
| 609 if (name != NULL) { | |
| 610 PrintF(out, "%s", name); | |
| 611 } else { | |
| 612 static const int named_bitsets[] = { | |
| 613 #define BITSET_CONSTANT(type, value) k##type & kSemantic, | |
| 614 SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT) | |
| 615 #undef BITSET_CONSTANT | |
| 616 | |
| 617 #define BITSET_CONSTANT(type, value) k##type & kRepresentation, | |
| 618 REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT) | |
| 619 #undef BITSET_CONSTANT | |
| 620 }; | |
| 621 | |
| 622 bool is_first = true; | |
| 623 PrintF(out, "("); | |
| 624 for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) { | |
| 625 int subset = named_bitsets[i]; | |
| 626 if ((bitset & subset) == subset) { | |
| 627 if (!is_first) PrintF(out, " | "); | |
| 628 is_first = false; | |
| 629 PrintF(out, "%s", bitset_name(subset)); | |
| 630 bitset -= subset; | |
| 631 } | |
| 632 } | |
| 633 ASSERT(bitset == 0); | |
| 634 PrintF(out, ")"); | |
| 635 } | |
| 636 } | |
| 637 | |
| 638 | |
| 639 template<class Config> | |
| 640 void TypeImpl<Config>::TypePrint(FILE* out, PrintDim dim) { | |
| 601 if (this->IsBitset()) { | 641 if (this->IsBitset()) { |
| 602 int bitset = this->AsBitset(); | 642 int bitset = this->AsBitset(); |
| 603 const char* name = bitset_name(bitset); | 643 switch (dim) { |
| 604 if (name != NULL) { | 644 case BOTH_DIMS: |
| 605 PrintF(out, "%s", name); | 645 BitsetTypePrint(out, bitset & kSemantic); |
| 606 } else { | 646 PrintF("/"); |
| 607 bool is_first = true; | 647 BitsetTypePrint(out, bitset & kRepresentation); |
| 608 PrintF(out, "("); | 648 break; |
| 609 for (int mask = 1; mask != 0; mask = mask << 1) { | 649 case SEMANTIC_DIM: |
| 610 if ((bitset & mask) != 0) { | 650 BitsetTypePrint(out, bitset & kSemantic); |
| 611 if (!is_first) PrintF(out, " | "); | 651 break; |
| 612 is_first = false; | 652 case REPRESENTATION_DIM: |
| 613 PrintF(out, "%s", bitset_name(mask)); | 653 BitsetTypePrint(out, bitset & kRepresentation); |
| 614 } | 654 break; |
| 615 } | |
| 616 PrintF(out, ")"); | |
| 617 } | 655 } |
| 618 } else if (this->IsConstant()) { | 656 } else if (this->IsConstant()) { |
| 619 PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant())); | 657 PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant())); |
| 620 Config::from_bitset(this->LubBitset())->TypePrint(out); | 658 Config::from_bitset(this->LubBitset())->TypePrint(out); |
| 621 PrintF(")"); | 659 PrintF(")"); |
| 622 } else if (this->IsClass()) { | 660 } else if (this->IsClass()) { |
| 623 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass())); | 661 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass())); |
| 624 Config::from_bitset(this->LubBitset())->TypePrint(out); | 662 Config::from_bitset(this->LubBitset())->TypePrint(out); |
| 625 PrintF(")"); | 663 PrintF(")"); |
| 626 } else if (this->IsUnion()) { | 664 } else if (this->IsUnion()) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 647 | 685 |
| 648 template TypeImpl<ZoneTypeConfig>::TypeHandle | 686 template TypeImpl<ZoneTypeConfig>::TypeHandle |
| 649 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 687 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
| 650 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 688 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
| 651 template TypeImpl<HeapTypeConfig>::TypeHandle | 689 template TypeImpl<HeapTypeConfig>::TypeHandle |
| 652 TypeImpl<HeapTypeConfig>::Convert<Type>( | 690 TypeImpl<HeapTypeConfig>::Convert<Type>( |
| 653 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 691 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
| 654 | 692 |
| 655 | 693 |
| 656 } } // namespace v8::internal | 694 } } // namespace v8::internal |
| OLD | NEW |