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

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
« no previous file with comments | « vm/object.h ('k') | no next file » | 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) 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());
487 ASSERT(original_size >= used_size);
488 if (original_size > used_size) {
489 intptr_t leftover_size = original_size - used_size;
490
491 uword addr = RawObject::ToAddr(obj.raw()) + used_size;
492 if (leftover_size >= Array::InstanceSize(0)) {
493 // As we have enough space to use an array object, update the leftover
494 // space as an Array object.
495 RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
496 uword tags = 0;
497 tags = RawObject::SizeTag::update(leftover_size, tags);
498 tags = RawObject::ClassIdTag::update(kArrayCid, tags);
499 raw->ptr()->tags_ = tags;
500 intptr_t leftover_len =
501 ((leftover_size - Array::InstanceSize(0)) / kWordSize);
502 ASSERT(Array::InstanceSize(leftover_len) == leftover_size);
503 raw->ptr()->tags_ = tags;
504 raw->ptr()->length_ = Smi::New(leftover_len);
505 } else {
506 // Update the leftover space as a basic object.
507 ASSERT(leftover_size == Object::InstanceSize());
508 RawObject* raw =
509 reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
510 uword tags = 0;
511 tags = RawObject::SizeTag::update(leftover_size, tags);
512 tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
513 raw->ptr()->tags_ = tags;
514 }
515 }
516 }
517
518
477 RawClass* Object::CreateAndRegisterInterface(const char* cname, 519 RawClass* Object::CreateAndRegisterInterface(const char* cname,
478 const Script& script, 520 const Script& script,
479 const Library& lib) { 521 const Library& lib) {
480 const String& name = String::Handle(Symbols::New(cname)); 522 const String& name = String::Handle(Symbols::New(cname));
481 const Class& cls = Class::Handle( 523 const Class& cls = Class::Handle(
482 Class::NewInterface(name, script, Scanner::kDummyTokenIndex)); 524 Class::NewInterface(name, script, Scanner::kDummyTokenIndex));
483 lib.AddClass(cls); 525 lib.AddClass(cls);
484 return cls.raw(); 526 return cls.raw();
485 } 527 }
486 528
(...skipping 9890 matching lines...) Expand 10 before | Expand all | Expand 10 after
10377 if (obj.Length() > 0) { 10419 if (obj.Length() > 0) {
10378 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length()); 10420 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length());
10379 } 10421 }
10380 } else { 10422 } else {
10381 ASSERT(array_len >= Utf8::Length(*this)); 10423 ASSERT(array_len >= Utf8::Length(*this));
10382 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); 10424 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
10383 } 10425 }
10384 } 10426 }
10385 10427
10386 10428
10429 static void AddFinalizer(const Object& referent,
10430 void* peer,
10431 Dart_WeakPersistentHandleFinalizer callback) {
10432 ASSERT(callback != NULL);
10433 ApiState* state = Isolate::Current()->api_state();
10434 ASSERT(state != NULL);
10435 FinalizablePersistentHandle* weak_ref =
10436 state->weak_persistent_handles().AllocateHandle();
10437 weak_ref->set_raw(referent);
10438 weak_ref->set_peer(peer);
10439 weak_ref->set_callback(callback);
10440 }
10441
10442
10443 RawString* String::MakeExternal(void* array,
10444 intptr_t length,
10445 void* peer,
10446 Dart_PeerFinalizer cback) const {
10447 ASSERT(array != NULL);
10448 intptr_t str_length = this->Length();
10449 ASSERT(length >= (str_length * this->CharSize()));
10450 intptr_t class_id = raw()->GetClassId();
10451 intptr_t used_size = 0;
10452 intptr_t original_size = 0;
10453 uword tags = 0;
10454 NoGCScope no_gc;
10455
10456 if (class_id == kOneByteStringCid) {
10457 used_size = ExternalOneByteString::InstanceSize();
10458 original_size = OneByteString::InstanceSize(str_length);
10459 ASSERT(original_size >= used_size);
10460
10461 // Copy the data into the external array.
10462 if (str_length > 0) {
10463 memmove(array, OneByteString::CharAddr(*this, 0), str_length);
10464 }
10465
10466 // Update the class information of the object.
10467 const intptr_t class_id = kExternalOneByteStringCid;
10468 tags = RawObject::SizeTag::update(used_size, tags);
10469 tags = RawObject::ClassIdTag::update(class_id, tags);
10470 raw_ptr()->tags_ = tags;
10471 const String& result = String::Handle(this->raw());
10472 ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
10473 reinterpret_cast<const uint8_t*>(array), peer, cback);
10474 result.SetLength(str_length);
10475 result.SetHash(0);
10476 ExternalOneByteString::SetExternalData(result, ext_data);
10477 AddFinalizer(result, ext_data, ExternalOneByteString::Finalize);
10478 } else {
10479 ASSERT(class_id == kTwoByteStringCid);
10480 used_size = ExternalTwoByteString::InstanceSize();
10481 original_size = TwoByteString::InstanceSize(str_length);
10482 ASSERT(original_size >= used_size);
10483
10484 // Copy the data into the external array.
10485 if (str_length > 0) {
10486 memmove(array,
10487 TwoByteString::CharAddr(*this, 0),
10488 (str_length * kTwoByteChar));
10489 }
10490
10491 // Update the class information of the object.
10492 const intptr_t class_id = kExternalTwoByteStringCid;
10493 tags = RawObject::SizeTag::update(used_size, tags);
10494 tags = RawObject::ClassIdTag::update(class_id, tags);
10495 raw_ptr()->tags_ = tags;
10496 const String& result = String::Handle(this->raw());
10497 ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
10498 reinterpret_cast<const uint16_t*>(array), peer, cback);
10499 result.SetLength(str_length);
10500 result.SetHash(0);
10501 ExternalTwoByteString::SetExternalData(result, ext_data);
10502 AddFinalizer(result, ext_data, ExternalTwoByteString::Finalize);
10503 }
10504
10505 // If there is any left over space fill it with either an Array object or
10506 // just a plain object (depending on the amount of left over space) so
10507 // that it can be traversed over successfully during garbage collection.
10508 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
10509
10510 return this->raw();
10511 }
10512
10513
10387 RawString* String::Transform(int32_t (*mapping)(int32_t ch), 10514 RawString* String::Transform(int32_t (*mapping)(int32_t ch),
10388 const String& str, 10515 const String& str,
10389 Heap::Space space) { 10516 Heap::Space space) {
10390 ASSERT(!str.IsNull()); 10517 ASSERT(!str.IsNull());
10391 bool has_mapping = false; 10518 bool has_mapping = false;
10392 int32_t dst_max = 0; 10519 int32_t dst_max = 0;
10393 intptr_t len = str.Length(); 10520 intptr_t len = str.Length();
10394 // TODO(cshapiro): assume a transform is required, rollback if not. 10521 // TODO(cshapiro): assume a transform is required, rollback if not.
10395 for (intptr_t i = 0; i < len; ++i) { 10522 for (intptr_t i = 0; i < len; ++i) {
10396 int32_t src = str.CharAt(i); 10523 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)); 10894 const String& result = String::Handle(TwoByteString::New(len, space));
10768 for (intptr_t i = 0; i < len; ++i) { 10895 for (intptr_t i = 0; i < len; ++i) {
10769 int32_t ch = mapping(str.CharAt(i)); 10896 int32_t ch = mapping(str.CharAt(i));
10770 ASSERT(ch >= 0 && ch <= 0xFFFF); 10897 ASSERT(ch >= 0 && ch <= 0xFFFF);
10771 *CharAddr(result, i) = ch; 10898 *CharAddr(result, i) = ch;
10772 } 10899 }
10773 return TwoByteString::raw(result); 10900 return TwoByteString::raw(result);
10774 } 10901 }
10775 10902
10776 10903
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( 10904 RawExternalOneByteString* ExternalOneByteString::New(
10792 const uint8_t* data, 10905 const uint8_t* data,
10793 intptr_t len, 10906 intptr_t len,
10794 void* peer, 10907 void* peer,
10795 Dart_PeerFinalizer callback, 10908 Dart_PeerFinalizer callback,
10796 Heap::Space space) { 10909 Heap::Space space) {
10797 ASSERT(Isolate::Current()->object_store()-> 10910 ASSERT(Isolate::Current()->object_store()->
10798 external_one_byte_string_class() != Class::null()); 10911 external_one_byte_string_class() != Class::null());
10799 if (len < 0 || len > kMaxElements) { 10912 if (len < 0 || len > kMaxElements) {
10800 // This should be caught before we reach here. 10913 // 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; 11123 array.raw_ptr()->tags_ = tags;
11011 array.SetLength(used_len); 11124 array.SetLength(used_len);
11012 11125
11013 // Null the GrowableObjectArray, we are removing it's backing array. 11126 // Null the GrowableObjectArray, we are removing it's backing array.
11014 growable_array.SetLength(0); 11127 growable_array.SetLength(0);
11015 growable_array.SetData(new_array); 11128 growable_array.SetData(new_array);
11016 11129
11017 // If there is any left over space fill it with either an Array object or 11130 // 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 11131 // just a plain object (depending on the amount of left over space) so
11019 // that it can be traversed over successfully during garbage collection. 11132 // that it can be traversed over successfully during garbage collection.
11020 if (capacity_size != used_size) { 11133 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);
11021 ASSERT(capacity_len > used_len);
11022 intptr_t leftover_size = capacity_size - used_size;
11023 11134
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(); 11135 return array.raw();
11048 } 11136 }
11049 11137
11050 11138
11051 RawImmutableArray* ImmutableArray::New(intptr_t len, 11139 RawImmutableArray* ImmutableArray::New(intptr_t len,
11052 Heap::Space space) { 11140 Heap::Space space) {
11053 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != 11141 ASSERT(Isolate::Current()->object_store()->immutable_array_class() !=
11054 Class::null()); 11142 Class::null());
11055 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); 11143 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space));
11056 } 11144 }
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
12003 } 12091 }
12004 return result.raw(); 12092 return result.raw();
12005 } 12093 }
12006 12094
12007 12095
12008 const char* WeakProperty::ToCString() const { 12096 const char* WeakProperty::ToCString() const {
12009 return "_WeakProperty"; 12097 return "_WeakProperty";
12010 } 12098 }
12011 12099
12012 } // namespace dart 12100 } // namespace dart
OLDNEW
« no previous file with comments | « vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698