| Index: runtime/vm/object.h
|
| diff --git a/runtime/vm/object.h b/runtime/vm/object.h
|
| index b10a26689a326be397cec18f1ec48f5cfe2654cb..2836dda969ab3435a680294b02d436ae91c882f3 100644
|
| --- a/runtime/vm/object.h
|
| +++ b/runtime/vm/object.h
|
| @@ -150,7 +150,9 @@ class Object {
|
| virtual ~Object() { }
|
|
|
| RawObject* raw() const { return raw_; }
|
| - void operator=(RawObject* value) { SetRaw(value); }
|
| + void operator=(RawObject* value) {
|
| + initializeHandle(this, value);
|
| + }
|
|
|
| void set_tags(intptr_t value) const {
|
| // TODO(asiva): Remove the capability of setting tags in general. The mask
|
| @@ -178,7 +180,7 @@ class Object {
|
| // Class testers.
|
| #define DEFINE_CLASS_TESTER(clazz) \
|
| virtual bool Is##clazz() const { return false; }
|
| -CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
|
| + CLASS_LIST_FOR_HANDLES(DEFINE_CLASS_TESTER);
|
| #undef DEFINE_CLASS_TESTER
|
|
|
| bool IsNull() const { return raw_ == null_; }
|
| @@ -212,7 +214,7 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
|
|
|
| static Object& Handle(Isolate* isolate, RawObject* raw_ptr) {
|
| Object* obj = reinterpret_cast<Object*>(VMHandles::AllocateHandle(isolate));
|
| - obj->SetRaw(raw_ptr);
|
| + initializeHandle(obj, raw_ptr);
|
| return *obj;
|
| }
|
|
|
| @@ -231,7 +233,7 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
|
| static Object& ZoneHandle(Isolate* isolate, RawObject* raw_ptr) {
|
| Object* obj = reinterpret_cast<Object*>(
|
| VMHandles::AllocateZoneHandle(isolate));
|
| - obj->SetRaw(raw_ptr);
|
| + initializeHandle(obj, raw_ptr);
|
| return *obj;
|
| }
|
|
|
| @@ -371,6 +373,17 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
|
| const String& name,
|
| const Library& lib);
|
|
|
| + /* Initialize the handle based on the raw_ptr in the presence of null. */
|
| + static void initializeHandle(Object* obj, RawObject* raw_ptr) {
|
| + if (raw_ptr != Object::null()) {
|
| + obj->SetRaw(raw_ptr);
|
| + } else {
|
| + obj->raw_ = Object::null();
|
| + Object fake_object;
|
| + obj->set_vtable(fake_object.vtable());
|
| + }
|
| + }
|
| +
|
| cpp_vtable* vtable_address() const {
|
| uword vtable_addr = reinterpret_cast<uword>(this);
|
| return reinterpret_cast<cpp_vtable*>(vtable_addr);
|
| @@ -425,6 +438,10 @@ CLASS_LIST_NO_OBJECT(DEFINE_CLASS_TESTER);
|
| friend void RawObject::Validate(Isolate* isolate) const;
|
| friend class Closure;
|
| friend class SnapshotReader;
|
| + friend class OneByteString;
|
| + friend class TwoByteString;
|
| + friend class ExternalOneByteString;
|
| + friend class ExternalTwoByteString;
|
|
|
| // Disallow allocation.
|
| void* operator new(size_t size);
|
| @@ -715,6 +732,9 @@ class Class : public Object {
|
| const String& name,
|
| int num_fields);
|
|
|
| + // Allocate the raw string classes.
|
| + static RawClass* NewStringClass(intptr_t class_id);
|
| +
|
| // Allocate a class representing a function signature described by
|
| // signature_function, which must be a closure function or a signature
|
| // function.
|
| @@ -2563,6 +2583,11 @@ class Code : public Object {
|
| // Returns an array indexed by deopt id, containing the extracted ICData.
|
| RawArray* ExtractTypeFeedbackArray() const;
|
|
|
| + // Returns deopt-ids of all static calls that were never resolved, i.e.,
|
| + // never executed.
|
| + void ExtractUncalledStaticCallDeoptIds(
|
| + GrowableArray<intptr_t>* deopt_ids) const;
|
| +
|
| private:
|
| // An object finder visitor interface.
|
| class FindRawCodeVisitor : public FindObjectVisitor {
|
| @@ -3659,9 +3684,9 @@ class String : public Instance {
|
| static intptr_t Hash(const uint16_t* characters, intptr_t len);
|
| static intptr_t Hash(const uint32_t* characters, intptr_t len);
|
|
|
| - virtual int32_t CharAt(intptr_t index) const;
|
| + int32_t CharAt(intptr_t index) const;
|
|
|
| - virtual intptr_t CharSize() const;
|
| + intptr_t CharSize() const;
|
|
|
| inline bool Equals(const String& str) const;
|
| inline bool Equals(const String& str,
|
| @@ -3682,12 +3707,28 @@ class String : public Instance {
|
|
|
| bool IsSymbol() const { return raw()->IsCanonical(); }
|
|
|
| - virtual bool IsExternal() const { return false; }
|
| - virtual void* GetPeer() const {
|
| - UNREACHABLE();
|
| - return NULL;
|
| + bool IsOneByteString() const {
|
| + return raw()->GetClassId() == kOneByteStringCid;
|
| + }
|
| +
|
| + bool IsTwoByteString() const {
|
| + return raw()->GetClassId() == kTwoByteStringCid;
|
| + }
|
| +
|
| + bool IsExternalOneByteString() const {
|
| + return raw()->GetClassId() == kExternalOneByteStringCid;
|
| }
|
|
|
| + bool IsExternalTwoByteString() const {
|
| + return raw()->GetClassId() == kExternalTwoByteStringCid;
|
| + }
|
| +
|
| + bool IsExternal() const {
|
| + return RawObject::IsExternalStringClassId(raw()->GetClassId());
|
| + }
|
| +
|
| + void* GetPeer() const;
|
| +
|
| void ToUTF8(uint8_t* utf8_array, intptr_t array_len) const;
|
|
|
| // Creates a new String object from a C string that is assumed to contain
|
| @@ -3791,30 +3832,33 @@ class String : public Instance {
|
|
|
| template<typename HandleType, typename ElementType>
|
| static void ReadFromImpl(SnapshotReader* reader,
|
| - HandleType* str_obj,
|
| + String* str_obj,
|
| intptr_t len,
|
| intptr_t tags,
|
| Snapshot::Kind kind);
|
|
|
| HEAP_OBJECT_IMPLEMENTATION(String, Instance);
|
|
|
| + friend class Class;
|
| friend class Symbols;
|
| + friend class OneByteString;
|
| + friend class TwoByteString;
|
| + friend class ExternalOneByteString;
|
| + friend class ExternalTwoByteString;
|
| };
|
|
|
|
|
| -class OneByteString : public String {
|
| +class OneByteString : public AllStatic {
|
| public:
|
| - virtual int32_t CharAt(intptr_t index) const {
|
| - return *CharAddr(index);
|
| + static int32_t CharAt(const String& str, intptr_t index) {
|
| + return *CharAddr(str, index);
|
| }
|
|
|
| - virtual intptr_t CharSize() const {
|
| - return kOneByteChar;
|
| - }
|
| -
|
| - RawOneByteString* EscapeSpecialCharacters(bool raw_str) const;
|
| + static RawOneByteString* EscapeSpecialCharacters(const String& str,
|
| + bool raw_str);
|
|
|
| - bool EqualsIgnoringPrivateKey(const OneByteString& str) const;
|
| + static bool EqualsIgnoringPrivateKey(const String& str1,
|
| + const String& str2);
|
|
|
| // We use the same maximum elements for all strings.
|
| static const intptr_t kBytesPerElement = 1;
|
| @@ -3828,9 +3872,9 @@ class OneByteString : public String {
|
| }
|
|
|
| static intptr_t InstanceSize(intptr_t len) {
|
| - ASSERT(sizeof(RawOneByteString) == kSizeofRawString);
|
| + ASSERT(sizeof(RawOneByteString) == String::kSizeofRawString);
|
| ASSERT(0 <= len && len <= kMaxElements);
|
| - return RoundedAllocationSize(
|
| + return String::RoundedAllocationSize(
|
| sizeof(RawOneByteString) + (len * kBytesPerElement));
|
| }
|
|
|
| @@ -3851,7 +3895,7 @@ class OneByteString : public String {
|
| static RawOneByteString* New(const uint32_t* characters,
|
| intptr_t len,
|
| Heap::Space space);
|
| - static RawOneByteString* New(const OneByteString& str,
|
| + static RawOneByteString* New(const String& str,
|
| Heap::Space space);
|
|
|
| static RawOneByteString* Concat(const String& str1,
|
| @@ -3865,30 +3909,47 @@ class OneByteString : public String {
|
| const String& str,
|
| Heap::Space space);
|
|
|
| + static const ClassId kClassId = kOneByteStringCid;
|
| +
|
| + static RawOneByteString* null() {
|
| + return reinterpret_cast<RawOneByteString*>(Object::null());
|
| + }
|
| +
|
| private:
|
| - uint8_t* CharAddr(intptr_t index) const {
|
| - // TODO(iposva): Determine if we should throw an exception here.
|
| - ASSERT((index >= 0) && (index < Length()));
|
| - return &raw_ptr()->data_[index];
|
| + static RawOneByteString* raw(const String& str) {
|
| + return reinterpret_cast<RawOneByteString*>(str.raw());
|
| + }
|
| +
|
| + static RawOneByteString* raw_ptr(const String& str) {
|
| + return reinterpret_cast<RawOneByteString*>(str.raw_ptr());
|
| }
|
|
|
| - HEAP_OBJECT_IMPLEMENTATION(OneByteString, String);
|
| + static uint8_t* CharAddr(const String& str, intptr_t index) {
|
| + ASSERT((index >= 0) && (index < str.Length()));
|
| + ASSERT(str.IsOneByteString());
|
| + NoGCScope no_gc;
|
| + return &raw_ptr(str)->data_[index];
|
| + }
|
| +
|
| + static RawOneByteString* ReadFrom(SnapshotReader* reader,
|
| + intptr_t object_id,
|
| + intptr_t tags,
|
| + Snapshot::Kind kind);
|
| +
|
| friend class Class;
|
| friend class String;
|
| + friend class SnapshotReader;
|
| };
|
|
|
|
|
| -class TwoByteString : public String {
|
| +class TwoByteString : public AllStatic {
|
| public:
|
| - virtual int32_t CharAt(intptr_t index) const {
|
| - return *CharAddr(index);
|
| + static int32_t CharAt(const String& str, intptr_t index) {
|
| + return *CharAddr(str, index);
|
| }
|
|
|
| - virtual intptr_t CharSize() const {
|
| - return kTwoByteChar;
|
| - }
|
| -
|
| - RawTwoByteString* EscapeSpecialCharacters(bool raw_str) const;
|
| + static RawTwoByteString* EscapeSpecialCharacters(const String& str,
|
| + bool raw_str);
|
|
|
| // We use the same maximum elements for all strings.
|
| static const intptr_t kBytesPerElement = 2;
|
| @@ -3902,9 +3963,9 @@ class TwoByteString : public String {
|
| }
|
|
|
| static intptr_t InstanceSize(intptr_t len) {
|
| - ASSERT(sizeof(RawTwoByteString) == kSizeofRawString);
|
| + ASSERT(sizeof(RawTwoByteString) == String::kSizeofRawString);
|
| ASSERT(0 <= len && len <= kMaxElements);
|
| - return RoundedAllocationSize(
|
| + return String::RoundedAllocationSize(
|
| sizeof(RawTwoByteString) + (len * kBytesPerElement));
|
| }
|
|
|
| @@ -3917,7 +3978,7 @@ class TwoByteString : public String {
|
| const uint32_t* characters,
|
| intptr_t len,
|
| Heap::Space space);
|
| - static RawTwoByteString* New(const TwoByteString& str,
|
| + static RawTwoByteString* New(const String& str,
|
| Heap::Space space);
|
|
|
| static RawTwoByteString* Concat(const String& str1,
|
| @@ -3931,31 +3992,48 @@ class TwoByteString : public String {
|
| const String& str,
|
| Heap::Space space);
|
|
|
| + static RawTwoByteString* null() {
|
| + return reinterpret_cast<RawTwoByteString*>(Object::null());
|
| + }
|
| +
|
| +
|
| + static const ClassId kClassId = kTwoByteStringCid;
|
| +
|
| private:
|
| - uint16_t* CharAddr(intptr_t index) const {
|
| - ASSERT((index >= 0) && (index < Length()));
|
| - return &raw_ptr()->data_[index];
|
| + static RawTwoByteString* raw(const String& str) {
|
| + return reinterpret_cast<RawTwoByteString*>(str.raw());
|
| + }
|
| +
|
| + static RawTwoByteString* raw_ptr(const String& str) {
|
| + return reinterpret_cast<RawTwoByteString*>(str.raw_ptr());
|
| + }
|
| +
|
| + static uint16_t* CharAddr(const String& str, intptr_t index) {
|
| + ASSERT((index >= 0) && (index < str.Length()));
|
| + ASSERT(str.IsTwoByteString());
|
| + NoGCScope no_gc;
|
| + return &raw_ptr(str)->data_[index];
|
| }
|
|
|
| - HEAP_OBJECT_IMPLEMENTATION(TwoByteString, String);
|
| + static RawTwoByteString* ReadFrom(SnapshotReader* reader,
|
| + intptr_t object_id,
|
| + intptr_t tags,
|
| + Snapshot::Kind kind);
|
| +
|
| friend class Class;
|
| friend class String;
|
| + friend class SnapshotReader;
|
| };
|
|
|
|
|
| -class ExternalOneByteString : public String {
|
| +class ExternalOneByteString : public AllStatic {
|
| public:
|
| - virtual int32_t CharAt(intptr_t index) const {
|
| - return *CharAddr(index);
|
| - }
|
| -
|
| - virtual intptr_t CharSize() const {
|
| - return kOneByteChar;
|
| + static int32_t CharAt(const String& str, intptr_t index) {
|
| + return *CharAddr(str, index);
|
| }
|
|
|
| - virtual bool IsExternal() const { return true; }
|
| - virtual void* GetPeer() const {
|
| - return raw_ptr()->external_data_->peer();
|
| + static void* GetPeer(const String& str) {
|
| + return raw_ptr(str)->external_data_->peer();
|
| }
|
|
|
| // We use the same maximum elements for all strings.
|
| @@ -3963,7 +4041,7 @@ class ExternalOneByteString : public String {
|
| static const intptr_t kMaxElements = String::kMaxElements;
|
|
|
| static intptr_t InstanceSize() {
|
| - return RoundedAllocationSize(sizeof(RawExternalOneByteString));
|
| + return String::RoundedAllocationSize(sizeof(RawExternalOneByteString));
|
| }
|
|
|
| static RawExternalOneByteString* New(const uint8_t* characters,
|
| @@ -3972,38 +4050,56 @@ class ExternalOneByteString : public String {
|
| Dart_PeerFinalizer callback,
|
| Heap::Space space);
|
|
|
| + static RawExternalOneByteString* null() {
|
| + return reinterpret_cast<RawExternalOneByteString*>(Object::null());
|
| + }
|
| +
|
| + static const ClassId kClassId = kExternalOneByteStringCid;
|
| +
|
| private:
|
| - const uint8_t* CharAddr(intptr_t index) const {
|
| - // TODO(iposva): Determine if we should throw an exception here.
|
| - ASSERT((index >= 0) && (index < Length()));
|
| - return &(raw_ptr()->external_data_->data()[index]);
|
| + static RawExternalOneByteString* raw(const String& str) {
|
| + return reinterpret_cast<RawExternalOneByteString*>(str.raw());
|
| }
|
|
|
| - void SetExternalData(ExternalStringData<uint8_t>* data) {
|
| - raw_ptr()->external_data_ = data;
|
| + static RawExternalOneByteString* raw_ptr(const String& str) {
|
| + return reinterpret_cast<RawExternalOneByteString*>(str.raw_ptr());
|
| + }
|
| +
|
| + static const uint8_t* CharAddr(const String& str, intptr_t index) {
|
| + ASSERT((index >= 0) && (index < str.Length()));
|
| + ASSERT(str.IsExternalOneByteString());
|
| + NoGCScope no_gc;
|
| + return &(raw_ptr(str)->external_data_->data()[index]);
|
| + }
|
| +
|
| + static void SetExternalData(const String& str,
|
| + ExternalStringData<uint8_t>* data) {
|
| + ASSERT(str.IsExternalOneByteString());
|
| + NoGCScope no_gc;
|
| + raw_ptr(str)->external_data_ = data;
|
| }
|
|
|
| static void Finalize(Dart_Handle handle, void* peer);
|
|
|
| - HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString, String);
|
| + static RawExternalOneByteString* ReadFrom(SnapshotReader* reader,
|
| + intptr_t object_id,
|
| + intptr_t tags,
|
| + Snapshot::Kind kind);
|
| +
|
| friend class Class;
|
| friend class String;
|
| + friend class SnapshotReader;
|
| };
|
|
|
|
|
| -class ExternalTwoByteString : public String {
|
| +class ExternalTwoByteString : public AllStatic {
|
| public:
|
| - virtual int32_t CharAt(intptr_t index) const {
|
| - return *CharAddr(index);
|
| - }
|
| -
|
| - virtual intptr_t CharSize() const {
|
| - return kTwoByteChar;
|
| + static int32_t CharAt(const String& str, intptr_t index) {
|
| + return *CharAddr(str, index);
|
| }
|
|
|
| - virtual bool IsExternal() const { return true; }
|
| - virtual void* GetPeer() const {
|
| - return raw_ptr()->external_data_->peer();
|
| + static void* GetPeer(const String& str) {
|
| + return raw_ptr(str)->external_data_->peer();
|
| }
|
|
|
| // We use the same maximum elements for all strings.
|
| @@ -4011,7 +4107,7 @@ class ExternalTwoByteString : public String {
|
| static const intptr_t kMaxElements = String::kMaxElements;
|
|
|
| static intptr_t InstanceSize() {
|
| - return RoundedAllocationSize(sizeof(RawExternalTwoByteString));
|
| + return String::RoundedAllocationSize(sizeof(RawExternalTwoByteString));
|
| }
|
|
|
| static RawExternalTwoByteString* New(const uint16_t* characters,
|
| @@ -4020,22 +4116,45 @@ class ExternalTwoByteString : public String {
|
| Dart_PeerFinalizer callback,
|
| Heap::Space space = Heap::kNew);
|
|
|
| + static RawExternalTwoByteString* null() {
|
| + return reinterpret_cast<RawExternalTwoByteString*>(Object::null());
|
| + }
|
| +
|
| + static const ClassId kClassId = kExternalTwoByteStringCid;
|
| +
|
| private:
|
| - const uint16_t* CharAddr(intptr_t index) const {
|
| - // TODO(iposva): Determine if we should throw an exception here.
|
| - ASSERT((index >= 0) && (index < Length()));
|
| - return &(raw_ptr()->external_data_->data()[index]);
|
| + static RawExternalTwoByteString* raw(const String& str) {
|
| + return reinterpret_cast<RawExternalTwoByteString*>(str.raw());
|
| }
|
|
|
| - void SetExternalData(ExternalStringData<uint16_t>* data) {
|
| - raw_ptr()->external_data_ = data;
|
| + static RawExternalTwoByteString* raw_ptr(const String& str) {
|
| + return reinterpret_cast<RawExternalTwoByteString*>(str.raw_ptr());
|
| + }
|
| +
|
| + static const uint16_t* CharAddr(const String& str, intptr_t index) {
|
| + ASSERT((index >= 0) && (index < str.Length()));
|
| + ASSERT(str.IsExternalTwoByteString());
|
| + NoGCScope no_gc;
|
| + return &(raw_ptr(str)->external_data_->data()[index]);
|
| + }
|
| +
|
| + static void SetExternalData(const String& str,
|
| + ExternalStringData<uint16_t>* data) {
|
| + ASSERT(str.IsExternalTwoByteString());
|
| + NoGCScope no_gc;
|
| + raw_ptr(str)->external_data_ = data;
|
| }
|
|
|
| static void Finalize(Dart_Handle handle, void* peer);
|
|
|
| - HEAP_OBJECT_IMPLEMENTATION(ExternalTwoByteString, String);
|
| + static RawExternalTwoByteString* ReadFrom(SnapshotReader* reader,
|
| + intptr_t object_id,
|
| + intptr_t tags,
|
| + Snapshot::Kind kind);
|
| +
|
| friend class Class;
|
| friend class String;
|
| + friend class SnapshotReader;
|
| };
|
|
|
|
|
| @@ -5675,11 +5794,12 @@ void Object::SetRaw(RawObject* value) {
|
| if ((reinterpret_cast<uword>(raw_) & kSmiTagMask) == kSmiTag) {
|
| set_vtable(Smi::handle_vtable_);
|
| return;
|
| - } else if (raw_ == null_) {
|
| - set_vtable(handle_vtable_);
|
| - return;
|
| }
|
| -
|
| + intptr_t cid = raw_->GetClassId();
|
| + if (cid >= kNumPredefinedCids) {
|
| + cid = kInstanceCid;
|
| + }
|
| + set_vtable(builtin_vtables_[cid]);
|
| #if defined(DEBUG)
|
| Isolate* isolate = Isolate::Current();
|
| if (FLAG_verify_handles) {
|
| @@ -5688,17 +5808,9 @@ void Object::SetRaw(RawObject* value) {
|
| ASSERT(isolate_heap->Contains(reinterpret_cast<uword>(raw_->ptr())) ||
|
| vm_isolate_heap->Contains(reinterpret_cast<uword>(raw_->ptr())));
|
| }
|
| + ASSERT(builtin_vtables_[cid] ==
|
| + isolate->class_table()->At(cid)->ptr()->handle_vtable_);
|
| #endif
|
| - intptr_t cid = raw_->GetClassId();
|
| - if (cid < kNumPredefinedCids) {
|
| -#if defined(DEBUG)
|
| - ASSERT(builtin_vtables_[cid] ==
|
| - isolate->class_table()->At(cid)->ptr()->handle_vtable_);
|
| -#endif
|
| - set_vtable(builtin_vtables_[cid]);
|
| - } else {
|
| - set_vtable(builtin_vtables_[kInstanceCid]);
|
| - }
|
| }
|
|
|
|
|
|
|