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

Unified Diff: runtime/vm/object.cc

Issue 184653003: Support displaying of types in the observatory (back-end only for now): (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 months 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/object.cc
===================================================================
--- runtime/vm/object.cc (revision 33387)
+++ runtime/vm/object.cc (working copy)
@@ -3234,6 +3234,70 @@
}
+intptr_t Class::NumCanonicalTypes() const {
+ if (CanonicalType() != Type::null()) {
+ return 1;
+ }
+ const Object& types = Object::Handle(canonical_types());
+ if (types.IsNull() || !types.IsArray()) {
+ return 0;
+ }
+ intptr_t num_types = Array::Cast(types).Length();
+ while (Array::Cast(types).At(num_types - 1) == Type::null()) {
+ num_types--;
+ }
+ return num_types;
+}
+
+
+intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
+ Isolate* isolate = Isolate::Current();
+ if (EnsureIsFinalized(isolate) != Error::null()) {
+ return -1;
+ }
+ if (needle.raw() == CanonicalType()) {
+ return 0;
+ }
+ ReusableHandleScope reused_handles(isolate);
+ Object& types = reused_handles.ObjectHandle();
+ types = canonical_types();
+ if (types.IsNull() || !types.IsArray()) {
+ return -1;
+ }
+ const intptr_t len = Array::Cast(types).Length();
+ AbstractType& type = reused_handles.AbstractTypeHandle();
+ for (intptr_t i = 0; i < len; i++) {
+ type ^= Array::Cast(types).At(i);
+ if (needle.raw() == type.raw()) {
+ return i;
+ }
+ }
+ // No type found.
+ return -1;
+}
+
+
+RawType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
+ Type& type = Type::Handle();
+ if (idx == 0) {
+ type = CanonicalType();
+ if (!type.IsNull()) {
+ return type.raw();
+ }
+ }
+ Object& types = Object::Handle(canonical_types());
+ if (types.IsNull() || !types.IsArray()) {
+ types = empty_array().raw();
+ }
+ if ((idx < 0) || (idx >= Array::Cast(types).Length())) {
+ return Type::null();
+ }
+ type ^= Array::Cast(types).At(idx);
+ ASSERT(!type.IsNull());
+ return type.raw();
+}
+
+
void Class::set_allocation_stub(const Code& value) const {
ASSERT(!value.IsNull());
ASSERT(raw_ptr()->allocation_stub_ == Code::null());
@@ -3594,7 +3658,7 @@
ASSERT(!funcs.IsNull());
Function& function = reused_handles.FunctionHandle();
String& function_name = reused_handles.StringHandle();
- intptr_t len = funcs.Length();
+ const intptr_t len = funcs.Length();
for (intptr_t i = 0; i < len; i++) {
function ^= funcs.At(i);
function_name ^= function.name();
@@ -3789,6 +3853,7 @@
}
}
}
+ jsobj.AddPropertyF("canonicalTypes", "classes/%" Pd "/types", id());
}
}
@@ -4001,13 +4066,80 @@
void TypeArguments::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
+ if (IsNull()) {
+ jsobj.AddProperty("type", ref ? "@Null" : "Null");
+ jsobj.AddProperty("id", "objects/null");
+ return;
+ }
+ // The index in the canonical_type_arguments table cannot be used as part of
+ // the object id (as in typearguments/id), because the indices are not
+ // preserved when the table grows and the entries get rehashed. Use the ring.
+ Isolate* isolate = Isolate::Current();
+ ObjectStore* object_store = isolate->object_store();
+ const Array& table = Array::Handle(object_store->canonical_type_arguments());
+ ASSERT(table.Length() > 0);
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ const intptr_t id = ring->GetIdForObject(raw());
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddPropertyF("id", "objects/%" Pd "", id);
+ jsobj.AddProperty("name", String::Handle(UserVisibleName()).ToCString());
+ jsobj.AddProperty("length", Length());
+ jsobj.AddProperty("num_instantiations", NumInstantiations());
+ if (ref) {
+ return;
+ }
+ {
+ JSONArray jsarr(&jsobj, "types");
+ AbstractType& type_arg = AbstractType::Handle();
+ for (intptr_t i = 0; i < Length(); i++) {
+ type_arg = TypeAt(i);
+ jsarr.AddValue(type_arg);
+ }
+ }
+ if (!IsInstantiated()) {
+ JSONArray jsarr(&jsobj, "instantiations");
+ Array& prior_instantiations = Array::Handle(instantiations());
+ ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
+ TypeArguments& type_args = TypeArguments::Handle();
+ intptr_t i = 0;
+ while (true) {
+ if (prior_instantiations.At(i) == Smi::New(StubCode::kNoInstantiator)) {
+ break;
+ }
+ JSONObject instantiation(&jsarr);
+ type_args ^= prior_instantiations.At(i);
+ instantiation.AddProperty("instantiator", type_args, true);
+ type_args ^= prior_instantiations.At(i + 1);
+ instantiation.AddProperty("instantiated", type_args, true);
+ i += 2;
+ }
+ }
}
+bool TypeArguments::HasInstantiations() const {
+ const Array& prior_instantiations = Array::Handle(instantiations());
+ ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
+ return prior_instantiations.Length() > 1;
+}
+
+
+intptr_t TypeArguments::NumInstantiations() const {
+ const Array& prior_instantiations = Array::Handle(instantiations());
+ ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
+ intptr_t i = 0;
+ while (prior_instantiations.At(i) != Smi::New(StubCode::kNoInstantiator)) {
+ i += 2;
+ }
+ return i/2;
+}
+
+
RawArray* TypeArguments::instantiations() const {
return raw_ptr()->instantiations_;
}
+
void TypeArguments::set_instantiations(const Array& value) const {
ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->instantiations_, value.raw());
@@ -4247,7 +4379,7 @@
ASSERT(!prior_instantiations.IsNull() && prior_instantiations.IsArray());
// The instantiations cache is initialized with Object::zero_array() and is
// therefore guaranteed to contain kNoInstantiator. No length check needed.
- ASSERT(prior_instantiations.Length() > 0);
+ ASSERT(prior_instantiations.Length() > 0); // Always at least a sentinel.
intptr_t index = 0;
while (true) {
if (prior_instantiations.At(index) == instantiator_type_arguments.raw()) {
@@ -4370,6 +4502,21 @@
const Smi& used = Smi::Handle(isolate, Smi::New(used_elements));
table.SetAt(table_size, used);
+ // TODO(regis): Use a trail to compute hashes of TypeRef, or duplicates will
+ // show up in the table (different hashes but equal).
+#if 0 // #ifdef DEBUG
+ // Verify that there are no duplicates.
+ // Duplicates could appear if hash values are not kept constant across
+ // snapshots, e.g. if class ids are not preserved by the snapshots.
+ TypeArguments& other = TypeArguments::Handle();
+ for (intptr_t i = 0; i < table_size; i++) {
+ if ((i != index) && (table.At(i) != TypeArguments::null())) {
+ other ^= table.At(i);
+ ASSERT(!arguments.Equals(other));
+ }
+ }
+#endif
+
// Rehash if table is 75% full.
if (used_elements > ((table_size / 4) * 3)) {
GrowCanonicalTypeArguments(isolate, table);
@@ -12132,7 +12279,7 @@
return;
} else {
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
+ const intptr_t id = ring->GetIdForObject(raw());
if (IsClosure()) {
const Function& closureFunc = Function::Handle(Closure::function(*this));
jsobj.AddProperty("closureFunc", closureFunc);
@@ -12569,7 +12716,7 @@
void AbstractType::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ UNREACHABLE();
}
@@ -13088,7 +13235,26 @@
void Type::PrintToJSONStream(JSONStream* stream, bool ref) const {
+ ASSERT(IsCanonical());
JSONObject jsobj(stream);
+ jsobj.AddProperty("type", JSONType(ref));
+ const Class& type_cls = Class::Handle(type_class());
+ intptr_t id = type_cls.FindCanonicalTypeIndex(*this);
+ if (id >= 0) {
+ intptr_t cid = type_cls.id();
+ jsobj.AddPropertyF("id", "classes/%" Pd "/types/%" Pd "", cid, id);
+ } else {
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ id = ring->GetIdForObject(raw());
Cutch 2014/03/11 13:50:01 How frequently does this path happen?
regis 2014/03/14 23:52:07 If I call PrintToJSON on all canonicalized type ar
+ jsobj.AddPropertyF("id", "objects/%" Pd "", id);
+ }
+ const char* type_name = String::Handle(UserVisibleName()).ToCString();
+ jsobj.AddProperty("name", type_name);
+ if (ref) {
+ return;
+ }
+ jsobj.AddProperty("type_class", type_cls);
+ jsobj.AddProperty("type_arguments", TypeArguments::Handle(arguments()));
}
@@ -13257,6 +13423,16 @@
void TypeRef::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ const intptr_t id = ring->GetIdForObject(raw());
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddPropertyF("id", "objects/%" Pd "", id);
+ const char* type_name = String::Handle(UserVisibleName()).ToCString();
+ jsobj.AddProperty("name", type_name);
+ if (ref) {
+ return;
+ }
+ jsobj.AddProperty("ref_type", AbstractType::Handle(type()));
}
@@ -13461,6 +13637,19 @@
void TypeParameter::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ const intptr_t id = ring->GetIdForObject(raw());
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddPropertyF("id", "objects/%" Pd "", id);
+ jsobj.AddProperty("name", String::Handle(name()).ToCString());
+ const Class& cls = Class::Handle(parameterized_class());
+ jsobj.AddProperty("parameterized_class", cls);
+ if (ref) {
+ return;
+ }
+ jsobj.AddProperty("index", index());
+ const AbstractType& upper_bound = AbstractType::Handle(bound());
+ jsobj.AddProperty("upper_bound", upper_bound);
}
@@ -13642,6 +13831,17 @@
void BoundedType::PrintToJSONStream(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
+ ObjectIdRing* ring = Isolate::Current()->object_id_ring();
+ const intptr_t id = ring->GetIdForObject(raw());
+ jsobj.AddProperty("type", JSONType(ref));
+ jsobj.AddPropertyF("id", "objects/%" Pd "", id);
+ const char* type_name = String::Handle(UserVisibleName()).ToCString();
+ jsobj.AddProperty("name", type_name);
+ if (ref) {
+ return;
+ }
+ jsobj.AddProperty("bounded_type", AbstractType::Handle(type()));
+ jsobj.AddProperty("upper_bound", AbstractType::Handle(bound()));
}
@@ -13675,7 +13875,7 @@
void MixinAppType::PrintToJSONStream(JSONStream* stream, bool ref) const {
- JSONObject jsobj(stream);
+ UNREACHABLE();
}
@@ -16296,7 +16496,7 @@
JSONObject jsobj(stream);
Class& cls = Class::Handle(this->clazz());
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
+ const intptr_t id = ring->GetIdForObject(raw());
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
jsobj.AddProperty("class", cls);
@@ -16636,7 +16836,7 @@
JSONObject jsobj(stream);
Class& cls = Class::Handle(this->clazz());
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
- intptr_t id = ring->GetIdForObject(raw());
+ const intptr_t id = ring->GetIdForObject(raw());
jsobj.AddProperty("type", JSONType(ref));
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
jsobj.AddProperty("class", cls);

Powered by Google App Engine
This is Rietveld 408576698