Skip to content

Commit

Permalink
Support stacktrace and objecthistogram service commands
Browse files Browse the repository at this point in the history
R=asiva@google.com

Review URL: https://codereview.chromium.org//19870006

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@25726 260f80e4-7a28-3924-810f-c04153c831b5
  • Loading branch information
johnmccutchan committed Aug 2, 2013
1 parent 8cc2fe2 commit 97ef50a
Show file tree
Hide file tree
Showing 26 changed files with 717 additions and 76 deletions.
2 changes: 2 additions & 0 deletions runtime/bin/vmservice/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.buildlog
pubspec.lock
33 changes: 20 additions & 13 deletions runtime/bin/vmservice/running_isolate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ part of vmservice;

class RunningIsolate implements ServiceRequestRouter {
final SendPort sendPort;
String id = 'Unknown';
String name = 'Unknown';

RunningIsolate(this.sendPort);

Future sendMessage(String request) {
Future sendMessage(List request) {
final completer = new Completer.sync();
final receivePort = new ReceivePort();
sendServiceMessage(sendPort, receivePort, request);
Expand All @@ -25,24 +25,31 @@ class RunningIsolate implements ServiceRequestRouter {
return completer.future;
}

bool route(ServiceRequest request) {
// Do nothing for now.
return false;
Future route(ServiceRequest request) {
// Send message to isolate.
var message = request.toServiceCallMessage();
return sendMessage(message).then((response) {
request.setResponse(response);
return new Future.value(request);
});
}

void sendIdRequest() {
var request = JSON.stringify({'p': ['id'], 'k': [], 'v': []});
sendMessage(request).then(_handleIdResponse);
void _sendNameRequest() {
var request = new ServiceRequest();
request.parse(Uri.parse('/name'));
sendMessage(request.toServiceCallMessage()).then(_handleNameResponse);
}

void _handleIdResponse(responseString) {
var response;
void _handleNameResponse(String responseString) {
try {
response = JSON.parse(responseString);
var response = JSON.parse(responseString);
name = response['name'];
} catch (e) {
id = 'Error retrieving isolate id.';
name = 'Error retrieving isolate name.';
return;
}
id = response['id'];
if (name == null) {
name = 'Error retrieving isolate name.';
}
}
}
21 changes: 13 additions & 8 deletions runtime/bin/vmservice/running_isolates.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class RunningIsolates implements ServiceRequestRouter {
}
var ri = new RunningIsolate(sp);
isolates[sp.hashCode] = ri;
ri.sendIdRequest();
ri._sendNameRequest();
}

void isolateShutdown(SendPort sp) {
Expand All @@ -31,40 +31,45 @@ class RunningIsolates implements ServiceRequestRouter {
isolates.forEach((sp, ri) {
members.add({
'id': sp,
'name': ri.id
'name': ri.name
});
});
result['type'] = 'IsolateList';
result['members'] = members;
request.setResponse(JSON.stringify(result));
}

bool route(ServiceRequest request) {
Future route(ServiceRequest request) {
if (request.pathSegments.length == 0) {
return false;
return null;
}
if (request.pathSegments[0] != 'isolates') {
return false;
return null;
}
if (request.pathSegments.length == 1) {
// Requesting list of running isolates.
_isolateCollectionRequest(request);
return true;
return new Future.value(request);
}
var isolateId;
try {
isolateId = int.parse(request.pathSegments[1]);
} catch (e) {
request.setErrorResponse('Could not parse isolate id: $e');
return true;
return new Future.value(request);
}
var isolate = isolates[isolateId];
if (isolate == null) {
request.setErrorResponse('Cannot find isolate id: $isolateId');
return true;
return new Future.value(request);
}
// Consume '/isolates/isolateId'
request.pathSegments.removeRange(0, 2);
if (request.pathSegments.length == 0) {
// The request is now empty.
request.setErrorResponse('No request for isolate: /isolates/$isolateId');
return new Future.value(request);
}
return isolate.route(request);
}
}
13 changes: 9 additions & 4 deletions runtime/bin/vmservice/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,20 @@ class Server {
// Did not understand the request uri.
serviceRequest.setErrorResponse('Invalid request uri: ${request.uri}');
} else {
r = service.runningIsolates.route(serviceRequest);
if (!r) {
var f = service.runningIsolates.route(serviceRequest);
if (f != null) {
f.then((_) {
request.response.headers.contentType = jsonContentType;
request.response.write(serviceRequest.response);
request.response.close();
}).catchError((e) { });
return;
} else {
// Nothing responds to this type of request.
serviceRequest.setErrorResponse('No route for: $path');
}
}

// Send response back over HTTP.
request.response.headers.contentType = jsonContentType;
request.response.write(serviceRequest.response);
request.response.close();
Expand All @@ -62,4 +68,3 @@ class Server {
});
}
}

11 changes: 4 additions & 7 deletions runtime/bin/vmservice/service_request.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,14 @@ class ServiceRequest {
return true;
}

String toServiceCallMessage() {
return JSON.stringify({
'p': pathSegments,
'k': parameters.keys.toList(),
'v': parameters.values.toList()
});
List toServiceCallMessage() {
return [pathSegments, parameters.keys.toList(), parameters.values.toList()];
}

void setErrorResponse(String error) {
_response = JSON.stringify({
'error': error,
'type': 'error',
'msg': error,
'pathSegments': pathSegments,
'parameters': parameters
});
Expand Down
2 changes: 1 addition & 1 deletion runtime/bin/vmservice/service_request_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
part of vmservice;

abstract class ServiceRequestRouter {
bool route(ServiceRequest request);
Future route(ServiceRequest request);
}
2 changes: 2 additions & 0 deletions runtime/bin/vmservice_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ bool VmService::_Start(intptr_t server_port) {

result = LoadResources(library);
SHUTDOWN_ON_ERROR(result);
result = Dart_CompileAll();
SHUTDOWN_ON_ERROR(result);

port_ = Dart_GetMainPortId();

Expand Down
39 changes: 39 additions & 0 deletions runtime/vm/disassembler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "vm/assembler.h"
#include "vm/globals.h"
#include "vm/os.h"
#include "vm/json_stream.h"

namespace dart {

Expand Down Expand Up @@ -36,4 +37,42 @@ void DisassembleToStdout::Print(const char* format, ...) {
va_end(args);
}


void DisassembleToJSONStream::ConsumeInstruction(char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size,
uword pc) {
uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc);
stream_->OpenObject();
stream_->PrintProperty("type", "DisassembledInstruction");
stream_->PrintfProperty("pc", "%p", pc_ptr);
stream_->PrintProperty("hex", hex_buffer);
stream_->PrintProperty("human", human_buffer);
stream_->CloseObject();
}


void DisassembleToJSONStream::Print(const char* format, ...) {
va_list args;
va_start(args, format);
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
va_end(args);
char* p = reinterpret_cast<char*>(malloc(len+1));
va_start(args, format);
intptr_t len2 = OS::VSNPrint(p, len, format, args);
va_end(args);
ASSERT(len == len2);
for (intptr_t i = 0; i < len; i++) {
if (p[i] == '\n' || p[i] == '\r') {
p[i] = ' ';
}
}
stream_->OpenObject();
stream_->PrintProperty("type", "DisassembledInstructionComment");
stream_->PrintProperty("comment", p);
stream_->CloseObject();
free(p);
}

} // namespace dart
23 changes: 23 additions & 0 deletions runtime/vm/disassembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace dart {

// Froward declaration.
class MemoryRegion;
class JSONStream;

// Disassembly formatter interface, which consumes the
// disassembled instructions in any desired form.
Expand Down Expand Up @@ -54,6 +55,28 @@ class DisassembleToStdout : public DisassemblyFormatter {
};


// Disassemble into a JSONStream.
class DisassembleToJSONStream : public DisassemblyFormatter {
public:
explicit DisassembleToJSONStream(JSONStream* stream) : DisassemblyFormatter(),
stream_(stream) { }
~DisassembleToJSONStream() { }

virtual void ConsumeInstruction(char* hex_buffer,
intptr_t hex_size,
char* human_buffer,
intptr_t human_size,
uword pc);

virtual void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);

private:
JSONStream* stream_;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(DisassembleToJSONStream);
};


// Disassemble instructions.
class Disassembler : public AllStatic {
public:
Expand Down
Loading

0 comments on commit 97ef50a

Please sign in to comment.