| Index: src/top.cc
|
| diff --git a/src/top.cc b/src/top.cc
|
| index 9ce65429642d26e1bc027e5345d0ed362e3ce6f8..1f0d159fe8bdfd0e33f253b43d2ec464c8b13b9e 100644
|
| --- a/src/top.cc
|
| +++ b/src/top.cc
|
| @@ -66,6 +66,13 @@ v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
|
| void ThreadLocalTop::Initialize() {
|
| c_entry_fp_ = 0;
|
| handler_ = 0;
|
| +#ifdef USE_SIMULATOR
|
| +#ifdef V8_TARGET_ARCH_ARM
|
| + simulator_ = assembler::arm::Simulator::current();
|
| +#elif V8_TARGET_ARCH_MIPS
|
| + simulator_ = assembler::mips::Simulator::current();
|
| +#endif
|
| +#endif
|
| #ifdef ENABLE_LOGGING_AND_PROFILING
|
| js_entry_sp_ = 0;
|
| #endif
|
| @@ -107,11 +114,22 @@ void Top::IterateThread(ThreadVisitor* v, char* t) {
|
|
|
|
|
| void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
|
| - v->VisitPointer(&(thread->pending_exception_));
|
| + // Visit the roots from the top for a given thread.
|
| + Object *pending;
|
| + // The pending exception can sometimes be a failure. We can't show
|
| + // that to the GC, which only understands objects.
|
| + if (thread->pending_exception_->ToObject(&pending)) {
|
| + v->VisitPointer(&pending);
|
| + thread->pending_exception_ = pending; // In case GC updated it.
|
| + }
|
| v->VisitPointer(&(thread->pending_message_obj_));
|
| v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_)));
|
| v->VisitPointer(BitCast<Object**>(&(thread->context_)));
|
| - v->VisitPointer(&(thread->scheduled_exception_));
|
| + Object* scheduled;
|
| + if (thread->scheduled_exception_->ToObject(&scheduled)) {
|
| + v->VisitPointer(&scheduled);
|
| + thread->scheduled_exception_ = scheduled;
|
| + }
|
|
|
| for (v8::TryCatch* block = thread->TryCatchHandler();
|
| block != NULL;
|
| @@ -688,7 +706,7 @@ Failure* Top::Throw(Object* exception, MessageLocation* location) {
|
| }
|
|
|
|
|
| -Failure* Top::ReThrow(Object* exception, MessageLocation* location) {
|
| +Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) {
|
| // Set the exception being re-thrown.
|
| set_pending_exception(exception);
|
| return Failure::Exception();
|
| @@ -710,8 +728,8 @@ void Top::ScheduleThrow(Object* exception) {
|
| }
|
|
|
|
|
| -Object* Top::PromoteScheduledException() {
|
| - Object* thrown = scheduled_exception();
|
| +Failure* Top::PromoteScheduledException() {
|
| + MaybeObject* thrown = scheduled_exception();
|
| clear_scheduled_exception();
|
| // Re-throw the exception to avoid getting repeated error reporting.
|
| return ReThrow(thrown);
|
| @@ -794,19 +812,23 @@ bool Top::ShouldReturnException(bool* is_caught_externally,
|
| }
|
|
|
|
|
| -void Top::DoThrow(Object* exception,
|
| +void Top::DoThrow(MaybeObject* exception,
|
| MessageLocation* location,
|
| const char* message) {
|
| ASSERT(!has_pending_exception());
|
|
|
| HandleScope scope;
|
| - Handle<Object> exception_handle(exception);
|
| + Object* exception_object = Smi::FromInt(0);
|
| + bool is_object = exception->ToObject(&exception_object);
|
| + Handle<Object> exception_handle(exception_object);
|
|
|
| // Determine reporting and whether the exception is caught externally.
|
| bool is_caught_externally = false;
|
| bool is_out_of_memory = exception == Failure::OutOfMemoryException();
|
| bool is_termination_exception = exception == Heap::termination_exception();
|
| bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory;
|
| + // Only real objects can be caught by JS.
|
| + ASSERT(!catchable_by_javascript || is_object);
|
| bool should_return_exception =
|
| ShouldReturnException(&is_caught_externally, catchable_by_javascript);
|
| bool report_exception = catchable_by_javascript && should_return_exception;
|
| @@ -842,6 +864,7 @@ void Top::DoThrow(Object* exception,
|
| stack_trace_for_uncaught_exceptions_frame_limit,
|
| stack_trace_for_uncaught_exceptions_options);
|
| }
|
| + ASSERT(is_object); // Can't use the handle unless there's a real object.
|
| message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
|
| location, HandleVector<Object>(&exception_handle, 1), stack_trace,
|
| stack_trace_object);
|
| @@ -867,7 +890,13 @@ void Top::DoThrow(Object* exception,
|
| // NOTE: Notifying the debugger or generating the message
|
| // may have caused new exceptions. For now, we just ignore
|
| // that and set the pending exception to the original one.
|
| - set_pending_exception(*exception_handle);
|
| + if (is_object) {
|
| + set_pending_exception(*exception_handle);
|
| + } else {
|
| + // Failures are not on the heap so they neither need nor work with handles.
|
| + ASSERT(exception_handle->IsFailure());
|
| + set_pending_exception(exception);
|
| + }
|
| }
|
|
|
|
|
| @@ -889,7 +918,10 @@ void Top::ReportPendingMessages() {
|
| thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
|
| }
|
| } else {
|
| - Handle<Object> exception(pending_exception());
|
| + // At this point all non-object (failure) exceptions have
|
| + // been dealt with so this shouldn't fail.
|
| + Object* pending_exception_object = pending_exception()->ToObjectUnchecked();
|
| + Handle<Object> exception(pending_exception_object);
|
| thread_local_.external_caught_exception_ = false;
|
| if (external_caught) {
|
| thread_local_.TryCatchHandler()->can_continue_ = true;
|
| @@ -983,13 +1015,13 @@ void Top::SetCaptureStackTraceForUncaughtExceptions(
|
|
|
| bool Top::is_out_of_memory() {
|
| if (has_pending_exception()) {
|
| - Object* e = pending_exception();
|
| + MaybeObject* e = pending_exception();
|
| if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
|
| return true;
|
| }
|
| }
|
| if (has_scheduled_exception()) {
|
| - Object* e = scheduled_exception();
|
| + MaybeObject* e = scheduled_exception();
|
| if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
|
| return true;
|
| }
|
| @@ -1035,6 +1067,15 @@ char* Top::ArchiveThread(char* to) {
|
|
|
| char* Top::RestoreThread(char* from) {
|
| memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_));
|
| + // This might be just paranoia, but it seems to be needed in case a
|
| + // thread_local_ is restored on a separate OS thread.
|
| +#ifdef USE_SIMULATOR
|
| +#ifdef V8_TARGET_ARCH_ARM
|
| + thread_local_.simulator_ = assembler::arm::Simulator::current();
|
| +#elif V8_TARGET_ARCH_MIPS
|
| + thread_local_.simulator_ = assembler::mips::Simulator::current();
|
| +#endif
|
| +#endif
|
| return from + sizeof(thread_local_);
|
| }
|
|
|
|
|