Index: src/top.cc |
=================================================================== |
--- src/top.cc (revision 3208) |
+++ src/top.cc (working copy) |
@@ -31,8 +31,9 @@ |
#include "bootstrapper.h" |
#include "debug.h" |
#include "execution.h" |
-#include "string-stream.h" |
#include "platform.h" |
+#include "simulator.h" |
+#include "string-stream.h" |
namespace v8 { |
namespace internal { |
@@ -50,6 +51,30 @@ |
NULL |
}; |
+ |
+v8::TryCatch* ThreadLocalTop::TryCatchHandler() { |
+ return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address()); |
+} |
+ |
+ |
+void ThreadLocalTop::Initialize() { |
+ c_entry_fp_ = 0; |
+ handler_ = 0; |
+#ifdef ENABLE_LOGGING_AND_PROFILING |
+ js_entry_sp_ = 0; |
+#endif |
+ stack_is_cooked_ = false; |
+ try_catch_handler_address_ = NULL; |
+ context_ = NULL; |
+ int id = ThreadManager::CurrentId(); |
+ thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id; |
+ external_caught_exception_ = false; |
+ failed_access_check_callback_ = NULL; |
+ save_context_ = NULL; |
+ catcher_ = NULL; |
+} |
+ |
+ |
Address Top::get_address_from_id(Top::AddressId id) { |
return top_addresses[id]; |
} |
@@ -70,9 +95,9 @@ |
v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); |
v->VisitPointer(&(thread->scheduled_exception_)); |
- for (v8::TryCatch* block = thread->try_catch_handler_; |
+ for (v8::TryCatch* block = thread->TryCatchHandler(); |
block != NULL; |
- block = block->next_) { |
+ block = TRY_CATCH_FROM_ADDRESS(block->next_)) { |
v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); |
v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); |
} |
@@ -91,23 +116,10 @@ |
void Top::InitializeThreadLocal() { |
- thread_local_.c_entry_fp_ = 0; |
- thread_local_.handler_ = 0; |
-#ifdef ENABLE_LOGGING_AND_PROFILING |
- thread_local_.js_entry_sp_ = 0; |
-#endif |
- thread_local_.stack_is_cooked_ = false; |
- thread_local_.try_catch_handler_ = NULL; |
- thread_local_.context_ = NULL; |
- int id = ThreadManager::CurrentId(); |
- thread_local_.thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id; |
- thread_local_.external_caught_exception_ = false; |
- thread_local_.failed_access_check_callback_ = NULL; |
+ thread_local_.Initialize(); |
clear_pending_exception(); |
clear_pending_message(); |
clear_scheduled_exception(); |
- thread_local_.save_context_ = NULL; |
- thread_local_.catcher_ = NULL; |
} |
@@ -254,46 +266,24 @@ |
} |
-// There are cases where the C stack is separated from JS stack (ARM simulator). |
-// To figure out the order of top-most JS try-catch handler and the top-most C |
-// try-catch handler, the C try-catch handler keeps a reference to the top-most |
-// JS try_catch handler when it was created. |
-// |
-// Here is a picture to explain the idea: |
-// Top::thread_local_.handler_ Top::thread_local_.try_catch_handler_ |
-// |
-// | | |
-// v v |
-// |
-// | JS handler | | C try_catch handler | |
-// | next |--+ +-------- | js_handler_ | |
-// | | | next_ |--+ |
-// | | | |
-// | JS handler |--+ <---------+ | |
-// | next | |
-// |
-// If the top-most JS try-catch handler is not equal to |
-// Top::thread_local_.try_catch_handler_.js_handler_, it means the JS handler |
-// is on the top. Otherwise, it means the C try-catch handler is on the top. |
-// |
void Top::RegisterTryCatchHandler(v8::TryCatch* that) { |
- StackHandler* handler = |
- reinterpret_cast<StackHandler*>(thread_local_.handler_); |
- |
- // Find the top-most try-catch handler. |
- while (handler != NULL && !handler->is_try_catch()) { |
- handler = handler->next(); |
- } |
- |
- that->js_handler_ = handler; // casted to void* |
- thread_local_.try_catch_handler_ = that; |
+ // The ARM simulator has a separate JS stack. We therefore register |
+ // the C++ try catch handler with the simulator and get back an |
+ // address that can be used for comparisons with addresses into the |
+ // JS stack. When running without the simulator, the address |
+ // returned will be the address of the C++ try catch handler itself. |
+ Address address = reinterpret_cast<Address>( |
+ SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that))); |
+ thread_local_.set_try_catch_handler_address(address); |
} |
void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { |
- ASSERT(thread_local_.try_catch_handler_ == that); |
- thread_local_.try_catch_handler_ = that->next_; |
+ ASSERT(thread_local_.TryCatchHandler() == that); |
+ thread_local_.set_try_catch_handler_address( |
+ reinterpret_cast<Address>(that->next_)); |
thread_local_.catcher_ = NULL; |
+ SimulatorStack::UnregisterCTryCatch(); |
} |
@@ -725,20 +715,18 @@ |
// Get the address of the external handler so we can compare the address to |
// determine which one is closer to the top of the stack. |
- v8::TryCatch* try_catch = thread_local_.try_catch_handler_; |
+ Address external_handler_address = thread_local_.try_catch_handler_address(); |
// The exception has been externally caught if and only if there is |
// an external handler which is on top of the top-most try-catch |
// handler. |
- // |
- // See comments in RegisterTryCatchHandler for details. |
- *is_caught_externally = try_catch != NULL && |
- (handler == NULL || handler == try_catch->js_handler_ || |
+ *is_caught_externally = external_handler_address != NULL && |
+ (handler == NULL || handler->address() > external_handler_address || |
!catchable_by_javascript); |
if (*is_caught_externally) { |
// Only report the exception if the external handler is verbose. |
- return thread_local_.try_catch_handler_->is_verbose_; |
+ return thread_local_.TryCatchHandler()->is_verbose_; |
} else { |
// Report the exception if it isn't caught by JavaScript code. |
return handler == NULL; |
@@ -775,7 +763,7 @@ |
MessageLocation potential_computed_location; |
bool try_catch_needs_message = |
is_caught_externally && |
- thread_local_.try_catch_handler_->capture_message_; |
+ thread_local_.TryCatchHandler()->capture_message_; |
if (report_exception || try_catch_needs_message) { |
if (location == NULL) { |
// If no location was specified we use a computed one instead |
@@ -806,7 +794,7 @@ |
} |
if (is_caught_externally) { |
- thread_local_.catcher_ = thread_local_.try_catch_handler_; |
+ thread_local_.catcher_ = thread_local_.TryCatchHandler(); |
} |
// NOTE: Notifying the debugger or generating the message |
@@ -830,15 +818,15 @@ |
} else if (thread_local_.pending_exception_ == |
Heap::termination_exception()) { |
if (external_caught) { |
- thread_local_.try_catch_handler_->can_continue_ = false; |
- thread_local_.try_catch_handler_->exception_ = Heap::null_value(); |
+ thread_local_.TryCatchHandler()->can_continue_ = false; |
+ thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); |
} |
} else { |
Handle<Object> exception(pending_exception()); |
thread_local_.external_caught_exception_ = false; |
if (external_caught) { |
- thread_local_.try_catch_handler_->can_continue_ = true; |
- thread_local_.try_catch_handler_->exception_ = |
+ thread_local_.TryCatchHandler()->can_continue_ = true; |
+ thread_local_.TryCatchHandler()->exception_ = |
thread_local_.pending_exception_; |
if (!thread_local_.pending_message_obj_->IsTheHole()) { |
try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
@@ -892,9 +880,9 @@ |
// If the exception is externally caught, clear it if there are no |
// JavaScript frames on the way to the C++ frame that has the |
// external handler. |
- ASSERT(thread_local_.try_catch_handler_ != NULL); |
+ ASSERT(thread_local_.try_catch_handler_address() != NULL); |
Address external_handler_address = |
- reinterpret_cast<Address>(thread_local_.try_catch_handler_); |
+ thread_local_.try_catch_handler_address(); |
JavaScriptFrameIterator it; |
if (it.done() || (it.frame()->sp() > external_handler_address)) { |
clear_exception = true; |