2012-01-16 12:28:10 +00:00
|
|
|
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
2011-10-05 05:20:07 +00:00
|
|
|
// 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"
|
2012-01-16 12:28:10 +00:00
|
|
|
#include "platform/assert.h"
|
2012-04-23 22:26:09 +00:00
|
|
|
#include "lib/mirrors.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/compiler_stats.h"
|
|
|
|
#include "vm/dart_api_state.h"
|
2011-12-14 18:27:58 +00:00
|
|
|
#include "vm/dart_entry.h"
|
2011-11-30 17:04:45 +00:00
|
|
|
#include "vm/debugger.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/debuginfo.h"
|
|
|
|
#include "vm/heap.h"
|
2012-04-19 19:47:27 +00:00
|
|
|
#include "vm/message_handler.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/object_store.h"
|
|
|
|
#include "vm/parser.h"
|
|
|
|
#include "vm/port.h"
|
|
|
|
#include "vm/random.h"
|
|
|
|
#include "vm/stack_frame.h"
|
|
|
|
#include "vm/stub_code.h"
|
2012-07-25 23:41:53 +00:00
|
|
|
#include "vm/symbols.h"
|
2011-10-05 05:20:07 +00:00
|
|
|
#include "vm/thread.h"
|
|
|
|
#include "vm/timer.h"
|
|
|
|
#include "vm/visitor.h"
|
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
2012-02-25 00:33:25 +00:00
|
|
|
DEFINE_FLAG(bool, report_usage_count, false,
|
|
|
|
"Track function usage and report.");
|
2012-01-18 21:46:27 +00:00
|
|
|
DEFINE_FLAG(bool, trace_isolates, false,
|
|
|
|
"Trace isolate creation and shut down.");
|
2011-10-05 05:20:07 +00:00
|
|
|
DECLARE_FLAG(bool, generate_gdb_symbols);
|
|
|
|
|
|
|
|
|
2012-02-01 18:53:40 +00:00
|
|
|
class IsolateMessageHandler : public MessageHandler {
|
|
|
|
public:
|
|
|
|
explicit IsolateMessageHandler(Isolate* isolate);
|
|
|
|
~IsolateMessageHandler();
|
|
|
|
|
|
|
|
const char* name() const;
|
|
|
|
void MessageNotify(Message::Priority priority);
|
2012-04-19 19:47:27 +00:00
|
|
|
bool HandleMessage(Message* message);
|
2012-02-01 18:53:40 +00:00
|
|
|
|
|
|
|
#if defined(DEBUG)
|
|
|
|
// Check that it is safe to access this handler.
|
|
|
|
void CheckAccess();
|
|
|
|
#endif
|
2012-05-30 17:07:19 +00:00
|
|
|
bool IsCurrentIsolate() const;
|
2012-10-04 00:13:37 +00:00
|
|
|
virtual Isolate* GetIsolate() const { return isolate_; }
|
2012-05-30 17:07:19 +00:00
|
|
|
|
2012-02-01 18:53:40 +00:00
|
|
|
private:
|
|
|
|
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.
|
2012-03-12 23:51:03 +00:00
|
|
|
isolate_->ScheduleInterrupts(Isolate::kMessageInterrupt);
|
2012-02-01 18:53:40 +00:00
|
|
|
}
|
|
|
|
Dart_MessageNotifyCallback callback = isolate_->message_notify_callback();
|
|
|
|
if (callback) {
|
|
|
|
// Allow the embedder to handle message notification.
|
|
|
|
(*callback)(Api::CastIsolate(isolate_));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-19 19:47:27 +00:00
|
|
|
bool IsolateMessageHandler::HandleMessage(Message* message) {
|
|
|
|
StartIsolateScope start_scope(isolate_);
|
2012-10-05 19:52:55 +00:00
|
|
|
StackZone zone(isolate_);
|
2012-04-19 19:47:27 +00:00
|
|
|
HandleScope handle_scope(isolate_);
|
|
|
|
|
2012-08-27 20:25:44 +00:00
|
|
|
// Parse the message.
|
|
|
|
SnapshotReader reader(message->data(), message->len(),
|
|
|
|
Snapshot::kMessage, Isolate::Current());
|
|
|
|
const Object& msg_obj = Object::Handle(reader.ReadObject());
|
|
|
|
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.
|
|
|
|
|
2012-04-19 19:47:27 +00:00
|
|
|
if (message->IsOOB()) {
|
|
|
|
// For now the only OOB messages are Mirrors messages.
|
2012-04-23 22:26:09 +00:00
|
|
|
HandleMirrorsMessage(isolate_, message->reply_port(), msg);
|
2012-04-19 19:47:27 +00:00
|
|
|
delete message;
|
|
|
|
} else {
|
|
|
|
const Object& result = Object::Handle(
|
|
|
|
DartLibraryCalls::HandleMessage(
|
|
|
|
message->dest_port(), message->reply_port(), msg));
|
|
|
|
delete message;
|
|
|
|
if (result.IsError()) {
|
2012-07-02 21:42:53 +00:00
|
|
|
isolate_->object_store()->set_sticky_error(Error::Cast(result));
|
2012-04-19 19:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ASSERT(result.IsNull());
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-01 18:53:40 +00:00
|
|
|
#if defined(DEBUG)
|
|
|
|
void IsolateMessageHandler::CheckAccess() {
|
2012-05-30 17:07:19 +00:00
|
|
|
ASSERT(IsCurrentIsolate());
|
2012-02-01 18:53:40 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2012-05-30 17:07:19 +00:00
|
|
|
bool IsolateMessageHandler::IsCurrentIsolate() const {
|
|
|
|
return (isolate_ == Isolate::Current());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-06 18:00:51 +00:00
|
|
|
#if defined(DEBUG)
|
|
|
|
// static
|
|
|
|
void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
|
|
|
|
ASSERT(isolate == Isolate::Current());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
Isolate::Isolate()
|
2012-07-03 00:10:23 +00:00
|
|
|
: store_buffer_block_(),
|
|
|
|
store_buffer_(),
|
2012-01-24 19:31:01 +00:00
|
|
|
message_notify_callback_(NULL),
|
2012-01-18 21:46:27 +00:00
|
|
|
name_(NULL),
|
2011-11-29 21:55:13 +00:00
|
|
|
main_port_(0),
|
2011-10-05 05:20:07 +00:00
|
|
|
heap_(NULL),
|
|
|
|
object_store_(NULL),
|
|
|
|
top_context_(Context::null()),
|
|
|
|
random_seed_(Random::kDefaultRandomSeed),
|
|
|
|
top_exit_frame_info_(0),
|
|
|
|
init_callback_data_(NULL),
|
|
|
|
library_tag_handler_(NULL),
|
|
|
|
api_state_(NULL),
|
|
|
|
stub_code_(NULL),
|
2011-11-30 17:04:45 +00:00
|
|
|
debugger_(NULL),
|
2011-10-05 05:20:07 +00:00
|
|
|
long_jump_base_(NULL),
|
|
|
|
timer_list_(),
|
2012-08-06 20:24:03 +00:00
|
|
|
deopt_id_(0),
|
2012-05-10 19:04:09 +00:00
|
|
|
ic_data_array_(Array::null()),
|
2011-12-16 18:41:20 +00:00
|
|
|
mutex_(new Mutex()),
|
2011-10-05 05:20:07 +00:00
|
|
|
stack_limit_(0),
|
2012-04-19 19:47:27 +00:00
|
|
|
saved_stack_limit_(0),
|
|
|
|
message_handler_(NULL),
|
2012-07-24 00:01:50 +00:00
|
|
|
spawn_data_(NULL),
|
|
|
|
gc_prologue_callbacks_(),
|
2012-07-31 17:27:15 +00:00
|
|
|
gc_epilogue_callbacks_(),
|
2012-08-30 20:39:48 +00:00
|
|
|
deopt_cpu_registers_copy_(NULL),
|
|
|
|
deopt_xmm_registers_copy_(NULL),
|
2012-07-31 17:27:15 +00:00
|
|
|
deopt_frame_copy_(NULL),
|
2012-08-30 20:39:48 +00:00
|
|
|
deopt_frame_copy_size_(0),
|
2012-10-02 11:25:53 +00:00
|
|
|
deferred_doubles_(NULL),
|
|
|
|
deferred_mints_(NULL) {
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Isolate::~Isolate() {
|
2012-01-18 21:46:27 +00:00
|
|
|
delete [] name_;
|
2011-10-05 05:20:07 +00:00
|
|
|
delete heap_;
|
|
|
|
delete object_store_;
|
|
|
|
delete api_state_;
|
|
|
|
delete stub_code_;
|
2012-01-19 18:33:32 +00:00
|
|
|
delete debugger_;
|
2011-12-16 18:41:20 +00:00
|
|
|
delete mutex_;
|
|
|
|
mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate.
|
2012-02-01 18:53:40 +00:00
|
|
|
delete message_handler_;
|
|
|
|
message_handler_ = NULL; // Fail fast if we send messages to a dead isolate.
|
2011-10-18 17:54:07 +00:00
|
|
|
}
|
|
|
|
|
2012-02-07 09:18:22 +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;
|
|
|
|
}
|
|
|
|
|
2011-10-18 17:54:07 +00:00
|
|
|
|
2012-01-18 21:46:27 +00:00
|
|
|
Isolate* Isolate::Init(const char* name_prefix) {
|
2011-10-05 05:20:07 +00:00
|
|
|
Isolate* result = new Isolate();
|
|
|
|
ASSERT(result != NULL);
|
|
|
|
|
|
|
|
// TODO(5411455): For now just set the recently created isolate as
|
|
|
|
// the current isolate.
|
|
|
|
SetCurrent(result);
|
|
|
|
|
2012-02-01 18:53:40 +00:00
|
|
|
// Setup the isolate message handler.
|
|
|
|
MessageHandler* handler = new IsolateMessageHandler(result);
|
|
|
|
ASSERT(handler != NULL);
|
|
|
|
result->set_message_handler(handler);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
|
|
|
// 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));
|
2012-02-01 18:53:40 +00:00
|
|
|
result->set_main_port(PortMap::CreatePort(result->message_handler()));
|
2012-01-18 21:46:27 +00:00
|
|
|
result->BuildName(name_prefix);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
2011-11-30 17:04:45 +00:00
|
|
|
result->debugger_ = new Debugger();
|
2011-12-07 22:13:49 +00:00
|
|
|
result->debugger_->Initialize(result);
|
2012-01-18 21:46:27 +00:00
|
|
|
if (FLAG_trace_isolates) {
|
2012-02-01 18:53:40 +00:00
|
|
|
if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) {
|
2012-01-18 21:46:27 +00:00
|
|
|
OS::Print("[+] Starting isolate:\n"
|
|
|
|
"\tisolate: %s\n", result->name());
|
|
|
|
}
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
// TODO(5411455): Use flag to override default value and Validate the
|
|
|
|
// stack size by querying OS.
|
|
|
|
uword Isolate::GetSpecifiedStackSize() {
|
2012-06-15 01:28:53 +00:00
|
|
|
ASSERT(Isolate::kStackSizeBuffer < Thread::GetMaxStackSize());
|
|
|
|
uword stack_size = Thread::GetMaxStackSize() - Isolate::kStackSizeBuffer;
|
2011-10-05 05:20:07 +00:00
|
|
|
return stack_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Isolate::SetStackLimitFromCurrentTOS(uword stack_top_value) {
|
|
|
|
SetStackLimit(stack_top_value - GetSpecifiedStackSize());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Isolate::SetStackLimit(uword limit) {
|
2011-12-16 18:41:20 +00:00
|
|
|
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_) {
|
2012-01-24 20:24:12 +00:00
|
|
|
stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
|
2011-12-16 18:41:20 +00:00
|
|
|
}
|
|
|
|
stack_limit_ |= interrupt_bits;
|
|
|
|
mutex_->Unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2012-08-01 17:15:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-06 20:24:03 +00:00
|
|
|
ICData* Isolate::GetICDataForDeoptId(intptr_t deopt_id) const {
|
2012-08-01 17:15:55 +00:00
|
|
|
if (ic_data_array() == Array::null()) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
const Array& array_handle = Array::Handle(ic_data_array());
|
2012-08-06 20:24:03 +00:00
|
|
|
if (deopt_id >= array_handle.Length()) {
|
2012-08-01 17:15:55 +00:00
|
|
|
// For computations being added in the optimizing compiler.
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ICData& ic_data_handle = ICData::ZoneHandle();
|
2012-08-06 20:24:03 +00:00
|
|
|
ic_data_handle ^= array_handle.At(deopt_id);
|
2012-08-01 17:15:55 +00:00
|
|
|
return &ic_data_handle;
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-25 00:33:25 +00:00
|
|
|
static int MostUsedFunctionFirst(const Function* const* a,
|
|
|
|
const Function* const* b) {
|
|
|
|
if ((*a)->usage_counter() > (*b)->usage_counter()) {
|
2011-10-05 05:20:07 +00:00
|
|
|
return -1;
|
2012-02-25 00:33:25 +00:00
|
|
|
} else if ((*a)->usage_counter() < (*b)->usage_counter()) {
|
2011-10-05 05:20:07 +00:00
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-13 14:23:10 +00:00
|
|
|
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);
|
2012-02-25 00:33:25 +00:00
|
|
|
if (function.usage_counter() > 0) {
|
2012-02-13 14:23:10 +00:00
|
|
|
functions->Add(&function);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
void Isolate::PrintInvokedFunctions() {
|
2011-11-12 05:55:22 +00:00
|
|
|
ASSERT(this == Isolate::Current());
|
2012-10-05 19:52:55 +00:00
|
|
|
StackZone zone(this);
|
2011-11-12 05:55:22 +00:00
|
|
|
HandleScope handle_scope(this);
|
2012-05-23 20:28:21 +00:00
|
|
|
const GrowableObjectArray& libraries =
|
|
|
|
GrowableObjectArray::Handle(object_store()->libraries());
|
2011-10-05 05:20:07 +00:00
|
|
|
Library& library = Library::Handle();
|
|
|
|
GrowableArray<const Function*> invoked_functions;
|
2012-05-23 20:28:21 +00:00
|
|
|
for (int i = 0; i < libraries.Length(); i++) {
|
|
|
|
library ^= libraries.At(i);
|
2011-10-05 05:20:07 +00:00
|
|
|
Class& cls = Class::Handle();
|
|
|
|
ClassDictionaryIterator iter(library);
|
|
|
|
while (iter.HasNext()) {
|
2011-10-20 23:29:06 +00:00
|
|
|
cls = iter.GetNextClass();
|
2012-02-13 14:23:10 +00:00
|
|
|
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);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-25 00:33:25 +00:00
|
|
|
invoked_functions.Sort(MostUsedFunctionFirst);
|
2011-10-05 05:20:07 +00:00
|
|
|
for (int i = 0; i < invoked_functions.length(); i++) {
|
2012-09-06 00:58:25 +00:00
|
|
|
OS::Print("%10"Pd" x %s\n",
|
2012-02-25 00:33:25 +00:00
|
|
|
invoked_functions[i]->usage_counter(),
|
2011-10-05 05:20:07 +00:00
|
|
|
invoked_functions[i]->ToFullyQualifiedCString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-09-07 22:17:56 +00:00
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
void Isolate::Shutdown() {
|
|
|
|
ASSERT(this == Isolate::Current());
|
2012-04-06 18:00:51 +00:00
|
|
|
ASSERT(top_resource() == NULL);
|
2011-10-05 05:20:07 +00:00
|
|
|
ASSERT((heap_ == NULL) || heap_->Verify());
|
|
|
|
|
2012-01-20 22:10:59 +00:00
|
|
|
// 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.
|
|
|
|
{
|
2012-10-05 19:52:55 +00:00
|
|
|
StackZone zone(this);
|
2012-01-20 22:10:59 +00:00
|
|
|
HandleScope handle_scope(this);
|
|
|
|
debugger_->Shutdown();
|
|
|
|
}
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
// Close all the ports owned by this isolate.
|
2012-02-01 18:53:40 +00:00
|
|
|
PortMap::ClosePorts(message_handler());
|
2011-10-05 05:20:07 +00:00
|
|
|
|
2012-02-01 18:53:40 +00:00
|
|
|
// Fail fast if anybody tries to post any more messsages to this isolate.
|
|
|
|
delete message_handler();
|
|
|
|
set_message_handler(NULL);
|
2011-10-05 05:20:07 +00:00
|
|
|
|
2012-09-07 22:17:56 +00:00
|
|
|
// Finalize any weak persistent handles with a non-null referent.
|
|
|
|
FinalizeWeakPersistentHandlesVisitor visitor;
|
|
|
|
api_state()->weak_persistent_handles().VisitHandles(&visitor);
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
// Dump all accumalated timer data for the isolate.
|
|
|
|
timer_list_.ReportTimers();
|
2012-02-25 00:33:25 +00:00
|
|
|
if (FLAG_report_usage_count) {
|
2011-10-05 05:20:07 +00:00
|
|
|
PrintInvokedFunctions();
|
|
|
|
}
|
|
|
|
CompilerStats::Print();
|
|
|
|
if (FLAG_generate_gdb_symbols) {
|
|
|
|
DebugInfo::UnregisterAllSections();
|
|
|
|
}
|
2012-01-18 21:46:27 +00:00
|
|
|
if (FLAG_trace_isolates) {
|
2012-10-05 19:52:55 +00:00
|
|
|
StackZone zone(this);
|
2012-07-25 23:41:53 +00:00
|
|
|
HandleScope handle_scope(this);
|
2012-09-06 00:58:25 +00:00
|
|
|
OS::Print("Number of symbols added = %"Pd"\n", Symbols::Size(this));
|
2012-01-18 21:46:27 +00:00
|
|
|
OS::Print("[-] Stopping isolate:\n"
|
|
|
|
"\tisolate: %s\n", name());
|
|
|
|
}
|
2011-10-05 05:20:07 +00:00
|
|
|
// TODO(5411455): For now just make sure there are no current isolates
|
|
|
|
// as we are shutting down the isolate.
|
|
|
|
SetCurrent(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-01 00:30:25 +00:00
|
|
|
Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
|
2011-12-16 18:41:20 +00:00
|
|
|
Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL;
|
2012-06-28 18:15:17 +00:00
|
|
|
Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL;
|
2011-12-16 18:41:20 +00:00
|
|
|
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
|
2012-03-13 23:41:59 +00:00
|
|
|
bool visit_prologue_weak_handles,
|
2011-10-05 05:20:07 +00:00
|
|
|
bool validate_frames) {
|
|
|
|
ASSERT(visitor != NULL);
|
|
|
|
|
|
|
|
// Visit objects in the object store.
|
|
|
|
object_store()->VisitObjectPointers(visitor);
|
|
|
|
|
2012-05-01 09:20:40 +00:00
|
|
|
// Visit objects in the class table.
|
|
|
|
class_table()->VisitObjectPointers(visitor);
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
// Visit objects in per isolate stubs.
|
|
|
|
StubCode::VisitObjectPointers(visitor);
|
|
|
|
|
|
|
|
// Visit objects in zones.
|
|
|
|
current_zone()->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) {
|
2012-03-13 23:41:59 +00:00
|
|
|
api_state()->VisitObjectPointers(visitor, visit_prologue_weak_handles);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Visit the top context which is stored in the isolate.
|
|
|
|
visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_context_));
|
2011-11-30 17:04:45 +00:00
|
|
|
|
2012-05-10 19:04:09 +00:00
|
|
|
// Visit the currently active IC data array.
|
|
|
|
visitor->VisitPointer(reinterpret_cast<RawObject**>(&ic_data_array_));
|
|
|
|
|
2011-11-30 17:04:45 +00:00
|
|
|
// Visit objects in the debugger.
|
|
|
|
debugger()->VisitObjectPointers(visitor);
|
2011-10-05 05:20:07 +00:00
|
|
|
}
|
|
|
|
|
2011-12-20 01:44:53 +00:00
|
|
|
|
2012-03-13 23:41:59 +00:00
|
|
|
void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor,
|
|
|
|
bool visit_prologue_weak_handles) {
|
2011-12-20 01:44:53 +00:00
|
|
|
if (api_state() != NULL) {
|
2012-03-13 23:41:59 +00:00
|
|
|
api_state()->VisitWeakHandles(visitor, visit_prologue_weak_handles);
|
2011-12-20 01:44:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-05 05:20:07 +00:00
|
|
|
} // namespace dart
|