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

Side by Side Diff: runtime/vm/service.cc

Issue 2872503004: vm-service: Add optional 'scope' parameter to 'evaluate' and 'evaluateInFrame'. (Closed)
Patch Set: . Created 3 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/service.h" 5 #include "vm/service.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "include/dart_native_api.h" 8 #include "include/dart_native_api.h"
9 #include "platform/globals.h" 9 #include "platform/globals.h"
10 10
11 #include "vm/compiler.h" 11 #include "vm/compiler.h"
12 #include "vm/cpu.h" 12 #include "vm/cpu.h"
13 #include "vm/dart_api_impl.h" 13 #include "vm/dart_api_impl.h"
14 #include "vm/dart_api_state.h" 14 #include "vm/dart_api_state.h"
15 #include "vm/dart_entry.h" 15 #include "vm/dart_entry.h"
16 #include "vm/debugger.h" 16 #include "vm/debugger.h"
17 #include "vm/isolate.h" 17 #include "vm/isolate.h"
18 #include "vm/kernel_isolate.h"
18 #include "vm/lockers.h" 19 #include "vm/lockers.h"
19 #include "vm/malloc_hooks.h" 20 #include "vm/malloc_hooks.h"
20 #include "vm/message.h" 21 #include "vm/message.h"
21 #include "vm/message_handler.h" 22 #include "vm/message_handler.h"
23 #include "vm/native_arguments.h"
22 #include "vm/native_entry.h" 24 #include "vm/native_entry.h"
23 #include "vm/native_arguments.h"
24 #include "vm/native_symbol.h" 25 #include "vm/native_symbol.h"
25 #include "vm/object.h" 26 #include "vm/object.h"
26 #include "vm/object_graph.h" 27 #include "vm/object_graph.h"
27 #include "vm/object_id_ring.h" 28 #include "vm/object_id_ring.h"
28 #include "vm/object_store.h" 29 #include "vm/object_store.h"
29 #include "vm/parser.h" 30 #include "vm/parser.h"
30 #include "vm/port.h" 31 #include "vm/port.h"
31 #include "vm/profiler_service.h" 32 #include "vm/profiler_service.h"
32 #include "vm/reusable_handles.h" 33 #include "vm/reusable_handles.h"
33 #include "vm/safepoint.h" 34 #include "vm/safepoint.h"
34 #include "vm/service_event.h" 35 #include "vm/service_event.h"
35 #include "vm/service_isolate.h" 36 #include "vm/service_isolate.h"
36 #include "vm/source_report.h" 37 #include "vm/source_report.h"
37 #include "vm/stack_frame.h" 38 #include "vm/stack_frame.h"
38 #include "vm/symbols.h" 39 #include "vm/symbols.h"
39 #include "vm/timeline.h" 40 #include "vm/timeline.h"
40 #include "vm/type_table.h" 41 #include "vm/type_table.h"
41 #include "vm/unicode.h" 42 #include "vm/unicode.h"
42 #include "vm/version.h" 43 #include "vm/version.h"
43 #include "vm/kernel_isolate.h"
44 44
45 namespace dart { 45 namespace dart {
46 46
47 #define Z (T->zone()) 47 #define Z (T->zone())
48 48
49 49
50 DECLARE_FLAG(bool, trace_service); 50 DECLARE_FLAG(bool, trace_service);
51 DECLARE_FLAG(bool, trace_service_pause_events); 51 DECLARE_FLAG(bool, trace_service_pause_events);
52 DECLARE_FLAG(bool, profile_vm); 52 DECLARE_FLAG(bool, profile_vm);
53 DEFINE_FLAG(charp, 53 DEFINE_FLAG(charp,
(...skipping 2160 matching lines...) Expand 10 before | Expand all | Expand 10 after
2214 result.PrintJSON(js, true); 2214 result.PrintJSON(js, true);
2215 return true; 2215 return true;
2216 } 2216 }
2217 2217
2218 2218
2219 static const MethodParameter* evaluate_params[] = { 2219 static const MethodParameter* evaluate_params[] = {
2220 RUNNABLE_ISOLATE_PARAMETER, NULL, 2220 RUNNABLE_ISOLATE_PARAMETER, NULL,
2221 }; 2221 };
2222 2222
2223 2223
2224 static bool IsAlpha(char c) {
2225 return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
2226 }
2227 static bool IsAlphaNum(char c) {
2228 return (c >= '0' && c <= '9') || IsAlpha(c);
2229 }
2230 static bool IsWhitespace(char c) {
2231 return c <= ' ';
siva 2017/05/18 20:56:48 should this also include tab?
rmacnak 2017/05/19 00:56:44 This includes tab.
2232 }
2233 static bool IsObjectIdChar(char c) {
2234 return IsAlphaNum(c) || c == '/' || c == '-' || c == '@' || c == '%';
2235 }
2236
2237
2238 // TODO(vm-service): Consider whether we should pass structured objects in
2239 // service messages instead of always flattening them to C strings.
2240 static bool ParseScope(const char* scope,
2241 const GrowableObjectArray& names,
2242 const GrowableObjectArray& values) {
2243 const char* c = scope;
2244 if (*c++ != '{') return false;
2245
2246 String& str = String::Handle();
2247 for (;;) {
2248 while (IsWhitespace(*c)) {
2249 c++;
2250 }
2251
2252 if (*c == '}') return true;
2253
2254 const char* name = c;
2255 if (!IsAlpha(*c)) return false;
2256 while (IsAlphaNum(*c)) {
2257 c++;
2258 }
2259 str = String::FromUTF8(reinterpret_cast<const uint8_t*>(name), c - name);
siva 2017/05/18 20:56:48 Is this really a UTF8 array or can you just use On
rmacnak 2017/05/19 00:56:44 The input came from a String::ToCString(). But swi
2260 names.Add(str);
2261
2262 while (IsWhitespace(*c)) {
2263 c++;
2264 }
2265
2266 if (*c++ != ':') return false;
2267
2268 while (IsWhitespace(*c)) {
2269 c++;
2270 }
2271
2272 const char* id = c;
2273 if (!IsObjectIdChar(*c)) return false;
2274 while (IsObjectIdChar(*c)) {
2275 c++;
2276 }
2277 str = String::FromUTF8(reinterpret_cast<const uint8_t*>(id), c - id);
siva 2017/05/18 20:56:49 Ditto comment here. Also why do we need to create
2278 values.Add(str);
2279
2280 while (IsWhitespace(*c)) {
2281 c++;
2282 }
2283 if (*c == ',') c++;
2284 }
2285
2286 return false;
2287 }
2288
2289
2290 static bool BuildScope(Thread* thread,
2291 JSONStream* js,
2292 const GrowableObjectArray& names,
2293 const GrowableObjectArray& values) {
2294 const char* scope = js->LookupParam("scope");
2295 if (scope != NULL) {
2296 if (!ParseScope(scope, names, values)) {
2297 PrintInvalidParamError(js, "scope");
2298 return true;
2299 }
2300 String& id = String::Handle();
2301 Object& obj = Object::Handle();
2302 for (intptr_t i = 0; i < values.Length(); i++) {
2303 id ^= values.At(i);
2304 ObjectIdRing::LookupResult lookup_result;
2305 obj = LookupHeapObject(thread, id.ToCString(), &lookup_result);
2306 if (obj.raw() == Object::sentinel().raw()) {
2307 if (lookup_result == ObjectIdRing::kCollected) {
2308 PrintSentinel(js, kCollectedSentinel);
2309 } else if (lookup_result == ObjectIdRing::kExpired) {
2310 PrintSentinel(js, kExpiredSentinel);
2311 } else {
2312 PrintInvalidParamError(js, "targetId");
2313 }
2314 return true;
2315 }
2316 if ((!obj.IsInstance() && !obj.IsNull()) || ContainsNonInstance(obj)) {
2317 js->PrintError(kInvalidParams,
2318 "%s: invalid scope 'targetId' parameter: "
2319 "Cannot evaluate against a VM-internal object",
2320 js->method());
2321 return true;
2322 }
2323 values.SetAt(i, obj);
2324 }
2325 }
2326 return false;
2327 }
2328
2329
2224 static bool Evaluate(Thread* thread, JSONStream* js) { 2330 static bool Evaluate(Thread* thread, JSONStream* js) {
2225 if (!thread->isolate()->compilation_allowed()) { 2331 if (!thread->isolate()->compilation_allowed()) {
2226 js->PrintError(kFeatureDisabled, 2332 js->PrintError(kFeatureDisabled,
2227 "Cannot evaluate when running a precompiled program."); 2333 "Cannot evaluate when running a precompiled program.");
2228 return true; 2334 return true;
2229 } 2335 }
2230 const char* target_id = js->LookupParam("targetId"); 2336 const char* target_id = js->LookupParam("targetId");
2231 if (target_id == NULL) { 2337 if (target_id == NULL) {
2232 PrintMissingParamError(js, "targetId"); 2338 PrintMissingParamError(js, "targetId");
2233 return true; 2339 return true;
2234 } 2340 }
2235 const char* expr = js->LookupParam("expression"); 2341 const char* expr = js->LookupParam("expression");
2236 if (expr == NULL) { 2342 if (expr == NULL) {
2237 PrintMissingParamError(js, "expression"); 2343 PrintMissingParamError(js, "expression");
2238 return true; 2344 return true;
2239 } 2345 }
2346
2240 Zone* zone = thread->zone(); 2347 Zone* zone = thread->zone();
2348 const GrowableObjectArray& names =
2349 GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
2350 const GrowableObjectArray& values =
2351 GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
2352 if (BuildScope(thread, js, names, values)) {
2353 return true;
2354 }
2355 const Array& names_array = Array::Handle(zone, Array::MakeArray(names));
2356 const Array& values_array = Array::Handle(zone, Array::MakeArray(values));
2357
2241 const String& expr_str = String::Handle(zone, String::New(expr)); 2358 const String& expr_str = String::Handle(zone, String::New(expr));
2242 ObjectIdRing::LookupResult lookup_result; 2359 ObjectIdRing::LookupResult lookup_result;
2243 Object& obj = 2360 Object& obj =
2244 Object::Handle(zone, LookupHeapObject(thread, target_id, &lookup_result)); 2361 Object::Handle(zone, LookupHeapObject(thread, target_id, &lookup_result));
2245 if (obj.raw() == Object::sentinel().raw()) { 2362 if (obj.raw() == Object::sentinel().raw()) {
2246 if (lookup_result == ObjectIdRing::kCollected) { 2363 if (lookup_result == ObjectIdRing::kCollected) {
2247 PrintSentinel(js, kCollectedSentinel); 2364 PrintSentinel(js, kCollectedSentinel);
2248 } else if (lookup_result == ObjectIdRing::kExpired) { 2365 } else if (lookup_result == ObjectIdRing::kExpired) {
2249 PrintSentinel(js, kExpiredSentinel); 2366 PrintSentinel(js, kExpiredSentinel);
2250 } else { 2367 } else {
2251 PrintInvalidParamError(js, "targetId"); 2368 PrintInvalidParamError(js, "targetId");
2252 } 2369 }
2253 return true; 2370 return true;
2254 } 2371 }
2255 if (obj.IsLibrary()) { 2372 if (obj.IsLibrary()) {
2256 const Library& lib = Library::Cast(obj); 2373 const Library& lib = Library::Cast(obj);
2257 const Object& result = Object::Handle( 2374 const Object& result =
2258 zone, 2375 Object::Handle(zone, lib.Evaluate(expr_str, names_array, values_array));
2259 lib.Evaluate(expr_str, Array::empty_array(), Array::empty_array()));
2260 result.PrintJSON(js, true); 2376 result.PrintJSON(js, true);
2261 return true; 2377 return true;
2262 } 2378 }
2263 if (obj.IsClass()) { 2379 if (obj.IsClass()) {
2264 const Class& cls = Class::Cast(obj); 2380 const Class& cls = Class::Cast(obj);
2265 const Object& result = Object::Handle( 2381 const Object& result =
2266 zone, 2382 Object::Handle(zone, cls.Evaluate(expr_str, names_array, values_array));
2267 cls.Evaluate(expr_str, Array::empty_array(), Array::empty_array()));
2268 result.PrintJSON(js, true); 2383 result.PrintJSON(js, true);
2269 return true; 2384 return true;
2270 } 2385 }
2271 if ((obj.IsInstance() || obj.IsNull()) && !ContainsNonInstance(obj)) { 2386 if ((obj.IsInstance() || obj.IsNull()) && !ContainsNonInstance(obj)) {
2272 // We don't use Instance::Cast here because it doesn't allow null. 2387 // We don't use Instance::Cast here because it doesn't allow null.
2273 Instance& instance = Instance::Handle(zone); 2388 Instance& instance = Instance::Handle(zone);
2274 instance ^= obj.raw(); 2389 instance ^= obj.raw();
2275 const Class& receiver_cls = Class::Handle(zone, instance.clazz()); 2390 const Class& receiver_cls = Class::Handle(zone, instance.clazz());
2276 const Object& result = Object::Handle( 2391 const Object& result = Object::Handle(
2277 zone, instance.Evaluate(receiver_cls, expr_str, Array::empty_array(), 2392 zone,
2278 Array::empty_array())); 2393 instance.Evaluate(receiver_cls, expr_str, names_array, values_array));
2279 result.PrintJSON(js, true); 2394 result.PrintJSON(js, true);
2280 return true; 2395 return true;
2281 } 2396 }
2282 js->PrintError(kInvalidParams, 2397 js->PrintError(kInvalidParams,
2283 "%s: invalid 'targetId' parameter: " 2398 "%s: invalid 'targetId' parameter: "
2284 "Cannot evaluate against a VM-internal object", 2399 "Cannot evaluate against a VM-internal object",
2285 js->method()); 2400 js->method());
2286 return true; 2401 return true;
2287 } 2402 }
2288 2403
(...skipping 13 matching lines...) Expand all
2302 } 2417 }
2303 DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); 2418 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
2304 intptr_t framePos = UIntParameter::Parse(js->LookupParam("frameIndex")); 2419 intptr_t framePos = UIntParameter::Parse(js->LookupParam("frameIndex"));
2305 if (framePos >= stack->Length()) { 2420 if (framePos >= stack->Length()) {
2306 PrintInvalidParamError(js, "frameIndex"); 2421 PrintInvalidParamError(js, "frameIndex");
2307 return true; 2422 return true;
2308 } 2423 }
2309 ActivationFrame* frame = stack->FrameAt(framePos); 2424 ActivationFrame* frame = stack->FrameAt(framePos);
2310 2425
2311 Zone* zone = thread->zone(); 2426 Zone* zone = thread->zone();
2427 const GrowableObjectArray& names =
2428 GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
2429 const GrowableObjectArray& values =
2430 GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
2431 if (BuildScope(thread, js, names, values)) {
2432 return true;
2433 }
2434
2312 const char* expr = js->LookupParam("expression"); 2435 const char* expr = js->LookupParam("expression");
2313 const String& expr_str = String::Handle(zone, String::New(expr)); 2436 const String& expr_str = String::Handle(zone, String::New(expr));
2314 2437
2315 const Object& result = Object::Handle(zone, frame->Evaluate(expr_str)); 2438 const Object& result =
2439 Object::Handle(zone, frame->Evaluate(expr_str, names, values));
2316 result.PrintJSON(js, true); 2440 result.PrintJSON(js, true);
2317 return true; 2441 return true;
2318 } 2442 }
2319 2443
2320 2444
2321 class GetInstancesVisitor : public ObjectGraph::Visitor { 2445 class GetInstancesVisitor : public ObjectGraph::Visitor {
2322 public: 2446 public:
2323 GetInstancesVisitor(const Class& cls, const Array& storage) 2447 GetInstancesVisitor(const Class& cls, const Array& storage)
2324 : cls_(cls), storage_(storage), count_(0) {} 2448 : cls_(cls), storage_(storage), count_(0) {}
2325 2449
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
2922 } 3046 }
2923 3047
2924 static const char* const timeline_streams_enum_names[] = { 3048 static const char* const timeline_streams_enum_names[] = {
2925 "all", 3049 "all",
2926 #define DEFINE_NAME(name, unused) #name, 3050 #define DEFINE_NAME(name, unused) #name,
2927 TIMELINE_STREAM_LIST(DEFINE_NAME) 3051 TIMELINE_STREAM_LIST(DEFINE_NAME)
2928 #undef DEFINE_NAME 3052 #undef DEFINE_NAME
2929 NULL}; 3053 NULL};
2930 3054
2931 static const MethodParameter* set_vm_timeline_flags_params[] = { 3055 static const MethodParameter* set_vm_timeline_flags_params[] = {
2932 NO_ISOLATE_PARAMETER, new EnumListParameter("recordedStreams", 3056 NO_ISOLATE_PARAMETER,
2933 false, 3057 new EnumListParameter("recordedStreams",
2934 timeline_streams_enum_names), 3058 false,
3059 timeline_streams_enum_names),
2935 NULL, 3060 NULL,
2936 }; 3061 };
2937 3062
2938 3063
2939 static bool HasStream(const char** recorded_streams, const char* stream) { 3064 static bool HasStream(const char** recorded_streams, const char* stream) {
2940 while (*recorded_streams != NULL) { 3065 while (*recorded_streams != NULL) {
2941 if ((strstr(*recorded_streams, "all") != NULL) || 3066 if ((strstr(*recorded_streams, "all") != NULL) ||
2942 (strstr(*recorded_streams, stream) != NULL)) { 3067 (strstr(*recorded_streams, stream) != NULL)) {
2943 return true; 3068 return true;
2944 } 3069 }
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
3602 3727
3603 void Append(FinalizablePersistentHandle* weak_persistent_handle) { 3728 void Append(FinalizablePersistentHandle* weak_persistent_handle) {
3604 if (!weak_persistent_handle->raw()->IsHeapObject()) { 3729 if (!weak_persistent_handle->raw()->IsHeapObject()) {
3605 return; // Free handle. 3730 return; // Free handle.
3606 } 3731 }
3607 3732
3608 JSONObject obj(handles_); 3733 JSONObject obj(handles_);
3609 obj.AddProperty("type", "_WeakPersistentHandle"); 3734 obj.AddProperty("type", "_WeakPersistentHandle");
3610 const Object& object = Object::Handle(weak_persistent_handle->raw()); 3735 const Object& object = Object::Handle(weak_persistent_handle->raw());
3611 obj.AddProperty("object", object); 3736 obj.AddProperty("object", object);
3612 obj.AddPropertyF("peer", "0x%" Px "", reinterpret_cast<uintptr_t>( 3737 obj.AddPropertyF(
3613 weak_persistent_handle->peer())); 3738 "peer", "0x%" Px "",
3739 reinterpret_cast<uintptr_t>(weak_persistent_handle->peer()));
3614 obj.AddPropertyF( 3740 obj.AddPropertyF(
3615 "callbackAddress", "0x%" Px "", 3741 "callbackAddress", "0x%" Px "",
3616 reinterpret_cast<uintptr_t>(weak_persistent_handle->callback())); 3742 reinterpret_cast<uintptr_t>(weak_persistent_handle->callback()));
3617 // Attempt to include a native symbol name. 3743 // Attempt to include a native symbol name.
3618 char* name = NativeSymbolResolver::LookupSymbolName( 3744 char* name = NativeSymbolResolver::LookupSymbolName(
3619 reinterpret_cast<uintptr_t>(weak_persistent_handle->callback()), NULL); 3745 reinterpret_cast<uintptr_t>(weak_persistent_handle->callback()), NULL);
3620 obj.AddProperty("callbackSymbolName", (name == NULL) ? "" : name); 3746 obj.AddProperty("callbackSymbolName", (name == NULL) ? "" : name);
3621 if (name != NULL) { 3747 if (name != NULL) {
3622 NativeSymbolResolver::FreeSymbolName(name); 3748 NativeSymbolResolver::FreeSymbolName(name);
3623 } 3749 }
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
4204 if (strcmp(method_name, method.name) == 0) { 4330 if (strcmp(method_name, method.name) == 0) {
4205 return &method; 4331 return &method;
4206 } 4332 }
4207 } 4333 }
4208 return NULL; 4334 return NULL;
4209 } 4335 }
4210 4336
4211 #endif // !PRODUCT 4337 #endif // !PRODUCT
4212 4338
4213 } // namespace dart 4339 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698