Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index 83dcfc0e454e6977881b1aec3297d9738815cd7a..37fa9c353ac608ca9dacb7b22a9ebc3d42ec1ab6 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -1818,14 +1818,10 @@ intptr_t Class::FindFunctionIndex(const Function& needle) const { |
funcs ^= functions(); |
ASSERT(!funcs.IsNull()); |
Function& function = reused_handles.FunctionHandle(); |
- String& function_name = reused_handles.StringHandle(); |
- String& needle_name = String::Handle(isolate); |
- needle_name ^= needle.name(); |
const intptr_t len = funcs.Length(); |
for (intptr_t i = 0; i < len; i++) { |
function ^= funcs.At(i); |
- function_name ^= function.name(); |
- if (function_name.Equals(needle_name)) { |
+ if (function.raw() == needle.raw()) { |
return i; |
} |
} |
@@ -1834,6 +1830,106 @@ intptr_t Class::FindFunctionIndex(const Function& needle) const { |
} |
+RawFunction* Class::FunctionFromIndex(intptr_t idx) const { |
+ const Array& funcs = Array::Handle(functions()); |
+ if ((idx < 0) || (idx >= funcs.Length())) { |
+ return Function::null(); |
+ } |
+ Function& func = Function::Handle(); |
+ func ^= funcs.At(idx); |
+ ASSERT(!func.IsNull()); |
+ return func.raw(); |
+} |
+ |
+ |
+RawFunction* Class::ImplicitClosureFunctionFromIndex(intptr_t idx) const { |
+ const Array& funcs = Array::Handle(functions()); |
+ if ((idx < 0) || (idx >= funcs.Length())) { |
+ return Function::null(); |
+ } |
+ Function& func = Function::Handle(); |
+ func ^= funcs.At(idx); |
+ ASSERT(!func.IsNull()); |
+ if (!func.HasImplicitClosureFunction()) { |
+ return Function::null(); |
+ } |
+ const Function& closure_func = |
+ Function::Handle(func.ImplicitClosureFunction()); |
+ ASSERT(!closure_func.IsNull()); |
+ return closure_func.raw(); |
+} |
+ |
+ |
+intptr_t Class::FindImplicitClosureFunctionIndex(const Function& needle) const { |
+ Isolate* isolate = Isolate::Current(); |
+ if (EnsureIsFinalized(isolate) != Error::null()) { |
+ return -1; |
+ } |
+ ReusableHandleScope reused_handles(isolate); |
+ Array& funcs = reused_handles.ArrayHandle(); |
+ funcs ^= functions(); |
+ ASSERT(!funcs.IsNull()); |
+ Function& function = reused_handles.FunctionHandle(); |
+ Function& implicit_closure = Function::Handle(); |
+ const intptr_t len = funcs.Length(); |
+ for (intptr_t i = 0; i < len; i++) { |
+ function ^= funcs.At(i); |
+ implicit_closure ^= function.implicit_closure_function(); |
+ if (implicit_closure.IsNull()) { |
+ // Skip non-implicit closure functions. |
+ continue; |
+ } |
+ if (needle.raw() == implicit_closure.raw()) { |
+ return i; |
+ } |
+ } |
+ // No function found. |
+ return -1; |
+} |
+ |
+ |
+ |
+intptr_t Class::FindInvocationDispatcherFunctionIndex( |
+ const Function& needle) const { |
+ Isolate* isolate = Isolate::Current(); |
+ if (EnsureIsFinalized(isolate) != Error::null()) { |
+ return -1; |
+ } |
+ ReusableHandleScope reused_handles(isolate); |
+ Array& funcs = reused_handles.ArrayHandle(); |
+ funcs ^= invocation_dispatcher_cache(); |
+ ASSERT(!funcs.IsNull()); |
+ Object& object = reused_handles.ObjectHandle(); |
+ const intptr_t len = funcs.Length(); |
+ for (intptr_t i = 0; i < len; i++) { |
+ object = funcs.At(i); |
+ // The invocation_dispatcher_cache is a table with some entries that |
+ // are functions. |
+ if (object.IsFunction()) { |
+ if (Function::Cast(object).raw() == needle.raw()) { |
+ return i; |
+ } |
+ } |
+ } |
+ // No function found. |
+ return -1; |
+} |
+ |
+ |
+ |
+RawFunction* Class::InvocationDispatcherFunctionFromIndex(intptr_t idx) const { |
+ ReusableHandleScope reused_handles(Isolate::Current()); |
+ Array& dispatcher_cache = reused_handles.ArrayHandle(); |
+ dispatcher_cache ^= invocation_dispatcher_cache(); |
+ Object& object = reused_handles.ObjectHandle(); |
+ object = dispatcher_cache.At(idx); |
+ if (!object.IsFunction()) { |
+ return Function::null(); |
+ } |
+ return Function::Cast(object).raw(); |
+} |
+ |
+ |
void Class::AddClosureFunction(const Function& function) const { |
GrowableObjectArray& closures = |
GrowableObjectArray::Handle(raw_ptr()->closure_functions_); |
@@ -1874,7 +1970,7 @@ RawFunction* Class::LookupClosureFunction(intptr_t token_pos) const { |
return closure.raw(); |
} |
-intptr_t Class::FindClosureIndex(intptr_t token_pos) const { |
+intptr_t Class::FindClosureIndex(const Function& needle) const { |
if (closures() == GrowableObjectArray::null()) { |
return -1; |
} |
@@ -1884,19 +1980,27 @@ intptr_t Class::FindClosureIndex(intptr_t token_pos) const { |
GrowableObjectArray::Handle(isolate, closures()); |
Function& closure = reused_handles.FunctionHandle(); |
intptr_t num_closures = closures_array.Length(); |
- intptr_t best_fit_token_pos = -1; |
- intptr_t best_fit_index = -1; |
for (intptr_t i = 0; i < num_closures; i++) { |
closure ^= closures_array.At(i); |
ASSERT(!closure.IsNull()); |
- if ((closure.token_pos() <= token_pos) && |
- (token_pos <= closure.end_token_pos()) && |
- (best_fit_token_pos < closure.token_pos())) { |
- best_fit_index = i; |
- best_fit_token_pos = closure.token_pos(); |
+ if (closure.raw() == needle.raw()) { |
+ return i; |
} |
} |
- return best_fit_index; |
+ return -1; |
+} |
+ |
+ |
+RawFunction* Class::ClosureFunctionFromIndex(intptr_t idx) const { |
+ const GrowableObjectArray& closures_array = |
+ GrowableObjectArray::Handle(closures()); |
+ if ((idx < 0) || (idx >= closures_array.Length())) { |
+ return Function::null(); |
+ } |
+ Function& func = Function::Handle(); |
+ func ^= closures_array.At(idx); |
+ ASSERT(!func.IsNull()); |
+ return func.raw(); |
} |
@@ -2477,6 +2581,18 @@ intptr_t Class::FindFieldIndex(const Field& needle) const { |
} |
+RawField* Class::FieldFromIndex(intptr_t idx) const { |
+ const Array& flds = Array::Handle(fields()); |
+ if ((idx < 0) || (idx >= flds.Length())) { |
+ return Field::null(); |
+ } |
+ Field& field = Field::Handle(); |
+ field ^= flds.At(idx); |
+ ASSERT(!field.IsNull()); |
+ return field.raw(); |
+} |
+ |
+ |
template <class FakeInstance> |
RawClass* Class::New(intptr_t index) { |
ASSERT(Object::class_class() != Class::null()); |
@@ -4451,6 +4567,54 @@ RawType* Function::RedirectionType() const { |
} |
+const char* Function::KindToCString(RawFunction::Kind kind) { |
+ switch (kind) { |
+ case RawFunction::kRegularFunction: |
+ return "kRegularFunction"; |
+ break; |
+ case RawFunction::kClosureFunction: |
+ return "kClosureFunction"; |
+ break; |
+ case RawFunction::kSignatureFunction: |
+ return "kSignatureFunction"; |
+ break; |
+ case RawFunction::kGetterFunction: |
+ return "kGetterFunction"; |
+ break; |
+ case RawFunction::kSetterFunction: |
+ return "kSetterFunction"; |
+ break; |
+ case RawFunction::kConstructor: |
+ return "kConstructor"; |
+ break; |
+ case RawFunction::kImplicitGetter: |
+ return "kImplicitGetter"; |
+ break; |
+ case RawFunction::kImplicitSetter: |
+ return "kImplicitSetter"; |
+ break; |
+ case RawFunction::kImplicitStaticFinalGetter: |
+ return "kImplicitStaticFinalGetter"; |
+ break; |
+ case RawFunction::kStaticInitializer: |
+ return "kStaticInitializer"; |
+ break; |
+ case RawFunction::kMethodExtractor: |
+ return "kMethodExtractor"; |
+ break; |
+ case RawFunction::kNoSuchMethodDispatcher: |
+ return "kNoSuchMethodDispatcher"; |
+ break; |
+ case RawFunction::kInvokeFieldDispatcher: |
+ return "kInvokeFieldDispatcher"; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ return NULL; |
+ } |
+} |
+ |
+ |
void Function::SetRedirectionType(const Type& type) const { |
ASSERT(IsFactory()); |
Object& obj = Object::Handle(raw_ptr()->data_); |
@@ -5711,25 +5875,30 @@ void Function::PrintToJSONStream(JSONStream* stream, bool ref) const { |
const char* function_name = |
String::Handle(QualifiedUserVisibleName()).ToCString(); |
Class& cls = Class::Handle(Owner()); |
+ ASSERT(!cls.IsNull()); |
Error& err = Error::Handle(); |
err ^= cls.EnsureIsFinalized(Isolate::Current()); |
ASSERT(err.IsNull()); |
- const Function& func = *this; |
- intptr_t id; |
+ intptr_t id = -1; |
+ const char* selector = NULL; |
if (IsNonImplicitClosureFunction()) { |
- id = cls.FindClosureIndex(token_pos()); |
+ id = cls.FindClosureIndex(*this); |
+ selector = "closures"; |
+ } else if (IsImplicitClosureFunction()) { |
+ id = cls.FindImplicitClosureFunctionIndex(*this); |
+ selector = "implicit_closures"; |
+ } else if (IsNoSuchMethodDispatcher() || IsInvokeFieldDispatcher()) { |
+ id = cls.FindInvocationDispatcherFunctionIndex(*this); |
+ selector = "dispatchers"; |
} else { |
- id = cls.FindFunctionIndex(func); |
+ id = cls.FindFunctionIndex(*this); |
+ selector = "functions"; |
} |
ASSERT(id >= 0); |
intptr_t cid = cls.id(); |
JSONObject jsobj(stream); |
jsobj.AddProperty("type", JSONType(ref)); |
- if (IsNonImplicitClosureFunction()) { |
- jsobj.AddPropertyF("id", "classes/%" Pd "/closures/%" Pd "", cid, id); |
- } else { |
- jsobj.AddPropertyF("id", "classes/%" Pd "/functions/%" Pd "", cid, id); |
- } |
+ jsobj.AddPropertyF("id", "classes/%" Pd "/%s/%" Pd "", cid, selector, id); |
jsobj.AddProperty("name", internal_function_name); |
jsobj.AddProperty("user_name", function_name); |
if (ref) return; |
@@ -5737,44 +5906,7 @@ void Function::PrintToJSONStream(JSONStream* stream, bool ref) const { |
jsobj.AddProperty("is_const", is_const()); |
jsobj.AddProperty("is_optimizable", is_optimizable()); |
jsobj.AddProperty("is_inlinable", IsInlineable()); |
- const char* kind_string = NULL; |
- switch (kind()) { |
- case RawFunction::kRegularFunction: |
- kind_string = "regular"; |
- break; |
- case RawFunction::kGetterFunction: |
- kind_string = "getter"; |
- break; |
- case RawFunction::kSetterFunction: |
- kind_string = "setter"; |
- break; |
- case RawFunction::kImplicitGetter: |
- kind_string = "implicit getter"; |
- break; |
- case RawFunction::kImplicitSetter: |
- kind_string = "implicit setter"; |
- break; |
- case RawFunction::kMethodExtractor: |
- kind_string = "method extractor"; |
- break; |
- case RawFunction::kNoSuchMethodDispatcher: |
- kind_string = "no such method"; |
- break; |
- case RawFunction::kClosureFunction: |
- kind_string = "closure"; |
- break; |
- case RawFunction::kConstructor: |
- kind_string = "constructor"; |
- break; |
- case RawFunction::kStaticInitializer: |
- kind_string = "static initializer"; |
- break; |
- case RawFunction::kImplicitStaticFinalGetter: |
- kind_string = "static final getter"; |
- break; |
- default: |
- UNREACHABLE(); |
- } |
+ const char* kind_string = Function::KindToCString(kind()); |
jsobj.AddProperty("kind", kind_string); |
jsobj.AddProperty("unoptimized_code", Object::Handle(unoptimized_code())); |
jsobj.AddProperty("usage_counter", usage_counter()); |
@@ -9691,10 +9823,26 @@ void Code::SetStaticCallTargetCodeAt(uword pc, const Code& code) const { |
} |
-void Code::Disassemble() const { |
+void Code::Disassemble(DisassemblyFormatter* formatter) const { |
+ const bool fix_patch = CodePatcher::CodeIsPatchable(*this) && |
+ CodePatcher::IsEntryPatched(*this); |
+ if (fix_patch) { |
+ // The disassembler may choke on illegal instructions if the code has been |
+ // patched, un-patch the code before disassembling and re-patch after. |
+ CodePatcher::RestoreEntry(*this); |
+ } |
const Instructions& instr = Instructions::Handle(instructions()); |
uword start = instr.EntryPoint(); |
- Disassembler::Disassemble(start, start + instr.size(), comments()); |
+ if (formatter == NULL) { |
+ Disassembler::Disassemble(start, start + instr.size(), comments()); |
+ } else { |
+ Disassembler::Disassemble(start, start + instr.size(), formatter, |
+ comments()); |
+ } |
+ if (fix_patch) { |
+ // Redo the patch. |
+ CodePatcher::PatchEntry(*this); |
+ } |
} |
@@ -9876,16 +10024,16 @@ const char* Code::ToCString() const { |
void Code::PrintToJSONStream(JSONStream* stream, bool ref) const { |
- Isolate* isolate = Isolate::Current(); |
- ObjectIdRing* ring = isolate->object_id_ring(); |
- intptr_t id = ring->GetIdForObject(raw()); |
JSONObject jsobj(stream); |
jsobj.AddProperty("type", JSONType(ref)); |
- jsobj.AddPropertyF("id", "objects/%" Pd "", id); |
+ jsobj.AddPropertyF("id", "code/%" Px "", EntryPoint()); |
+ jsobj.AddPropertyF("start", "%" Px "", EntryPoint()); |
+ jsobj.AddPropertyF("end", "%" Px "", EntryPoint() + Size()); |
Function& func = Function::Handle(); |
- String& name = String::Handle(); |
func ^= function(); |
ASSERT(!func.IsNull()); |
+ String& name = String::Handle(); |
+ ASSERT(!func.IsNull()); |
name ^= func.name(); |
const char* internal_function_name = name.ToCString(); |
jsobj.AddPropertyF("name", "%s%s", is_optimized() ? "*" : "", |
@@ -9902,10 +10050,7 @@ void Code::PrintToJSONStream(JSONStream* stream, bool ref) const { |
jsobj.AddProperty("function", Object::Handle(function())); |
JSONArray jsarr(&jsobj, "disassembly"); |
DisassembleToJSONStream formatter(jsarr); |
- const Instructions& instr = Instructions::Handle(instructions()); |
- uword start = instr.EntryPoint(); |
- Disassembler::Disassemble(start, start + instr.size(), &formatter, |
- comments()); |
+ Disassemble(&formatter); |
} |