00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "api.h"
00031 #include "bootstrapper.h"
00032 #include "debug.h"
00033 #include "execution.h"
00034 #include "string-stream.h"
00035 #include "platform.h"
00036
00037 namespace v8 { namespace internal {
00038
00039 ThreadLocalTop Top::thread_local_;
00040 Mutex* Top::break_access_;
00041 StackFrame::Id Top::break_frame_id_;
00042 int Top::break_count_;
00043 int Top::break_id_;
00044
00045 NoAllocationStringAllocator* preallocated_message_space = NULL;
00046
00047 Address top_addresses[] = {
00048 #define C(name) reinterpret_cast<Address>(Top::name()),
00049 TOP_ADDRESS_LIST(C)
00050 #undef C
00051 NULL
00052 };
00053
00054 Address Top::get_address_from_id(Top::AddressId id) {
00055 return top_addresses[id];
00056 }
00057
00058 char* Top::Iterate(ObjectVisitor* v, char* thread_storage) {
00059 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
00060 Iterate(v, thread);
00061 return thread_storage + sizeof(ThreadLocalTop);
00062 }
00063
00064
00065 #define VISIT(field) v->VisitPointer(reinterpret_cast<Object**>(&(field)));
00066
00067 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
00068 v->VisitPointer(&(thread->pending_exception_));
00069 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
00070 v->VisitPointer(&(thread->scheduled_exception_));
00071
00072 for (v8::TryCatch* block = thread->try_catch_handler_;
00073 block != NULL;
00074 block = block->next_) {
00075 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_)));
00076 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_)));
00077 }
00078
00079
00080 for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
00081 it.frame()->Iterate(v);
00082 }
00083 }
00084 #undef VISIT
00085
00086
00087 void Top::Iterate(ObjectVisitor* v) {
00088 ThreadLocalTop* current_t = &thread_local_;
00089 Iterate(v, current_t);
00090 }
00091
00092
00093 void Top::InitializeThreadLocal() {
00094 thread_local_.c_entry_fp_ = 0;
00095 thread_local_.handler_ = 0;
00096 thread_local_.stack_is_cooked_ = false;
00097 thread_local_.try_catch_handler_ = NULL;
00098 thread_local_.context_ = NULL;
00099 thread_local_.external_caught_exception_ = false;
00100 thread_local_.failed_access_check_callback_ = NULL;
00101 clear_pending_exception();
00102 clear_scheduled_exception();
00103 thread_local_.save_context_ = NULL;
00104 thread_local_.catcher_ = NULL;
00105 }
00106
00107
00108
00109
00110
00111 class PreallocatedMemoryThread: public Thread {
00112 public:
00113 PreallocatedMemoryThread() : keep_running_(true) {
00114 wait_for_ever_semaphore_ = OS::CreateSemaphore(0);
00115 data_ready_semaphore_ = OS::CreateSemaphore(0);
00116 }
00117
00118
00119
00120 void Run() {
00121 EmbeddedVector<char, 32 * 1024> local_buffer;
00122
00123
00124 OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
00125 local_buffer.length());
00126
00127
00128 data_ = &local_buffer[0];
00129 length_ = sizeof(local_buffer);
00130 data_ready_semaphore_->Signal();
00131
00132 while (keep_running_) {
00133
00134 wait_for_ever_semaphore_->Wait();
00135 }
00136
00137
00138
00139 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
00140 local_buffer.length());
00141 }
00142
00143 static char* data() {
00144 if (data_ready_semaphore_ != NULL) {
00145
00146 data_ready_semaphore_->Wait();
00147 delete data_ready_semaphore_;
00148 data_ready_semaphore_ = NULL;
00149 }
00150 return data_;
00151 }
00152
00153 static unsigned length() {
00154 if (data_ready_semaphore_ != NULL) {
00155
00156 data_ready_semaphore_->Wait();
00157 delete data_ready_semaphore_;
00158 data_ready_semaphore_ = NULL;
00159 }
00160 return length_;
00161 }
00162
00163 static void StartThread() {
00164 if (the_thread_ != NULL) return;
00165
00166 the_thread_ = new PreallocatedMemoryThread();
00167 the_thread_->Start();
00168 }
00169
00170
00171 static void StopThread() {
00172 if (the_thread_ == NULL) return;
00173
00174 the_thread_->keep_running_ = false;
00175 wait_for_ever_semaphore_->Signal();
00176
00177
00178 the_thread_->Join();
00179
00180 if (data_ready_semaphore_ != NULL) {
00181 delete data_ready_semaphore_;
00182 data_ready_semaphore_ = NULL;
00183 }
00184
00185 delete wait_for_ever_semaphore_;
00186 wait_for_ever_semaphore_ = NULL;
00187
00188
00189 delete the_thread_;
00190 the_thread_ = NULL;
00191 }
00192
00193 private:
00194
00195 bool keep_running_;
00196
00197
00198 static PreallocatedMemoryThread* the_thread_;
00199
00200 static Semaphore* wait_for_ever_semaphore_;
00201
00202 static Semaphore* data_ready_semaphore_;
00203
00204
00205 static char* data_;
00206 static unsigned length_;
00207
00208 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
00209 };
00210
00211 PreallocatedMemoryThread* PreallocatedMemoryThread::the_thread_ = NULL;
00212 Semaphore* PreallocatedMemoryThread::wait_for_ever_semaphore_ = NULL;
00213 Semaphore* PreallocatedMemoryThread::data_ready_semaphore_ = NULL;
00214 char* PreallocatedMemoryThread::data_ = NULL;
00215 unsigned PreallocatedMemoryThread::length_ = 0;
00216
00217 static bool initialized = false;
00218
00219 void Top::Initialize() {
00220 CHECK(!initialized);
00221
00222 InitializeThreadLocal();
00223
00224 break_access_ = OS::CreateMutex();
00225 break_frame_id_ = StackFrame::NO_ID;
00226 break_count_ = 0;
00227 break_id_ = 0;
00228
00229
00230 if (FLAG_preallocate_message_memory && (preallocated_message_space == NULL)) {
00231
00232 PreallocatedMemoryThread::StartThread();
00233 preallocated_message_space =
00234 new NoAllocationStringAllocator(PreallocatedMemoryThread::data(),
00235 PreallocatedMemoryThread::length());
00236 PreallocatedStorage::Init(PreallocatedMemoryThread::length() / 4);
00237 }
00238 initialized = true;
00239 }
00240
00241
00242 void Top::TearDown() {
00243 if (initialized) {
00244
00245 if (preallocated_message_space != NULL) {
00246 delete preallocated_message_space;
00247 preallocated_message_space = NULL;
00248 }
00249
00250 PreallocatedMemoryThread::StopThread();
00251 initialized = false;
00252 }
00253 }
00254
00255
00256 void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
00257 thread_local_.try_catch_handler_ = that;
00258 }
00259
00260
00261 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) {
00262 ASSERT(thread_local_.try_catch_handler_ == that);
00263 thread_local_.try_catch_handler_ = that->next_;
00264 }
00265
00266
00267 void Top::new_break(StackFrame::Id break_frame_id) {
00268 ExecutionAccess access;
00269 break_frame_id_ = break_frame_id;
00270 break_id_ = ++break_count_;
00271 }
00272
00273
00274 void Top::set_break(StackFrame::Id break_frame_id, int break_id) {
00275 ExecutionAccess access;
00276 break_frame_id_ = break_frame_id;
00277 break_id_ = break_id;
00278 }
00279
00280
00281 bool Top::check_break(int break_id) {
00282 ExecutionAccess access;
00283 return break_id == break_id_;
00284 }
00285
00286
00287 bool Top::is_break() {
00288 ExecutionAccess access;
00289 return break_id_ != 0;
00290 }
00291
00292
00293 StackFrame::Id Top::break_frame_id() {
00294 ExecutionAccess access;
00295 return break_frame_id_;
00296 }
00297
00298
00299 int Top::break_id() {
00300 ExecutionAccess access;
00301 return break_id_;
00302 }
00303
00304
00305 void Top::MarkCompactPrologue() {
00306 MarkCompactPrologue(&thread_local_);
00307 }
00308
00309
00310 void Top::MarkCompactPrologue(char* data) {
00311 MarkCompactPrologue(reinterpret_cast<ThreadLocalTop*>(data));
00312 }
00313
00314
00315 void Top::MarkCompactPrologue(ThreadLocalTop* thread) {
00316 StackFrame::CookFramesForThread(thread);
00317 }
00318
00319
00320 void Top::MarkCompactEpilogue(char* data) {
00321 MarkCompactEpilogue(reinterpret_cast<ThreadLocalTop*>(data));
00322 }
00323
00324
00325 void Top::MarkCompactEpilogue() {
00326 MarkCompactEpilogue(&thread_local_);
00327 }
00328
00329
00330 void Top::MarkCompactEpilogue(ThreadLocalTop* thread) {
00331 StackFrame::UncookFramesForThread(thread);
00332 }
00333
00334
00335 static int stack_trace_nesting_level = 0;
00336 static StringStream* incomplete_message = NULL;
00337
00338
00339 Handle<String> Top::StackTrace() {
00340 if (stack_trace_nesting_level == 0) {
00341 stack_trace_nesting_level++;
00342 HeapStringAllocator allocator;
00343 StringStream::ClearMentionedObjectCache();
00344 StringStream accumulator(&allocator);
00345 incomplete_message = &accumulator;
00346 PrintStack(&accumulator);
00347 Handle<String> stack_trace = accumulator.ToString();
00348 incomplete_message = NULL;
00349 stack_trace_nesting_level = 0;
00350 return stack_trace;
00351 } else if (stack_trace_nesting_level == 1) {
00352 stack_trace_nesting_level++;
00353 OS::PrintError(
00354 "\n\nAttempt to print stack while printing stack (double fault)\n");
00355 OS::PrintError(
00356 "If you are lucky you may find a partial stack dump on stdout.\n\n");
00357 incomplete_message->OutputToStdOut();
00358 return Factory::empty_symbol();
00359 } else {
00360 OS::Abort();
00361
00362 return Factory::empty_symbol();
00363 }
00364 }
00365
00366
00367 void Top::PrintStack() {
00368 if (stack_trace_nesting_level == 0) {
00369 stack_trace_nesting_level++;
00370
00371 StringAllocator* allocator;
00372 if (preallocated_message_space == NULL) {
00373 allocator = new HeapStringAllocator();
00374 } else {
00375 allocator = preallocated_message_space;
00376 }
00377
00378 NativeAllocationChecker allocation_checker(
00379 !FLAG_preallocate_message_memory ?
00380 NativeAllocationChecker::ALLOW :
00381 NativeAllocationChecker::DISALLOW);
00382
00383 StringStream::ClearMentionedObjectCache();
00384 StringStream accumulator(allocator);
00385 incomplete_message = &accumulator;
00386 PrintStack(&accumulator);
00387 accumulator.OutputToStdOut();
00388 accumulator.Log();
00389 incomplete_message = NULL;
00390 stack_trace_nesting_level = 0;
00391 if (preallocated_message_space == NULL) {
00392
00393 delete allocator;
00394 }
00395 } else if (stack_trace_nesting_level == 1) {
00396 stack_trace_nesting_level++;
00397 OS::PrintError(
00398 "\n\nAttempt to print stack while printing stack (double fault)\n");
00399 OS::PrintError(
00400 "If you are lucky you may find a partial stack dump on stdout.\n\n");
00401 incomplete_message->OutputToStdOut();
00402 }
00403 }
00404
00405
00406 static void PrintFrames(StringStream* accumulator,
00407 StackFrame::PrintMode mode) {
00408 StackFrameIterator it;
00409 for (int i = 0; !it.done(); it.Advance()) {
00410 it.frame()->Print(accumulator, mode, i++);
00411 }
00412 }
00413
00414
00415 void Top::PrintStack(StringStream* accumulator) {
00416
00417 AssertNoAllocation nogc;
00418 ASSERT(StringStream::IsMentionedObjectCacheClear());
00419
00420
00421 if (c_entry_fp(GetCurrentThread()) == 0) return;
00422
00423 accumulator->Add(
00424 "\n==== Stack trace ============================================\n\n");
00425 PrintFrames(accumulator, StackFrame::OVERVIEW);
00426
00427 accumulator->Add(
00428 "\n==== Details ================================================\n\n");
00429 PrintFrames(accumulator, StackFrame::DETAILS);
00430
00431 accumulator->PrintMentionedObjectCache();
00432 accumulator->Add("=====================\n\n");
00433 }
00434
00435
00436 void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) {
00437 ASSERT(thread_local_.failed_access_check_callback_ == NULL);
00438 thread_local_.failed_access_check_callback_ = callback;
00439 }
00440
00441
00442 void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
00443 if (!thread_local_.failed_access_check_callback_) return;
00444
00445 ASSERT(receiver->IsAccessCheckNeeded());
00446 ASSERT(Top::context());
00447
00448 AssertNoAllocation no_gc;
00449
00450
00451 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
00452 Object* info = constructor->shared()->function_data();
00453 if (info == Heap::undefined_value()) return;
00454
00455 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
00456 if (data_obj == Heap::undefined_value()) return;
00457
00458 HandleScope scope;
00459 Handle<JSObject> receiver_handle(receiver);
00460 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
00461 thread_local_.failed_access_check_callback_(
00462 v8::Utils::ToLocal(receiver_handle),
00463 type,
00464 v8::Utils::ToLocal(data));
00465 }
00466
00467
00468 enum MayAccessDecision {
00469 YES, NO, UNKNOWN
00470 };
00471
00472
00473 static MayAccessDecision MayAccessPreCheck(JSObject* receiver,
00474 v8::AccessType type) {
00475
00476 if (Bootstrapper::IsActive()) return YES;
00477
00478 if (receiver->IsJSGlobalProxy()) {
00479 Object* receiver_context = JSGlobalProxy::cast(receiver)->context();
00480 if (!receiver_context->IsContext()) return NO;
00481
00482
00483
00484 Context* global_context = Top::context()->global()->global_context();
00485 if (receiver_context == global_context) return YES;
00486
00487 if (Context::cast(receiver_context)->security_token() ==
00488 global_context->security_token())
00489 return YES;
00490 }
00491
00492 return UNKNOWN;
00493 }
00494
00495
00496 bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) {
00497 ASSERT(receiver->IsAccessCheckNeeded());
00498
00499
00500 ASSERT(Top::context());
00501
00502 AssertNoAllocation no_gc;
00503
00504 MayAccessDecision decision = MayAccessPreCheck(receiver, type);
00505 if (decision != UNKNOWN) return decision == YES;
00506
00507
00508 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
00509 Object* info = constructor->shared()->function_data();
00510 if (info == Heap::undefined_value()) return false;
00511
00512 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
00513 if (data_obj == Heap::undefined_value()) return false;
00514
00515 Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
00516 v8::NamedSecurityCallback callback =
00517 v8::ToCData<v8::NamedSecurityCallback>(fun_obj);
00518
00519 if (!callback) return false;
00520
00521 HandleScope scope;
00522 Handle<JSObject> receiver_handle(receiver);
00523 Handle<Object> key_handle(key);
00524 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
00525 LOG(ApiNamedSecurityCheck(key));
00526 bool result = false;
00527 {
00528
00529 VMState state(OTHER);
00530 result = callback(v8::Utils::ToLocal(receiver_handle),
00531 v8::Utils::ToLocal(key_handle),
00532 type,
00533 v8::Utils::ToLocal(data));
00534 }
00535 return result;
00536 }
00537
00538
00539 bool Top::MayIndexedAccess(JSObject* receiver,
00540 uint32_t index,
00541 v8::AccessType type) {
00542 ASSERT(receiver->IsAccessCheckNeeded());
00543
00544
00545 ASSERT(Top::context());
00546
00547 AssertNoAllocation no_gc;
00548
00549 MayAccessDecision decision = MayAccessPreCheck(receiver, type);
00550 if (decision != UNKNOWN) return decision == YES;
00551
00552
00553 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
00554 Object* info = constructor->shared()->function_data();
00555 if (info == Heap::undefined_value()) return false;
00556
00557 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info();
00558 if (data_obj == Heap::undefined_value()) return false;
00559
00560 Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
00561 v8::IndexedSecurityCallback callback =
00562 v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);
00563
00564 if (!callback) return false;
00565
00566 HandleScope scope;
00567 Handle<JSObject> receiver_handle(receiver);
00568 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
00569 LOG(ApiIndexedSecurityCheck(index));
00570 bool result = false;
00571 {
00572
00573 VMState state(OTHER);
00574 result = callback(v8::Utils::ToLocal(receiver_handle),
00575 index,
00576 type,
00577 v8::Utils::ToLocal(data));
00578 }
00579 return result;
00580 }
00581
00582
00583 Failure* Top::StackOverflow() {
00584 HandleScope scope;
00585 Handle<String> key = Factory::stack_overflow_symbol();
00586 Handle<JSObject> boilerplate =
00587 Handle<JSObject>::cast(GetProperty(Top::builtins(), key));
00588 Handle<Object> exception = Copy(boilerplate);
00589
00590
00591
00592
00593
00594
00595
00596 static const char* kMessage =
00597 "Uncaught RangeError: Maximum call stack size exceeded";
00598 DoThrow(*exception, NULL, kMessage);
00599 return Failure::Exception();
00600 }
00601
00602
00603 Failure* Top::Throw(Object* exception, MessageLocation* location) {
00604 DoThrow(exception, location, NULL);
00605 return Failure::Exception();
00606 }
00607
00608
00609 Failure* Top::ReThrow(Object* exception, MessageLocation* location) {
00610
00611 set_pending_exception(exception);
00612 return Failure::Exception();
00613 }
00614
00615
00616 void Top::ScheduleThrow(Object* exception) {
00617
00618
00619 Throw(exception);
00620 thread_local_.scheduled_exception_ = pending_exception();
00621 thread_local_.external_caught_exception_ = false;
00622 clear_pending_exception();
00623 }
00624
00625
00626 Object* Top::PromoteScheduledException() {
00627 Object* thrown = scheduled_exception();
00628 clear_scheduled_exception();
00629
00630 return ReThrow(thrown);
00631 }
00632
00633
00634
00635
00636
00637
00638 class StackTraceFrameIterator: public JavaScriptFrameIterator {
00639 public:
00640 StackTraceFrameIterator() {
00641 if (!done() && !frame()->function()->IsJSFunction()) Advance();
00642 }
00643
00644 void Advance() {
00645 while (true) {
00646 JavaScriptFrameIterator::Advance();
00647 if (done()) return;
00648 if (frame()->function()->IsJSFunction()) return;
00649 }
00650 }
00651 };
00652
00653
00654 void Top::PrintCurrentStackTrace(FILE* out) {
00655 StackTraceFrameIterator it;
00656 while (!it.done()) {
00657 HandleScope scope;
00658
00659 JavaScriptFrame* frame = it.frame();
00660 int pos = frame->FindCode()->SourcePosition(frame->pc());
00661 Handle<Object> pos_obj(Smi::FromInt(pos));
00662
00663 Handle<JSFunction> fun(JSFunction::cast(frame->function()));
00664 Handle<Object> recv(frame->receiver());
00665
00666
00667 it.Advance();
00668 Handle<Object> is_top_level = it.done()
00669 ? Factory::true_value()
00670 : Factory::false_value();
00671
00672 Handle<String> line =
00673 Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
00674 if (line->length() > 0) {
00675 line->PrintOn(out);
00676 fprintf(out, "\n");
00677 }
00678 }
00679 }
00680
00681
00682 void Top::ComputeLocation(MessageLocation* target) {
00683 *target = MessageLocation(empty_script(), -1, -1);
00684 StackTraceFrameIterator it;
00685 if (!it.done()) {
00686 JavaScriptFrame* frame = it.frame();
00687 JSFunction* fun = JSFunction::cast(frame->function());
00688 Object* script = fun->shared()->script();
00689 if (script->IsScript() &&
00690 !(Script::cast(script)->source()->IsUndefined())) {
00691 int pos = frame->FindCode()->SourcePosition(frame->pc());
00692
00693 Handle<Script> casted_script(Script::cast(script));
00694 *target = MessageLocation(casted_script, pos, pos + 1);
00695 }
00696 }
00697 }
00698
00699
00700 void Top::ReportUncaughtException(Handle<Object> exception,
00701 MessageLocation* location,
00702 Handle<String> stack_trace) {
00703 Handle<Object> message =
00704 MessageHandler::MakeMessageObject("uncaught_exception",
00705 location,
00706 HandleVector<Object>(&exception, 1),
00707 stack_trace);
00708
00709
00710 MessageHandler::ReportMessage(location, message);
00711 }
00712
00713
00714 bool Top::ShouldReportException(bool* is_caught_externally) {
00715 StackHandler* handler =
00716 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
00717
00718
00719
00720
00721 bool has_external_handler = (thread_local_.try_catch_handler_ != NULL);
00722 Address external_handler_address =
00723 reinterpret_cast<Address>(thread_local_.try_catch_handler_);
00724
00725
00726
00727
00728
00729
00730 while (handler != NULL && !handler->is_try_catch()) {
00731 handler = handler->next();
00732 }
00733
00734
00735
00736
00737 *is_caught_externally = has_external_handler &&
00738 (handler == NULL || handler->address() > external_handler_address);
00739
00740
00741
00742 bool is_uncaught_by_js = (handler == NULL);
00743
00744
00745
00746 if (!has_external_handler) return is_uncaught_by_js;
00747
00748 if (is_uncaught_by_js || handler->address() > external_handler_address) {
00749
00750 return thread_local_.try_catch_handler_->is_verbose_;
00751 } else {
00752
00753 return is_uncaught_by_js;
00754 }
00755 }
00756
00757
00758 void Top::DoThrow(Object* exception,
00759 MessageLocation* location,
00760 const char* message) {
00761 ASSERT(!has_pending_exception());
00762
00763 HandleScope scope;
00764 Handle<Object> exception_handle(exception);
00765
00766
00767 bool is_caught_externally = false;
00768 bool report_exception = (exception != Failure::OutOfMemoryException()) &&
00769 ShouldReportException(&is_caught_externally);
00770
00771
00772 Handle<Object> message_obj;
00773 MessageLocation potential_computed_location;
00774 bool try_catch_needs_message =
00775 is_caught_externally &&
00776 thread_local_.try_catch_handler_->capture_message_;
00777 if (report_exception || try_catch_needs_message) {
00778 if (location == NULL) {
00779
00780 ComputeLocation(&potential_computed_location);
00781 location = &potential_computed_location;
00782 }
00783 Handle<String> stack_trace;
00784 if (FLAG_trace_exception) stack_trace = StackTrace();
00785 message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
00786 location, HandleVector<Object>(&exception_handle, 1), stack_trace);
00787 }
00788
00789
00790
00791
00792 thread_local_.catcher_ = NULL;
00793 if (is_caught_externally) {
00794 thread_local_.catcher_ = thread_local_.try_catch_handler_;
00795 thread_local_.try_catch_handler_->exception_ =
00796 reinterpret_cast<void*>(*exception_handle);
00797 if (!message_obj.is_null()) {
00798 thread_local_.try_catch_handler_->message_ =
00799 reinterpret_cast<void*>(*message_obj);
00800 }
00801 }
00802
00803
00804 Debugger::OnException(exception_handle, report_exception);
00805
00806 if (report_exception) {
00807 if (message != NULL) {
00808 MessageHandler::ReportMessage(message);
00809 } else if (!message_obj.is_null()) {
00810 MessageHandler::ReportMessage(location, message_obj);
00811 }
00812 }
00813
00814
00815
00816
00817 set_pending_exception(*exception_handle);
00818 }
00819
00820
00821 void Top::TraceException(bool flag) {
00822 FLAG_trace_exception = flag;
00823 }
00824
00825
00826 bool Top::optional_reschedule_exception(bool is_bottom_call) {
00827 if (!is_out_of_memory() &&
00828 (thread_local_.external_caught_exception_ || is_bottom_call)) {
00829 thread_local_.external_caught_exception_ = false;
00830 clear_pending_exception();
00831 return false;
00832 } else {
00833 thread_local_.scheduled_exception_ = pending_exception();
00834 clear_pending_exception();
00835 return true;
00836 }
00837 }
00838
00839
00840 bool Top::is_out_of_memory() {
00841 if (has_pending_exception()) {
00842 Object* e = pending_exception();
00843 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
00844 return true;
00845 }
00846 }
00847 if (has_scheduled_exception()) {
00848 Object* e = scheduled_exception();
00849 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
00850 return true;
00851 }
00852 }
00853 return false;
00854 }
00855
00856
00857 Handle<Context> Top::global_context() {
00858 GlobalObject* global = thread_local_.context_->global();
00859 return Handle<Context>(global->global_context());
00860 }
00861
00862
00863 Object* Top::LookupSpecialFunction(JSObject* receiver,
00864 JSObject* prototype,
00865 JSFunction* function) {
00866 if (receiver->IsJSArray()) {
00867 FixedArray* table = context()->global_context()->special_function_table();
00868 for (int index = 0; index < table->length(); index +=3) {
00869 if ((prototype == table->get(index)) &&
00870 (function == table->get(index+1))) {
00871 return table->get(index+2);
00872 }
00873 }
00874 }
00875 return Heap::undefined_value();
00876 }
00877
00878
00879 char* Top::ArchiveThread(char* to) {
00880 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_));
00881 InitializeThreadLocal();
00882 return to + sizeof(thread_local_);
00883 }
00884
00885
00886 char* Top::RestoreThread(char* from) {
00887 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_));
00888 return from + sizeof(thread_local_);
00889 }
00890
00891
00892 ExecutionAccess::ExecutionAccess() {
00893 Top::break_access_->Lock();
00894 }
00895
00896
00897 ExecutionAccess::~ExecutionAccess() {
00898 Top::break_access_->Unlock();
00899 }
00900
00901
00902 } }