| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stdlib.h> | 5 #include <stdlib.h> |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #include "src/ast.h" | 9 #include "src/ast.h" |
| 10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 EnsureInitialized(); | 115 EnsureInitialized(); |
| 116 ThreadId thread_id = ThreadId::Current(); | 116 ThreadId thread_id = ThreadId::Current(); |
| 117 PerIsolateThreadData* per_thread = NULL; | 117 PerIsolateThreadData* per_thread = NULL; |
| 118 { | 118 { |
| 119 base::LockGuard<base::Mutex> lock_guard(process_wide_mutex_.Pointer()); | 119 base::LockGuard<base::Mutex> lock_guard(process_wide_mutex_.Pointer()); |
| 120 per_thread = thread_data_table_->Lookup(this, thread_id); | 120 per_thread = thread_data_table_->Lookup(this, thread_id); |
| 121 if (per_thread == NULL) { | 121 if (per_thread == NULL) { |
| 122 per_thread = new PerIsolateThreadData(this, thread_id); | 122 per_thread = new PerIsolateThreadData(this, thread_id); |
| 123 thread_data_table_->Insert(per_thread); | 123 thread_data_table_->Insert(per_thread); |
| 124 } | 124 } |
| 125 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread); | 125 DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread); |
| 126 } | 126 } |
| 127 return per_thread; | 127 return per_thread; |
| 128 } | 128 } |
| 129 | 129 |
| 130 | 130 |
| 131 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { | 131 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { |
| 132 ThreadId thread_id = ThreadId::Current(); | 132 ThreadId thread_id = ThreadId::Current(); |
| 133 return FindPerThreadDataForThread(thread_id); | 133 return FindPerThreadDataForThread(thread_id); |
| 134 } | 134 } |
| 135 | 135 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 } | 242 } |
| 243 #endif // DEBUG | 243 #endif // DEBUG |
| 244 | 244 |
| 245 | 245 |
| 246 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) { | 246 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) { |
| 247 thread_local_top()->set_try_catch_handler(that); | 247 thread_local_top()->set_try_catch_handler(that); |
| 248 } | 248 } |
| 249 | 249 |
| 250 | 250 |
| 251 void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) { | 251 void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) { |
| 252 ASSERT(thread_local_top()->try_catch_handler() == that); | 252 DCHECK(thread_local_top()->try_catch_handler() == that); |
| 253 thread_local_top()->set_try_catch_handler(that->next_); | 253 thread_local_top()->set_try_catch_handler(that->next_); |
| 254 thread_local_top()->catcher_ = NULL; | 254 thread_local_top()->catcher_ = NULL; |
| 255 } | 255 } |
| 256 | 256 |
| 257 | 257 |
| 258 Handle<String> Isolate::StackTraceString() { | 258 Handle<String> Isolate::StackTraceString() { |
| 259 if (stack_trace_nesting_level_ == 0) { | 259 if (stack_trace_nesting_level_ == 0) { |
| 260 stack_trace_nesting_level_++; | 260 stack_trace_nesting_level_++; |
| 261 HeapStringAllocator allocator; | 261 HeapStringAllocator allocator; |
| 262 StringStream::ClearMentionedObjectCache(this); | 262 StringStream::ClearMentionedObjectCache(this); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 | 336 |
| 337 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, | 337 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, |
| 338 Handle<Object> caller) { | 338 Handle<Object> caller) { |
| 339 // Get stack trace limit. | 339 // Get stack trace limit. |
| 340 Handle<Object> error = Object::GetProperty( | 340 Handle<Object> error = Object::GetProperty( |
| 341 this, js_builtins_object(), "$Error").ToHandleChecked(); | 341 this, js_builtins_object(), "$Error").ToHandleChecked(); |
| 342 if (!error->IsJSObject()) return factory()->undefined_value(); | 342 if (!error->IsJSObject()) return factory()->undefined_value(); |
| 343 | 343 |
| 344 Handle<String> stackTraceLimit = | 344 Handle<String> stackTraceLimit = |
| 345 factory()->InternalizeUtf8String("stackTraceLimit"); | 345 factory()->InternalizeUtf8String("stackTraceLimit"); |
| 346 ASSERT(!stackTraceLimit.is_null()); | 346 DCHECK(!stackTraceLimit.is_null()); |
| 347 Handle<Object> stack_trace_limit = | 347 Handle<Object> stack_trace_limit = |
| 348 JSObject::GetDataProperty(Handle<JSObject>::cast(error), | 348 JSObject::GetDataProperty(Handle<JSObject>::cast(error), |
| 349 stackTraceLimit); | 349 stackTraceLimit); |
| 350 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); | 350 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); |
| 351 int limit = FastD2IChecked(stack_trace_limit->Number()); | 351 int limit = FastD2IChecked(stack_trace_limit->Number()); |
| 352 limit = Max(limit, 0); // Ensure that limit is not negative. | 352 limit = Max(limit, 0); // Ensure that limit is not negative. |
| 353 | 353 |
| 354 int initial_size = Min(limit, 10); | 354 int initial_size = Min(limit, 10); |
| 355 Handle<FixedArray> elements = | 355 Handle<FixedArray> elements = |
| 356 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); | 356 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 380 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue; | 380 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue; |
| 381 if (cursor + 4 > elements->length()) { | 381 if (cursor + 4 > elements->length()) { |
| 382 int new_capacity = JSObject::NewElementsCapacity(elements->length()); | 382 int new_capacity = JSObject::NewElementsCapacity(elements->length()); |
| 383 Handle<FixedArray> new_elements = | 383 Handle<FixedArray> new_elements = |
| 384 factory()->NewFixedArrayWithHoles(new_capacity); | 384 factory()->NewFixedArrayWithHoles(new_capacity); |
| 385 for (int i = 0; i < cursor; i++) { | 385 for (int i = 0; i < cursor; i++) { |
| 386 new_elements->set(i, elements->get(i)); | 386 new_elements->set(i, elements->get(i)); |
| 387 } | 387 } |
| 388 elements = new_elements; | 388 elements = new_elements; |
| 389 } | 389 } |
| 390 ASSERT(cursor + 4 <= elements->length()); | 390 DCHECK(cursor + 4 <= elements->length()); |
| 391 | 391 |
| 392 | 392 |
| 393 Handle<Code> code = frames[i].code(); | 393 Handle<Code> code = frames[i].code(); |
| 394 Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this); | 394 Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this); |
| 395 // The stack trace API should not expose receivers and function | 395 // The stack trace API should not expose receivers and function |
| 396 // objects on frames deeper than the top-most one with a strict | 396 // objects on frames deeper than the top-most one with a strict |
| 397 // mode function. The number of sloppy frames is stored as | 397 // mode function. The number of sloppy frames is stored as |
| 398 // first element in the result array. | 398 // first element in the result array. |
| 399 if (!encountered_strict_function) { | 399 if (!encountered_strict_function) { |
| 400 if (fun->shared()->strict_mode() == STRICT) { | 400 if (fun->shared()->strict_mode() == STRICT) { |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 void Isolate::PrintStack(StringStream* accumulator) { | 592 void Isolate::PrintStack(StringStream* accumulator) { |
| 593 if (!IsInitialized()) { | 593 if (!IsInitialized()) { |
| 594 accumulator->Add( | 594 accumulator->Add( |
| 595 "\n==== JS stack trace is not available =======================\n\n"); | 595 "\n==== JS stack trace is not available =======================\n\n"); |
| 596 accumulator->Add( | 596 accumulator->Add( |
| 597 "\n==== Isolate for the thread is not initialized =============\n\n"); | 597 "\n==== Isolate for the thread is not initialized =============\n\n"); |
| 598 return; | 598 return; |
| 599 } | 599 } |
| 600 // The MentionedObjectCache is not GC-proof at the moment. | 600 // The MentionedObjectCache is not GC-proof at the moment. |
| 601 DisallowHeapAllocation no_gc; | 601 DisallowHeapAllocation no_gc; |
| 602 ASSERT(StringStream::IsMentionedObjectCacheClear(this)); | 602 DCHECK(StringStream::IsMentionedObjectCacheClear(this)); |
| 603 | 603 |
| 604 // Avoid printing anything if there are no frames. | 604 // Avoid printing anything if there are no frames. |
| 605 if (c_entry_fp(thread_local_top()) == 0) return; | 605 if (c_entry_fp(thread_local_top()) == 0) return; |
| 606 | 606 |
| 607 accumulator->Add( | 607 accumulator->Add( |
| 608 "\n==== JS stack trace =========================================\n\n"); | 608 "\n==== JS stack trace =========================================\n\n"); |
| 609 PrintFrames(this, accumulator, StackFrame::OVERVIEW); | 609 PrintFrames(this, accumulator, StackFrame::OVERVIEW); |
| 610 | 610 |
| 611 accumulator->Add( | 611 accumulator->Add( |
| 612 "\n==== Details ================================================\n\n"); | 612 "\n==== Details ================================================\n\n"); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 637 | 637 |
| 638 | 638 |
| 639 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver, | 639 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver, |
| 640 v8::AccessType type) { | 640 v8::AccessType type) { |
| 641 if (!thread_local_top()->failed_access_check_callback_) { | 641 if (!thread_local_top()->failed_access_check_callback_) { |
| 642 Handle<String> message = factory()->InternalizeUtf8String("no access"); | 642 Handle<String> message = factory()->InternalizeUtf8String("no access"); |
| 643 ScheduleThrow(*factory()->NewTypeError(message)); | 643 ScheduleThrow(*factory()->NewTypeError(message)); |
| 644 return; | 644 return; |
| 645 } | 645 } |
| 646 | 646 |
| 647 ASSERT(receiver->IsAccessCheckNeeded()); | 647 DCHECK(receiver->IsAccessCheckNeeded()); |
| 648 ASSERT(context()); | 648 DCHECK(context()); |
| 649 | 649 |
| 650 // Get the data object from access check info. | 650 // Get the data object from access check info. |
| 651 HandleScope scope(this); | 651 HandleScope scope(this); |
| 652 Handle<Object> data; | 652 Handle<Object> data; |
| 653 { DisallowHeapAllocation no_gc; | 653 { DisallowHeapAllocation no_gc; |
| 654 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); | 654 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 655 if (!access_check_info) return; | 655 if (!access_check_info) return; |
| 656 data = handle(access_check_info->data(), this); | 656 data = handle(access_check_info->data(), this); |
| 657 } | 657 } |
| 658 | 658 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 return YES; | 692 return YES; |
| 693 } | 693 } |
| 694 | 694 |
| 695 return UNKNOWN; | 695 return UNKNOWN; |
| 696 } | 696 } |
| 697 | 697 |
| 698 | 698 |
| 699 bool Isolate::MayNamedAccess(Handle<JSObject> receiver, | 699 bool Isolate::MayNamedAccess(Handle<JSObject> receiver, |
| 700 Handle<Object> key, | 700 Handle<Object> key, |
| 701 v8::AccessType type) { | 701 v8::AccessType type) { |
| 702 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); | 702 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); |
| 703 | 703 |
| 704 // Skip checks for hidden properties access. Note, we do not | 704 // Skip checks for hidden properties access. Note, we do not |
| 705 // require existence of a context in this case. | 705 // require existence of a context in this case. |
| 706 if (key.is_identical_to(factory()->hidden_string())) return true; | 706 if (key.is_identical_to(factory()->hidden_string())) return true; |
| 707 | 707 |
| 708 // Check for compatibility between the security tokens in the | 708 // Check for compatibility between the security tokens in the |
| 709 // current lexical context and the accessed object. | 709 // current lexical context and the accessed object. |
| 710 ASSERT(context()); | 710 DCHECK(context()); |
| 711 | 711 |
| 712 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); | 712 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); |
| 713 if (decision != UNKNOWN) return decision == YES; | 713 if (decision != UNKNOWN) return decision == YES; |
| 714 | 714 |
| 715 HandleScope scope(this); | 715 HandleScope scope(this); |
| 716 Handle<Object> data; | 716 Handle<Object> data; |
| 717 v8::NamedSecurityCallback callback; | 717 v8::NamedSecurityCallback callback; |
| 718 { DisallowHeapAllocation no_gc; | 718 { DisallowHeapAllocation no_gc; |
| 719 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); | 719 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| 720 if (!access_check_info) return false; | 720 if (!access_check_info) return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 731 return callback(v8::Utils::ToLocal(receiver), | 731 return callback(v8::Utils::ToLocal(receiver), |
| 732 v8::Utils::ToLocal(key), | 732 v8::Utils::ToLocal(key), |
| 733 type, | 733 type, |
| 734 v8::Utils::ToLocal(data)); | 734 v8::Utils::ToLocal(data)); |
| 735 } | 735 } |
| 736 | 736 |
| 737 | 737 |
| 738 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver, | 738 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver, |
| 739 uint32_t index, | 739 uint32_t index, |
| 740 v8::AccessType type) { | 740 v8::AccessType type) { |
| 741 ASSERT(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); | 741 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); |
| 742 // Check for compatibility between the security tokens in the | 742 // Check for compatibility between the security tokens in the |
| 743 // current lexical context and the accessed object. | 743 // current lexical context and the accessed object. |
| 744 ASSERT(context()); | 744 DCHECK(context()); |
| 745 | 745 |
| 746 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); | 746 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); |
| 747 if (decision != UNKNOWN) return decision == YES; | 747 if (decision != UNKNOWN) return decision == YES; |
| 748 | 748 |
| 749 HandleScope scope(this); | 749 HandleScope scope(this); |
| 750 Handle<Object> data; | 750 Handle<Object> data; |
| 751 v8::IndexedSecurityCallback callback; | 751 v8::IndexedSecurityCallback callback; |
| 752 { DisallowHeapAllocation no_gc; | 752 { DisallowHeapAllocation no_gc; |
| 753 // Get named access check callback | 753 // Get named access check callback |
| 754 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); | 754 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 PropagatePendingExceptionToExternalTryCatch(); | 870 PropagatePendingExceptionToExternalTryCatch(); |
| 871 if (has_pending_exception()) { | 871 if (has_pending_exception()) { |
| 872 thread_local_top()->scheduled_exception_ = pending_exception(); | 872 thread_local_top()->scheduled_exception_ = pending_exception(); |
| 873 thread_local_top()->external_caught_exception_ = false; | 873 thread_local_top()->external_caught_exception_ = false; |
| 874 clear_pending_exception(); | 874 clear_pending_exception(); |
| 875 } | 875 } |
| 876 } | 876 } |
| 877 | 877 |
| 878 | 878 |
| 879 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) { | 879 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) { |
| 880 ASSERT(handler == try_catch_handler()); | 880 DCHECK(handler == try_catch_handler()); |
| 881 ASSERT(handler->HasCaught()); | 881 DCHECK(handler->HasCaught()); |
| 882 ASSERT(handler->rethrow_); | 882 DCHECK(handler->rethrow_); |
| 883 ASSERT(handler->capture_message_); | 883 DCHECK(handler->capture_message_); |
| 884 Object* message = reinterpret_cast<Object*>(handler->message_obj_); | 884 Object* message = reinterpret_cast<Object*>(handler->message_obj_); |
| 885 Object* script = reinterpret_cast<Object*>(handler->message_script_); | 885 Object* script = reinterpret_cast<Object*>(handler->message_script_); |
| 886 ASSERT(message->IsJSMessageObject() || message->IsTheHole()); | 886 DCHECK(message->IsJSMessageObject() || message->IsTheHole()); |
| 887 ASSERT(script->IsScript() || script->IsTheHole()); | 887 DCHECK(script->IsScript() || script->IsTheHole()); |
| 888 thread_local_top()->pending_message_obj_ = message; | 888 thread_local_top()->pending_message_obj_ = message; |
| 889 thread_local_top()->pending_message_script_ = script; | 889 thread_local_top()->pending_message_script_ = script; |
| 890 thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_; | 890 thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_; |
| 891 thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_; | 891 thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_; |
| 892 } | 892 } |
| 893 | 893 |
| 894 | 894 |
| 895 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) { | 895 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) { |
| 896 ASSERT(has_scheduled_exception()); | 896 DCHECK(has_scheduled_exception()); |
| 897 if (scheduled_exception() == handler->exception_) { | 897 if (scheduled_exception() == handler->exception_) { |
| 898 ASSERT(scheduled_exception() != heap()->termination_exception()); | 898 DCHECK(scheduled_exception() != heap()->termination_exception()); |
| 899 clear_scheduled_exception(); | 899 clear_scheduled_exception(); |
| 900 } | 900 } |
| 901 } | 901 } |
| 902 | 902 |
| 903 | 903 |
| 904 Object* Isolate::PromoteScheduledException() { | 904 Object* Isolate::PromoteScheduledException() { |
| 905 Object* thrown = scheduled_exception(); | 905 Object* thrown = scheduled_exception(); |
| 906 clear_scheduled_exception(); | 906 clear_scheduled_exception(); |
| 907 // Re-throw the exception to avoid getting repeated error reporting. | 907 // Re-throw the exception to avoid getting repeated error reporting. |
| 908 return ReThrow(thrown); | 908 return ReThrow(thrown); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1002 *error_constructor) { | 1002 *error_constructor) { |
| 1003 return true; | 1003 return true; |
| 1004 } | 1004 } |
| 1005 } | 1005 } |
| 1006 return false; | 1006 return false; |
| 1007 } | 1007 } |
| 1008 | 1008 |
| 1009 static int fatal_exception_depth = 0; | 1009 static int fatal_exception_depth = 0; |
| 1010 | 1010 |
| 1011 void Isolate::DoThrow(Object* exception, MessageLocation* location) { | 1011 void Isolate::DoThrow(Object* exception, MessageLocation* location) { |
| 1012 ASSERT(!has_pending_exception()); | 1012 DCHECK(!has_pending_exception()); |
| 1013 | 1013 |
| 1014 HandleScope scope(this); | 1014 HandleScope scope(this); |
| 1015 Handle<Object> exception_handle(exception, this); | 1015 Handle<Object> exception_handle(exception, this); |
| 1016 | 1016 |
| 1017 // Determine reporting and whether the exception is caught externally. | 1017 // Determine reporting and whether the exception is caught externally. |
| 1018 bool catchable_by_javascript = is_catchable_by_javascript(exception); | 1018 bool catchable_by_javascript = is_catchable_by_javascript(exception); |
| 1019 bool can_be_caught_externally = false; | 1019 bool can_be_caught_externally = false; |
| 1020 bool should_report_exception = | 1020 bool should_report_exception = |
| 1021 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); | 1021 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); |
| 1022 bool report_exception = catchable_by_javascript && should_report_exception; | 1022 bool report_exception = catchable_by_javascript && should_report_exception; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1156 // Do not forget to clean catcher_ if currently thrown exception cannot | 1156 // Do not forget to clean catcher_ if currently thrown exception cannot |
| 1157 // be caught. If necessary, ReThrow will update the catcher. | 1157 // be caught. If necessary, ReThrow will update the catcher. |
| 1158 thread_local_top()->catcher_ = can_be_caught_externally ? | 1158 thread_local_top()->catcher_ = can_be_caught_externally ? |
| 1159 try_catch_handler() : NULL; | 1159 try_catch_handler() : NULL; |
| 1160 | 1160 |
| 1161 set_pending_exception(*exception_handle); | 1161 set_pending_exception(*exception_handle); |
| 1162 } | 1162 } |
| 1163 | 1163 |
| 1164 | 1164 |
| 1165 bool Isolate::HasExternalTryCatch() { | 1165 bool Isolate::HasExternalTryCatch() { |
| 1166 ASSERT(has_pending_exception()); | 1166 DCHECK(has_pending_exception()); |
| 1167 | 1167 |
| 1168 return (thread_local_top()->catcher_ != NULL) && | 1168 return (thread_local_top()->catcher_ != NULL) && |
| 1169 (try_catch_handler() == thread_local_top()->catcher_); | 1169 (try_catch_handler() == thread_local_top()->catcher_); |
| 1170 } | 1170 } |
| 1171 | 1171 |
| 1172 | 1172 |
| 1173 bool Isolate::IsFinallyOnTop() { | 1173 bool Isolate::IsFinallyOnTop() { |
| 1174 // Get the address of the external handler so we can compare the address to | 1174 // Get the address of the external handler so we can compare the address to |
| 1175 // determine which one is closer to the top of the stack. | 1175 // determine which one is closer to the top of the stack. |
| 1176 Address external_handler_address = | 1176 Address external_handler_address = |
| 1177 thread_local_top()->try_catch_handler_address(); | 1177 thread_local_top()->try_catch_handler_address(); |
| 1178 ASSERT(external_handler_address != NULL); | 1178 DCHECK(external_handler_address != NULL); |
| 1179 | 1179 |
| 1180 // The exception has been externally caught if and only if there is | 1180 // The exception has been externally caught if and only if there is |
| 1181 // an external handler which is on top of the top-most try-finally | 1181 // an external handler which is on top of the top-most try-finally |
| 1182 // handler. | 1182 // handler. |
| 1183 // There should be no try-catch blocks as they would prohibit us from | 1183 // There should be no try-catch blocks as they would prohibit us from |
| 1184 // finding external catcher in the first place (see catcher_ check above). | 1184 // finding external catcher in the first place (see catcher_ check above). |
| 1185 // | 1185 // |
| 1186 // Note, that finally clause would rethrow an exception unless it's | 1186 // Note, that finally clause would rethrow an exception unless it's |
| 1187 // aborted by jumps in control flow like return, break, etc. and we'll | 1187 // aborted by jumps in control flow like return, break, etc. and we'll |
| 1188 // have another chances to set proper v8::TryCatch. | 1188 // have another chances to set proper v8::TryCatch. |
| 1189 StackHandler* handler = | 1189 StackHandler* handler = |
| 1190 StackHandler::FromAddress(Isolate::handler(thread_local_top())); | 1190 StackHandler::FromAddress(Isolate::handler(thread_local_top())); |
| 1191 while (handler != NULL && handler->address() < external_handler_address) { | 1191 while (handler != NULL && handler->address() < external_handler_address) { |
| 1192 ASSERT(!handler->is_catch()); | 1192 DCHECK(!handler->is_catch()); |
| 1193 if (handler->is_finally()) return true; | 1193 if (handler->is_finally()) return true; |
| 1194 | 1194 |
| 1195 handler = handler->next(); | 1195 handler = handler->next(); |
| 1196 } | 1196 } |
| 1197 | 1197 |
| 1198 return false; | 1198 return false; |
| 1199 } | 1199 } |
| 1200 | 1200 |
| 1201 | 1201 |
| 1202 void Isolate::ReportPendingMessages() { | 1202 void Isolate::ReportPendingMessages() { |
| 1203 ASSERT(has_pending_exception()); | 1203 DCHECK(has_pending_exception()); |
| 1204 bool can_clear_message = PropagatePendingExceptionToExternalTryCatch(); | 1204 bool can_clear_message = PropagatePendingExceptionToExternalTryCatch(); |
| 1205 | 1205 |
| 1206 HandleScope scope(this); | 1206 HandleScope scope(this); |
| 1207 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) { | 1207 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) { |
| 1208 // Do nothing: if needed, the exception has been already propagated to | 1208 // Do nothing: if needed, the exception has been already propagated to |
| 1209 // v8::TryCatch. | 1209 // v8::TryCatch. |
| 1210 } else { | 1210 } else { |
| 1211 if (thread_local_top_.has_pending_message_) { | 1211 if (thread_local_top_.has_pending_message_) { |
| 1212 thread_local_top_.has_pending_message_ = false; | 1212 thread_local_top_.has_pending_message_ = false; |
| 1213 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { | 1213 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1225 MessageHandler::ReportMessage(this, NULL, message_obj); | 1225 MessageHandler::ReportMessage(this, NULL, message_obj); |
| 1226 } | 1226 } |
| 1227 } | 1227 } |
| 1228 } | 1228 } |
| 1229 } | 1229 } |
| 1230 if (can_clear_message) clear_pending_message(); | 1230 if (can_clear_message) clear_pending_message(); |
| 1231 } | 1231 } |
| 1232 | 1232 |
| 1233 | 1233 |
| 1234 MessageLocation Isolate::GetMessageLocation() { | 1234 MessageLocation Isolate::GetMessageLocation() { |
| 1235 ASSERT(has_pending_exception()); | 1235 DCHECK(has_pending_exception()); |
| 1236 | 1236 |
| 1237 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && | 1237 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && |
| 1238 thread_local_top_.has_pending_message_ && | 1238 thread_local_top_.has_pending_message_ && |
| 1239 !thread_local_top_.pending_message_obj_->IsTheHole() && | 1239 !thread_local_top_.pending_message_obj_->IsTheHole() && |
| 1240 !thread_local_top_.pending_message_obj_->IsTheHole()) { | 1240 !thread_local_top_.pending_message_obj_->IsTheHole()) { |
| 1241 Handle<Script> script( | 1241 Handle<Script> script( |
| 1242 Script::cast(thread_local_top_.pending_message_script_)); | 1242 Script::cast(thread_local_top_.pending_message_script_)); |
| 1243 int start_pos = thread_local_top_.pending_message_start_pos_; | 1243 int start_pos = thread_local_top_.pending_message_start_pos_; |
| 1244 int end_pos = thread_local_top_.pending_message_end_pos_; | 1244 int end_pos = thread_local_top_.pending_message_end_pos_; |
| 1245 return MessageLocation(script, start_pos, end_pos); | 1245 return MessageLocation(script, start_pos, end_pos); |
| 1246 } | 1246 } |
| 1247 | 1247 |
| 1248 return MessageLocation(); | 1248 return MessageLocation(); |
| 1249 } | 1249 } |
| 1250 | 1250 |
| 1251 | 1251 |
| 1252 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { | 1252 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { |
| 1253 ASSERT(has_pending_exception()); | 1253 DCHECK(has_pending_exception()); |
| 1254 PropagatePendingExceptionToExternalTryCatch(); | 1254 PropagatePendingExceptionToExternalTryCatch(); |
| 1255 | 1255 |
| 1256 bool is_termination_exception = | 1256 bool is_termination_exception = |
| 1257 pending_exception() == heap_.termination_exception(); | 1257 pending_exception() == heap_.termination_exception(); |
| 1258 | 1258 |
| 1259 // Do not reschedule the exception if this is the bottom call. | 1259 // Do not reschedule the exception if this is the bottom call. |
| 1260 bool clear_exception = is_bottom_call; | 1260 bool clear_exception = is_bottom_call; |
| 1261 | 1261 |
| 1262 if (is_termination_exception) { | 1262 if (is_termination_exception) { |
| 1263 if (is_bottom_call) { | 1263 if (is_bottom_call) { |
| 1264 thread_local_top()->external_caught_exception_ = false; | 1264 thread_local_top()->external_caught_exception_ = false; |
| 1265 clear_pending_exception(); | 1265 clear_pending_exception(); |
| 1266 return false; | 1266 return false; |
| 1267 } | 1267 } |
| 1268 } else if (thread_local_top()->external_caught_exception_) { | 1268 } else if (thread_local_top()->external_caught_exception_) { |
| 1269 // If the exception is externally caught, clear it if there are no | 1269 // If the exception is externally caught, clear it if there are no |
| 1270 // JavaScript frames on the way to the C++ frame that has the | 1270 // JavaScript frames on the way to the C++ frame that has the |
| 1271 // external handler. | 1271 // external handler. |
| 1272 ASSERT(thread_local_top()->try_catch_handler_address() != NULL); | 1272 DCHECK(thread_local_top()->try_catch_handler_address() != NULL); |
| 1273 Address external_handler_address = | 1273 Address external_handler_address = |
| 1274 thread_local_top()->try_catch_handler_address(); | 1274 thread_local_top()->try_catch_handler_address(); |
| 1275 JavaScriptFrameIterator it(this); | 1275 JavaScriptFrameIterator it(this); |
| 1276 if (it.done() || (it.frame()->sp() > external_handler_address)) { | 1276 if (it.done() || (it.frame()->sp() > external_handler_address)) { |
| 1277 clear_exception = true; | 1277 clear_exception = true; |
| 1278 } | 1278 } |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 // Clear the exception if needed. | 1281 // Clear the exception if needed. |
| 1282 if (clear_exception) { | 1282 if (clear_exception) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 | 1344 |
| 1345 | 1345 |
| 1346 char* Isolate::RestoreThread(char* from) { | 1346 char* Isolate::RestoreThread(char* from) { |
| 1347 MemCopy(reinterpret_cast<char*>(thread_local_top()), from, | 1347 MemCopy(reinterpret_cast<char*>(thread_local_top()), from, |
| 1348 sizeof(ThreadLocalTop)); | 1348 sizeof(ThreadLocalTop)); |
| 1349 // This might be just paranoia, but it seems to be needed in case a | 1349 // This might be just paranoia, but it seems to be needed in case a |
| 1350 // thread_local_top_ is restored on a separate OS thread. | 1350 // thread_local_top_ is restored on a separate OS thread. |
| 1351 #ifdef USE_SIMULATOR | 1351 #ifdef USE_SIMULATOR |
| 1352 thread_local_top()->simulator_ = Simulator::current(this); | 1352 thread_local_top()->simulator_ = Simulator::current(this); |
| 1353 #endif | 1353 #endif |
| 1354 ASSERT(context() == NULL || context()->IsContext()); | 1354 DCHECK(context() == NULL || context()->IsContext()); |
| 1355 return from + sizeof(ThreadLocalTop); | 1355 return from + sizeof(ThreadLocalTop); |
| 1356 } | 1356 } |
| 1357 | 1357 |
| 1358 | 1358 |
| 1359 Isolate::ThreadDataTable::ThreadDataTable() | 1359 Isolate::ThreadDataTable::ThreadDataTable() |
| 1360 : list_(NULL) { | 1360 : list_(NULL) { |
| 1361 } | 1361 } |
| 1362 | 1362 |
| 1363 | 1363 |
| 1364 Isolate::ThreadDataTable::~ThreadDataTable() { | 1364 Isolate::ThreadDataTable::~ThreadDataTable() { |
| 1365 // TODO(svenpanne) The assertion below would fire if an embedder does not | 1365 // TODO(svenpanne) The assertion below would fire if an embedder does not |
| 1366 // cleanly dispose all Isolates before disposing v8, so we are conservative | 1366 // cleanly dispose all Isolates before disposing v8, so we are conservative |
| 1367 // and leave it out for now. | 1367 // and leave it out for now. |
| 1368 // ASSERT_EQ(NULL, list_); | 1368 // DCHECK_EQ(NULL, list_); |
| 1369 } | 1369 } |
| 1370 | 1370 |
| 1371 | 1371 |
| 1372 Isolate::PerIsolateThreadData::~PerIsolateThreadData() { | 1372 Isolate::PerIsolateThreadData::~PerIsolateThreadData() { |
| 1373 #if defined(USE_SIMULATOR) | 1373 #if defined(USE_SIMULATOR) |
| 1374 delete simulator_; | 1374 delete simulator_; |
| 1375 #endif | 1375 #endif |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 | 1378 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1636 } | 1636 } |
| 1637 | 1637 |
| 1638 | 1638 |
| 1639 Isolate::~Isolate() { | 1639 Isolate::~Isolate() { |
| 1640 TRACE_ISOLATE(destructor); | 1640 TRACE_ISOLATE(destructor); |
| 1641 | 1641 |
| 1642 // Has to be called while counters_ are still alive | 1642 // Has to be called while counters_ are still alive |
| 1643 runtime_zone_.DeleteKeptSegment(); | 1643 runtime_zone_.DeleteKeptSegment(); |
| 1644 | 1644 |
| 1645 // The entry stack must be empty when we get here. | 1645 // The entry stack must be empty when we get here. |
| 1646 ASSERT(entry_stack_ == NULL || entry_stack_->previous_item == NULL); | 1646 DCHECK(entry_stack_ == NULL || entry_stack_->previous_item == NULL); |
| 1647 | 1647 |
| 1648 delete entry_stack_; | 1648 delete entry_stack_; |
| 1649 entry_stack_ = NULL; | 1649 entry_stack_ = NULL; |
| 1650 | 1650 |
| 1651 delete[] assembler_spare_buffer_; | 1651 delete[] assembler_spare_buffer_; |
| 1652 assembler_spare_buffer_ = NULL; | 1652 assembler_spare_buffer_ = NULL; |
| 1653 | 1653 |
| 1654 delete unicode_cache_; | 1654 delete unicode_cache_; |
| 1655 unicode_cache_ = NULL; | 1655 unicode_cache_ = NULL; |
| 1656 | 1656 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1730 } | 1730 } |
| 1731 | 1731 |
| 1732 | 1732 |
| 1733 void Isolate::InitializeThreadLocal() { | 1733 void Isolate::InitializeThreadLocal() { |
| 1734 thread_local_top_.isolate_ = this; | 1734 thread_local_top_.isolate_ = this; |
| 1735 thread_local_top_.Initialize(); | 1735 thread_local_top_.Initialize(); |
| 1736 } | 1736 } |
| 1737 | 1737 |
| 1738 | 1738 |
| 1739 bool Isolate::PropagatePendingExceptionToExternalTryCatch() { | 1739 bool Isolate::PropagatePendingExceptionToExternalTryCatch() { |
| 1740 ASSERT(has_pending_exception()); | 1740 DCHECK(has_pending_exception()); |
| 1741 | 1741 |
| 1742 bool has_external_try_catch = HasExternalTryCatch(); | 1742 bool has_external_try_catch = HasExternalTryCatch(); |
| 1743 if (!has_external_try_catch) { | 1743 if (!has_external_try_catch) { |
| 1744 thread_local_top_.external_caught_exception_ = false; | 1744 thread_local_top_.external_caught_exception_ = false; |
| 1745 return true; | 1745 return true; |
| 1746 } | 1746 } |
| 1747 | 1747 |
| 1748 bool catchable_by_js = is_catchable_by_javascript(pending_exception()); | 1748 bool catchable_by_js = is_catchable_by_javascript(pending_exception()); |
| 1749 if (catchable_by_js && IsFinallyOnTop()) { | 1749 if (catchable_by_js && IsFinallyOnTop()) { |
| 1750 thread_local_top_.external_caught_exception_ = false; | 1750 thread_local_top_.external_caught_exception_ = false; |
| 1751 return false; | 1751 return false; |
| 1752 } | 1752 } |
| 1753 | 1753 |
| 1754 thread_local_top_.external_caught_exception_ = true; | 1754 thread_local_top_.external_caught_exception_ = true; |
| 1755 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) { | 1755 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) { |
| 1756 try_catch_handler()->can_continue_ = false; | 1756 try_catch_handler()->can_continue_ = false; |
| 1757 try_catch_handler()->has_terminated_ = true; | 1757 try_catch_handler()->has_terminated_ = true; |
| 1758 try_catch_handler()->exception_ = heap()->null_value(); | 1758 try_catch_handler()->exception_ = heap()->null_value(); |
| 1759 } else { | 1759 } else { |
| 1760 v8::TryCatch* handler = try_catch_handler(); | 1760 v8::TryCatch* handler = try_catch_handler(); |
| 1761 ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() || | 1761 DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() || |
| 1762 thread_local_top_.pending_message_obj_->IsTheHole()); | 1762 thread_local_top_.pending_message_obj_->IsTheHole()); |
| 1763 ASSERT(thread_local_top_.pending_message_script_->IsScript() || | 1763 DCHECK(thread_local_top_.pending_message_script_->IsScript() || |
| 1764 thread_local_top_.pending_message_script_->IsTheHole()); | 1764 thread_local_top_.pending_message_script_->IsTheHole()); |
| 1765 handler->can_continue_ = true; | 1765 handler->can_continue_ = true; |
| 1766 handler->has_terminated_ = false; | 1766 handler->has_terminated_ = false; |
| 1767 handler->exception_ = pending_exception(); | 1767 handler->exception_ = pending_exception(); |
| 1768 // Propagate to the external try-catch only if we got an actual message. | 1768 // Propagate to the external try-catch only if we got an actual message. |
| 1769 if (thread_local_top_.pending_message_obj_->IsTheHole()) return true; | 1769 if (thread_local_top_.pending_message_obj_->IsTheHole()) return true; |
| 1770 | 1770 |
| 1771 handler->message_obj_ = thread_local_top_.pending_message_obj_; | 1771 handler->message_obj_ = thread_local_top_.pending_message_obj_; |
| 1772 handler->message_script_ = thread_local_top_.pending_message_script_; | 1772 handler->message_script_ = thread_local_top_.pending_message_script_; |
| 1773 handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_; | 1773 handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_; |
| 1774 handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_; | 1774 handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_; |
| 1775 } | 1775 } |
| 1776 return true; | 1776 return true; |
| 1777 } | 1777 } |
| 1778 | 1778 |
| 1779 | 1779 |
| 1780 void Isolate::InitializeLoggingAndCounters() { | 1780 void Isolate::InitializeLoggingAndCounters() { |
| 1781 if (logger_ == NULL) { | 1781 if (logger_ == NULL) { |
| 1782 logger_ = new Logger(this); | 1782 logger_ = new Logger(this); |
| 1783 } | 1783 } |
| 1784 if (counters_ == NULL) { | 1784 if (counters_ == NULL) { |
| 1785 counters_ = new Counters(this); | 1785 counters_ = new Counters(this); |
| 1786 } | 1786 } |
| 1787 } | 1787 } |
| 1788 | 1788 |
| 1789 | 1789 |
| 1790 bool Isolate::Init(Deserializer* des) { | 1790 bool Isolate::Init(Deserializer* des) { |
| 1791 ASSERT(state_ != INITIALIZED); | 1791 DCHECK(state_ != INITIALIZED); |
| 1792 TRACE_ISOLATE(init); | 1792 TRACE_ISOLATE(init); |
| 1793 | 1793 |
| 1794 stress_deopt_count_ = FLAG_deopt_every_n_times; | 1794 stress_deopt_count_ = FLAG_deopt_every_n_times; |
| 1795 | 1795 |
| 1796 has_fatal_error_ = false; | 1796 has_fatal_error_ = false; |
| 1797 | 1797 |
| 1798 if (function_entry_hook() != NULL) { | 1798 if (function_entry_hook() != NULL) { |
| 1799 // When function entry hooking is in effect, we have to create the code | 1799 // When function entry hooking is in effect, we have to create the code |
| 1800 // stubs from scratch to get entry hooks, rather than loading the previously | 1800 // stubs from scratch to get entry hooks, rather than loading the previously |
| 1801 // generated stubs from disk. | 1801 // generated stubs from disk. |
| 1802 // If this assert fires, the initialization path has regressed. | 1802 // If this assert fires, the initialization path has regressed. |
| 1803 ASSERT(des == NULL); | 1803 DCHECK(des == NULL); |
| 1804 } | 1804 } |
| 1805 | 1805 |
| 1806 // The initialization process does not handle memory exhaustion. | 1806 // The initialization process does not handle memory exhaustion. |
| 1807 DisallowAllocationFailure disallow_allocation_failure(this); | 1807 DisallowAllocationFailure disallow_allocation_failure(this); |
| 1808 | 1808 |
| 1809 memory_allocator_ = new MemoryAllocator(this); | 1809 memory_allocator_ = new MemoryAllocator(this); |
| 1810 code_range_ = new CodeRange(this); | 1810 code_range_ = new CodeRange(this); |
| 1811 | 1811 |
| 1812 // Safe after setting Heap::isolate_, and initializing StackGuard | 1812 // Safe after setting Heap::isolate_, and initializing StackGuard |
| 1813 heap_.SetStackLimits(); | 1813 heap_.SetStackLimits(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 | 1858 |
| 1859 { // NOLINT | 1859 { // NOLINT |
| 1860 // Ensure that the thread has a valid stack guard. The v8::Locker object | 1860 // Ensure that the thread has a valid stack guard. The v8::Locker object |
| 1861 // will ensure this too, but we don't have to use lockers if we are only | 1861 // will ensure this too, but we don't have to use lockers if we are only |
| 1862 // using one thread. | 1862 // using one thread. |
| 1863 ExecutionAccess lock(this); | 1863 ExecutionAccess lock(this); |
| 1864 stack_guard_.InitThread(lock); | 1864 stack_guard_.InitThread(lock); |
| 1865 } | 1865 } |
| 1866 | 1866 |
| 1867 // SetUp the object heap. | 1867 // SetUp the object heap. |
| 1868 ASSERT(!heap_.HasBeenSetUp()); | 1868 DCHECK(!heap_.HasBeenSetUp()); |
| 1869 if (!heap_.SetUp()) { | 1869 if (!heap_.SetUp()) { |
| 1870 V8::FatalProcessOutOfMemory("heap setup"); | 1870 V8::FatalProcessOutOfMemory("heap setup"); |
| 1871 return false; | 1871 return false; |
| 1872 } | 1872 } |
| 1873 | 1873 |
| 1874 deoptimizer_data_ = new DeoptimizerData(memory_allocator_); | 1874 deoptimizer_data_ = new DeoptimizerData(memory_allocator_); |
| 1875 | 1875 |
| 1876 const bool create_heap_objects = (des == NULL); | 1876 const bool create_heap_objects = (des == NULL); |
| 1877 if (create_heap_objects && !heap_.CreateHeapObjects()) { | 1877 if (create_heap_objects && !heap_.CreateHeapObjects()) { |
| 1878 V8::FatalProcessOutOfMemory("heap object creation"); | 1878 V8::FatalProcessOutOfMemory("heap object creation"); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2024 } | 2024 } |
| 2025 return stats_table_; | 2025 return stats_table_; |
| 2026 } | 2026 } |
| 2027 | 2027 |
| 2028 | 2028 |
| 2029 void Isolate::Enter() { | 2029 void Isolate::Enter() { |
| 2030 Isolate* current_isolate = NULL; | 2030 Isolate* current_isolate = NULL; |
| 2031 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); | 2031 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); |
| 2032 if (current_data != NULL) { | 2032 if (current_data != NULL) { |
| 2033 current_isolate = current_data->isolate_; | 2033 current_isolate = current_data->isolate_; |
| 2034 ASSERT(current_isolate != NULL); | 2034 DCHECK(current_isolate != NULL); |
| 2035 if (current_isolate == this) { | 2035 if (current_isolate == this) { |
| 2036 ASSERT(Current() == this); | 2036 DCHECK(Current() == this); |
| 2037 ASSERT(entry_stack_ != NULL); | 2037 DCHECK(entry_stack_ != NULL); |
| 2038 ASSERT(entry_stack_->previous_thread_data == NULL || | 2038 DCHECK(entry_stack_->previous_thread_data == NULL || |
| 2039 entry_stack_->previous_thread_data->thread_id().Equals( | 2039 entry_stack_->previous_thread_data->thread_id().Equals( |
| 2040 ThreadId::Current())); | 2040 ThreadId::Current())); |
| 2041 // Same thread re-enters the isolate, no need to re-init anything. | 2041 // Same thread re-enters the isolate, no need to re-init anything. |
| 2042 entry_stack_->entry_count++; | 2042 entry_stack_->entry_count++; |
| 2043 return; | 2043 return; |
| 2044 } | 2044 } |
| 2045 } | 2045 } |
| 2046 | 2046 |
| 2047 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread(); | 2047 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread(); |
| 2048 ASSERT(data != NULL); | 2048 DCHECK(data != NULL); |
| 2049 ASSERT(data->isolate_ == this); | 2049 DCHECK(data->isolate_ == this); |
| 2050 | 2050 |
| 2051 EntryStackItem* item = new EntryStackItem(current_data, | 2051 EntryStackItem* item = new EntryStackItem(current_data, |
| 2052 current_isolate, | 2052 current_isolate, |
| 2053 entry_stack_); | 2053 entry_stack_); |
| 2054 entry_stack_ = item; | 2054 entry_stack_ = item; |
| 2055 | 2055 |
| 2056 SetIsolateThreadLocals(this, data); | 2056 SetIsolateThreadLocals(this, data); |
| 2057 | 2057 |
| 2058 // In case it's the first time some thread enters the isolate. | 2058 // In case it's the first time some thread enters the isolate. |
| 2059 set_thread_id(data->thread_id()); | 2059 set_thread_id(data->thread_id()); |
| 2060 } | 2060 } |
| 2061 | 2061 |
| 2062 | 2062 |
| 2063 void Isolate::Exit() { | 2063 void Isolate::Exit() { |
| 2064 ASSERT(entry_stack_ != NULL); | 2064 DCHECK(entry_stack_ != NULL); |
| 2065 ASSERT(entry_stack_->previous_thread_data == NULL || | 2065 DCHECK(entry_stack_->previous_thread_data == NULL || |
| 2066 entry_stack_->previous_thread_data->thread_id().Equals( | 2066 entry_stack_->previous_thread_data->thread_id().Equals( |
| 2067 ThreadId::Current())); | 2067 ThreadId::Current())); |
| 2068 | 2068 |
| 2069 if (--entry_stack_->entry_count > 0) return; | 2069 if (--entry_stack_->entry_count > 0) return; |
| 2070 | 2070 |
| 2071 ASSERT(CurrentPerIsolateThreadData() != NULL); | 2071 DCHECK(CurrentPerIsolateThreadData() != NULL); |
| 2072 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this); | 2072 DCHECK(CurrentPerIsolateThreadData()->isolate_ == this); |
| 2073 | 2073 |
| 2074 // Pop the stack. | 2074 // Pop the stack. |
| 2075 EntryStackItem* item = entry_stack_; | 2075 EntryStackItem* item = entry_stack_; |
| 2076 entry_stack_ = item->previous_item; | 2076 entry_stack_ = item->previous_item; |
| 2077 | 2077 |
| 2078 PerIsolateThreadData* previous_thread_data = item->previous_thread_data; | 2078 PerIsolateThreadData* previous_thread_data = item->previous_thread_data; |
| 2079 Isolate* previous_isolate = item->previous_isolate; | 2079 Isolate* previous_isolate = item->previous_isolate; |
| 2080 | 2080 |
| 2081 delete item; | 2081 delete item; |
| 2082 | 2082 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2094 } | 2094 } |
| 2095 | 2095 |
| 2096 | 2096 |
| 2097 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) { | 2097 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) { |
| 2098 #ifdef DEBUG | 2098 #ifdef DEBUG |
| 2099 // In debug mode assert that the linked list is well-formed. | 2099 // In debug mode assert that the linked list is well-formed. |
| 2100 DeferredHandles* deferred_iterator = deferred; | 2100 DeferredHandles* deferred_iterator = deferred; |
| 2101 while (deferred_iterator->previous_ != NULL) { | 2101 while (deferred_iterator->previous_ != NULL) { |
| 2102 deferred_iterator = deferred_iterator->previous_; | 2102 deferred_iterator = deferred_iterator->previous_; |
| 2103 } | 2103 } |
| 2104 ASSERT(deferred_handles_head_ == deferred_iterator); | 2104 DCHECK(deferred_handles_head_ == deferred_iterator); |
| 2105 #endif | 2105 #endif |
| 2106 if (deferred_handles_head_ == deferred) { | 2106 if (deferred_handles_head_ == deferred) { |
| 2107 deferred_handles_head_ = deferred_handles_head_->next_; | 2107 deferred_handles_head_ = deferred_handles_head_->next_; |
| 2108 } | 2108 } |
| 2109 if (deferred->next_ != NULL) { | 2109 if (deferred->next_ != NULL) { |
| 2110 deferred->next_->previous_ = deferred->previous_; | 2110 deferred->next_->previous_ = deferred->previous_; |
| 2111 } | 2111 } |
| 2112 if (deferred->previous_ != NULL) { | 2112 if (deferred->previous_ != NULL) { |
| 2113 deferred->previous_->next_ = deferred->next_; | 2113 deferred->previous_->next_ = deferred->next_; |
| 2114 } | 2114 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2156 bool Isolate::use_crankshaft() const { | 2156 bool Isolate::use_crankshaft() const { |
| 2157 return FLAG_crankshaft && | 2157 return FLAG_crankshaft && |
| 2158 !serializer_enabled_ && | 2158 !serializer_enabled_ && |
| 2159 CpuFeatures::SupportsCrankshaft(); | 2159 CpuFeatures::SupportsCrankshaft(); |
| 2160 } | 2160 } |
| 2161 | 2161 |
| 2162 | 2162 |
| 2163 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { | 2163 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { |
| 2164 Map* root_array_map = | 2164 Map* root_array_map = |
| 2165 get_initial_js_array_map(GetInitialFastElementsKind()); | 2165 get_initial_js_array_map(GetInitialFastElementsKind()); |
| 2166 ASSERT(root_array_map != NULL); | 2166 DCHECK(root_array_map != NULL); |
| 2167 JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype()); | 2167 JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype()); |
| 2168 | 2168 |
| 2169 // Check that the array prototype hasn't been altered WRT empty elements. | 2169 // Check that the array prototype hasn't been altered WRT empty elements. |
| 2170 if (root_array_map->prototype() != initial_array_proto) return false; | 2170 if (root_array_map->prototype() != initial_array_proto) return false; |
| 2171 if (initial_array_proto->elements() != heap()->empty_fixed_array()) { | 2171 if (initial_array_proto->elements() != heap()->empty_fixed_array()) { |
| 2172 return false; | 2172 return false; |
| 2173 } | 2173 } |
| 2174 | 2174 |
| 2175 // Check that the object prototype hasn't been altered WRT empty elements. | 2175 // Check that the object prototype hasn't been altered WRT empty elements. |
| 2176 JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype()); | 2176 JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2188 | 2188 |
| 2189 | 2189 |
| 2190 CodeStubInterfaceDescriptor* | 2190 CodeStubInterfaceDescriptor* |
| 2191 Isolate::code_stub_interface_descriptor(int index) { | 2191 Isolate::code_stub_interface_descriptor(int index) { |
| 2192 return code_stub_interface_descriptors_ + index; | 2192 return code_stub_interface_descriptors_ + index; |
| 2193 } | 2193 } |
| 2194 | 2194 |
| 2195 | 2195 |
| 2196 CallInterfaceDescriptor* | 2196 CallInterfaceDescriptor* |
| 2197 Isolate::call_descriptor(CallDescriptorKey index) { | 2197 Isolate::call_descriptor(CallDescriptorKey index) { |
| 2198 ASSERT(0 <= index && index < NUMBER_OF_CALL_DESCRIPTORS); | 2198 DCHECK(0 <= index && index < NUMBER_OF_CALL_DESCRIPTORS); |
| 2199 return &call_descriptors_[index]; | 2199 return &call_descriptors_[index]; |
| 2200 } | 2200 } |
| 2201 | 2201 |
| 2202 | 2202 |
| 2203 Object* Isolate::FindCodeObject(Address a) { | 2203 Object* Isolate::FindCodeObject(Address a) { |
| 2204 return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a); | 2204 return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a); |
| 2205 } | 2205 } |
| 2206 | 2206 |
| 2207 | 2207 |
| 2208 #ifdef DEBUG | 2208 #ifdef DEBUG |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2261 // Fire callbacks. Increase call depth to prevent recursive callbacks. | 2261 // Fire callbacks. Increase call depth to prevent recursive callbacks. |
| 2262 v8::Isolate::SuppressMicrotaskExecutionScope suppress( | 2262 v8::Isolate::SuppressMicrotaskExecutionScope suppress( |
| 2263 reinterpret_cast<v8::Isolate*>(this)); | 2263 reinterpret_cast<v8::Isolate*>(this)); |
| 2264 for (int i = 0; i < call_completed_callbacks_.length(); i++) { | 2264 for (int i = 0; i < call_completed_callbacks_.length(); i++) { |
| 2265 call_completed_callbacks_.at(i)(); | 2265 call_completed_callbacks_.at(i)(); |
| 2266 } | 2266 } |
| 2267 } | 2267 } |
| 2268 | 2268 |
| 2269 | 2269 |
| 2270 void Isolate::EnqueueMicrotask(Handle<Object> microtask) { | 2270 void Isolate::EnqueueMicrotask(Handle<Object> microtask) { |
| 2271 ASSERT(microtask->IsJSFunction() || microtask->IsCallHandlerInfo()); | 2271 DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo()); |
| 2272 Handle<FixedArray> queue(heap()->microtask_queue(), this); | 2272 Handle<FixedArray> queue(heap()->microtask_queue(), this); |
| 2273 int num_tasks = pending_microtask_count(); | 2273 int num_tasks = pending_microtask_count(); |
| 2274 ASSERT(num_tasks <= queue->length()); | 2274 DCHECK(num_tasks <= queue->length()); |
| 2275 if (num_tasks == 0) { | 2275 if (num_tasks == 0) { |
| 2276 queue = factory()->NewFixedArray(8); | 2276 queue = factory()->NewFixedArray(8); |
| 2277 heap()->set_microtask_queue(*queue); | 2277 heap()->set_microtask_queue(*queue); |
| 2278 } else if (num_tasks == queue->length()) { | 2278 } else if (num_tasks == queue->length()) { |
| 2279 queue = FixedArray::CopySize(queue, num_tasks * 2); | 2279 queue = FixedArray::CopySize(queue, num_tasks * 2); |
| 2280 heap()->set_microtask_queue(*queue); | 2280 heap()->set_microtask_queue(*queue); |
| 2281 } | 2281 } |
| 2282 ASSERT(queue->get(num_tasks)->IsUndefined()); | 2282 DCHECK(queue->get(num_tasks)->IsUndefined()); |
| 2283 queue->set(num_tasks, *microtask); | 2283 queue->set(num_tasks, *microtask); |
| 2284 set_pending_microtask_count(num_tasks + 1); | 2284 set_pending_microtask_count(num_tasks + 1); |
| 2285 } | 2285 } |
| 2286 | 2286 |
| 2287 | 2287 |
| 2288 void Isolate::RunMicrotasks() { | 2288 void Isolate::RunMicrotasks() { |
| 2289 // %RunMicrotasks may be called in mjsunit tests, which violates | 2289 // %RunMicrotasks may be called in mjsunit tests, which violates |
| 2290 // this assertion, hence the check for --allow-natives-syntax. | 2290 // this assertion, hence the check for --allow-natives-syntax. |
| 2291 // TODO(adamk): However, this also fails some layout tests. | 2291 // TODO(adamk): However, this also fails some layout tests. |
| 2292 // | 2292 // |
| 2293 // ASSERT(FLAG_allow_natives_syntax || | 2293 // DCHECK(FLAG_allow_natives_syntax || |
| 2294 // handle_scope_implementer()->CallDepthIsZero()); | 2294 // handle_scope_implementer()->CallDepthIsZero()); |
| 2295 | 2295 |
| 2296 // Increase call depth to prevent recursive callbacks. | 2296 // Increase call depth to prevent recursive callbacks. |
| 2297 v8::Isolate::SuppressMicrotaskExecutionScope suppress( | 2297 v8::Isolate::SuppressMicrotaskExecutionScope suppress( |
| 2298 reinterpret_cast<v8::Isolate*>(this)); | 2298 reinterpret_cast<v8::Isolate*>(this)); |
| 2299 | 2299 |
| 2300 while (pending_microtask_count() > 0) { | 2300 while (pending_microtask_count() > 0) { |
| 2301 HandleScope scope(this); | 2301 HandleScope scope(this); |
| 2302 int num_tasks = pending_microtask_count(); | 2302 int num_tasks = pending_microtask_count(); |
| 2303 Handle<FixedArray> queue(heap()->microtask_queue(), this); | 2303 Handle<FixedArray> queue(heap()->microtask_queue(), this); |
| 2304 ASSERT(num_tasks <= queue->length()); | 2304 DCHECK(num_tasks <= queue->length()); |
| 2305 set_pending_microtask_count(0); | 2305 set_pending_microtask_count(0); |
| 2306 heap()->set_microtask_queue(heap()->empty_fixed_array()); | 2306 heap()->set_microtask_queue(heap()->empty_fixed_array()); |
| 2307 | 2307 |
| 2308 for (int i = 0; i < num_tasks; i++) { | 2308 for (int i = 0; i < num_tasks; i++) { |
| 2309 HandleScope scope(this); | 2309 HandleScope scope(this); |
| 2310 Handle<Object> microtask(queue->get(i), this); | 2310 Handle<Object> microtask(queue->get(i), this); |
| 2311 if (microtask->IsJSFunction()) { | 2311 if (microtask->IsJSFunction()) { |
| 2312 Handle<JSFunction> microtask_function = | 2312 Handle<JSFunction> microtask_function = |
| 2313 Handle<JSFunction>::cast(microtask); | 2313 Handle<JSFunction>::cast(microtask); |
| 2314 SaveContext save(this); | 2314 SaveContext save(this); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2333 v8::ToCData<v8::MicrotaskCallback>(callback_info->callback()); | 2333 v8::ToCData<v8::MicrotaskCallback>(callback_info->callback()); |
| 2334 void* data = v8::ToCData<void*>(callback_info->data()); | 2334 void* data = v8::ToCData<void*>(callback_info->data()); |
| 2335 callback(data); | 2335 callback(data); |
| 2336 } | 2336 } |
| 2337 } | 2337 } |
| 2338 } | 2338 } |
| 2339 } | 2339 } |
| 2340 | 2340 |
| 2341 | 2341 |
| 2342 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) { | 2342 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) { |
| 2343 ASSERT(!use_counter_callback_); | 2343 DCHECK(!use_counter_callback_); |
| 2344 use_counter_callback_ = callback; | 2344 use_counter_callback_ = callback; |
| 2345 } | 2345 } |
| 2346 | 2346 |
| 2347 | 2347 |
| 2348 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) { | 2348 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) { |
| 2349 if (use_counter_callback_) { | 2349 if (use_counter_callback_) { |
| 2350 use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature); | 2350 use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature); |
| 2351 } | 2351 } |
| 2352 } | 2352 } |
| 2353 | 2353 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2369 if (prev_ && prev_->Intercept(flag)) return true; | 2369 if (prev_ && prev_->Intercept(flag)) return true; |
| 2370 // Then check whether this scope intercepts. | 2370 // Then check whether this scope intercepts. |
| 2371 if ((flag & intercept_mask_)) { | 2371 if ((flag & intercept_mask_)) { |
| 2372 intercepted_flags_ |= flag; | 2372 intercepted_flags_ |= flag; |
| 2373 return true; | 2373 return true; |
| 2374 } | 2374 } |
| 2375 return false; | 2375 return false; |
| 2376 } | 2376 } |
| 2377 | 2377 |
| 2378 } } // namespace v8::internal | 2378 } } // namespace v8::internal |
| OLD | NEW |