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

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());
487 if (original_size > used_size) {
Anton Muhin 2012/11/07 10:05:46 maybe turn that into an assert?
siva 2012/11/07 21:43:27 I did not want it to be an assert because then the
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);
Anton Muhin 2012/11/07 10:05:46 may there be any issues with alignment? maybe add
siva 2012/11/07 21:43:27 Objects are always aligned, we have asserts for th
497 tags = RawObject::ClassIdTag::update(kArrayCid, tags);
498 raw->ptr()->tags_ = tags;
499 intptr_t leftover_len =
500 ((leftover_size - Array::InstanceSize(0)) / kWordSize);
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 9800 matching lines...) Expand 10 before | Expand all | Expand 10 after
10287 if (obj.Length() > 0) { 10327 if (obj.Length() > 0) {
10288 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length()); 10328 memmove(utf8_array, OneByteString::CharAddr(obj, 0), obj.Length());
10289 } 10329 }
10290 } else { 10330 } else {
10291 ASSERT(array_len >= Utf8::Length(*this)); 10331 ASSERT(array_len >= Utf8::Length(*this));
10292 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len); 10332 Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
10293 } 10333 }
10294 } 10334 }
10295 10335
10296 10336
10337 static void AddFinalizer(const Object& referent,
10338 void* peer,
10339 Dart_WeakPersistentHandleFinalizer callback) {
10340 ASSERT(callback != NULL);
10341 ApiState* state = Isolate::Current()->api_state();
10342 ASSERT(state != NULL);
10343 FinalizablePersistentHandle* weak_ref =
10344 state->weak_persistent_handles().AllocateHandle();
10345 weak_ref->set_raw(referent);
10346 weak_ref->set_peer(peer);
10347 weak_ref->set_callback(callback);
10348 }
10349
10350
10351 RawString* String::MakeExternal(void* array,
10352 intptr_t length,
10353 void* peer,
10354 Dart_PeerFinalizer cback) const {
10355 ASSERT(array != NULL);
10356 intptr_t str_length = this->Length();
10357 ASSERT(length >= (str_length * this->CharSize()));
10358 intptr_t class_id = raw()->GetClassId();
10359 intptr_t used_size = 0;
10360 intptr_t original_size = 0;
10361 uword tags = 0;
10362 NoGCScope no_gc;
10363
10364 if (class_id == kOneByteStringCid) {
10365 used_size = ExternalOneByteString::InstanceSize();
10366 original_size = OneByteString::InstanceSize(str_length);
10367 ASSERT(original_size >= used_size);
Anton Muhin 2012/11/07 10:05:46 is it always true? something like zero length str
siva 2012/11/07 21:43:27 Yes this is always true as we always align objects
Anton Muhin 2012/11/08 08:05:29 Okay. In v8 zero length string would be just a he
10368
10369 // Copy the data into the external array.
10370 memmove(array, OneByteString::CharAddr(*this, 0), str_length);
Anton Muhin 2012/11/07 10:05:46 that might be very unpleasant thing when one attem
siva 2012/11/07 21:43:27 I am not sure I understand your suggestion here. T
Anton Muhin 2012/11/08 08:05:29 Yes, the embedder has to do that, but he hasn't to
10371
10372 // Update the class information of the object.
10373 const intptr_t class_id = kExternalOneByteStringCid;
10374 tags = RawObject::SizeTag::update(used_size, tags);
10375 tags = RawObject::ClassIdTag::update(class_id, tags);
10376 raw_ptr()->tags_ = tags;
10377 const String& result = String::Handle(this->raw());
10378 ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
10379 reinterpret_cast<const uint8_t*>(array), peer, cback);
10380 result.SetLength(str_length);
10381 result.SetHash(0);
10382 ExternalOneByteString::SetExternalData(result, ext_data);
10383 AddFinalizer(result, ext_data, ExternalOneByteString::Finalize);
10384 } else {
10385 ASSERT(class_id == kTwoByteStringCid);
10386 used_size = ExternalTwoByteString::InstanceSize();
10387 original_size = TwoByteString::InstanceSize(str_length);
10388 ASSERT(original_size >= used_size);
10389
10390 // Copy the data into the external array.
10391 memmove(array,
10392 TwoByteString::CharAddr(*this, 0),
10393 (str_length * kTwoByteChar));
10394
10395 // Update the class information of the object.
10396 const intptr_t class_id = kExternalTwoByteStringCid;
10397 tags = RawObject::SizeTag::update(used_size, tags);
10398 tags = RawObject::ClassIdTag::update(class_id, tags);
10399 raw_ptr()->tags_ = tags;
10400 const String& result = String::Handle(this->raw());
10401 ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
10402 reinterpret_cast<const uint16_t*>(array), peer, cback);
10403 result.SetLength(str_length);
10404 result.SetHash(0);
10405 ExternalTwoByteString::SetExternalData(result, ext_data);
10406 AddFinalizer(result, ext_data, ExternalTwoByteString::Finalize);
10407 }
10408
10409 // If there is any left over space fill it with either an Array object or
10410 // just a plain object (depending on the amount of left over space) so
10411 // that it can be traversed over successfully during garbage collection.
10412 Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);
10413
10414 return this->raw();
10415 }
10416
10417
10297 RawString* String::Transform(int32_t (*mapping)(int32_t ch), 10418 RawString* String::Transform(int32_t (*mapping)(int32_t ch),
10298 const String& str, 10419 const String& str,
10299 Heap::Space space) { 10420 Heap::Space space) {
10300 ASSERT(!str.IsNull()); 10421 ASSERT(!str.IsNull());
10301 bool has_mapping = false; 10422 bool has_mapping = false;
10302 int32_t dst_max = 0; 10423 int32_t dst_max = 0;
10303 intptr_t len = str.Length(); 10424 intptr_t len = str.Length();
10304 // TODO(cshapiro): assume a transform is required, rollback if not. 10425 // TODO(cshapiro): assume a transform is required, rollback if not.
10305 for (intptr_t i = 0; i < len; ++i) { 10426 for (intptr_t i = 0; i < len; ++i) {
10306 int32_t src = str.CharAt(i); 10427 int32_t src = str.CharAt(i);
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
10677 const String& result = String::Handle(TwoByteString::New(len, space)); 10798 const String& result = String::Handle(TwoByteString::New(len, space));
10678 for (intptr_t i = 0; i < len; ++i) { 10799 for (intptr_t i = 0; i < len; ++i) {
10679 int32_t ch = mapping(str.CharAt(i)); 10800 int32_t ch = mapping(str.CharAt(i));
10680 ASSERT(ch >= 0 && ch <= 0xFFFF); 10801 ASSERT(ch >= 0 && ch <= 0xFFFF);
10681 *CharAddr(result, i) = ch; 10802 *CharAddr(result, i) = ch;
10682 } 10803 }
10683 return TwoByteString::raw(result); 10804 return TwoByteString::raw(result);
10684 } 10805 }
10685 10806
10686 10807
10687 static void AddFinalizer(const Object& referent,
10688 void* peer,
10689 Dart_WeakPersistentHandleFinalizer callback) {
10690 ASSERT(callback != NULL);
10691 ApiState* state = Isolate::Current()->api_state();
10692 ASSERT(state != NULL);
10693 FinalizablePersistentHandle* weak_ref =
10694 state->weak_persistent_handles().AllocateHandle();
10695 weak_ref->set_raw(referent);
10696 weak_ref->set_peer(peer);
10697 weak_ref->set_callback(callback);
10698 }
10699
10700
10701 RawExternalOneByteString* ExternalOneByteString::New( 10808 RawExternalOneByteString* ExternalOneByteString::New(
10702 const uint8_t* data, 10809 const uint8_t* data,
10703 intptr_t len, 10810 intptr_t len,
10704 void* peer, 10811 void* peer,
10705 Dart_PeerFinalizer callback, 10812 Dart_PeerFinalizer callback,
10706 Heap::Space space) { 10813 Heap::Space space) {
10707 ASSERT(Isolate::Current()->object_store()-> 10814 ASSERT(Isolate::Current()->object_store()->
10708 external_one_byte_string_class() != Class::null()); 10815 external_one_byte_string_class() != Class::null());
10709 if (len < 0 || len > kMaxElements) { 10816 if (len < 0 || len > kMaxElements) {
10710 // This should be caught before we reach here. 10817 // This should be caught before we reach here.
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
10920 array.raw_ptr()->tags_ = tags; 11027 array.raw_ptr()->tags_ = tags;
10921 array.SetLength(used_len); 11028 array.SetLength(used_len);
10922 11029
10923 // Null the GrowableObjectArray, we are removing it's backing array. 11030 // Null the GrowableObjectArray, we are removing it's backing array.
10924 growable_array.SetLength(0); 11031 growable_array.SetLength(0);
10925 growable_array.SetData(new_array); 11032 growable_array.SetData(new_array);
10926 11033
10927 // If there is any left over space fill it with either an Array object or 11034 // If there is any left over space fill it with either an Array object or
10928 // just a plain object (depending on the amount of left over space) so 11035 // just a plain object (depending on the amount of left over space) so
10929 // that it can be traversed over successfully during garbage collection. 11036 // that it can be traversed over successfully during garbage collection.
10930 if (capacity_size != used_size) { 11037 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);
10931 ASSERT(capacity_len > used_len);
10932 intptr_t leftover_size = capacity_size - used_size;
10933 11038
10934 uword addr = RawObject::ToAddr(array.raw()) + used_size;
10935 if (leftover_size >= Array::InstanceSize(0)) {
10936 // As we have enough space to use an array object, update the leftover
10937 // space as an Array object.
10938 RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
10939 tags = 0;
10940 tags = RawObject::SizeTag::update(leftover_size, tags);
10941 tags = RawObject::ClassIdTag::update(kArrayCid, tags);
10942 raw->ptr()->tags_ = tags;
10943 intptr_t leftover_len =
10944 ((leftover_size - Array::InstanceSize(0)) / kWordSize);
10945 raw->ptr()->tags_ = tags;
10946 raw->ptr()->length_ = Smi::New(leftover_len);
10947 } else {
10948 // Update the leftover space as a basic object.
10949 ASSERT(leftover_size == Object::InstanceSize());
10950 RawObject* raw = reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
10951 tags = 0;
10952 tags = RawObject::SizeTag::update(leftover_size, tags);
10953 tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
10954 raw->ptr()->tags_ = tags;
10955 }
10956 }
10957 return array.raw(); 11039 return array.raw();
10958 } 11040 }
10959 11041
10960 11042
10961 RawImmutableArray* ImmutableArray::New(intptr_t len, 11043 RawImmutableArray* ImmutableArray::New(intptr_t len,
10962 Heap::Space space) { 11044 Heap::Space space) {
10963 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != 11045 ASSERT(Isolate::Current()->object_store()->immutable_array_class() !=
10964 Class::null()); 11046 Class::null());
10965 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); 11047 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space));
10966 } 11048 }
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
11913 } 11995 }
11914 return result.raw(); 11996 return result.raw();
11915 } 11997 }
11916 11998
11917 11999
11918 const char* WeakProperty::ToCString() const { 12000 const char* WeakProperty::ToCString() const {
11919 return "_WeakProperty"; 12001 return "_WeakProperty";
11920 } 12002 }
11921 12003
11922 } // namespace dart 12004 } // namespace dart
OLDNEW
« vm/dart_api_impl_test.cc ('K') | « vm/object.h ('k') | vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698