dart-sdk/runtime/vm/isolate.cc

1199 lines
36 KiB
C++
Raw Normal View History

// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/isolate.h"
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/json.h"
#include "lib/mirrors.h"
#include "vm/code_observers.h"
#include "vm/compiler_stats.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/heap.h"
#include "vm/heap_histogram.h"
#include "vm/message_handler.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/port.h"
#include "vm/reusable_handles.h"
#include "vm/service.h"
#include "vm/simulator.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/thread.h"
#include "vm/timer.h"
#include "vm/visitor.h"
namespace dart {
DEFINE_FLAG(bool, report_usage_count, false,
"Track function usage and report.");
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
DEFINE_FLAG(bool, trace_isolates, false,
"Trace isolate creation and shut down.");
DECLARE_FLAG(bool, trace_deoptimization_verbose);
void Isolate::RegisterClass(const Class& cls) {
class_table()->Register(cls);
if (object_histogram() != NULL) object_histogram()->RegisterClass(cls);
}
class IsolateMessageHandler : public MessageHandler {
public:
explicit IsolateMessageHandler(Isolate* isolate);
~IsolateMessageHandler();
const char* name() const;
void MessageNotify(Message::Priority priority);
bool HandleMessage(Message* message);
#if defined(DEBUG)
// Check that it is safe to access this handler.
void CheckAccess();
#endif
bool IsCurrentIsolate() const;
virtual Isolate* GetIsolate() const { return isolate_; }
bool UnhandledExceptionCallbackHandler(const Object& message,
const UnhandledException& error);
private:
bool ProcessUnhandledException(const Object& message, const Error& result);
RawFunction* ResolveCallbackFunction();
Isolate* isolate_;
};
IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate)
: isolate_(isolate) {
}
IsolateMessageHandler::~IsolateMessageHandler() {
}
const char* IsolateMessageHandler::name() const {
return isolate_->name();
}
void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
if (priority >= Message::kOOBPriority) {
// Handle out of band messages even if the isolate is busy.
isolate_->ScheduleInterrupts(Isolate::kMessageInterrupt);
}
Dart_MessageNotifyCallback callback = isolate_->message_notify_callback();
if (callback) {
// Allow the embedder to handle message notification.
(*callback)(Api::CastIsolate(isolate_));
}
}
bool IsolateMessageHandler::HandleMessage(Message* message) {
StartIsolateScope start_scope(isolate_);
StackZone zone(isolate_);
HandleScope handle_scope(isolate_);
// 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.
Object& receive_port = Object::Handle();
if (!message->IsOOB()) {
receive_port = DartLibraryCalls::LookupReceivePort(message->dest_port());
if (receive_port.IsError()) {
return ProcessUnhandledException(Instance::Handle(),
Error::Cast(receive_port));
}
if (receive_port.IsNull()) {
delete message;
return true;
}
}
// Parse the message.
SnapshotReader reader(message->data(), message->len(),
Snapshot::kMessage, Isolate::Current());
const Object& msg_obj = Object::Handle(reader.ReadObject());
if (msg_obj.IsError()) {
// An error occurred while reading the message.
return ProcessUnhandledException(Instance::Handle(), Error::Cast(msg_obj));
}
if (!msg_obj.IsNull() && !msg_obj.IsInstance()) {
// TODO(turnidge): We need to decide what an isolate does with
// malformed messages. If they (eventually) come from a remote
// machine, then it might make sense to drop the message entirely.
// In the case that the message originated locally, which is
// always true for now, then this should never occur.
UNREACHABLE();
}
Instance& msg = Instance::Handle();
msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null.
bool success = true;
if (message->IsOOB()) {
Service::HandleServiceMessage(isolate_, message->reply_port(), msg);
} else {
const Object& result = Object::Handle(
DartLibraryCalls::HandleMessage(
receive_port, message->reply_port(), msg));
if (result.IsError()) {
success = ProcessUnhandledException(msg, Error::Cast(result));
} else {
ASSERT(result.IsNull());
}
}
delete message;
return success;
}
RawFunction* IsolateMessageHandler::ResolveCallbackFunction() {
ASSERT(isolate_->object_store()->unhandled_exception_handler() != NULL);
String& callback_name = String::Handle(isolate_);
if (isolate_->object_store()->unhandled_exception_handler() !=
String::null()) {
callback_name = isolate_->object_store()->unhandled_exception_handler();
} else {
callback_name = String::New("_unhandledExceptionCallback");
}
Library& lib =
Library::Handle(isolate_, isolate_->object_store()->isolate_library());
Function& func =
Function::Handle(isolate_, lib.LookupLocalFunction(callback_name));
if (func.IsNull()) {
lib = isolate_->object_store()->root_library();
func = lib.LookupLocalFunction(callback_name);
}
return func.raw();
}
bool IsolateMessageHandler::UnhandledExceptionCallbackHandler(
const Object& message, const UnhandledException& error) {
const Instance& cause = Instance::Handle(isolate_, error.exception());
const Instance& stacktrace =
Instance::Handle(isolate_, error.stacktrace());
// Wrap these args into an IsolateUncaughtException object.
const Array& exception_args = Array::Handle(Array::New(3));
exception_args.SetAt(0, message);
exception_args.SetAt(1, cause);
exception_args.SetAt(2, stacktrace);
const Object& exception =
Object::Handle(isolate_,
Exceptions::Create(Exceptions::kIsolateUnhandledException,
exception_args));
if (exception.IsError()) {
return false;
}
ASSERT(exception.IsInstance());
// Invoke script's callback function.
Object& function = Object::Handle(isolate_, ResolveCallbackFunction());
if (function.IsNull() || function.IsError()) {
return false;
}
const Array& callback_args = Array::Handle(Array::New(1));
callback_args.SetAt(0, exception);
const Object& result =
Object::Handle(DartEntry::InvokeFunction(Function::Cast(function),
callback_args));
if (result.IsError()) {
const Error& err = Error::Cast(result);
OS::PrintErr("failed calling unhandled exception callback: %s\n",
err.ToErrorCString());
return false;
}
ASSERT(result.IsBool());
bool continue_from_exception = Bool::Cast(result).value();
if (continue_from_exception) {
isolate_->object_store()->clear_sticky_error();
}
return continue_from_exception;
}
#if defined(DEBUG)
void IsolateMessageHandler::CheckAccess() {
ASSERT(IsCurrentIsolate());
}
#endif
bool IsolateMessageHandler::IsCurrentIsolate() const {
return (isolate_ == Isolate::Current());
}
bool IsolateMessageHandler::ProcessUnhandledException(
const Object& message, const Error& result) {
if (result.IsUnhandledException()) {
// Invoke the isolate's uncaught exception handler, if it exists.
const UnhandledException& error = UnhandledException::Cast(result);
RawInstance* exception = error.exception();
if ((exception != isolate_->object_store()->out_of_memory()) &&
(exception != isolate_->object_store()->stack_overflow())) {
if (UnhandledExceptionCallbackHandler(message, error)) {
return true;
}
}
}
// Invoke the isolate's unhandled exception callback if there is one.
if (Isolate::UnhandledExceptionCallback() != NULL) {
Dart_EnterScope();
Dart_Handle error = Api::NewHandle(isolate_, result.raw());
(Isolate::UnhandledExceptionCallback())(error);
Dart_ExitScope();
}
isolate_->object_store()->set_sticky_error(result);
return false;
}
#if defined(DEBUG)
// static
void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
ASSERT(isolate == Isolate::Current());
}
#endif
void DeferredDouble::Materialize() {
RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot());
*double_slot = Double::New(value());
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr("materializing double at %"Px": %g\n",
reinterpret_cast<uword>(slot()), value());
}
}
void DeferredMint::Materialize() {
RawMint** mint_slot = reinterpret_cast<RawMint**>(slot());
ASSERT(!Smi::IsValid64(value()));
Mint& mint = Mint::Handle();
mint ^= Integer::New(value());
*mint_slot = mint.raw();
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr("materializing mint at %"Px": %"Pd64"\n",
reinterpret_cast<uword>(slot()), value());
}
}
void DeferredFloat32x4::Materialize() {
RawFloat32x4** float32x4_slot = reinterpret_cast<RawFloat32x4**>(slot());
RawFloat32x4* raw_float32x4 = Float32x4::New(value());
*float32x4_slot = raw_float32x4;
if (FLAG_trace_deoptimization_verbose) {
float x = raw_float32x4->x();
float y = raw_float32x4->y();
float z = raw_float32x4->z();
float w = raw_float32x4->w();
OS::PrintErr("materializing Float32x4 at %"Px": %g,%g,%g,%g\n",
reinterpret_cast<uword>(slot()), x, y, z, w);
}
}
void DeferredUint32x4::Materialize() {
RawUint32x4** uint32x4_slot = reinterpret_cast<RawUint32x4**>(slot());
RawUint32x4* raw_uint32x4 = Uint32x4::New(value());
*uint32x4_slot = raw_uint32x4;
if (FLAG_trace_deoptimization_verbose) {
uint32_t x = raw_uint32x4->x();
uint32_t y = raw_uint32x4->y();
uint32_t z = raw_uint32x4->z();
uint32_t w = raw_uint32x4->w();
OS::PrintErr("materializing Uint32x4 at %"Px": %x,%x,%x,%x\n",
reinterpret_cast<uword>(slot()), x, y, z, w);
}
}
Implement a variation of scalar replacement for non-escaping allocations. AllocationSinking pass discovers non-escaping allocations that have no input uses other than uses in the stores into its own fields. Every environment use of such allocation is replaced by a state snapshot (MaterializeObject instruction) that describes the state of each initialized field in the object. State snapshots are computed through an additional round of load-forwarding. Once snapshots are computed allocations are removed from the graph. MaterializeObject instructions are not compiled into native code but produce deoptimization instructions instead that describe how object should be materialized at deoptimization. Deoptimization instructions now follow the following format: [mat obj #1]...[mat obj #N][ret addr][... mat arguments ...][... real frames ...] - the prefix describes each object to materialize on deopt via kMaterializeObject instruction; - actual values that are needed for materialization are emited as a part of bottom-most stack frame. This is done to simplify implementation: they need to be discoverable by a GC during materialization phase. At the end of deoptimization they will be removed from the stack; - normal stack slots can refer to materialized objects via kMaterializedObjectRef instruction. Additionally this change contains fixes in load-forwarding that are needed to guarantee that all artificial LoadField instructions inserted during AllocationSinking are correctly replaced with actual values. Limitations of the current implementation: - can't eliminate allocations that flow into phis but otherwise don't actually escape; - can't sink allocations out of loops; - allocation with type arguments are not handled. R=regis@google.com, srdjan@google.com, zra@google.com Review URL: https://codereview.chromium.org//14935005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@22485 260f80e4-7a28-3924-810f-c04153c831b5
2013-05-07 23:40:42 +00:00
void DeferredObjectRef::Materialize() {
DeferredObject* obj = Isolate::Current()->GetDeferredObject(index());
*slot() = obj->object();
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr("writing instance ref at %"Px": %s\n",
reinterpret_cast<uword>(slot()),
Instance::Handle(obj->object()).ToCString());
}
}
RawInstance* DeferredObject::object() {
if (object_ == NULL) {
Materialize();
}
return object_->raw();
}
void DeferredObject::Materialize() {
Class& cls = Class::Handle();
cls ^= GetClass();
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr("materializing instance of %s (%"Px", %"Pd" fields)\n",
cls.ToCString(),
reinterpret_cast<uword>(args_),
field_count_);
}
const Instance& obj = Instance::ZoneHandle(Instance::New(cls));
Field& field = Field::Handle();
Object& value = Object::Handle();
for (intptr_t i = 0; i < field_count_; i++) {
field ^= GetField(i);
value = GetValue(i);
obj.SetField(field, value);
if (FLAG_trace_deoptimization_verbose) {
OS::PrintErr(" %s <- %s\n",
String::Handle(field.name()).ToCString(),
value.ToCString());
}
}
object_ = &obj;
}
#define REUSABLE_HANDLE_INITIALIZERS(object) \
object##_handle_(NULL),
Isolate::Isolate()
: store_buffer_(),
message_notify_callback_(NULL),
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
name_(NULL),
start_time_(OS::GetCurrentTimeMicros()),
Add a mid-sized integration test for the Dart Embedding Api which demonstrates how to create a custom isolate abstraction. In this test, we use an event queue to share a single thread among our custom isolates. Add a callback which allows embedders to see when a port is created. Not sure if I should keep this or not. New apis: Dart_CreatePort() -- allocates a port id and adds a port->isolate mapping. Dart_IsolateHasActivePorts() -- does the current isolate have open ports? (this name a bit awkward...) Bail out of PortMap::ClosePorts() early if there are no open ports. This suppresses calls to the close_port_callback when there are no open ports. Use DART_CHECK_VALID to provide better error output when the test lib has errors. ------------------------- Sample output of the test: -- (isolate=0x815600) Constructing isolate -- Enter: CustomIsolateImpl_start -- -- Adding port (7111) -> isolate (0x830800) -- -- Adding StartEvent to queue -- -- Exit: CustomIsolateImpl_start -- -- Adding port (7112) -> isolate (0x815600) -- -- Posting message dest(7111) reply(0) -- -- Adding MessageEvent to queue -- -- Starting event loop -- >> StartEvent with isolate(0x830800)-- -- (isolate=0x830800) Running isolateMain $$ MessageEvent with dest port 7111-- -- (isolate=0x830800) Received: 42 -- Posting message dest(7112) reply(0) -- -- Adding MessageEvent to queue -- $$ MessageEvent with dest port 7112-- -- Closing port (7112) -- -- Adding ShutdownEvent to queue -- -- (isolate=0x815600) Received: 43 << ShutdownEvent with isolate(0x815600)-- -- Finished event loop -- Review URL: http://codereview.chromium.org//8588040 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@1906 260f80e4-7a28-3924-810f-c04153c831b5
2011-11-29 21:55:13 +00:00
main_port_(0),
heap_(NULL),
object_store_(NULL),
top_context_(Context::null()),
top_exit_frame_info_(0),
init_callback_data_(NULL),
library_tag_handler_(NULL),
api_state_(NULL),
stub_code_(NULL),
debugger_(NULL),
single_step_(false),
simulator_(NULL),
long_jump_base_(NULL),
timer_list_(),
deopt_id_(0),
mutex_(new Mutex()),
stack_limit_(0),
saved_stack_limit_(0),
message_handler_(NULL),
spawn_data_(0),
is_runnable_(false),
gc_prologue_callbacks_(),
gc_epilogue_callbacks_(),
defer_finalization_count_(0),
deopt_cpu_registers_copy_(NULL),
deopt_fpu_registers_copy_(NULL),
deopt_frame_copy_(NULL),
deopt_frame_copy_size_(0),
Implement a variation of scalar replacement for non-escaping allocations. AllocationSinking pass discovers non-escaping allocations that have no input uses other than uses in the stores into its own fields. Every environment use of such allocation is replaced by a state snapshot (MaterializeObject instruction) that describes the state of each initialized field in the object. State snapshots are computed through an additional round of load-forwarding. Once snapshots are computed allocations are removed from the graph. MaterializeObject instructions are not compiled into native code but produce deoptimization instructions instead that describe how object should be materialized at deoptimization. Deoptimization instructions now follow the following format: [mat obj #1]...[mat obj #N][ret addr][... mat arguments ...][... real frames ...] - the prefix describes each object to materialize on deopt via kMaterializeObject instruction; - actual values that are needed for materialization are emited as a part of bottom-most stack frame. This is done to simplify implementation: they need to be discoverable by a GC during materialization phase. At the end of deoptimization they will be removed from the stack; - normal stack slots can refer to materialized objects via kMaterializedObjectRef instruction. Additionally this change contains fixes in load-forwarding that are needed to guarantee that all artificial LoadField instructions inserted during AllocationSinking are correctly replaced with actual values. Limitations of the current implementation: - can't eliminate allocations that flow into phis but otherwise don't actually escape; - can't sink allocations out of loops; - allocation with type arguments are not handled. R=regis@google.com, srdjan@google.com, zra@google.com Review URL: https://codereview.chromium.org//14935005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@22485 260f80e4-7a28-3924-810f-c04153c831b5
2013-05-07 23:40:42 +00:00
deferred_boxes_(NULL),
deferred_object_refs_(NULL),
deferred_objects_count_(0),
deferred_objects_(NULL),
stacktrace_(NULL),
stack_frame_index_(-1),
object_histogram_(NULL),
object_id_ring_(NULL),
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
reusable_handles_() {
if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) {
object_histogram_ = new ObjectHistogram(this);
}
}
#undef REUSABLE_HANDLE_INITIALIZERS
Isolate::~Isolate() {
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
delete [] name_;
delete heap_;
delete object_store_;
delete api_state_;
delete stub_code_;
delete debugger_;
#if defined(USING_SIMULATOR)
delete simulator_;
#endif
delete mutex_;
mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate.
delete message_handler_;
message_handler_ = NULL; // Fail fast if we send messages to a dead isolate.
delete object_histogram_;
Allow embedders to provide custom message delivery for an isolate. ============== Added Dart_SetPostMessageCallback and Dart_SetClosePortCallback. These allow the embedder to provide custom message/port behavior for their application. The vm provides standard implementations that work with the standard run loop. Added Dart_HandleMessage, which processes one message on the current isolate. Embedders can use this to write their own message processing loops. Rewrote code to use this internally. Added Isolate::StandardRunLoop() to share code between Dart_RunLoop and lib/isolate.cc Changed the interface to PortMap::PostMessage. PostMessage is now agnostic to message delivery mechanism. Note that PortMap is now out of the "ReceiveMessage" business entirely. Moved MessageQueue and friends out to message_queue.cc/h. Moved the monitor from the Isolate into the MessageQueue. No need for outsiders to mess. Added MessageQueue::Wait. Moved monitor locking from PortMap into MessageQueue itself, which was easier for me to reason about. Wrote some tests. Removed PortMessage::Handle. The code turned into Dart_HandleMessage. Regularized the nomenclature around ports. Type is now always Dart_Port instead of intptr_t. Variables end in _port instead of _id. Use the term "dest" instead of "target" or "send". Added a family of new tests to port_test. Added EXPECT_NE to the test framework. Review URL: http://codereview.chromium.org//8297004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@516 260f80e4-7a28-3924-810f-c04153c831b5
2011-10-18 17:54:07 +00:00
}
void Isolate::SetCurrent(Isolate* current) {
Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current));
}
// The single thread local key which stores all the thread local data
// for a thread. Since an Isolate is the central repository for
// storing all isolate specific information a single thread local key
// is sufficient.
ThreadLocalKey Isolate::isolate_key = Thread::kUnsetThreadLocalKey;
void Isolate::InitOnce() {
ASSERT(isolate_key == Thread::kUnsetThreadLocalKey);
isolate_key = Thread::CreateThreadLocal();
ASSERT(isolate_key != Thread::kUnsetThreadLocalKey);
create_callback_ = NULL;
}
Allow embedders to provide custom message delivery for an isolate. ============== Added Dart_SetPostMessageCallback and Dart_SetClosePortCallback. These allow the embedder to provide custom message/port behavior for their application. The vm provides standard implementations that work with the standard run loop. Added Dart_HandleMessage, which processes one message on the current isolate. Embedders can use this to write their own message processing loops. Rewrote code to use this internally. Added Isolate::StandardRunLoop() to share code between Dart_RunLoop and lib/isolate.cc Changed the interface to PortMap::PostMessage. PostMessage is now agnostic to message delivery mechanism. Note that PortMap is now out of the "ReceiveMessage" business entirely. Moved MessageQueue and friends out to message_queue.cc/h. Moved the monitor from the Isolate into the MessageQueue. No need for outsiders to mess. Added MessageQueue::Wait. Moved monitor locking from PortMap into MessageQueue itself, which was easier for me to reason about. Wrote some tests. Removed PortMessage::Handle. The code turned into Dart_HandleMessage. Regularized the nomenclature around ports. Type is now always Dart_Port instead of intptr_t. Variables end in _port instead of _id. Use the term "dest" instead of "target" or "send". Added a family of new tests to port_test. Added EXPECT_NE to the test framework. Review URL: http://codereview.chromium.org//8297004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@516 260f80e4-7a28-3924-810f-c04153c831b5
2011-10-18 17:54:07 +00:00
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
Isolate* Isolate::Init(const char* name_prefix) {
Isolate* result = new Isolate();
ASSERT(result != NULL);
// TODO(5411455): For now just set the recently created isolate as
// the current isolate.
SetCurrent(result);
// Setup the isolate specific resuable handles.
#define REUSABLE_HANDLE_ALLOCATION(object) \
result->object##_handle_ = result->AllocateReusableHandle<object>(); \
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION)
#undef REUSABLE_HANDLE_ALLOCATION
// Setup the isolate message handler.
MessageHandler* handler = new IsolateMessageHandler(result);
ASSERT(handler != NULL);
result->set_message_handler(handler);
// Setup the Dart API state.
ApiState* state = new ApiState();
ASSERT(state != NULL);
result->set_api_state(state);
// Initialize stack top and limit in case we are running the isolate in the
// main thread.
// TODO(5411455): Need to figure out how to set the stack limit for the
// main thread.
result->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&result));
result->set_main_port(PortMap::CreatePort(result->message_handler()));
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
result->BuildName(name_prefix);
result->debugger_ = new Debugger();
result->debugger_->Initialize(result);
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
if (FLAG_trace_isolates) {
if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) {
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
OS::Print("[+] Starting isolate:\n"
"\tisolate: %s\n", result->name());
}
}
return result;
}
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
void Isolate::BuildName(const char* name_prefix) {
ASSERT(name_ == NULL);
if (name_prefix == NULL) {
name_prefix = "isolate";
}
const char* kFormat = "%s-%lld";
intptr_t len = OS::SNPrint(NULL, 0, kFormat, name_prefix, main_port()) + 1;
name_ = new char[len];
OS::SNPrint(name_, len, kFormat, name_prefix, main_port());
}
// TODO(5411455): Use flag to override default value and Validate the
// stack size by querying OS.
uword Isolate::GetSpecifiedStackSize() {
ASSERT(Isolate::kStackSizeBuffer < Thread::GetMaxStackSize());
uword stack_size = Thread::GetMaxStackSize() - Isolate::kStackSizeBuffer;
return stack_size;
}
void Isolate::SetStackLimitFromCurrentTOS(uword stack_top_value) {
#if defined(USING_SIMULATOR)
// Ignore passed-in native stack top and use Simulator stack top.
Simulator* sim = Simulator::Current(); // May allocate a simulator.
ASSERT(simulator() == sim); // This isolate's simulator is the current one.
stack_top_value = sim->StackTop();
// The overflow area is accounted for by the simulator.
#endif
SetStackLimit(stack_top_value - GetSpecifiedStackSize());
}
void Isolate::SetStackLimit(uword limit) {
MutexLocker ml(mutex_);
if (stack_limit_ == saved_stack_limit_) {
// No interrupt pending, set stack_limit_ too.
stack_limit_ = limit;
}
saved_stack_limit_ = limit;
}
void Isolate::ScheduleInterrupts(uword interrupt_bits) {
// TODO(turnidge): Can't use MutexLocker here because MutexLocker is
// a StackResource, which requires a current isolate. Should
// MutexLocker really be a StackResource?
mutex_->Lock();
ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask.
if (stack_limit_ == saved_stack_limit_) {
stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
}
stack_limit_ |= interrupt_bits;
mutex_->Unlock();
}
bool Isolate::MakeRunnable() {
ASSERT(Isolate::Current() == NULL);
// Can't use MutexLocker here because MutexLocker is
// a StackResource, which requires a current isolate.
mutex_->Lock();
// Check if we are in a valid state to make the isolate runnable.
if (is_runnable_ == true) {
mutex_->Unlock();
return false; // Already runnable.
}
// 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());
if (state != NULL) {
ASSERT(this == state->isolate());
Run();
}
mutex_->Unlock();
return true;
}
static void StoreError(Isolate* isolate, const Object& obj) {
ASSERT(obj.IsError());
isolate->object_store()->set_sticky_error(Error::Cast(obj));
}
static bool RunIsolate(uword parameter) {
Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
IsolateSpawnState* state = NULL;
{
MutexLocker ml(isolate->mutex());
state = reinterpret_cast<IsolateSpawnState*>(isolate->spawn_data());
isolate->set_spawn_data(0);
}
{
StartIsolateScope start_scope(isolate);
StackZone zone(isolate);
HandleScope handle_scope(isolate);
if (!ClassFinalizer::FinalizePendingClasses()) {
// Error is in sticky error already.
return false;
}
// Set up specific unhandled exception handler.
const String& callback_name = String::Handle(
isolate, String::New(state->exception_callback_name()));
isolate->object_store()->
set_unhandled_exception_handler(callback_name);
Object& result = Object::Handle();
result = state->ResolveFunction();
delete state;
state = NULL;
if (result.IsError()) {
StoreError(isolate, result);
return false;
}
ASSERT(result.IsFunction());
Function& func = Function::Handle(isolate);
func ^= result.raw();
result = DartEntry::InvokeFunction(func, Object::empty_array());
if (result.IsError()) {
StoreError(isolate, result);
return false;
}
}
return true;
}
static void ShutdownIsolate(uword parameter) {
Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
StartIsolateScope start_scope(isolate);
StackZone zone(isolate);
HandleScope handle_scope(isolate);
Error& error = Error::Handle();
error = isolate->object_store()->sticky_error();
if (!error.IsNull()) {
OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString());
}
Dart::RunShutdownCallback();
}
{
// Shut the isolate down.
SwitchIsolateScope switch_scope(isolate);
Dart::ShutdownIsolate();
}
}
void Isolate::Run() {
message_handler()->Run(Dart::thread_pool(),
RunIsolate,
ShutdownIsolate,
reinterpret_cast<uword>(this));
}
uword Isolate::GetAndClearInterrupts() {
MutexLocker ml(mutex_);
if (stack_limit_ == saved_stack_limit_) {
return 0; // No interrupt was requested.
}
uword interrupt_bits = stack_limit_ & kInterruptsMask;
stack_limit_ = saved_stack_limit_;
return interrupt_bits;
}
static int MostUsedFunctionFirst(const Function* const* a,
const Function* const* b) {
if ((*a)->usage_counter() > (*b)->usage_counter()) {
return -1;
} else if ((*a)->usage_counter() < (*b)->usage_counter()) {
return 1;
} else {
return 0;
}
}
static void AddFunctionsFromClass(const Class& cls,
GrowableArray<const Function*>* functions) {
const Array& class_functions = Array::Handle(cls.functions());
// Class 'dynamic' is allocated/initialized in a special way, leaving
// the functions field NULL instead of empty.
const int func_len = class_functions.IsNull() ? 0 : class_functions.Length();
for (int j = 0; j < func_len; j++) {
Function& function = Function::Handle();
function ^= class_functions.At(j);
if (function.usage_counter() > 0) {
functions->Add(&function);
}
}
}
void Isolate::PrintInvokedFunctions() {
ASSERT(this == Isolate::Current());
StackZone zone(this);
HandleScope handle_scope(this);
const GrowableObjectArray& libraries =
GrowableObjectArray::Handle(object_store()->libraries());
Library& library = Library::Handle();
GrowableArray<const Function*> invoked_functions;
for (int i = 0; i < libraries.Length(); i++) {
library ^= libraries.At(i);
Class& cls = Class::Handle();
ClassDictionaryIterator iter(library);
while (iter.HasNext()) {
cls = iter.GetNextClass();
AddFunctionsFromClass(cls, &invoked_functions);
}
Array& anon_classes = Array::Handle(library.raw_ptr()->anonymous_classes_);
for (int i = 0; i < library.raw_ptr()->num_anonymous_; i++) {
cls ^= anon_classes.At(i);
AddFunctionsFromClass(cls, &invoked_functions);
}
}
invoked_functions.Sort(MostUsedFunctionFirst);
for (int i = 0; i < invoked_functions.length(); i++) {
OS::Print("%10"Pd" x %s\n",
invoked_functions[i]->usage_counter(),
invoked_functions[i]->ToFullyQualifiedCString());
}
}
class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor {
public:
FinalizeWeakPersistentHandlesVisitor() {
}
void VisitHandle(uword addr) {
FinalizablePersistentHandle* handle =
reinterpret_cast<FinalizablePersistentHandle*>(addr);
FinalizablePersistentHandle::Finalize(handle);
}
private:
DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor);
};
void Isolate::Shutdown() {
ASSERT(this == Isolate::Current());
ASSERT(top_resource() == NULL);
ASSERT((heap_ == NULL) || heap_->Verify());
if (FLAG_print_object_histogram) {
StackZone stack_zone(this);
HandleScope handle_scope(this);
heap()->CollectAllGarbage();
object_histogram()->Print();
}
// Clean up debugger resources. Shutting down the debugger
// requires a handle zone. We must set up a temporary zone because
// Isolate::Shutdown is called without a zone.
{
StackZone zone(this);
HandleScope handle_scope(this);
debugger_->Shutdown();
}
// Close all the ports owned by this isolate.
PortMap::ClosePorts(message_handler());
// Fail fast if anybody tries to post any more messsages to this isolate.
delete message_handler();
set_message_handler(NULL);
// Finalize any weak persistent handles with a non-null referent.
FinalizeWeakPersistentHandlesVisitor visitor;
api_state()->weak_persistent_handles().VisitHandles(&visitor);
// Dump all accumalated timer data for the isolate.
timer_list_.ReportTimers();
if (FLAG_report_usage_count) {
PrintInvokedFunctions();
}
CompilerStats::Print();
// TODO(asiva): Move this code to Dart::Cleanup when we have that method
// as the cleanup for Dart::InitOnce.
CodeObservers::DeleteAll();
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
if (FLAG_trace_isolates) {
StackZone zone(this);
HandleScope handle_scope(this);
heap()->PrintSizes();
megamorphic_cache_table()->PrintSizes();
Symbols::DumpStats();
Give isolates names to be used during debugging. Implement --trace_isolates. ------------- Sample output of --trace_isolates for the CrossIsolateMessageTest: [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/main-7112 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [+] Starting isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7117 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7115 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 7118 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7117 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 7119 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7114 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 7120 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7119 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 dest_port: 7120 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 reply_port: 0 dest: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 dest_port: 7118 [>] Posting message: source: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7116 [>] Posting message: source: CrossIsolateMessageTest.dart/main-7112 reply_port: 0 dest: CrossIsolateMessageTest.dart/main-7112 dest_port: 7113 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate2.main-7115 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/CrossIsolate1.main-7114 [-] Stopping isolate: isolate: CrossIsolateMessageTest.dart/main-7112 Review URL: https://chromiumcodereview.appspot.com//9242035 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@3416 260f80e4-7a28-3924-810f-c04153c831b5
2012-01-18 21:46:27 +00:00
OS::Print("[-] Stopping isolate:\n"
"\tisolate: %s\n", name());
}
// TODO(5411455): For now just make sure there are no current isolates
// as we are shutting down the isolate.
SetCurrent(NULL);
}
Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL;
Dart_IsolateUnhandledExceptionCallback
Isolate::unhandled_exception_callback_ = NULL;
Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL;
Dart_FileOpenCallback Isolate::file_open_callback_ = NULL;
Dart_FileReadCallback Isolate::file_read_callback_ = NULL;
Dart_FileWriteCallback Isolate::file_write_callback_ = NULL;
Dart_FileCloseCallback Isolate::file_close_callback_ = NULL;
Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL;
void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
bool visit_prologue_weak_handles,
bool validate_frames) {
ASSERT(visitor != NULL);
// Visit objects in the object store.
object_store()->VisitObjectPointers(visitor);
// Visit objects in the class table.
class_table()->VisitObjectPointers(visitor);
// Visit objects in the megamorphic cache.
megamorphic_cache_table()->VisitObjectPointers(visitor);
// Visit objects in per isolate stubs.
StubCode::VisitObjectPointers(visitor);
// Visit objects in zones.
current_zone()->VisitObjectPointers(visitor);
// Visit objects in isolate specific handles area.
reusable_handles_.VisitObjectPointers(visitor);
// Iterate over all the stack frames and visit objects on the stack.
StackFrameIterator frames_iterator(validate_frames);
StackFrame* frame = frames_iterator.NextFrame();
while (frame != NULL) {
frame->VisitObjectPointers(visitor);
frame = frames_iterator.NextFrame();
}
// Visit the dart api state for all local and persistent handles.
if (api_state() != NULL) {
api_state()->VisitObjectPointers(visitor, visit_prologue_weak_handles);
}
// Visit the top context which is stored in the isolate.
visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_context_));
// Visit objects in the debugger.
debugger()->VisitObjectPointers(visitor);
}
void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor,
bool visit_prologue_weak_handles) {
if (api_state() != NULL) {
api_state()->VisitWeakHandles(visitor, visit_prologue_weak_handles);
}
}
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(", ");
}
ActivationFrame* frame = stack->ActivationFrameAt(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 NULL;
}
ActivationFrame* frame = stack->ActivationFrameAt(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.
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());
}
buffer.Printf("]}");
isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length());
ml.Notify();
return true;
}
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;
}
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(),
heap()->Used(Heap::kNew) / KB,
heap()->Capacity(Heap::kNew) / KB,
heap()->Used(Heap::kOld) / KB,
heap()->Capacity(Heap::kOld) / KB);
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());
T::initializeHandle(handle, T::null());
return handle;
}
Implement a variation of scalar replacement for non-escaping allocations. AllocationSinking pass discovers non-escaping allocations that have no input uses other than uses in the stores into its own fields. Every environment use of such allocation is replaced by a state snapshot (MaterializeObject instruction) that describes the state of each initialized field in the object. State snapshots are computed through an additional round of load-forwarding. Once snapshots are computed allocations are removed from the graph. MaterializeObject instructions are not compiled into native code but produce deoptimization instructions instead that describe how object should be materialized at deoptimization. Deoptimization instructions now follow the following format: [mat obj #1]...[mat obj #N][ret addr][... mat arguments ...][... real frames ...] - the prefix describes each object to materialize on deopt via kMaterializeObject instruction; - actual values that are needed for materialization are emited as a part of bottom-most stack frame. This is done to simplify implementation: they need to be discoverable by a GC during materialization phase. At the end of deoptimization they will be removed from the stack; - normal stack slots can refer to materialized objects via kMaterializedObjectRef instruction. Additionally this change contains fixes in load-forwarding that are needed to guarantee that all artificial LoadField instructions inserted during AllocationSinking are correctly replaced with actual values. Limitations of the current implementation: - can't eliminate allocations that flow into phis but otherwise don't actually escape; - can't sink allocations out of loops; - allocation with type arguments are not handled. R=regis@google.com, srdjan@google.com, zra@google.com Review URL: https://codereview.chromium.org//14935005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@22485 260f80e4-7a28-3924-810f-c04153c831b5
2013-05-07 23:40:42 +00:00
static void FillDeferredSlots(DeferredSlot** slot_list) {
DeferredSlot* slot = *slot_list;
*slot_list = NULL;
while (slot != NULL) {
DeferredSlot* current = slot;
slot = slot->next();
current->Materialize();
delete current;
}
}
void Isolate::MaterializeDeferredBoxes() {
FillDeferredSlots(&deferred_boxes_);
}
void Isolate::MaterializeDeferredObjects() {
FillDeferredSlots(&deferred_object_refs_);
}
static char* GetRootScriptUri(Isolate* isolate) {
const Library& library =
Library::Handle(isolate->object_store()->root_library());
ASSERT(!library.IsNull());
const String& script_name = String::Handle(library.url());
return isolate->current_zone()->MakeCopyOfString(script_name.ToCString());
}
IsolateSpawnState::IsolateSpawnState(const Function& func,
const Function& callback_func)
: isolate_(NULL),
script_url_(NULL),
library_url_(NULL),
function_name_(NULL),
exception_callback_name_(NULL) {
script_url_ = strdup(GetRootScriptUri(Isolate::Current()));
const Class& cls = Class::Handle(func.Owner());
ASSERT(cls.IsTopLevel());
const Library& lib = Library::Handle(cls.library());
const String& lib_url = String::Handle(lib.url());
library_url_ = strdup(lib_url.ToCString());
const String& func_name = String::Handle(func.name());
function_name_ = strdup(func_name.ToCString());
if (!callback_func.IsNull()) {
const String& callback_name = String::Handle(callback_func.name());
exception_callback_name_ = strdup(callback_name.ToCString());
} else {
exception_callback_name_ = strdup("_unhandledExceptionCallback");
}
}
IsolateSpawnState::IsolateSpawnState(const char* script_url)
: isolate_(NULL),
library_url_(NULL),
function_name_(NULL),
exception_callback_name_(NULL) {
script_url_ = strdup(script_url);
library_url_ = NULL;
function_name_ = strdup("main");
exception_callback_name_ = strdup("_unhandledExceptionCallback");
}
IsolateSpawnState::~IsolateSpawnState() {
free(script_url_);
free(library_url_);
free(function_name_);
free(exception_callback_name_);
}
RawObject* IsolateSpawnState::ResolveFunction() {
// Resolve the library.
Library& lib = Library::Handle();
if (library_url()) {
const String& lib_url = String::Handle(String::New(library_url()));
lib = Library::LookupLibrary(lib_url);
if (lib.IsNull() || lib.IsError()) {
const String& msg = String::Handle(String::NewFormatted(
"Unable to find library '%s'.", library_url()));
return LanguageError::New(msg);
}
} else {
lib = isolate()->object_store()->root_library();
}
ASSERT(!lib.IsNull());
// Resolve the function.
const String& func_name =
String::Handle(String::New(function_name()));
const Function& func = Function::Handle(lib.LookupLocalFunction(func_name));
if (func.IsNull()) {
const String& msg = String::Handle(String::NewFormatted(
"Unable to resolve function '%s' in library '%s'.",
function_name(), (library_url() ? library_url() : script_url())));
return LanguageError::New(msg);
}
return func.raw();
}
void IsolateSpawnState::Cleanup() {
SwitchIsolateScope switch_scope(isolate());
Dart::ShutdownIsolate();
}
} // namespace dart