Index: runtime/vm/isolate.cc |
=================================================================== |
--- runtime/vm/isolate.cc (revision 32126) |
+++ runtime/vm/isolate.cc (working copy) |
@@ -104,6 +104,9 @@ |
StartIsolateScope start_scope(isolate_); |
StackZone zone(isolate_); |
HandleScope handle_scope(isolate_); |
+ // TODO(turnidge): Rework collection total dart execution. This can |
+ // overcount when other things (gc, compilation) are active. |
+ TIMERSCOPE(time_dart_execution); |
// If the message is in band we lookup the receive port to dispatch to. If |
// the receive port is closed, we drop the message without deserializing it. |
@@ -300,7 +303,7 @@ |
stack_limit_(0), |
saved_stack_limit_(0), |
message_handler_(NULL), |
- spawn_data_(0), |
+ spawn_state_(NULL), |
is_runnable_(false), |
gc_prologue_callbacks_(), |
gc_epilogue_callbacks_(), |
@@ -336,6 +339,7 @@ |
message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. |
ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted. |
delete object_histogram_; |
+ delete spawn_state_; |
} |
void Isolate::SetCurrent(Isolate* current) { |
@@ -498,7 +502,7 @@ |
// Set the isolate as runnable and if we are being spawned schedule |
// isolate on thread pool for execution. |
is_runnable_ = true; |
- IsolateSpawnState* state = reinterpret_cast<IsolateSpawnState*>(spawn_data()); |
+ IsolateSpawnState* state = spawn_state(); |
if (state != NULL) { |
ASSERT(this == state->isolate()); |
Run(); |
@@ -518,9 +522,9 @@ |
Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
IsolateSpawnState* state = NULL; |
{ |
+ // TODO(turnidge): Is this locking required here at all anymore? |
MutexLocker ml(isolate->mutex()); |
- state = reinterpret_cast<IsolateSpawnState*>(isolate->spawn_data()); |
- isolate->set_spawn_data(0); |
+ state = isolate->spawn_state(); |
} |
{ |
StartIsolateScope start_scope(isolate); |
@@ -540,8 +544,6 @@ |
Object& result = Object::Handle(); |
result = state->ResolveFunction(); |
bool is_spawn_uri = state->is_spawn_uri(); |
- delete state; |
- state = NULL; |
if (result.IsError()) { |
StoreError(isolate, result); |
return false; |
@@ -820,202 +822,51 @@ |
} |
-static Monitor* status_sync = NULL; |
- |
- |
-bool Isolate::FetchStacktrace() { |
- Isolate* isolate = Isolate::Current(); |
- MonitorLocker ml(status_sync); |
- DebuggerStackTrace* stack = Debugger::CollectStackTrace(); |
- TextBuffer buffer(256); |
- buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"stacktrace\": [ ", |
- reinterpret_cast<int64_t>(isolate)); |
- intptr_t n_frames = stack->Length(); |
- String& url = String::Handle(); |
- String& function = String::Handle(); |
- for (int i = 0; i < n_frames; i++) { |
- if (i > 0) { |
- buffer.Printf(", "); |
+void Isolate::PrintToJSONStream(JSONStream* stream) { |
+ fprintf(stderr, "Printing isolate %" Pd "\n", |
+ static_cast<intptr_t>(main_port())); |
+ JSONObject jsobj(stream); |
+ jsobj.AddProperty("type", "Isolate"); |
+ jsobj.AddPropertyF("id", "isolates/%" Pd "", |
+ static_cast<intptr_t>(main_port())); |
+ jsobj.AddPropertyF("name", "%" Pd "", |
+ static_cast<intptr_t>(main_port())); |
+ IsolateSpawnState* state = spawn_state(); |
+ if (state != NULL) { |
+ const Object& entry = Object::Handle(this, state->ResolveFunction()); |
+ if (!entry.IsNull() && entry.IsFunction()) { |
+ Function& func = Function::Handle(this); |
+ func ^= entry.raw(); |
+ jsobj.AddProperty("entry", func); |
} |
- ActivationFrame* frame = stack->FrameAt(i); |
- url ^= frame->SourceUrl(); |
- function ^= frame->function().UserVisibleName(); |
- buffer.Printf("{ \"url\": \"%s\", ", url.ToCString()); |
- buffer.Printf("\"line\": %" Pd ", ", frame->LineNumber()); |
- buffer.Printf("\"function\": \"%s\", ", function.ToCString()); |
- |
- const Code& code = frame->code(); |
- buffer.Printf("\"code\": { "); |
- buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true"); |
- buffer.Printf("\"optimized\": %s }}", |
- code.is_optimized() ? "false" : "true"); |
} |
- buffer.Printf("]}"); |
- isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length()); |
- ml.Notify(); |
- return true; |
-} |
- |
- |
-bool Isolate::FetchStackFrameDetails() { |
- Isolate* isolate = Isolate::Current(); |
- ASSERT(isolate->stack_frame_index_ >= 0); |
- MonitorLocker ml(status_sync); |
- DebuggerStackTrace* stack = Debugger::CollectStackTrace(); |
- intptr_t frame_index = isolate->stack_frame_index_; |
- if (frame_index >= stack->Length()) { |
- // Frame no longer available. |
- return false; |
+ { |
+ JSONObject jsheap(&jsobj, "heap"); |
+ jsheap.AddProperty("usedNew", heap()->UsedInWords(Heap::kNew)); |
+ jsheap.AddProperty("capacityNew", heap()->CapacityInWords(Heap::kNew)); |
+ jsheap.AddProperty("usedOld", heap()->UsedInWords(Heap::kOld)); |
+ jsheap.AddProperty("capacityOld", heap()->CapacityInWords(Heap::kOld)); |
} |
- ActivationFrame* frame = stack->FrameAt(frame_index); |
- TextBuffer buffer(256); |
- buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"frame_index\": %" Pd ", ", |
- reinterpret_cast<int64_t>(isolate), frame_index); |
- const Code& code = frame->code(); |
- buffer.Printf("\"code\": { \"size\": %" Pd ", ", code.Size()); |
- buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true"); |
- buffer.Printf("\"optimized\": %s }, ", |
- code.is_optimized() ? "false" : "true"); |
- // TODO(tball): add compilation stats (time, etc.), when available. |
+ DebuggerStackTrace* stack = debugger()->StackTrace(); |
+ if (stack->Length() > 0) { |
+ JSONObject jsframe(&jsobj, "topFrame"); |
- buffer.Printf("\"local_vars\": [ "); |
- intptr_t n_local_vars = frame->NumLocalVariables(); |
- String& var_name = String::Handle(); |
- Instance& value = Instance::Handle(); |
- for (int i = 0; i < n_local_vars; i++) { |
- if (i > 0) { |
- buffer.Printf(", "); |
- } |
- intptr_t token_pos, end_pos; |
- frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value); |
- buffer.Printf( |
- "{ \"name\": \"%s\", \"pos\": %" Pd ", \"end_pos\": %" Pd ", " |
- "\"value\": \"%s\" }", |
- var_name.ToCString(), token_pos, end_pos, value.ToCString()); |
+ ActivationFrame* frame = stack->FrameAt(0); |
+ frame->PrintToJSONObject(&jsobj); |
+ // TODO(turnidge): Implement depth differently -- differentiate |
+ // inlined frames. |
+ jsobj.AddProperty("depth", (intptr_t)0); |
} |
- buffer.Printf("]}"); |
- isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length()); |
- ml.Notify(); |
- return true; |
-} |
+ const Library& lib = |
+ Library::Handle(object_store()->root_library()); |
+ jsobj.AddProperty("rootLib", lib); |
-char* Isolate::DoStacktraceInterrupt(Dart_IsolateInterruptCallback cb) { |
- ASSERT(stacktrace_ == NULL); |
- SetVmStatsCallback(cb); |
- if (status_sync == NULL) { |
- status_sync = new Monitor(); |
- } |
- if (is_runnable()) { |
- ScheduleInterrupts(Isolate::kVmStatusInterrupt); |
- { |
- MonitorLocker ml(status_sync); |
- if (stacktrace_ == NULL) { // It may already be available. |
- ml.Wait(1000); |
- } |
- } |
- SetVmStatsCallback(NULL); |
- } |
- char* result = stacktrace_; |
- stacktrace_ = NULL; |
- if (result == NULL) { |
- // Return empty stack. |
- TextBuffer buffer(256); |
- buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"stacktrace\": []}", |
- reinterpret_cast<int64_t>(this)); |
- |
- result = OS::StrNDup(buffer.buf(), buffer.length()); |
- } |
- ASSERT(result != NULL); |
- // result is freed by VmStats::WebServer(). |
- return result; |
+ timer_list().PrintTimersToJSONProperty(&jsobj); |
} |
-char* Isolate::GetStatusStacktrace() { |
- return DoStacktraceInterrupt(&FetchStacktrace); |
-} |
- |
-char* Isolate::GetStatusStackFrame(intptr_t index) { |
- ASSERT(index >= 0); |
- stack_frame_index_ = index; |
- char* result = DoStacktraceInterrupt(&FetchStackFrameDetails); |
- stack_frame_index_ = -1; |
- return result; |
-} |
- |
- |
-// Returns the isolate's general detail information. |
-char* Isolate::GetStatusDetails() { |
- const char* format = "{\n" |
- " \"handle\": \"0x%" Px64 "\",\n" |
- " \"name\": \"%s\",\n" |
- " \"port\": %" Pd ",\n" |
- " \"starttime\": %" Pd ",\n" |
- " \"stacklimit\": %" Pd ",\n" |
- " \"newspace\": {\n" |
- " \"used\": %" Pd ",\n" |
- " \"capacity\": %" Pd "\n" |
- " },\n" |
- " \"oldspace\": {\n" |
- " \"used\": %" Pd ",\n" |
- " \"capacity\": %" Pd "\n" |
- " }\n" |
- "}"; |
- char buffer[300]; |
- int64_t address = reinterpret_cast<int64_t>(this); |
- int n = OS::SNPrint(buffer, 300, format, address, name(), main_port(), |
- start_time() / 1000L, saved_stack_limit(), |
- RoundWordsToKB(heap()->UsedInWords(Heap::kNew)), |
- RoundWordsToKB(heap()->CapacityInWords(Heap::kNew)), |
- RoundWordsToKB(heap()->UsedInWords(Heap::kOld)), |
- RoundWordsToKB(heap()->CapacityInWords(Heap::kOld))); |
- ASSERT(n < 300); |
- return strdup(buffer); |
-} |
- |
- |
-char* Isolate::GetStatus(const char* request) { |
- char* p = const_cast<char*>(request); |
- const char* service_type = "/isolate/"; |
- ASSERT(!strncmp(p, service_type, strlen(service_type))); |
- p += strlen(service_type); |
- |
- // Extract isolate handle. |
- int64_t addr; |
- OS::StringToInt64(p, &addr); |
- // TODO(tball): add validity check when issue 9600 is fixed. |
- Isolate* isolate = reinterpret_cast<Isolate*>(addr); |
- p += strcspn(p, "/"); |
- |
- // Query "/isolate/<handle>". |
- if (strlen(p) == 0) { |
- return isolate->GetStatusDetails(); |
- } |
- |
- // Query "/isolate/<handle>/stacktrace" |
- if (!strcmp(p, "/stacktrace")) { |
- return isolate->GetStatusStacktrace(); |
- } |
- |
- // Query "/isolate/<handle>/stacktrace/<frame-index>" |
- const char* stacktrace_query = "/stacktrace/"; |
- int64_t frame_index = -1; |
- if (!strncmp(p, stacktrace_query, strlen(stacktrace_query))) { |
- p += strlen(stacktrace_query); |
- OS::StringToInt64(p, &frame_index); |
- if (frame_index >= 0) { |
- return isolate->GetStatusStackFrame(frame_index); |
- } |
- } |
- |
- // TODO(tball): "/isolate/<handle>/stacktrace/<frame-index>"/disassemble" |
- |
- return NULL; // Unimplemented query. |
-} |
- |
- |
template<class T> |
T* Isolate::AllocateReusableHandle() { |
T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle()); |