Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(92)

Side by Side Diff: runtime/vm/object.cc

Issue 8773026: Canonicalize TypeArguments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_store.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/assert.h" 8 #include "vm/assert.h"
9 #include "vm/bigint_operations.h" 9 #include "vm/bigint_operations.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 // has been created. 384 // has been created.
385 cls.InitEmptyFields(); 385 cls.InitEmptyFields();
386 386
387 // Setup the symbol table used within the String class. 387 // Setup the symbol table used within the String class.
388 const int kInitialSymbolTableSize = 16; 388 const int kInitialSymbolTableSize = 16;
389 array = Array::New(kInitialSymbolTableSize + 1); 389 array = Array::New(kInitialSymbolTableSize + 1);
390 // Last element contains the count of used slots. 390 // Last element contains the count of used slots.
391 array.SetAt(kInitialSymbolTableSize, Smi::Handle(Smi::New(0))); 391 array.SetAt(kInitialSymbolTableSize, Smi::Handle(Smi::New(0)));
392 object_store->set_symbol_table(array); 392 object_store->set_symbol_table(array);
393 393
394 // canonical_type_arguments_ are NULL terminated.
395 array = Array::New(4);
396 object_store->set_canonical_type_arguments(array);
397
394 // Pre-allocate the OneByteString class needed by the symbol table. 398 // Pre-allocate the OneByteString class needed by the symbol table.
395 cls = Class::New<OneByteString>(); 399 cls = Class::New<OneByteString>();
396 object_store->set_one_byte_string_class(cls); 400 object_store->set_one_byte_string_class(cls);
397 401
398 // Basic infrastructure has been setup, initialize the class dictionary. 402 // Basic infrastructure has been setup, initialize the class dictionary.
399 Library::InitCoreLibrary(isolate); 403 Library::InitCoreLibrary(isolate);
400 Library& core_lib = Library::Handle(Library::CoreLibrary()); 404 Library& core_lib = Library::Handle(Library::CoreLibrary());
401 ASSERT(!core_lib.IsNull()); 405 ASSERT(!core_lib.IsNull());
402 Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary()); 406 Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
403 ASSERT(!core_impl_lib.IsNull()); 407 ASSERT(!core_impl_lib.IsNull());
(...skipping 1901 matching lines...) Expand 10 before | Expand all | Expand 10 after
2305 return chars; 2309 return chars;
2306 } 2310 }
2307 2311
2308 2312
2309 RawClass* InstantiatedType::type_class() const { 2313 RawClass* InstantiatedType::type_class() const {
2310 return AbstractType::Handle(uninstantiated_type()).type_class(); 2314 return AbstractType::Handle(uninstantiated_type()).type_class();
2311 } 2315 }
2312 2316
2313 2317
2314 RawAbstractTypeArguments* InstantiatedType::arguments() const { 2318 RawAbstractTypeArguments* InstantiatedType::arguments() const {
2315 return AbstractTypeArguments::NewInstantiatedTypeArguments( 2319 return InstantiatedTypeArguments::New(
2316 AbstractTypeArguments::Handle(AbstractType::Handle( 2320 AbstractTypeArguments::Handle(AbstractType::Handle(
2317 uninstantiated_type()).arguments()), 2321 uninstantiated_type()).arguments()),
2318 AbstractTypeArguments::Handle(instantiator_type_arguments())); 2322 AbstractTypeArguments::Handle(instantiator_type_arguments()));
2319 } 2323 }
2320 2324
2321 2325
2322 void InstantiatedType::set_uninstantiated_type( 2326 void InstantiatedType::set_uninstantiated_type(
2323 const AbstractType& value) const { 2327 const AbstractType& value) const {
2324 StorePointer(&raw_ptr()->uninstantiated_type_, value.raw()); 2328 StorePointer(&raw_ptr()->uninstantiated_type_, value.raw());
2325 } 2329 }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
2393 2397
2394 2398
2395 bool AbstractTypeArguments::IsUninstantiatedIdentity() const { 2399 bool AbstractTypeArguments::IsUninstantiatedIdentity() const {
2396 // AbstractTypeArguments is an abstract class. 2400 // AbstractTypeArguments is an abstract class.
2397 UNREACHABLE(); 2401 UNREACHABLE();
2398 return false; 2402 return false;
2399 } 2403 }
2400 2404
2401 2405
2402 bool AbstractTypeArguments::Equals(const AbstractTypeArguments& other) const { 2406 bool AbstractTypeArguments::Equals(const AbstractTypeArguments& other) const {
2403 // AbstractTypeArguments is an abstract class. 2407 if (this->raw() == other.raw()) {
2404 UNREACHABLE(); 2408 return true;
2405 return false; 2409 }
2410 intptr_t num_types = Length();
2411 if (num_types != other.Length()) {
2412 return false;
2413 }
2414 AbstractType& type = AbstractType::Handle();
2415 AbstractType& other_type = AbstractType::Handle();
2416 for (intptr_t i = 0; i < num_types; i++) {
2417 type = TypeAt(i);
2418 other_type = other.TypeAt(i);
2419 if (!type.Equals(other_type)) {
2420 return false;
2421 }
2422 }
2423 return true;
2406 } 2424 }
2407 2425
2408 2426
2409 bool AbstractTypeArguments::AreEqual( 2427 bool AbstractTypeArguments::AreEqual(
2410 const AbstractTypeArguments& arguments, 2428 const AbstractTypeArguments& arguments,
2411 const AbstractTypeArguments& other_arguments) { 2429 const AbstractTypeArguments& other_arguments) {
2412 if (arguments.raw() == other_arguments.raw()) { 2430 if (arguments.raw() == other_arguments.raw()) {
2413 return true; 2431 return true;
2414 } 2432 }
2415 if (arguments.IsNull()) { 2433 if (arguments.IsNull()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2465 other_type = other.TypeAt(i); 2483 other_type = other.TypeAt(i);
2466 ASSERT(!other_type.IsNull()); 2484 ASSERT(!other_type.IsNull());
2467 if (!type.IsMoreSpecificThan(other_type)) { 2485 if (!type.IsMoreSpecificThan(other_type)) {
2468 return false; 2486 return false;
2469 } 2487 }
2470 } 2488 }
2471 return true; 2489 return true;
2472 } 2490 }
2473 2491
2474 2492
2475 RawAbstractTypeArguments* AbstractTypeArguments::NewInstantiatedTypeArguments(
2476 const AbstractTypeArguments& uninstantiated_type_arguments,
2477 const AbstractTypeArguments& instantiator_type_arguments) {
2478 return InstantiatedTypeArguments::New(uninstantiated_type_arguments,
2479 instantiator_type_arguments);
2480 }
2481
2482
2483 const char* AbstractTypeArguments::ToCString() const { 2493 const char* AbstractTypeArguments::ToCString() const {
2484 // AbstractTypeArguments is an abstract class. 2494 // AbstractTypeArguments is an abstract class.
2485 UNREACHABLE(); 2495 UNREACHABLE();
2486 return "AbstractTypeArguments"; 2496 return "AbstractTypeArguments";
2487 } 2497 }
2488 2498
2489 2499
2490 intptr_t TypeArguments::Length() const { 2500 intptr_t TypeArguments::Length() const {
2491 ASSERT(!IsNull()); 2501 ASSERT(!IsNull());
2492 return Smi::Value(raw_ptr()->length_); 2502 return Smi::Value(raw_ptr()->length_);
2493 } 2503 }
2494 2504
2495 2505
2496 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const { 2506 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
2497 return *TypeAddr(index); 2507 return *TypeAddr(index);
2498 } 2508 }
2499 2509
2500 2510
2501 void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const { 2511 void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
2512 ASSERT(!is_canonical());
2502 // TODO(iposva): Add storing NoGCScope. 2513 // TODO(iposva): Add storing NoGCScope.
2503 *TypeAddr(index) = value.raw(); 2514 *TypeAddr(index) = value.raw();
2504 } 2515 }
2505 2516
2506 2517
2507 bool TypeArguments::IsResolved() const { 2518 bool TypeArguments::IsResolved() const {
2508 AbstractType& type = AbstractType::Handle(); 2519 AbstractType& type = AbstractType::Handle();
2509 intptr_t num_types = Length(); 2520 intptr_t num_types = Length();
2510 for (intptr_t i = 0; i < num_types; i++) { 2521 for (intptr_t i = 0; i < num_types; i++) {
2511 type = TypeAt(i); 2522 type = TypeAt(i);
2512 if (!type.IsResolved()) { 2523 if (!type.IsResolved()) {
2513 return false; 2524 return false;
2514 } 2525 }
2515 } 2526 }
2516 return true; 2527 return true;
2517 } 2528 }
2518 2529
2519 2530
2520 bool TypeArguments::IsInstantiated() const { 2531 bool TypeArguments::IsInstantiated() const {
2521 AbstractType& type = AbstractType::Handle(); 2532 AbstractType& type = AbstractType::Handle();
2522 intptr_t num_types = Length(); 2533 intptr_t num_types = Length();
2523 for (intptr_t i = 0; i < num_types; i++) { 2534 for (intptr_t i = 0; i < num_types; i++) {
2524 type = TypeAt(i); 2535 type = TypeAt(i);
2536 ASSERT(!type.IsNull());
2525 if (!type.IsInstantiated()) { 2537 if (!type.IsInstantiated()) {
2526 return false; 2538 return false;
2527 } 2539 }
2528 } 2540 }
2529 return true; 2541 return true;
2530 } 2542 }
2531 2543
2532 2544
2533 bool TypeArguments::IsUninstantiatedIdentity() const { 2545 bool TypeArguments::IsUninstantiatedIdentity() const {
2534 ASSERT(!IsInstantiated()); 2546 ASSERT(!IsInstantiated());
2535 AbstractType& type = AbstractType::Handle(); 2547 AbstractType& type = AbstractType::Handle();
2536 intptr_t num_types = Length(); 2548 intptr_t num_types = Length();
2537 for (intptr_t i = 0; i < num_types; i++) { 2549 for (intptr_t i = 0; i < num_types; i++) {
2538 type = TypeAt(i); 2550 type = TypeAt(i);
2539 if (!type.IsTypeParameter() || (type.Index() != i)) { 2551 if (!type.IsTypeParameter() || (type.Index() != i)) {
2540 return false; 2552 return false;
2541 } 2553 }
2542 } 2554 }
2543 return true; 2555 return true;
2544 } 2556 }
2545 2557
2546 2558
2547 bool TypeArguments::Equals(const AbstractTypeArguments& other) const {
2548 intptr_t num_types = Length();
2549 if (num_types != other.Length()) {
2550 return false;
2551 }
2552 AbstractType& type = AbstractType::Handle();
2553 AbstractType& other_type = AbstractType::Handle();
2554 for (intptr_t i = 0; i < num_types; i++) {
2555 type = TypeAt(i);
2556 other_type = other.TypeAt(i);
2557 if (!type.Equals(other_type)) {
2558 return false;
2559 }
2560 }
2561 return true;
2562 }
2563
2564
2565 RawAbstractTypeArguments* TypeArguments::InstantiateFrom( 2559 RawAbstractTypeArguments* TypeArguments::InstantiateFrom(
2566 const AbstractTypeArguments& instantiator_type_arguments, 2560 const AbstractTypeArguments& instantiator_type_arguments,
2567 intptr_t offset) const { 2561 intptr_t offset) const {
2568 ASSERT(!IsInstantiated()); 2562 ASSERT(!IsInstantiated());
2569 if ((offset == 0) && 2563 if ((offset == 0) &&
2570 !instantiator_type_arguments.IsNull() && 2564 !instantiator_type_arguments.IsNull() &&
2571 IsUninstantiatedIdentity() && 2565 IsUninstantiatedIdentity() &&
2572 (instantiator_type_arguments.Length() == Length())) { 2566 (instantiator_type_arguments.Length() == Length())) {
2573 return instantiator_type_arguments.raw(); 2567 return instantiator_type_arguments.raw();
2574 } 2568 }
(...skipping 21 matching lines...) Expand all
2596 2590
2597 const Class& type_arguments_class = 2591 const Class& type_arguments_class =
2598 Class::Handle(Object::type_arguments_class()); 2592 Class::Handle(Object::type_arguments_class());
2599 TypeArguments& result = TypeArguments::Handle(); 2593 TypeArguments& result = TypeArguments::Handle();
2600 { 2594 {
2601 RawObject* raw = Object::Allocate(type_arguments_class, 2595 RawObject* raw = Object::Allocate(type_arguments_class,
2602 TypeArguments::InstanceSize(len), 2596 TypeArguments::InstanceSize(len),
2603 Heap::kOld); 2597 Heap::kOld);
2604 NoGCScope no_gc; 2598 NoGCScope no_gc;
2605 result ^= raw; 2599 result ^= raw;
2600 result.set_is_canonical(false);
2601 // Length must be set before we start storing into the array.
2606 result.SetLength(len); 2602 result.SetLength(len);
2607 for (intptr_t i = 0; i < len; i++) { 2603 for (intptr_t i = 0; i < len; i++) {
2608 *result.TypeAddr(i) = Type::null(); 2604 *result.TypeAddr(i) = Type::null();
2609 } 2605 }
2610 } 2606 }
2611 return result.raw(); 2607 return result.raw();
2612 } 2608 }
2613 2609
2614 2610
2611
2615 RawAbstractType** TypeArguments::TypeAddr(intptr_t index) const { 2612 RawAbstractType** TypeArguments::TypeAddr(intptr_t index) const {
2616 // TODO(iposva): Determine if we should throw an exception here. 2613 // TODO(iposva): Determine if we should throw an exception here.
2617 ASSERT((index >= 0) && (index < Length())); 2614 ASSERT((index >= 0) && (index < Length()));
2618 return &raw_ptr()->types_[index]; 2615 return &raw_ptr()->types_[index];
2619 } 2616 }
2620 2617
2621 2618
2622 void TypeArguments::SetLength(intptr_t value) { 2619 void TypeArguments::SetLength(intptr_t value) {
2620 ASSERT(!is_canonical());
2623 // This is only safe because we create a new Smi, which does not cause 2621 // This is only safe because we create a new Smi, which does not cause
2624 // heap allocation. 2622 // heap allocation.
2625 raw_ptr()->length_ = Smi::New(value); 2623 raw_ptr()->length_ = Smi::New(value);
2626 } 2624 }
2627 2625
2628 2626
2627 RawAbstractTypeArguments* TypeArguments::Canonicalize() const {
2628 if (IsNull() || is_canonical() || !IsInstantiated()) {
2629 return this->raw();
2630 }
2631 ObjectStore* object_store = Isolate::Current()->object_store();
2632 // 'table' must be null terminated.
2633 Array& table = Array::Handle(object_store->canonical_type_arguments());
2634 ASSERT(table.Length() > 0);
2635 intptr_t index = 0;
2636 TypeArguments& other = TypeArguments::Handle();
2637 other ^= table.At(index);
2638 while (!other.IsNull()) {
2639 if (this->Equals(other)) {
2640 return other.raw();
2641 }
2642 other ^= table.At(++index);
2643 }
2644 // Not found. Add 'this' to table.
2645 if (index == table.Length() - 1) {
2646 table = Array::Grow(table, table.Length() + 4, Heap::kOld);
2647 object_store->set_canonical_type_arguments(table);
2648 }
2649 table.SetAt(index, *this);
2650 this->set_is_canonical(true);
2651 return this->raw();
2652 }
2653
2654
2655 bool TypeArguments::is_canonical() const {
2656 return raw_ptr()->is_canonical_;
2657 }
2658
2659
2660 void TypeArguments::set_is_canonical(bool value) const {
2661 raw_ptr()->is_canonical_ = value;
2662 }
2663
2664
2629 const char* TypeArguments::ToCString() const { 2665 const char* TypeArguments::ToCString() const {
2630 if (IsNull()) { 2666 if (IsNull()) {
2631 return "NULL TypeArguments"; 2667 return "NULL TypeArguments";
2632 } 2668 }
2633 const char* format = "%s [%s]"; 2669 const char* format = "%s [%s]";
2634 const char* prev_cstr = "TypeArguments:"; 2670 const char* prev_cstr = "TypeArguments:";
2635 for (int i = 0; i < Length(); i++) { 2671 for (int i = 0; i < Length(); i++) {
2636 const char* type_cstr = AbstractType::Handle(TypeAt(i)).ToCString(); 2672 const AbstractType& type_at = AbstractType::Handle(TypeAt(i));
2673 const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString();
2637 intptr_t len = OS::SNPrint(NULL, 0, format, prev_cstr, type_cstr) + 1; 2674 intptr_t len = OS::SNPrint(NULL, 0, format, prev_cstr, type_cstr) + 1;
2638 char* chars = reinterpret_cast<char*>( 2675 char* chars = reinterpret_cast<char*>(
2639 Isolate::Current()->current_zone()->Allocate(len)); 2676 Isolate::Current()->current_zone()->Allocate(len));
2640 OS::SNPrint(chars, len, format, prev_cstr, type_cstr); 2677 OS::SNPrint(chars, len, format, prev_cstr, type_cstr);
2641 prev_cstr = chars; 2678 prev_cstr = chars;
2642 } 2679 }
2643 return prev_cstr; 2680 return prev_cstr;
2644 } 2681 }
2645 2682
2646 2683
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2705 result.set_uninstantiated_type_arguments(uninstantiated_type_arguments); 2742 result.set_uninstantiated_type_arguments(uninstantiated_type_arguments);
2706 result.set_instantiator_type_arguments(instantiator_type_arguments); 2743 result.set_instantiator_type_arguments(instantiator_type_arguments);
2707 return result.raw(); 2744 return result.raw();
2708 } 2745 }
2709 2746
2710 2747
2711 const char* InstantiatedTypeArguments::ToCString() const { 2748 const char* InstantiatedTypeArguments::ToCString() const {
2712 if (IsNull()) { 2749 if (IsNull()) {
2713 return "NULL InstantiatedTypeArguments"; 2750 return "NULL InstantiatedTypeArguments";
2714 } 2751 }
2715 const char* format = "InstantiatedTypeArguments: [%s] instantiator: [%s]\n"; 2752 const char* format = "InstantiatedTypeArguments: [%s] instantiator: [%s]";
2716 const char* arg_cstr = 2753 const char* arg_cstr =
2717 AbstractTypeArguments::Handle( 2754 AbstractTypeArguments::Handle(
2718 uninstantiated_type_arguments()).ToCString(); 2755 uninstantiated_type_arguments()).ToCString();
2719 const char* instantiator_cstr = 2756 const char* instantiator_cstr =
2720 AbstractTypeArguments::Handle(instantiator_type_arguments()).ToCString(); 2757 AbstractTypeArguments::Handle(instantiator_type_arguments()).ToCString();
2721 intptr_t len = 2758 intptr_t len =
2722 OS::SNPrint(NULL, 0, format, arg_cstr, instantiator_cstr) + 1; 2759 OS::SNPrint(NULL, 0, format, arg_cstr, instantiator_cstr) + 1;
2723 char* chars = reinterpret_cast<char*>( 2760 char* chars = reinterpret_cast<char*>(
2724 Isolate::Current()->current_zone()->Allocate(len)); 2761 Isolate::Current()->current_zone()->Allocate(len));
2725 OS::SNPrint(chars, len, format, arg_cstr, instantiator_cstr); 2762 OS::SNPrint(chars, len, format, arg_cstr, instantiator_cstr);
(...skipping 2304 matching lines...) Expand 10 before | Expand all | Expand 10 after
5030 AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(); 5067 AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
5031 type_arguments ^= *FieldAddrAtOffset(field_offset); 5068 type_arguments ^= *FieldAddrAtOffset(field_offset);
5032 return type_arguments.raw(); 5069 return type_arguments.raw();
5033 } 5070 }
5034 5071
5035 5072
5036 void Instance::SetTypeArguments(const AbstractTypeArguments& value) const { 5073 void Instance::SetTypeArguments(const AbstractTypeArguments& value) const {
5037 const Class& cls = Class::Handle(clazz()); 5074 const Class& cls = Class::Handle(clazz());
5038 intptr_t field_offset = cls.type_arguments_instance_field_offset(); 5075 intptr_t field_offset = cls.type_arguments_instance_field_offset();
5039 ASSERT(field_offset != Class::kNoTypeArguments); 5076 ASSERT(field_offset != Class::kNoTypeArguments);
5040 *FieldAddrAtOffset(field_offset) = value.raw(); 5077 *FieldAddrAtOffset(field_offset) = value.Canonicalize();
5041 } 5078 }
5042 5079
5043 5080
5044 bool Instance::TestType(TypeTestKind test, 5081 bool Instance::TestType(TypeTestKind test,
5045 const AbstractType& other, 5082 const AbstractType& other,
5046 const AbstractTypeArguments& other_instantiator) const { 5083 const AbstractTypeArguments& other_instantiator) const {
5047 ASSERT(other.IsFinalized()); 5084 ASSERT(other.IsFinalized());
5048 ASSERT(!other.IsDynamicType()); 5085 ASSERT(!other.IsDynamicType());
5049 ASSERT(!other.IsVoidType()); 5086 ASSERT(!other.IsVoidType());
5050 if (IsNull()) { 5087 if (IsNull()) {
(...skipping 2232 matching lines...) Expand 10 before | Expand all | Expand 10 after
7283 const String& str = String::Handle(pattern()); 7320 const String& str = String::Handle(pattern());
7284 const char* format = "JSRegExp: pattern=%s flags=%s"; 7321 const char* format = "JSRegExp: pattern=%s flags=%s";
7285 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); 7322 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
7286 char* chars = reinterpret_cast<char*>( 7323 char* chars = reinterpret_cast<char*>(
7287 Isolate::Current()->current_zone()->Allocate(len + 1)); 7324 Isolate::Current()->current_zone()->Allocate(len + 1));
7288 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); 7325 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
7289 return chars; 7326 return chars;
7290 } 7327 }
7291 7328
7292 } // namespace dart 7329 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_store.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698