Chromium Code Reviews| Index: runtime/vm/service.cc |
| diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc |
| index 4cbc5ddba46f142d49aa4c71cb4551b87d1c3ebb..8e37ce0e0ae8837122232df068bfee1922d2b242 100644 |
| --- a/runtime/vm/service.cc |
| +++ b/runtime/vm/service.cc |
| @@ -259,6 +259,64 @@ static bool GetCodeId(const char* s, int64_t* timestamp, uword* address) { |
| } |
| +// Verifies that |s| begins with |directory| and then calls |GetIntegerId| on |
| +// the remainder of |s|. |
| +// NOTE: Callers are required to include a trailing / in |directory|. |
| +static bool GetIntegerIdFromDirectory(const char* s, |
| + const char* directory, |
| + intptr_t* service_id) { |
|
turnidge
2015/07/13 23:37:49
The word Directory here bothers me some.
How abou
Cutch
2015/07/14 15:53:47
Done.
|
| + ASSERT(s != NULL); |
| + ASSERT(directory != NULL); |
| + const intptr_t kInputLen = strlen(s); |
| + const intptr_t kDirectoryLen = strlen(directory); |
| + ASSERT(kDirectoryLen > 0); |
| + ASSERT(directory[kDirectoryLen - 1] == '/'); |
| + if (kInputLen <= kDirectoryLen) { |
| + return false; |
| + } |
| + if (strncmp(s, directory, kDirectoryLen) != 0) { |
| + return false; |
| + } |
| + // Directory prefix satisfied. Move forward. |
| + s += kDirectoryLen; |
| + // Attempt to read integer id. |
| + return GetIntegerId(s, service_id); |
| +} |
| + |
| + |
| +static bool ValidateClassId(Isolate* isolate, intptr_t cid) { |
|
turnidge
2015/07/13 23:37:49
Change name to IsValidClassId?
Cutch
2015/07/14 15:53:47
Done.
|
| + ASSERT(isolate != NULL); |
| + ClassTable* class_table = isolate->class_table(); |
| + ASSERT(class_table != NULL); |
| + return class_table->IsValidIndex(cid) && class_table->HasValidClassAt(cid); |
| +} |
| + |
| + |
| +static bool ValidateClassId(Isolate* isolate, const char* class_id) { |
| + intptr_t cid; |
| + if (!GetIntegerIdFromDirectory(class_id, "classes/", &cid)) { |
| + return false; |
| + } |
| + return ValidateClassId(isolate, cid); |
| +} |
|
turnidge
2015/07/13 23:37:49
I would like you to get rid of the overloaded vers
Cutch
2015/07/14 15:53:47
Done.
|
| + |
| + |
| +static RawClass* GetClassForId(Isolate* isolate, intptr_t cid) { |
| + ASSERT(isolate == Isolate::Current()); |
| + ASSERT(isolate != NULL); |
| + ClassTable* class_table = isolate->class_table(); |
| + ASSERT(class_table != NULL); |
| + return class_table->At(cid); |
| +} |
| + |
| + |
| +static RawClass* GetClassForId(Isolate* isolate, const char* class_id) { |
| + intptr_t cid; |
| + ASSERT(GetIntegerIdFromDirectory(class_id, "classes/", &cid)); |
|
turnidge
2015/07/13 23:37:49
Do ASSERTs get removed in release builds? I don't
Cutch
2015/07/14 15:53:47
Good catch.
|
| + return GetClassForId(isolate, cid); |
| +} |
| + |
| + |
| // TODO(johnmccutchan): Split into separate file and write unit tests. |
| class MethodParameter { |
| public: |
| @@ -342,6 +400,9 @@ class UIntParameter : public MethodParameter { |
| } |
| static intptr_t Parse(const char* value) { |
| + if (value == NULL) { |
| + return -1; |
| + } |
| char* end_ptr = NULL; |
| uintptr_t result = strtoul(value, &end_ptr, 10); |
| ASSERT(*end_ptr == '\0'); // Parsed full string |
| @@ -2232,6 +2293,7 @@ static Profile::TagOrder tags_enum_values[] = { |
| static const MethodParameter* get_cpu_profile_params[] = { |
| ISOLATE_PARAMETER, |
| new EnumParameter("tags", true, tags_enum_names), |
| + new IdParameter("classId", false), |
| NULL, |
| }; |
| @@ -2239,7 +2301,13 @@ static const MethodParameter* get_cpu_profile_params[] = { |
| static bool GetCpuProfile(Isolate* isolate, JSONStream* js) { |
|
turnidge
2015/07/13 23:37:49
As mentioned elsewhere, consider separating cpu an
Cutch
2015/07/14 15:53:47
Done.
|
| Profile::TagOrder tag_order = |
| EnumMapper(js->LookupParam("tags"), tags_enum_names, tags_enum_values); |
| - ProfilerService::PrintJSON(js, tag_order); |
| + const char* class_id = js->LookupParam("classId"); |
| + if (ValidateClassId(isolate, class_id)) { |
| + const Class& cls = Class::Handle(GetClassForId(isolate, class_id)); |
|
turnidge
2015/07/13 23:37:49
You are double-parsing the class id, once in Valid
Cutch
2015/07/14 15:53:47
Done.
|
| + ProfilerService::PrintAllocationJSON(js, tag_order, cls); |
| + } else { |
| + ProfilerService::PrintJSON(js, tag_order); |
| + } |
| return true; |
| } |
| @@ -2751,6 +2819,32 @@ static bool SetName(Isolate* isolate, JSONStream* js) { |
| } |
| +static const MethodParameter* trace_class_allocation_params[] = { |
| + ISOLATE_PARAMETER, |
| + new IdParameter("classId", true), |
| + new BoolParameter("enable", true), |
| + NULL, |
| +}; |
| + |
| + |
| +static bool TraceClassAllocation(Isolate* isolate, JSONStream* js) { |
| + const char* class_id = js->LookupParam("classId"); |
| + const bool enable = BoolParameter::Parse(js->LookupParam("enable")); |
| + |
| + if (!ValidateClassId(isolate, class_id)) { |
| + PrintInvalidParamError(js, "cid"); |
| + return true; |
| + } |
| + |
| + const Class& cls = Class::Handle(GetClassForId(isolate, class_id)); |
| + ASSERT(!cls.IsNull()); |
| + |
| + cls.SetTraceAllocation(enable); |
| + PrintSuccess(js); |
| + return true; |
| +} |
| + |
| + |
| static ServiceMethodDescriptor service_methods_[] = { |
| { "_dumpIdZone", DumpIdZone, NULL }, |
| { "_echo", Echo, |
| @@ -2837,6 +2931,8 @@ static ServiceMethodDescriptor service_methods_[] = { |
| set_library_debuggable_params }, |
| { "setName", SetName, |
| set_name_params }, |
| + { "_traceClassAllocation", TraceClassAllocation, |
|
turnidge
2015/07/13 23:37:49
Consider changing rpc name for consistency with se
Cutch
2015/07/14 15:53:48
Done.
|
| + trace_class_allocation_params }, |
| }; |