| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 | 36 |
| 37 | 37 |
| 38 #define RETURN_IF_SCHEDULED_EXCEPTION() \ | 38 #define RETURN_IF_SCHEDULED_EXCEPTION() \ |
| 39 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException() | 39 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException() |
| 40 | 40 |
| 41 // Top has static variables used for JavaScript execution. | 41 // Top has static variables used for JavaScript execution. |
| 42 | 42 |
| 43 class SaveContext; // Forward declaration. | 43 class SaveContext; // Forward declaration. |
| 44 class ThreadVisitor; // Defined in v8threads.h | 44 class ThreadVisitor; // Defined in v8threads.h |
| 45 | 45 |
| 46 class ThreadLocalTop BASE_EMBEDDED { | |
| 47 public: | |
| 48 // Initialize the thread data. | |
| 49 void Initialize(); | |
| 50 | |
| 51 // Get the top C++ try catch handler or NULL if none are registered. | |
| 52 // | |
| 53 // This method is not guarenteed to return an address that can be | |
| 54 // used for comparison with addresses into the JS stack. If such an | |
| 55 // address is needed, use try_catch_handler_address. | |
| 56 v8::TryCatch* TryCatchHandler(); | |
| 57 | |
| 58 // Get the address of the top C++ try catch handler or NULL if | |
| 59 // none are registered. | |
| 60 // | |
| 61 // This method always returns an address that can be compared to | |
| 62 // pointers into the JavaScript stack. When running on actual | |
| 63 // hardware, try_catch_handler_address and TryCatchHandler return | |
| 64 // the same pointer. When running on a simulator with a separate JS | |
| 65 // stack, try_catch_handler_address returns a JS stack address that | |
| 66 // corresponds to the place on the JS stack where the C++ handler | |
| 67 // would have been if the stack were not separate. | |
| 68 inline Address try_catch_handler_address() { | |
| 69 return try_catch_handler_address_; | |
| 70 } | |
| 71 | |
| 72 // Set the address of the top C++ try catch handler. | |
| 73 inline void set_try_catch_handler_address(Address address) { | |
| 74 try_catch_handler_address_ = address; | |
| 75 } | |
| 76 | |
| 77 void Free() { | |
| 78 ASSERT(!has_pending_message_); | |
| 79 ASSERT(!external_caught_exception_); | |
| 80 ASSERT(try_catch_handler_address_ == NULL); | |
| 81 } | |
| 82 | |
| 83 // The context where the current execution method is created and for variable | |
| 84 // lookups. | |
| 85 Context* context_; | |
| 86 int thread_id_; | |
| 87 Object* pending_exception_; | |
| 88 bool has_pending_message_; | |
| 89 const char* pending_message_; | |
| 90 Object* pending_message_obj_; | |
| 91 Script* pending_message_script_; | |
| 92 int pending_message_start_pos_; | |
| 93 int pending_message_end_pos_; | |
| 94 // Use a separate value for scheduled exceptions to preserve the | |
| 95 // invariants that hold about pending_exception. We may want to | |
| 96 // unify them later. | |
| 97 Object* scheduled_exception_; | |
| 98 bool external_caught_exception_; | |
| 99 SaveContext* save_context_; | |
| 100 v8::TryCatch* catcher_; | |
| 101 | |
| 102 // Stack. | |
| 103 Address c_entry_fp_; // the frame pointer of the top c entry frame | |
| 104 Address handler_; // try-blocks are chained through the stack | |
| 105 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 106 Address js_entry_sp_; // the stack pointer of the bottom js entry frame | |
| 107 #endif | |
| 108 bool stack_is_cooked_; | |
| 109 inline bool stack_is_cooked() { return stack_is_cooked_; } | |
| 110 inline void set_stack_is_cooked(bool value) { stack_is_cooked_ = value; } | |
| 111 | |
| 112 // Generated code scratch locations. | |
| 113 int32_t formal_count_; | |
| 114 | |
| 115 // Call back function to report unsafe JS accesses. | |
| 116 v8::FailedAccessCheckCallback failed_access_check_callback_; | |
| 117 | |
| 118 private: | |
| 119 Address try_catch_handler_address_; | |
| 120 }; | |
| 121 | |
| 122 #define TOP_ADDRESS_LIST(C) \ | 46 #define TOP_ADDRESS_LIST(C) \ |
| 123 C(handler_address) \ | 47 C(handler_address) \ |
| 124 C(c_entry_fp_address) \ | 48 C(c_entry_fp_address) \ |
| 125 C(context_address) \ | 49 C(context_address) \ |
| 126 C(pending_exception_address) \ | 50 C(pending_exception_address) \ |
| 127 C(external_caught_exception_address) | 51 C(external_caught_exception_address) |
| 128 | 52 |
| 129 #ifdef ENABLE_LOGGING_AND_PROFILING | 53 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 130 #define TOP_ADDRESS_LIST_PROF(C) \ | 54 #define TOP_ADDRESS_LIST_PROF(C) \ |
| 131 C(js_entry_sp_address) | 55 C(js_entry_sp_address) |
| 132 #else | 56 #else |
| 133 #define TOP_ADDRESS_LIST_PROF(C) | 57 #define TOP_ADDRESS_LIST_PROF(C) |
| 134 #endif | 58 #endif |
| 135 | 59 |
| 136 | 60 |
| 137 class Top { | 61 class Top { |
| 138 public: | 62 public: |
| 139 enum AddressId { | 63 enum AddressId { |
| 140 #define C(name) k_##name, | 64 #define C(name) k_##name, |
| 141 TOP_ADDRESS_LIST(C) | 65 TOP_ADDRESS_LIST(C) |
| 142 TOP_ADDRESS_LIST_PROF(C) | 66 TOP_ADDRESS_LIST_PROF(C) |
| 143 #undef C | 67 #undef C |
| 144 k_top_address_count | 68 k_top_address_count |
| 145 }; | 69 }; |
| 146 | 70 |
| 147 static Address get_address_from_id(AddressId id); | 71 static Address get_address_from_id(AddressId id); |
| 148 | 72 |
| 149 // Access to top context (where the current function object was created). | 73 // Access to top context (where the current function object was created). |
| 150 static Context* context() { return thread_local_.context_; } | 74 static Context* context() { return thread_local()->context_; } |
| 151 static void set_context(Context* context) { | 75 static void set_context(Context* context) { |
| 152 thread_local_.context_ = context; | 76 thread_local()->context_ = context; |
| 153 } | 77 } |
| 154 static Context** context_address() { return &thread_local_.context_; } | 78 static Context** context_address() { return &thread_local()->context_; } |
| 155 | 79 |
| 156 static SaveContext* save_context() {return thread_local_.save_context_; } | 80 static SaveContext* save_context() {return thread_local()->save_context_; } |
| 157 static void set_save_context(SaveContext* save) { | 81 static void set_save_context(SaveContext* save) { |
| 158 thread_local_.save_context_ = save; | 82 thread_local()->save_context_ = save; |
| 159 } | 83 } |
| 160 | 84 |
| 161 // Access to current thread id. | 85 // Access to current thread id. |
| 162 static int thread_id() { return thread_local_.thread_id_; } | 86 static int thread_id() { return thread_local()->thread_id_; } |
| 163 static void set_thread_id(int id) { thread_local_.thread_id_ = id; } | 87 static void set_thread_id(int id) { thread_local()->thread_id_ = id; } |
| 164 | 88 |
| 165 // Interface to pending exception. | 89 // Interface to pending exception. |
| 166 static Object* pending_exception() { | 90 static Object* pending_exception() { |
| 167 ASSERT(has_pending_exception()); | 91 ASSERT(has_pending_exception()); |
| 168 return thread_local_.pending_exception_; | 92 return thread_local()->pending_exception_; |
| 169 } | 93 } |
| 170 static bool external_caught_exception() { | 94 static bool external_caught_exception() { |
| 171 return thread_local_.external_caught_exception_; | 95 return thread_local()->external_caught_exception_; |
| 172 } | 96 } |
| 173 static void set_pending_exception(Object* exception) { | 97 static void set_pending_exception(Object* exception) { |
| 174 thread_local_.pending_exception_ = exception; | 98 thread_local()->pending_exception_ = exception; |
| 175 } | 99 } |
| 176 static void clear_pending_exception() { | 100 static void clear_pending_exception() { |
| 177 thread_local_.pending_exception_ = HEAP->the_hole_value(); | 101 thread_local()->pending_exception_ = HEAP->the_hole_value(); |
| 178 } | 102 } |
| 179 | 103 |
| 180 static Object** pending_exception_address() { | 104 static Object** pending_exception_address() { |
| 181 return &thread_local_.pending_exception_; | 105 return &thread_local()->pending_exception_; |
| 182 } | 106 } |
| 183 static bool has_pending_exception() { | 107 static bool has_pending_exception() { |
| 184 return !thread_local_.pending_exception_->IsTheHole(); | 108 return !thread_local()->pending_exception_->IsTheHole(); |
| 185 } | 109 } |
| 186 static void clear_pending_message() { | 110 static void clear_pending_message() { |
| 187 thread_local_.has_pending_message_ = false; | 111 thread_local()->has_pending_message_ = false; |
| 188 thread_local_.pending_message_ = NULL; | 112 thread_local()->pending_message_ = NULL; |
| 189 thread_local_.pending_message_obj_ = HEAP->the_hole_value(); | 113 thread_local()->pending_message_obj_ = HEAP->the_hole_value(); |
| 190 thread_local_.pending_message_script_ = NULL; | 114 thread_local()->pending_message_script_ = NULL; |
| 191 } | 115 } |
| 192 static v8::TryCatch* try_catch_handler() { | 116 static v8::TryCatch* try_catch_handler() { |
| 193 return thread_local_.TryCatchHandler(); | 117 return thread_local()->TryCatchHandler(); |
| 194 } | 118 } |
| 195 static Address try_catch_handler_address() { | 119 static Address try_catch_handler_address() { |
| 196 return thread_local_.try_catch_handler_address(); | 120 return thread_local()->try_catch_handler_address(); |
| 197 } | 121 } |
| 198 // This method is called by the api after operations that may throw | 122 // This method is called by the api after operations that may throw |
| 199 // exceptions. If an exception was thrown and not handled by an external | 123 // exceptions. If an exception was thrown and not handled by an external |
| 200 // handler the exception is scheduled to be rethrown when we return to running | 124 // handler the exception is scheduled to be rethrown when we return to running |
| 201 // JavaScript code. If an exception is scheduled true is returned. | 125 // JavaScript code. If an exception is scheduled true is returned. |
| 202 static bool OptionalRescheduleException(bool is_bottom_call); | 126 static bool OptionalRescheduleException(bool is_bottom_call); |
| 203 | 127 |
| 204 | 128 |
| 205 static bool* external_caught_exception_address() { | 129 static bool* external_caught_exception_address() { |
| 206 return &thread_local_.external_caught_exception_; | 130 return &thread_local()->external_caught_exception_; |
| 207 } | 131 } |
| 208 | 132 |
| 209 static Object** scheduled_exception_address() { | 133 static Object** scheduled_exception_address() { |
| 210 return &thread_local_.scheduled_exception_; | 134 return &thread_local()->scheduled_exception_; |
| 211 } | 135 } |
| 212 | 136 |
| 213 static Object* scheduled_exception() { | 137 static Object* scheduled_exception() { |
| 214 ASSERT(has_scheduled_exception()); | 138 ASSERT(has_scheduled_exception()); |
| 215 return thread_local_.scheduled_exception_; | 139 return thread_local()->scheduled_exception_; |
| 216 } | 140 } |
| 217 static bool has_scheduled_exception() { | 141 static bool has_scheduled_exception() { |
| 218 return !thread_local_.scheduled_exception_->IsTheHole(); | 142 return !thread_local()->scheduled_exception_->IsTheHole(); |
| 219 } | 143 } |
| 220 static void clear_scheduled_exception() { | 144 static void clear_scheduled_exception() { |
| 221 thread_local_.scheduled_exception_ = HEAP->the_hole_value(); | 145 thread_local()->scheduled_exception_ = HEAP->the_hole_value(); |
| 222 } | 146 } |
| 223 | 147 |
| 224 static void setup_external_caught() { | 148 static void setup_external_caught() { |
| 225 thread_local_.external_caught_exception_ = | 149 thread_local()->external_caught_exception_ = |
| 226 has_pending_exception() && | 150 has_pending_exception() && |
| 227 (thread_local_.catcher_ != NULL) && | 151 (thread_local()->catcher_ != NULL) && |
| 228 (try_catch_handler() == thread_local_.catcher_); | 152 (try_catch_handler() == thread_local()->catcher_); |
| 229 } | 153 } |
| 230 | 154 |
| 231 // Tells whether the current context has experienced an out of memory | 155 // Tells whether the current context has experienced an out of memory |
| 232 // exception. | 156 // exception. |
| 233 static bool is_out_of_memory(); | 157 static bool is_out_of_memory(); |
| 234 | 158 |
| 235 // JS execution stack (see frames.h). | 159 // JS execution stack (see frames.h). |
| 236 static Address c_entry_fp(ThreadLocalTop* thread) { | 160 static Address c_entry_fp(ThreadLocalTop* thread) { |
| 237 return thread->c_entry_fp_; | 161 return thread->c_entry_fp_; |
| 238 } | 162 } |
| 239 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } | 163 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } |
| 240 | 164 |
| 241 static inline Address* c_entry_fp_address() { | 165 static inline Address* c_entry_fp_address() { |
| 242 return &thread_local_.c_entry_fp_; | 166 return &thread_local()->c_entry_fp_; |
| 243 } | 167 } |
| 244 static inline Address* handler_address() { return &thread_local_.handler_; } | 168 static inline Address* handler_address() { return &thread_local()->handler_; } |
| 245 | 169 |
| 246 #ifdef ENABLE_LOGGING_AND_PROFILING | 170 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 247 // Bottom JS entry (see StackTracer::Trace in log.cc). | 171 // Bottom JS entry (see StackTracer::Trace in log.cc). |
| 248 static Address js_entry_sp(ThreadLocalTop* thread) { | 172 static Address js_entry_sp(ThreadLocalTop* thread) { |
| 249 return thread->js_entry_sp_; | 173 return thread->js_entry_sp_; |
| 250 } | 174 } |
| 251 static inline Address* js_entry_sp_address() { | 175 static inline Address* js_entry_sp_address() { |
| 252 return &thread_local_.js_entry_sp_; | 176 return &thread_local()->js_entry_sp_; |
| 253 } | 177 } |
| 254 #endif | 178 #endif |
| 255 | 179 |
| 256 // Generated code scratch locations. | 180 // Generated code scratch locations. |
| 257 static void* formal_count_address() { return &thread_local_.formal_count_; } | 181 static void* formal_count_address() { return &thread_local()->formal_count_; } |
| 258 | 182 |
| 259 static void MarkCompactPrologue(bool is_compacting); | 183 static void MarkCompactPrologue(bool is_compacting); |
| 260 static void MarkCompactEpilogue(bool is_compacting); | 184 static void MarkCompactEpilogue(bool is_compacting); |
| 261 static void MarkCompactPrologue(bool is_compacting, | 185 static void MarkCompactPrologue(bool is_compacting, |
| 262 char* archived_thread_data); | 186 char* archived_thread_data); |
| 263 static void MarkCompactEpilogue(bool is_compacting, | 187 static void MarkCompactEpilogue(bool is_compacting, |
| 264 char* archived_thread_data); | 188 char* archived_thread_data); |
| 265 static void PrintCurrentStackTrace(FILE* out); | 189 static void PrintCurrentStackTrace(FILE* out); |
| 266 static void PrintStackTrace(FILE* out, char* thread_data); | 190 static void PrintStackTrace(FILE* out, char* thread_data); |
| 267 static void PrintStack(StringStream* accumulator); | 191 static void PrintStack(StringStream* accumulator); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 263 } |
| 340 | 264 |
| 341 // Returns the current global context. | 265 // Returns the current global context. |
| 342 static Handle<Context> global_context(); | 266 static Handle<Context> global_context(); |
| 343 | 267 |
| 344 // Returns the global context of the calling JavaScript code. That | 268 // Returns the global context of the calling JavaScript code. That |
| 345 // is, the global context of the top-most JavaScript frame. | 269 // is, the global context of the top-most JavaScript frame. |
| 346 static Handle<Context> GetCallingGlobalContext(); | 270 static Handle<Context> GetCallingGlobalContext(); |
| 347 | 271 |
| 348 static Handle<JSBuiltinsObject> builtins() { | 272 static Handle<JSBuiltinsObject> builtins() { |
| 349 return Handle<JSBuiltinsObject>(thread_local_.context_->builtins()); | 273 return Handle<JSBuiltinsObject>(thread_local()->context_->builtins()); |
| 350 } | 274 } |
| 351 | 275 |
| 352 static void RegisterTryCatchHandler(v8::TryCatch* that); | 276 static void RegisterTryCatchHandler(v8::TryCatch* that); |
| 353 static void UnregisterTryCatchHandler(v8::TryCatch* that); | 277 static void UnregisterTryCatchHandler(v8::TryCatch* that); |
| 354 | 278 |
| 355 #define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \ | 279 #define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \ |
| 356 static Handle<type> name() { \ | 280 static Handle<type> name() { \ |
| 357 return Handle<type>(context()->global_context()->name()); \ | 281 return Handle<type>(context()->global_context()->name()); \ |
| 358 } | 282 } |
| 359 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR) | 283 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR) |
| 360 #undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR | 284 #undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR |
| 361 | 285 |
| 362 static inline ThreadLocalTop* GetCurrentThread() { return &thread_local_; } | |
| 363 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } | 286 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } |
| 364 static char* ArchiveThread(char* to); | 287 static char* ArchiveThread(char* to); |
| 365 static char* RestoreThread(char* from); | 288 static char* RestoreThread(char* from); |
| 366 static void FreeThreadResources() { thread_local_.Free(); } | 289 static void FreeThreadResources() { thread_local()->Free(); } |
| 367 | 290 |
| 368 static const char* kStackOverflowMessage; | 291 static const char* kStackOverflowMessage; |
| 369 | 292 |
| 370 private: | 293 private: |
| 371 // The context that initiated this JS execution. | 294 // The context that initiated this JS execution. |
| 372 static ThreadLocalTop thread_local_; | 295 static ThreadLocalTop* thread_local() { |
| 296 return Isolate::Current()->thread_local_top(); |
| 297 } |
| 373 static void InitializeThreadLocal(); | 298 static void InitializeThreadLocal(); |
| 374 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread); | 299 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread); |
| 375 static void MarkCompactPrologue(bool is_compacting, | 300 static void MarkCompactPrologue(bool is_compacting, |
| 376 ThreadLocalTop* archived_thread_data); | 301 ThreadLocalTop* archived_thread_data); |
| 377 static void MarkCompactEpilogue(bool is_compacting, | 302 static void MarkCompactEpilogue(bool is_compacting, |
| 378 ThreadLocalTop* archived_thread_data); | 303 ThreadLocalTop* archived_thread_data); |
| 379 | 304 |
| 380 friend class SaveContext; | 305 friend class SaveContext; |
| 381 friend class AssertNoContextChange; | 306 friend class AssertNoContextChange; |
| 382 friend class ExecutionAccess; | 307 friend class ExecutionAccess; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 | 374 |
| 450 class ExecutionAccess BASE_EMBEDDED { | 375 class ExecutionAccess BASE_EMBEDDED { |
| 451 public: | 376 public: |
| 452 ExecutionAccess(); | 377 ExecutionAccess(); |
| 453 ~ExecutionAccess(); | 378 ~ExecutionAccess(); |
| 454 }; | 379 }; |
| 455 | 380 |
| 456 } } // namespace v8::internal | 381 } } // namespace v8::internal |
| 457 | 382 |
| 458 #endif // V8_TOP_H_ | 383 #endif // V8_TOP_H_ |
| OLD | NEW |