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

Side by Side Diff: vm/object.cc

Issue 11360114: - Add functionality to morph a string into an external string (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 1 month 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 // pre-allocated in the vm isolate also. 467 // pre-allocated in the vm isolate also.
468 cls = Dart::vm_isolate()->object_store()->array_class(); 468 cls = Dart::vm_isolate()->object_store()->array_class();
469 str = Symbols::ObjectArray(); 469 str = Symbols::ObjectArray();
470 cls.set_name(str); 470 cls.set_name(str);
471 cls = Dart::vm_isolate()->object_store()->one_byte_string_class(); 471 cls = Dart::vm_isolate()->object_store()->one_byte_string_class();
472 str = Symbols::OneByteString(); 472 str = Symbols::OneByteString();
473 cls.set_name(str); 473 cls.set_name(str);
474 } 474 }
475 475
476 476
477 // Make unused space in an object whose type has been transformed safe
478 // for traversing during GC.
479 // The unused part of the transformed object is marked as an Array
480 // object or a regular Object so that it can be traversed during garbage
481 // collection.
482 void Object::MakeUnusedSpaceTraversable(const Object& obj,
483 intptr_t original_size,
484 intptr_t used_size) {
485 ASSERT(Isolate::Current()->no_gc_scope_depth() > 0);
486 ASSERT(!obj.IsNull());
Ivan Posva 2012/11/15 06:17:15 ASSERT(original_size >= used_size);
siva 2012/11/15 21:34:13 Done.
487 if (original_size > used_size) {
488 intptr_t leftover_size = original_size - used_size;
489
490 uword addr = RawObject::ToAddr(obj.raw()) + used_size;
491 if (leftover_size >= Array::InstanceSize(0)) {
492 // As we have enough space to use an array object, update the leftover
493 // space as an Array object.
494 RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
495 uword tags = 0;
496 tags = RawObject::SizeTag::update(leftover_size, tags);
497 tags = RawObject::ClassIdTag::update(kArrayCid, tags);
498 raw->ptr()->tags_ = tags;
499 intptr_t leftover_len =
500 ((leftover_size - Array::InstanceSize(0)) / kWordSize);
Ivan Posva 2012/11/15 06:17:15 ASSERT(Array::InstanceSize(leftover_len) == leftov
siva 2012/11/15 21:34:13 Done.
501 raw->ptr()->tags_ = tags;
502 raw->ptr()->length_ = Smi::New(leftover_len);
503 } else {
504 // Update the leftover space as a basic object.
505 ASSERT(leftover_size == Object::InstanceSize());
506 RawObject* raw =
507 reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
508 uword tags = 0;
509 tags = RawObject::SizeTag::update(leftover_size, tags);
510 tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
511 raw->ptr()->tags_ = tags;
512 }
513 }
514 }
515
516
477 RawClass* Object::CreateAndRegisterInterface(const char* cname, 517 RawClass* Object::CreateAndRegisterInterface(const char* cname,
478 const Script& script, 518 const Script& script,
479 const Library& lib) { 519 const Library& lib) {
480 const String& name = String::Handle(Symbols::New(cname)); 520 const String& name = String::Handle(Symbols::New(cname));
481 const Class& cls = Class::Handle( 521 const Class& cls = Class::Handle(
482 Class::NewInterface(name, script, Scanner::kDummyTokenIndex)); 522 Class::NewInterface(name, script, Scanner::kDummyTokenIndex));
483 lib.AddClass(cls); 523 lib.AddClass(cls);
484 return cls.raw(); 524 return cls.raw();
485 } 525 }
486 526
(...skipping 9890 matching lines...) Expand 10 before | Expand all | Expand 10 after
10377 if (obj.Length() > 0) { 10417 if (obj.Length() > 0) {
10378 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length()); 10418 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length());
10379 } 10419 }
10380 } else { 10420 } else {
10381 ASSERT(array_len >= Utf8::Length(*this)); 10421 ASSERT(array_len >= Utf8::Length(*this));
10382 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); 10422 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
10383 } 10423 }
10384 } 10424 }
10385 10425
10386 10426
10427 static void AddFinalizer(const Object& referent,
10428 void* peer,
10429 Dart_WeakPersistentHandleFinalizer callback) {
10430 ASSERT(callback != NULL);
10431 ApiState* state = Isolate::Current()->api_state();
10432 ASSERT(state != NULL);
10433 FinalizablePersistentHandle* weak_ref =
10434 state->weak_persistent_handles().AllocateHandle();
10435 weak_ref->set_raw(referent);
10436 weak_ref->set_peer(peer);
10437 weak_ref->set_callback(callback);
10438 }
10439
10440
10441 RawString* String::MakeExternal(void* array,
10442 intptr_t length,
10443 void* peer,
10444 Dart_PeerFinalizer cback) const {
10445 ASSERT(array != NULL);
10446 intptr_t str_length = this->Length();
10447 ASSERT(length >= (str_length * this->CharSize()));
10448 intptr_t class_id = raw()->GetClassId();
10449 intptr_t used_size = 0;
10450 intptr_t original_size = 0;
10451 uword tags = 0;
10452 NoGCScope no_gc;
10453
10454 if (class_id == kOneByteStringCid) {
10455 used_size = ExternalOneByteString::InstanceSize();
10456 original_size = OneByteString::InstanceSize(str_length);
10457 ASSERT(original_size >= used_size);
10458
10459 // Copy the data into the external array.
10460 if (str_length > 0) {
10461 memmove(array, OneByteString::CharAddr(*this, 0), str_length);
10462 }
10463
10464 // Update the class information of the object.
10465 const intptr_t class_id = kExternalOneByteStringCid;
10466 tags = RawObject::SizeTag::update(used_size, tags);
10467 tags = RawObject::ClassIdTag::update(class_id, tags);
10468 raw_ptr()->tags_ = tags;
10469 const String& result = String::Handle(this->raw());
10470 ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
10471 reinterpret_cast<const uint8_t*>(array), peer, cback);
10472 result.SetLength(str_length);
10473 result.SetHash(0);
10474 ExternalOneByteString::SetExternalData(result, ext_data);
10475 AddFinalizer(result, ext_data, ExternalOneByteString::Finalize);
10476 } else {
10477 ASSERT(class_id == kTwoByteStringCid);
10478 used_size = ExternalTwoByteString::InstanceSize();
10479 original_size = TwoByteString::InstanceSize(str_length);
10480 ASSERT(original_size >= used_size);
10481
10482 // Copy the data into the external array.
10483 if (str_length > 0) {
10484 memmove(array,
10485 TwoByteString::CharAddr(*this, 0),
10486 (str_length * kTwoByteChar));
10487 }
10488
10489 // Update the class information of the object.
10490 const intptr_t class_id = kExternalTwoByteStringCid;
10491 tags = RawObject::SizeTag::update(used_size, tags);
10492 tags = RawObject::ClassIdTag::update(class_id, tags);
10493 raw_ptr()->tags_ = tags;
10494 const String& result = String::Handle(this->raw());
10495 ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
10496 reinterpret_cast<const uint16_t*>(array), peer, cback);
10497 result.SetLength(str_length);
10498 result.SetHash(0);
10499 ExternalTwoByteString::SetExternalData(result, ext_data);
10500 AddFinalizer(result, ext_data, ExternalTwoByteString::Finalize);
10501 }
10502
10503 // If there is any left over space fill it with either an Array object or
10504 // just a plain object (depending on the amount of left over space) so
10505 // that it can be traversed over successfully during garbage collection.
10506 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
10507
10508 return this->raw();
10509 }
10510
10511
10387 RawString* String::Transform(int32_t (*mapping)(int32_t ch), 10512 RawString* String::Transform(int32_t (*mapping)(int32_t ch),
10388 const String& str, 10513 const String& str,
10389 Heap::Space space) { 10514 Heap::Space space) {
10390 ASSERT(!str.IsNull()); 10515 ASSERT(!str.IsNull());
10391 bool has_mapping = false; 10516 bool has_mapping = false;
10392 int32_t dst_max = 0; 10517 int32_t dst_max = 0;
10393 intptr_t len = str.Length(); 10518 intptr_t len = str.Length();
10394 // TODO(cshapiro): assume a transform is required, rollback if not. 10519 // TODO(cshapiro): assume a transform is required, rollback if not.
10395 for (intptr_t i = 0; i < len; ++i) { 10520 for (intptr_t i = 0; i < len; ++i) {
10396 int32_t src = str.CharAt(i); 10521 int32_t src = str.CharAt(i);
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
10767 const String& result = String::Handle(TwoByteString::New(len, space)); 10892 const String& result = String::Handle(TwoByteString::New(len, space));
10768 for (intptr_t i = 0; i < len; ++i) { 10893 for (intptr_t i = 0; i < len; ++i) {
10769 int32_t ch = mapping(str.CharAt(i)); 10894 int32_t ch = mapping(str.CharAt(i));
10770 ASSERT(ch >= 0 && ch <= 0xFFFF); 10895 ASSERT(ch >= 0 && ch <= 0xFFFF);
10771 *CharAddr(result, i) = ch; 10896 *CharAddr(result, i) = ch;
10772 } 10897 }
10773 return TwoByteString::raw(result); 10898 return TwoByteString::raw(result);
10774 } 10899 }
10775 10900
10776 10901
10777 static void AddFinalizer(const Object& referent,
10778 void* peer,
10779 Dart_WeakPersistentHandleFinalizer callback) {
10780 ASSERT(callback != NULL);
10781 ApiState* state = Isolate::Current()->api_state();
10782 ASSERT(state != NULL);
10783 FinalizablePersistentHandle* weak_ref =
10784 state->weak_persistent_handles().AllocateHandle();
10785 weak_ref->set_raw(referent);
10786 weak_ref->set_peer(peer);
10787 weak_ref->set_callback(callback);
10788 }
10789
10790
10791 RawExternalOneByteString* ExternalOneByteString::New( 10902 RawExternalOneByteString* ExternalOneByteString::New(
10792 const uint8_t* data, 10903 const uint8_t* data,
10793 intptr_t len, 10904 intptr_t len,
10794 void* peer, 10905 void* peer,
10795 Dart_PeerFinalizer callback, 10906 Dart_PeerFinalizer callback,
10796 Heap::Space space) { 10907 Heap::Space space) {
10797 ASSERT(Isolate::Current()->object_store()-> 10908 ASSERT(Isolate::Current()->object_store()->
10798 external_one_byte_string_class() != Class::null()); 10909 external_one_byte_string_class() != Class::null());
10799 if (len < 0 || len > kMaxElements) { 10910 if (len < 0 || len > kMaxElements) {
10800 // This should be caught before we reach here. 10911 // This should be caught before we reach here.
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
11010 array.raw_ptr()->tags_ = tags; 11121 array.raw_ptr()->tags_ = tags;
11011 array.SetLength(used_len); 11122 array.SetLength(used_len);
11012 11123
11013 // Null the GrowableObjectArray, we are removing it's backing array. 11124 // Null the GrowableObjectArray, we are removing it's backing array.
11014 growable_array.SetLength(0); 11125 growable_array.SetLength(0);
11015 growable_array.SetData(new_array); 11126 growable_array.SetData(new_array);
11016 11127
11017 // If there is any left over space fill it with either an Array object or 11128 // If there is any left over space fill it with either an Array object or
11018 // just a plain object (depending on the amount of left over space) so 11129 // just a plain object (depending on the amount of left over space) so
11019 // that it can be traversed over successfully during garbage collection. 11130 // that it can be traversed over successfully during garbage collection.
11020 if (capacity_size != used_size) { 11131 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);
11021 ASSERT(capacity_len > used_len);
11022 intptr_t leftover_size = capacity_size - used_size;
11023 11132
11024 uword addr = RawObject::ToAddr(array.raw()) + used_size;
11025 if (leftover_size >= Array::InstanceSize(0)) {
11026 // As we have enough space to use an array object, update the leftover
11027 // space as an Array object.
11028 RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
11029 tags = 0;
11030 tags = RawObject::SizeTag::update(leftover_size, tags);
11031 tags = RawObject::ClassIdTag::update(kArrayCid, tags);
11032 raw->ptr()->tags_ = tags;
11033 intptr_t leftover_len =
11034 ((leftover_size - Array::InstanceSize(0)) / kWordSize);
11035 raw->ptr()->tags_ = tags;
11036 raw->ptr()->length_ = Smi::New(leftover_len);
11037 } else {
11038 // Update the leftover space as a basic object.
11039 ASSERT(leftover_size == Object::InstanceSize());
11040 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
11041 tags = 0;
11042 tags = RawObject::SizeTag::update(leftover_size, tags);
11043 tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
11044 raw->ptr()->tags_ = tags;
11045 }
11046 }
11047 return array.raw(); 11133 return array.raw();
11048 } 11134 }
11049 11135
11050 11136
11051 RawImmutableArray* ImmutableArray::New(intptr_t len, 11137 RawImmutableArray* ImmutableArray::New(intptr_t len,
11052 Heap::Space space) { 11138 Heap::Space space) {
11053 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != 11139 ASSERT(Isolate::Current()->object_store()->immutable_array_class() !=
11054 Class::null()); 11140 Class::null());
11055 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); 11141 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space));
11056 } 11142 }
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
12003 } 12089 }
12004 return result.raw(); 12090 return result.raw();
12005 } 12091 }
12006 12092
12007 12093
12008 const char* WeakProperty::ToCString() const { 12094 const char* WeakProperty::ToCString() const {
12009 return "_WeakProperty"; 12095 return "_WeakProperty";
12010 } 12096 }
12011 12097
12012 } // namespace dart 12098 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698