Chromium Code Reviews| Index: runtime/vm/object.cc |
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
| index 83dcfc0e454e6977881b1aec3297d9738815cd7a..06c642968abf5b64b28decbb7b01e8468b724ebe 100644 |
| --- a/runtime/vm/object.cc |
| +++ b/runtime/vm/object.cc |
| @@ -1818,15 +1818,68 @@ 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; |
| + } |
| + } |
| + // No function found. |
| + return -1; |
| +} |
| + |
| + |
| + |
| +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. |
| @@ -1834,6 +1887,20 @@ intptr_t Class::FindFunctionIndex(const Function& needle) const { |
| } |
| + |
| +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 +1941,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 +1951,14 @@ 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; |
| } |
| @@ -4451,6 +4513,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,22 +5821,32 @@ 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; |
| if (IsNonImplicitClosureFunction()) { |
|
Ivan Posva
2014/01/03 01:52:17
Please consolidate this lookup with the one below.
Cutch
2014/01/03 16:01:56
Done.
|
| - id = cls.FindClosureIndex(token_pos()); |
| + id = cls.FindClosureIndex(*this); |
| + } else if (IsImplicitClosureFunction()) { |
| + id = cls.FindImplicitClosureFunctionIndex(*this); |
| + } else if (IsNoSuchMethodDispatcher() || IsInvokeFieldDispatcher()) { |
| + id = cls.FindInvocationDispatcherFunctionIndex(*this); |
| } else { |
| - id = cls.FindFunctionIndex(func); |
| + id = cls.FindFunctionIndex(*this); |
| } |
| + const char* kind_string = Function::KindToCString(kind()); |
| 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 if (IsImplicitClosureFunction()) { |
| + jsobj.AddPropertyF("id", "classes/%" Pd "/implicit_closures/%" Pd "", |
| + cid, id); |
| + } else if (IsNoSuchMethodDispatcher() || IsInvokeFieldDispatcher()) { |
| + jsobj.AddPropertyF("id", "classes/%" Pd "/dispatchers/%" Pd "", cid, id); |
| } else { |
| jsobj.AddPropertyF("id", "classes/%" Pd "/functions/%" Pd "", cid, id); |
| } |
| @@ -5737,44 +5857,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(); |
| - } |
| + |
| jsobj.AddProperty("kind", kind_string); |
| jsobj.AddProperty("unoptimized_code", Object::Handle(unoptimized_code())); |
| jsobj.AddProperty("usage_counter", usage_counter()); |
| @@ -9692,9 +9775,38 @@ void Code::SetStaticCallTargetCodeAt(uword pc, const Code& code) const { |
| void Code::Disassemble() 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 (fix_patch) { |
| + // Redo the patch. |
| + CodePatcher::PatchEntry(*this); |
| + } |
| +} |
| + |
| + |
| +void Code::Disassemble(DisassemblyFormatter* formatter) const { |
|
Ivan Posva
2014/01/03 01:52:17
Can you consolidate these two identical functions
Cutch
2014/01/03 16:01:56
Done.
|
| + 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(), formatter, comments()); |
| + if (fix_patch) { |
| + // Redo the patch. |
| + CodePatcher::PatchEntry(*this); |
| + } |
| } |
| @@ -9876,16 +9988,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 +10014,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); |
| } |