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

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

Issue 24834002: Refactor some deoptimization code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/deferred_objects.h ('k') | runtime/vm/deopt_instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/isolate.h" 5 #include "vm/deferred_objects.h"
6 6
7 #include "include/dart_api.h" 7 #include "vm/deopt_instructions.h"
8 #include "platform/assert.h" 8 #include "vm/flags.h"
9 #include "platform/json.h" 9 #include "vm/object.h"
10 #include "lib/mirrors.h"
11 #include "vm/code_observers.h"
12 #include "vm/compiler_stats.h"
13 #include "vm/coverage.h"
14 #include "vm/dart_api_state.h"
15 #include "vm/dart_entry.h"
16 #include "vm/debugger.h"
17 #include "vm/heap.h"
18 #include "vm/heap_histogram.h"
19 #include "vm/message_handler.h"
20 #include "vm/object_id_ring.h"
21 #include "vm/object_store.h"
22 #include "vm/parser.h"
23 #include "vm/port.h"
24 #include "vm/reusable_handles.h"
25 #include "vm/service.h"
26 #include "vm/simulator.h"
27 #include "vm/stack_frame.h"
28 #include "vm/stub_code.h"
29 #include "vm/symbols.h"
30 #include "vm/thread.h"
31 #include "vm/timer.h"
32 #include "vm/visitor.h"
33
34 10
35 namespace dart { 11 namespace dart {
36 12
37 DEFINE_FLAG(bool, report_usage_count, false,
38 "Track function usage and report.");
39 DEFINE_FLAG(bool, trace_isolates, false,
40 "Trace isolate creation and shut down.");
41 DECLARE_FLAG(bool, trace_deoptimization_verbose); 13 DECLARE_FLAG(bool, trace_deoptimization_verbose);
42 14
43 15
44 void Isolate::RegisterClass(const Class& cls) {
45 class_table()->Register(cls);
46 if (object_histogram() != NULL) object_histogram()->RegisterClass(cls);
47 }
48
49
50 class IsolateMessageHandler : public MessageHandler {
51 public:
52 explicit IsolateMessageHandler(Isolate* isolate);
53 ~IsolateMessageHandler();
54
55 const char* name() const;
56 void MessageNotify(Message::Priority priority);
57 bool HandleMessage(Message* message);
58
59 #if defined(DEBUG)
60 // Check that it is safe to access this handler.
61 void CheckAccess();
62 #endif
63 bool IsCurrentIsolate() const;
64 virtual Isolate* GetIsolate() const { return isolate_; }
65 bool UnhandledExceptionCallbackHandler(const Object& message,
66 const UnhandledException& error);
67
68 private:
69 bool ProcessUnhandledException(const Object& message, const Error& result);
70 RawFunction* ResolveCallbackFunction();
71 Isolate* isolate_;
72 };
73
74
75 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate)
76 : isolate_(isolate) {
77 }
78
79
80 IsolateMessageHandler::~IsolateMessageHandler() {
81 }
82
83 const char* IsolateMessageHandler::name() const {
84 return isolate_->name();
85 }
86
87
88 void IsolateMessageHandler::MessageNotify(Message::Priority priority) {
89 if (priority >= Message::kOOBPriority) {
90 // Handle out of band messages even if the isolate is busy.
91 isolate_->ScheduleInterrupts(Isolate::kMessageInterrupt);
92 }
93 Dart_MessageNotifyCallback callback = isolate_->message_notify_callback();
94 if (callback) {
95 // Allow the embedder to handle message notification.
96 (*callback)(Api::CastIsolate(isolate_));
97 }
98 }
99
100
101 bool IsolateMessageHandler::HandleMessage(Message* message) {
102 StartIsolateScope start_scope(isolate_);
103 StackZone zone(isolate_);
104 HandleScope handle_scope(isolate_);
105
106 // If the message is in band we lookup the receive port to dispatch to. If
107 // the receive port is closed, we drop the message without deserializing it.
108 Object& receive_port = Object::Handle();
109 if (!message->IsOOB()) {
110 receive_port = DartLibraryCalls::LookupReceivePort(message->dest_port());
111 if (receive_port.IsError()) {
112 return ProcessUnhandledException(Object::null_instance(),
113 Error::Cast(receive_port));
114 }
115 if (receive_port.IsNull()) {
116 delete message;
117 return true;
118 }
119 }
120
121 // Parse the message.
122 SnapshotReader reader(message->data(), message->len(),
123 Snapshot::kMessage, Isolate::Current());
124 const Object& msg_obj = Object::Handle(reader.ReadObject());
125 if (msg_obj.IsError()) {
126 // An error occurred while reading the message.
127 return ProcessUnhandledException(Object::null_instance(),
128 Error::Cast(msg_obj));
129 }
130 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) {
131 // TODO(turnidge): We need to decide what an isolate does with
132 // malformed messages. If they (eventually) come from a remote
133 // machine, then it might make sense to drop the message entirely.
134 // In the case that the message originated locally, which is
135 // always true for now, then this should never occur.
136 UNREACHABLE();
137 }
138
139 Instance& msg = Instance::Handle();
140 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null.
141
142 bool success = true;
143 if (message->IsOOB()) {
144 Service::HandleServiceMessage(isolate_, message->reply_port(), msg);
145 } else {
146 const Object& result = Object::Handle(
147 DartLibraryCalls::HandleMessage(
148 receive_port, message->reply_port(), msg));
149 if (result.IsError()) {
150 success = ProcessUnhandledException(msg, Error::Cast(result));
151 } else {
152 ASSERT(result.IsNull());
153 }
154 }
155 delete message;
156 return success;
157 }
158
159
160 RawFunction* IsolateMessageHandler::ResolveCallbackFunction() {
161 ASSERT(isolate_->object_store()->unhandled_exception_handler() != NULL);
162 String& callback_name = String::Handle(isolate_);
163 if (isolate_->object_store()->unhandled_exception_handler() !=
164 String::null()) {
165 callback_name = isolate_->object_store()->unhandled_exception_handler();
166 } else {
167 callback_name = String::New("_unhandledExceptionCallback");
168 }
169 Library& lib =
170 Library::Handle(isolate_, isolate_->object_store()->isolate_library());
171 Function& func =
172 Function::Handle(isolate_, lib.LookupLocalFunction(callback_name));
173 if (func.IsNull()) {
174 lib = isolate_->object_store()->root_library();
175 func = lib.LookupLocalFunction(callback_name);
176 }
177 return func.raw();
178 }
179
180
181 bool IsolateMessageHandler::UnhandledExceptionCallbackHandler(
182 const Object& message, const UnhandledException& error) {
183 const Instance& cause = Instance::Handle(isolate_, error.exception());
184 const Instance& stacktrace =
185 Instance::Handle(isolate_, error.stacktrace());
186
187 // Wrap these args into an IsolateUncaughtException object.
188 const Array& exception_args = Array::Handle(Array::New(3));
189 exception_args.SetAt(0, message);
190 exception_args.SetAt(1, cause);
191 exception_args.SetAt(2, stacktrace);
192 const Object& exception =
193 Object::Handle(isolate_,
194 Exceptions::Create(Exceptions::kIsolateUnhandledException,
195 exception_args));
196 if (exception.IsError()) {
197 return false;
198 }
199 ASSERT(exception.IsInstance());
200
201 // Invoke script's callback function.
202 Object& function = Object::Handle(isolate_, ResolveCallbackFunction());
203 if (function.IsNull() || function.IsError()) {
204 return false;
205 }
206 const Array& callback_args = Array::Handle(Array::New(1));
207 callback_args.SetAt(0, exception);
208 const Object& result =
209 Object::Handle(DartEntry::InvokeFunction(Function::Cast(function),
210 callback_args));
211 if (result.IsError()) {
212 const Error& err = Error::Cast(result);
213 OS::PrintErr("failed calling unhandled exception callback: %s\n",
214 err.ToErrorCString());
215 return false;
216 }
217
218 ASSERT(result.IsBool());
219 bool continue_from_exception = Bool::Cast(result).value();
220 if (continue_from_exception) {
221 isolate_->object_store()->clear_sticky_error();
222 }
223 return continue_from_exception;
224 }
225
226 #if defined(DEBUG)
227 void IsolateMessageHandler::CheckAccess() {
228 ASSERT(IsCurrentIsolate());
229 }
230 #endif
231
232
233 bool IsolateMessageHandler::IsCurrentIsolate() const {
234 return (isolate_ == Isolate::Current());
235 }
236
237
238 bool IsolateMessageHandler::ProcessUnhandledException(
239 const Object& message, const Error& result) {
240 if (result.IsUnhandledException()) {
241 // Invoke the isolate's uncaught exception handler, if it exists.
242 const UnhandledException& error = UnhandledException::Cast(result);
243 RawInstance* exception = error.exception();
244 if ((exception != isolate_->object_store()->out_of_memory()) &&
245 (exception != isolate_->object_store()->stack_overflow())) {
246 if (UnhandledExceptionCallbackHandler(message, error)) {
247 return true;
248 }
249 }
250 }
251
252 // Invoke the isolate's unhandled exception callback if there is one.
253 if (Isolate::UnhandledExceptionCallback() != NULL) {
254 Dart_EnterScope();
255 Dart_Handle error = Api::NewHandle(isolate_, result.raw());
256 (Isolate::UnhandledExceptionCallback())(error);
257 Dart_ExitScope();
258 }
259
260 isolate_->object_store()->set_sticky_error(result);
261 return false;
262 }
263
264
265 #if defined(DEBUG)
266 // static
267 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) {
268 ASSERT(isolate == Isolate::Current());
269 }
270 #endif
271
272
273 void DeferredDouble::Materialize() { 16 void DeferredDouble::Materialize() {
274 RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot()); 17 RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot());
275 *double_slot = Double::New(value()); 18 *double_slot = Double::New(value());
276 19
277 if (FLAG_trace_deoptimization_verbose) { 20 if (FLAG_trace_deoptimization_verbose) {
278 OS::PrintErr("materializing double at %" Px ": %g\n", 21 OS::PrintErr("materializing double at %" Px ": %g\n",
279 reinterpret_cast<uword>(slot()), value()); 22 reinterpret_cast<uword>(slot()), value());
280 } 23 }
281 } 24 }
282 25
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 uint32_t y = raw_uint32x4->y(); 64 uint32_t y = raw_uint32x4->y();
322 uint32_t z = raw_uint32x4->z(); 65 uint32_t z = raw_uint32x4->z();
323 uint32_t w = raw_uint32x4->w(); 66 uint32_t w = raw_uint32x4->w();
324 OS::PrintErr("materializing Uint32x4 at %" Px ": %x,%x,%x,%x\n", 67 OS::PrintErr("materializing Uint32x4 at %" Px ": %x,%x,%x,%x\n",
325 reinterpret_cast<uword>(slot()), x, y, z, w); 68 reinterpret_cast<uword>(slot()), x, y, z, w);
326 } 69 }
327 } 70 }
328 71
329 72
330 void DeferredObjectRef::Materialize() { 73 void DeferredObjectRef::Materialize() {
331 DeferredObject* obj = Isolate::Current()->GetDeferredObject(index()); 74 // TODO(turnidge): Consider passing the deopt_context to materialize
75 // instead of accessing it through the current isolate. It would
76 // make it easier to test deferred object materialization in a unit
77 // test eventually.
78 DeferredObject* obj =
79 Isolate::Current()->deopt_context()->GetDeferredObject(index());
332 *slot() = obj->object(); 80 *slot() = obj->object();
333 if (FLAG_trace_deoptimization_verbose) { 81 if (FLAG_trace_deoptimization_verbose) {
334 OS::PrintErr("writing instance ref at %" Px ": %s\n", 82 OS::PrintErr("writing instance ref at %" Px ": %s\n",
335 reinterpret_cast<uword>(slot()), 83 reinterpret_cast<uword>(slot()),
336 Instance::Handle(obj->object()).ToCString()); 84 Instance::Handle(obj->object()).ToCString());
337 } 85 }
338 } 86 }
339 87
340 88
341 RawInstance* DeferredObject::object() { 89 RawInstance* DeferredObject::object() {
(...skipping 27 matching lines...) Expand all
369 if (FLAG_trace_deoptimization_verbose) { 117 if (FLAG_trace_deoptimization_verbose) {
370 OS::PrintErr(" %s <- %s\n", 118 OS::PrintErr(" %s <- %s\n",
371 String::Handle(field.name()).ToCString(), 119 String::Handle(field.name()).ToCString(),
372 value.ToCString()); 120 value.ToCString());
373 } 121 }
374 } 122 }
375 123
376 object_ = &obj; 124 object_ = &obj;
377 } 125 }
378 126
379
380 #define REUSABLE_HANDLE_INITIALIZERS(object) \
381 object##_handle_(NULL),
382
383 Isolate::Isolate()
384 : store_buffer_(),
385 message_notify_callback_(NULL),
386 name_(NULL),
387 start_time_(OS::GetCurrentTimeMicros()),
388 main_port_(0),
389 heap_(NULL),
390 object_store_(NULL),
391 top_context_(Context::null()),
392 top_exit_frame_info_(0),
393 init_callback_data_(NULL),
394 library_tag_handler_(NULL),
395 api_state_(NULL),
396 stub_code_(NULL),
397 debugger_(NULL),
398 single_step_(false),
399 simulator_(NULL),
400 long_jump_base_(NULL),
401 timer_list_(),
402 deopt_id_(0),
403 mutex_(new Mutex()),
404 stack_limit_(0),
405 saved_stack_limit_(0),
406 message_handler_(NULL),
407 spawn_data_(0),
408 is_runnable_(false),
409 gc_prologue_callbacks_(),
410 gc_epilogue_callbacks_(),
411 defer_finalization_count_(0),
412 deopt_cpu_registers_copy_(NULL),
413 deopt_fpu_registers_copy_(NULL),
414 deopt_frame_copy_(NULL),
415 deopt_frame_copy_size_(0),
416 deferred_boxes_(NULL),
417 deferred_object_refs_(NULL),
418 deferred_objects_count_(0),
419 deferred_objects_(NULL),
420 stacktrace_(NULL),
421 stack_frame_index_(-1),
422 object_histogram_(NULL),
423 object_id_ring_(NULL),
424 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
425 reusable_handles_() {
426 if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) {
427 object_histogram_ = new ObjectHistogram(this);
428 }
429 }
430 #undef REUSABLE_HANDLE_INITIALIZERS
431
432
433 Isolate::~Isolate() {
434 delete [] name_;
435 delete heap_;
436 delete object_store_;
437 delete api_state_;
438 delete stub_code_;
439 delete debugger_;
440 #if defined(USING_SIMULATOR)
441 delete simulator_;
442 #endif
443 delete mutex_;
444 mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate.
445 delete message_handler_;
446 message_handler_ = NULL; // Fail fast if we send messages to a dead isolate.
447 delete object_histogram_;
448 }
449
450 void Isolate::SetCurrent(Isolate* current) {
451 Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current));
452 }
453
454
455 // The single thread local key which stores all the thread local data
456 // for a thread. Since an Isolate is the central repository for
457 // storing all isolate specific information a single thread local key
458 // is sufficient.
459 ThreadLocalKey Isolate::isolate_key = Thread::kUnsetThreadLocalKey;
460
461
462 void Isolate::InitOnce() {
463 ASSERT(isolate_key == Thread::kUnsetThreadLocalKey);
464 isolate_key = Thread::CreateThreadLocal();
465 ASSERT(isolate_key != Thread::kUnsetThreadLocalKey);
466 create_callback_ = NULL;
467 }
468
469
470 Isolate* Isolate::Init(const char* name_prefix) {
471 Isolate* result = new Isolate();
472 ASSERT(result != NULL);
473
474 // TODO(5411455): For now just set the recently created isolate as
475 // the current isolate.
476 SetCurrent(result);
477
478 // Setup the isolate specific resuable handles.
479 #define REUSABLE_HANDLE_ALLOCATION(object) \
480 result->object##_handle_ = result->AllocateReusableHandle<object>(); \
481
482 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION)
483 #undef REUSABLE_HANDLE_ALLOCATION
484
485 // Setup the isolate message handler.
486 MessageHandler* handler = new IsolateMessageHandler(result);
487 ASSERT(handler != NULL);
488 result->set_message_handler(handler);
489
490 // Setup the Dart API state.
491 ApiState* state = new ApiState();
492 ASSERT(state != NULL);
493 result->set_api_state(state);
494
495 // Initialize stack top and limit in case we are running the isolate in the
496 // main thread.
497 // TODO(5411455): Need to figure out how to set the stack limit for the
498 // main thread.
499 result->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&result));
500 result->set_main_port(PortMap::CreatePort(result->message_handler()));
501 result->BuildName(name_prefix);
502
503 result->debugger_ = new Debugger();
504 result->debugger_->Initialize(result);
505 if (FLAG_trace_isolates) {
506 if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) {
507 OS::Print("[+] Starting isolate:\n"
508 "\tisolate: %s\n", result->name());
509 }
510 }
511 return result;
512 }
513
514
515 void Isolate::BuildName(const char* name_prefix) {
516 ASSERT(name_ == NULL);
517 if (name_prefix == NULL) {
518 name_prefix = "isolate";
519 }
520 const char* kFormat = "%s-%lld";
521 intptr_t len = OS::SNPrint(NULL, 0, kFormat, name_prefix, main_port()) + 1;
522 name_ = new char[len];
523 OS::SNPrint(name_, len, kFormat, name_prefix, main_port());
524 }
525
526
527 // TODO(5411455): Use flag to override default value and Validate the
528 // stack size by querying OS.
529 uword Isolate::GetSpecifiedStackSize() {
530 ASSERT(Isolate::kStackSizeBuffer < Thread::GetMaxStackSize());
531 uword stack_size = Thread::GetMaxStackSize() - Isolate::kStackSizeBuffer;
532 return stack_size;
533 }
534
535
536 void Isolate::SetStackLimitFromCurrentTOS(uword stack_top_value) {
537 #if defined(USING_SIMULATOR)
538 // Ignore passed-in native stack top and use Simulator stack top.
539 Simulator* sim = Simulator::Current(); // May allocate a simulator.
540 ASSERT(simulator() == sim); // This isolate's simulator is the current one.
541 stack_top_value = sim->StackTop();
542 // The overflow area is accounted for by the simulator.
543 #endif
544 SetStackLimit(stack_top_value - GetSpecifiedStackSize());
545 }
546
547
548 void Isolate::SetStackLimit(uword limit) {
549 MutexLocker ml(mutex_);
550 if (stack_limit_ == saved_stack_limit_) {
551 // No interrupt pending, set stack_limit_ too.
552 stack_limit_ = limit;
553 }
554 saved_stack_limit_ = limit;
555 }
556
557
558 void Isolate::ScheduleInterrupts(uword interrupt_bits) {
559 // TODO(turnidge): Can't use MutexLocker here because MutexLocker is
560 // a StackResource, which requires a current isolate. Should
561 // MutexLocker really be a StackResource?
562 mutex_->Lock();
563 ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask.
564 if (stack_limit_ == saved_stack_limit_) {
565 stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask;
566 }
567 stack_limit_ |= interrupt_bits;
568 mutex_->Unlock();
569 }
570
571
572 bool Isolate::MakeRunnable() {
573 ASSERT(Isolate::Current() == NULL);
574 // Can't use MutexLocker here because MutexLocker is
575 // a StackResource, which requires a current isolate.
576 mutex_->Lock();
577 // Check if we are in a valid state to make the isolate runnable.
578 if (is_runnable_ == true) {
579 mutex_->Unlock();
580 return false; // Already runnable.
581 }
582 // Set the isolate as runnable and if we are being spawned schedule
583 // isolate on thread pool for execution.
584 is_runnable_ = true;
585 IsolateSpawnState* state = reinterpret_cast<IsolateSpawnState*>(spawn_data());
586 if (state != NULL) {
587 ASSERT(this == state->isolate());
588 Run();
589 }
590 mutex_->Unlock();
591 return true;
592 }
593
594
595 static void StoreError(Isolate* isolate, const Object& obj) {
596 ASSERT(obj.IsError());
597 isolate->object_store()->set_sticky_error(Error::Cast(obj));
598 }
599
600
601 static bool RunIsolate(uword parameter) {
602 Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
603 IsolateSpawnState* state = NULL;
604 {
605 MutexLocker ml(isolate->mutex());
606 state = reinterpret_cast<IsolateSpawnState*>(isolate->spawn_data());
607 isolate->set_spawn_data(0);
608 }
609 {
610 StartIsolateScope start_scope(isolate);
611 StackZone zone(isolate);
612 HandleScope handle_scope(isolate);
613 if (!ClassFinalizer::FinalizePendingClasses()) {
614 // Error is in sticky error already.
615 return false;
616 }
617
618 // Set up specific unhandled exception handler.
619 const String& callback_name = String::Handle(
620 isolate, String::New(state->exception_callback_name()));
621 isolate->object_store()->
622 set_unhandled_exception_handler(callback_name);
623
624 Object& result = Object::Handle();
625 result = state->ResolveFunction();
626 delete state;
627 state = NULL;
628 if (result.IsError()) {
629 StoreError(isolate, result);
630 return false;
631 }
632 ASSERT(result.IsFunction());
633 Function& func = Function::Handle(isolate);
634 func ^= result.raw();
635 result = DartEntry::InvokeFunction(func, Object::empty_array());
636 if (result.IsError()) {
637 StoreError(isolate, result);
638 return false;
639 }
640 }
641 return true;
642 }
643
644
645 static void ShutdownIsolate(uword parameter) {
646 Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
647 {
648 // Print the error if there is one. This may execute dart code to
649 // print the exception object, so we need to use a StartIsolateScope.
650 StartIsolateScope start_scope(isolate);
651 StackZone zone(isolate);
652 HandleScope handle_scope(isolate);
653 Error& error = Error::Handle();
654 error = isolate->object_store()->sticky_error();
655 if (!error.IsNull()) {
656 OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString());
657 }
658 Dart::RunShutdownCallback();
659 }
660 {
661 // Shut the isolate down.
662 SwitchIsolateScope switch_scope(isolate);
663 Dart::ShutdownIsolate();
664 }
665 }
666
667
668 void Isolate::Run() {
669 message_handler()->Run(Dart::thread_pool(),
670 RunIsolate,
671 ShutdownIsolate,
672 reinterpret_cast<uword>(this));
673 }
674
675
676 uword Isolate::GetAndClearInterrupts() {
677 MutexLocker ml(mutex_);
678 if (stack_limit_ == saved_stack_limit_) {
679 return 0; // No interrupt was requested.
680 }
681 uword interrupt_bits = stack_limit_ & kInterruptsMask;
682 stack_limit_ = saved_stack_limit_;
683 return interrupt_bits;
684 }
685
686
687 static int MostUsedFunctionFirst(const Function* const* a,
688 const Function* const* b) {
689 if ((*a)->usage_counter() > (*b)->usage_counter()) {
690 return -1;
691 } else if ((*a)->usage_counter() < (*b)->usage_counter()) {
692 return 1;
693 } else {
694 return 0;
695 }
696 }
697
698
699 static void AddFunctionsFromClass(const Class& cls,
700 GrowableArray<const Function*>* functions) {
701 const Array& class_functions = Array::Handle(cls.functions());
702 // Class 'dynamic' is allocated/initialized in a special way, leaving
703 // the functions field NULL instead of empty.
704 const int func_len = class_functions.IsNull() ? 0 : class_functions.Length();
705 for (int j = 0; j < func_len; j++) {
706 Function& function = Function::Handle();
707 function ^= class_functions.At(j);
708 if (function.usage_counter() > 0) {
709 functions->Add(&function);
710 }
711 }
712 }
713
714
715 void Isolate::PrintInvokedFunctions() {
716 ASSERT(this == Isolate::Current());
717 const GrowableObjectArray& libraries =
718 GrowableObjectArray::Handle(object_store()->libraries());
719 Library& library = Library::Handle();
720 GrowableArray<const Function*> invoked_functions;
721 for (int i = 0; i < libraries.Length(); i++) {
722 library ^= libraries.At(i);
723 Class& cls = Class::Handle();
724 ClassDictionaryIterator iter(library,
725 ClassDictionaryIterator::kIteratePrivate);
726 while (iter.HasNext()) {
727 cls = iter.GetNextClass();
728 AddFunctionsFromClass(cls, &invoked_functions);
729 }
730 }
731 invoked_functions.Sort(MostUsedFunctionFirst);
732 for (int i = 0; i < invoked_functions.length(); i++) {
733 OS::Print("%10" Pd " x %s\n",
734 invoked_functions[i]->usage_counter(),
735 invoked_functions[i]->ToFullyQualifiedCString());
736 }
737 }
738
739
740 class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor {
741 public:
742 FinalizeWeakPersistentHandlesVisitor() {
743 }
744
745 void VisitHandle(uword addr) {
746 FinalizablePersistentHandle* handle =
747 reinterpret_cast<FinalizablePersistentHandle*>(addr);
748 FinalizablePersistentHandle::Finalize(handle);
749 }
750
751 private:
752 DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor);
753 };
754
755
756 void Isolate::Shutdown() {
757 ASSERT(this == Isolate::Current());
758 ASSERT(top_resource() == NULL);
759 ASSERT((heap_ == NULL) || heap_->Verify());
760
761 // Create an area where we do have a zone and a handle scope so that we can
762 // call VM functions while tearing this isolate down.
763 {
764 StackZone stack_zone(this);
765 HandleScope handle_scope(this);
766
767 if (FLAG_print_object_histogram) {
768 heap()->CollectAllGarbage();
769 object_histogram()->Print();
770 }
771
772 // Clean up debugger resources.
773 debugger()->Shutdown();
774
775 // Close all the ports owned by this isolate.
776 PortMap::ClosePorts(message_handler());
777
778 // Fail fast if anybody tries to post any more messsages to this isolate.
779 delete message_handler();
780 set_message_handler(NULL);
781
782 // Dump all accumalated timer data for the isolate.
783 timer_list_.ReportTimers();
784 if (FLAG_report_usage_count) {
785 PrintInvokedFunctions();
786 }
787
788 // Write out the coverage data if collection has been enabled.
789 CodeCoverage::Write(this);
790
791 // Finalize any weak persistent handles with a non-null referent.
792 FinalizeWeakPersistentHandlesVisitor visitor;
793 api_state()->weak_persistent_handles().VisitHandles(&visitor);
794
795 CompilerStats::Print();
796 // TODO(asiva): Move this code to Dart::Cleanup when we have that method
797 // as the cleanup for Dart::InitOnce.
798 CodeObservers::DeleteAll();
799 if (FLAG_trace_isolates) {
800 heap()->PrintSizes();
801 megamorphic_cache_table()->PrintSizes();
802 Symbols::DumpStats();
803 OS::Print("[-] Stopping isolate:\n"
804 "\tisolate: %s\n", name());
805 }
806 }
807
808 // TODO(5411455): For now just make sure there are no current isolates
809 // as we are shutting down the isolate.
810 SetCurrent(NULL);
811 }
812
813
814 Dart_IsolateCreateCallback Isolate::create_callback_ = NULL;
815 Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL;
816 Dart_IsolateUnhandledExceptionCallback
817 Isolate::unhandled_exception_callback_ = NULL;
818 Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL;
819 Dart_FileOpenCallback Isolate::file_open_callback_ = NULL;
820 Dart_FileReadCallback Isolate::file_read_callback_ = NULL;
821 Dart_FileWriteCallback Isolate::file_write_callback_ = NULL;
822 Dart_FileCloseCallback Isolate::file_close_callback_ = NULL;
823 Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL;
824
825
826 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
827 bool visit_prologue_weak_handles,
828 bool validate_frames) {
829 ASSERT(visitor != NULL);
830
831 // Visit objects in the object store.
832 object_store()->VisitObjectPointers(visitor);
833
834 // Visit objects in the class table.
835 class_table()->VisitObjectPointers(visitor);
836
837 // Visit objects in the megamorphic cache.
838 megamorphic_cache_table()->VisitObjectPointers(visitor);
839
840 // Visit objects in per isolate stubs.
841 StubCode::VisitObjectPointers(visitor);
842
843 // Visit objects in zones.
844 current_zone()->VisitObjectPointers(visitor);
845
846 // Visit objects in isolate specific handles area.
847 reusable_handles_.VisitObjectPointers(visitor);
848
849 // Iterate over all the stack frames and visit objects on the stack.
850 StackFrameIterator frames_iterator(validate_frames);
851 StackFrame* frame = frames_iterator.NextFrame();
852 while (frame != NULL) {
853 frame->VisitObjectPointers(visitor);
854 frame = frames_iterator.NextFrame();
855 }
856
857 // Visit the dart api state for all local and persistent handles.
858 if (api_state() != NULL) {
859 api_state()->VisitObjectPointers(visitor, visit_prologue_weak_handles);
860 }
861
862 // Visit the top context which is stored in the isolate.
863 visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_context_));
864
865 // Visit objects in the debugger.
866 debugger()->VisitObjectPointers(visitor);
867 }
868
869
870 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor,
871 bool visit_prologue_weak_handles) {
872 if (api_state() != NULL) {
873 api_state()->VisitWeakHandles(visitor, visit_prologue_weak_handles);
874 }
875 }
876
877
878 static Monitor* status_sync = NULL;
879
880
881 bool Isolate::FetchStacktrace() {
882 Isolate* isolate = Isolate::Current();
883 MonitorLocker ml(status_sync);
884 DebuggerStackTrace* stack = Debugger::CollectStackTrace();
885 TextBuffer buffer(256);
886 buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"stacktrace\": [ ",
887 reinterpret_cast<int64_t>(isolate));
888 intptr_t n_frames = stack->Length();
889 String& url = String::Handle();
890 String& function = String::Handle();
891 for (int i = 0; i < n_frames; i++) {
892 if (i > 0) {
893 buffer.Printf(", ");
894 }
895 ActivationFrame* frame = stack->FrameAt(i);
896 url ^= frame->SourceUrl();
897 function ^= frame->function().UserVisibleName();
898 buffer.Printf("{ \"url\": \"%s\", ", url.ToCString());
899 buffer.Printf("\"line\": %" Pd ", ", frame->LineNumber());
900 buffer.Printf("\"function\": \"%s\", ", function.ToCString());
901
902 const Code& code = frame->code();
903 buffer.Printf("\"code\": { ");
904 buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true");
905 buffer.Printf("\"optimized\": %s }}",
906 code.is_optimized() ? "false" : "true");
907 }
908 buffer.Printf("]}");
909 isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length());
910 ml.Notify();
911 return true;
912 }
913
914
915 bool Isolate::FetchStackFrameDetails() {
916 Isolate* isolate = Isolate::Current();
917 ASSERT(isolate->stack_frame_index_ >= 0);
918 MonitorLocker ml(status_sync);
919 DebuggerStackTrace* stack = Debugger::CollectStackTrace();
920 intptr_t frame_index = isolate->stack_frame_index_;
921 if (frame_index >= stack->Length()) {
922 // Frame no longer available.
923 return false;
924 }
925 ActivationFrame* frame = stack->FrameAt(frame_index);
926 TextBuffer buffer(256);
927 buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"frame_index\": %" Pd ", ",
928 reinterpret_cast<int64_t>(isolate), frame_index);
929
930 const Code& code = frame->code();
931 buffer.Printf("\"code\": { \"size\": %" Pd ", ", code.Size());
932 buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true");
933 buffer.Printf("\"optimized\": %s }, ",
934 code.is_optimized() ? "false" : "true");
935 // TODO(tball): add compilation stats (time, etc.), when available.
936
937 buffer.Printf("\"local_vars\": [ ");
938 intptr_t n_local_vars = frame->NumLocalVariables();
939 String& var_name = String::Handle();
940 Instance& value = Instance::Handle();
941 for (int i = 0; i < n_local_vars; i++) {
942 if (i > 0) {
943 buffer.Printf(", ");
944 }
945 intptr_t token_pos, end_pos;
946 frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value);
947 buffer.Printf(
948 "{ \"name\": \"%s\", \"pos\": %" Pd ", \"end_pos\": %" Pd ", "
949 "\"value\": \"%s\" }",
950 var_name.ToCString(), token_pos, end_pos, value.ToCString());
951 }
952 buffer.Printf("]}");
953 isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length());
954 ml.Notify();
955 return true;
956 }
957
958
959 char* Isolate::DoStacktraceInterrupt(Dart_IsolateInterruptCallback cb) {
960 ASSERT(stacktrace_ == NULL);
961 SetVmStatsCallback(cb);
962 if (status_sync == NULL) {
963 status_sync = new Monitor();
964 }
965 if (is_runnable()) {
966 ScheduleInterrupts(Isolate::kVmStatusInterrupt);
967 {
968 MonitorLocker ml(status_sync);
969 if (stacktrace_ == NULL) { // It may already be available.
970 ml.Wait(1000);
971 }
972 }
973 SetVmStatsCallback(NULL);
974 }
975 char* result = stacktrace_;
976 stacktrace_ = NULL;
977 if (result == NULL) {
978 // Return empty stack.
979 TextBuffer buffer(256);
980 buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"stacktrace\": []}",
981 reinterpret_cast<int64_t>(this));
982
983 result = OS::StrNDup(buffer.buf(), buffer.length());
984 }
985 ASSERT(result != NULL);
986 // result is freed by VmStats::WebServer().
987 return result;
988 }
989
990
991 char* Isolate::GetStatusStacktrace() {
992 return DoStacktraceInterrupt(&FetchStacktrace);
993 }
994
995 char* Isolate::GetStatusStackFrame(intptr_t index) {
996 ASSERT(index >= 0);
997 stack_frame_index_ = index;
998 char* result = DoStacktraceInterrupt(&FetchStackFrameDetails);
999 stack_frame_index_ = -1;
1000 return result;
1001 }
1002
1003
1004 // Returns the isolate's general detail information.
1005 char* Isolate::GetStatusDetails() {
1006 const char* format = "{\n"
1007 " \"handle\": \"0x%" Px64 "\",\n"
1008 " \"name\": \"%s\",\n"
1009 " \"port\": %" Pd ",\n"
1010 " \"starttime\": %" Pd ",\n"
1011 " \"stacklimit\": %" Pd ",\n"
1012 " \"newspace\": {\n"
1013 " \"used\": %" Pd ",\n"
1014 " \"capacity\": %" Pd "\n"
1015 " },\n"
1016 " \"oldspace\": {\n"
1017 " \"used\": %" Pd ",\n"
1018 " \"capacity\": %" Pd "\n"
1019 " }\n"
1020 "}";
1021 char buffer[300];
1022 int64_t address = reinterpret_cast<int64_t>(this);
1023 int n = OS::SNPrint(buffer, 300, format, address, name(), main_port(),
1024 (start_time() / 1000L), saved_stack_limit(),
1025 heap()->Used(Heap::kNew) / KB,
1026 heap()->Capacity(Heap::kNew) / KB,
1027 heap()->Used(Heap::kOld) / KB,
1028 heap()->Capacity(Heap::kOld) / KB);
1029 ASSERT(n < 300);
1030 return strdup(buffer);
1031 }
1032
1033
1034 char* Isolate::GetStatus(const char* request) {
1035 char* p = const_cast<char*>(request);
1036 const char* service_type = "/isolate/";
1037 ASSERT(!strncmp(p, service_type, strlen(service_type)));
1038 p += strlen(service_type);
1039
1040 // Extract isolate handle.
1041 int64_t addr;
1042 OS::StringToInt64(p, &addr);
1043 // TODO(tball): add validity check when issue 9600 is fixed.
1044 Isolate* isolate = reinterpret_cast<Isolate*>(addr);
1045 p += strcspn(p, "/");
1046
1047 // Query "/isolate/<handle>".
1048 if (strlen(p) == 0) {
1049 return isolate->GetStatusDetails();
1050 }
1051
1052 // Query "/isolate/<handle>/stacktrace"
1053 if (!strcmp(p, "/stacktrace")) {
1054 return isolate->GetStatusStacktrace();
1055 }
1056
1057 // Query "/isolate/<handle>/stacktrace/<frame-index>"
1058 const char* stacktrace_query = "/stacktrace/";
1059 int64_t frame_index = -1;
1060 if (!strncmp(p, stacktrace_query, strlen(stacktrace_query))) {
1061 p += strlen(stacktrace_query);
1062 OS::StringToInt64(p, &frame_index);
1063 if (frame_index >= 0) {
1064 return isolate->GetStatusStackFrame(frame_index);
1065 }
1066 }
1067
1068 // TODO(tball): "/isolate/<handle>/stacktrace/<frame-index>"/disassemble"
1069
1070 return NULL; // Unimplemented query.
1071 }
1072
1073
1074 template<class T>
1075 T* Isolate::AllocateReusableHandle() {
1076 T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle());
1077 T::initializeHandle(handle, T::null());
1078 return handle;
1079 }
1080
1081
1082 static void FillDeferredSlots(DeferredSlot** slot_list) {
1083 DeferredSlot* slot = *slot_list;
1084 *slot_list = NULL;
1085
1086 while (slot != NULL) {
1087 DeferredSlot* current = slot;
1088 slot = slot->next();
1089
1090 current->Materialize();
1091
1092 delete current;
1093 }
1094 }
1095
1096
1097 void Isolate::MaterializeDeferredBoxes() {
1098 FillDeferredSlots(&deferred_boxes_);
1099 }
1100
1101
1102 void Isolate::MaterializeDeferredObjects() {
1103 FillDeferredSlots(&deferred_object_refs_);
1104 }
1105
1106
1107 static char* GetRootScriptUri(Isolate* isolate) {
1108 const Library& library =
1109 Library::Handle(isolate->object_store()->root_library());
1110 ASSERT(!library.IsNull());
1111 const String& script_name = String::Handle(library.url());
1112 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString());
1113 }
1114
1115
1116 IsolateSpawnState::IsolateSpawnState(const Function& func,
1117 const Function& callback_func)
1118 : isolate_(NULL),
1119 script_url_(NULL),
1120 library_url_(NULL),
1121 function_name_(NULL),
1122 exception_callback_name_(NULL) {
1123 script_url_ = strdup(GetRootScriptUri(Isolate::Current()));
1124 const Class& cls = Class::Handle(func.Owner());
1125 ASSERT(cls.IsTopLevel());
1126 const Library& lib = Library::Handle(cls.library());
1127 const String& lib_url = String::Handle(lib.url());
1128 library_url_ = strdup(lib_url.ToCString());
1129
1130 const String& func_name = String::Handle(func.name());
1131 function_name_ = strdup(func_name.ToCString());
1132 if (!callback_func.IsNull()) {
1133 const String& callback_name = String::Handle(callback_func.name());
1134 exception_callback_name_ = strdup(callback_name.ToCString());
1135 } else {
1136 exception_callback_name_ = strdup("_unhandledExceptionCallback");
1137 }
1138 }
1139
1140
1141 IsolateSpawnState::IsolateSpawnState(const char* script_url)
1142 : isolate_(NULL),
1143 library_url_(NULL),
1144 function_name_(NULL),
1145 exception_callback_name_(NULL) {
1146 script_url_ = strdup(script_url);
1147 library_url_ = NULL;
1148 function_name_ = strdup("main");
1149 exception_callback_name_ = strdup("_unhandledExceptionCallback");
1150 }
1151
1152
1153 IsolateSpawnState::~IsolateSpawnState() {
1154 free(script_url_);
1155 free(library_url_);
1156 free(function_name_);
1157 free(exception_callback_name_);
1158 }
1159
1160
1161 RawObject* IsolateSpawnState::ResolveFunction() {
1162 // Resolve the library.
1163 Library& lib = Library::Handle();
1164 if (library_url()) {
1165 const String& lib_url = String::Handle(String::New(library_url()));
1166 lib = Library::LookupLibrary(lib_url);
1167 if (lib.IsNull() || lib.IsError()) {
1168 const String& msg = String::Handle(String::NewFormatted(
1169 "Unable to find library '%s'.", library_url()));
1170 return LanguageError::New(msg);
1171 }
1172 } else {
1173 lib = isolate()->object_store()->root_library();
1174 }
1175 ASSERT(!lib.IsNull());
1176
1177 // Resolve the function.
1178 const String& func_name =
1179 String::Handle(String::New(function_name()));
1180 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name));
1181 if (func.IsNull()) {
1182 const String& msg = String::Handle(String::NewFormatted(
1183 "Unable to resolve function '%s' in library '%s'.",
1184 function_name(), (library_url() ? library_url() : script_url())));
1185 return LanguageError::New(msg);
1186 }
1187 return func.raw();
1188 }
1189
1190
1191 void IsolateSpawnState::Cleanup() {
1192 SwitchIsolateScope switch_scope(isolate());
1193 Dart::ShutdownIsolate();
1194 }
1195
1196 } // namespace dart 127 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/deferred_objects.h ('k') | runtime/vm/deopt_instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698