| 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 #define RETURN_IF_SCHEDULED_EXCEPTION() \ | 37 #define RETURN_IF_SCHEDULED_EXCEPTION() \ |
| 38 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException() | 38 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException() |
| 39 | 39 |
| 40 // Top has static variables used for JavaScript execution. | 40 // Top has static variables used for JavaScript execution. |
| 41 | 41 |
| 42 class SaveContext; // Forward declaration. | 42 class SaveContext; // Forward declaration. |
| 43 | 43 |
| 44 class ThreadLocalTop BASE_EMBEDDED { | 44 class ThreadLocalTop BASE_EMBEDDED { |
| 45 public: | 45 public: |
| 46 ThreadLocalTop(); |
| 46 // Initialize the thread data. | 47 // Initialize the thread data. |
| 47 void Initialize(); | 48 void Initialize(); |
| 48 | 49 |
| 49 // Get the top C++ try catch handler or NULL if none are registered. | 50 // Get the top C++ try catch handler or NULL if none are registered. |
| 50 // | 51 // |
| 51 // This method is not guarenteed to return an address that can be | 52 // This method is not guarenteed to return an address that can be |
| 52 // used for comparison with addresses into the JS stack. If such an | 53 // used for comparison with addresses into the JS stack. If such an |
| 53 // address is needed, use try_catch_handler_address. | 54 // address is needed, use try_catch_handler_address. |
| 54 v8::TryCatch* TryCatchHandler(); | 55 v8::TryCatch* TryCatchHandler(); |
| 55 | 56 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 inline void set_stack_is_cooked(bool value) { stack_is_cooked_ = value; } | 109 inline void set_stack_is_cooked(bool value) { stack_is_cooked_ = value; } |
| 109 | 110 |
| 110 // Generated code scratch locations. | 111 // Generated code scratch locations. |
| 111 int32_t formal_count_; | 112 int32_t formal_count_; |
| 112 | 113 |
| 113 // Call back function to report unsafe JS accesses. | 114 // Call back function to report unsafe JS accesses. |
| 114 v8::FailedAccessCheckCallback failed_access_check_callback_; | 115 v8::FailedAccessCheckCallback failed_access_check_callback_; |
| 115 | 116 |
| 116 private: | 117 private: |
| 117 Address try_catch_handler_address_; | 118 Address try_catch_handler_address_; |
| 119 DISALLOW_COPY_AND_ASSIGN(ThreadLocalTop); |
| 118 }; | 120 }; |
| 119 | 121 |
| 120 #define TOP_ADDRESS_LIST(C) \ | 122 #define TOP_ADDRESS_LIST(C) \ |
| 121 C(handler_address) \ | 123 C(handler_address) \ |
| 122 C(c_entry_fp_address) \ | 124 C(c_entry_fp_address) \ |
| 123 C(context_address) \ | 125 C(context_address) \ |
| 124 C(pending_exception_address) \ | 126 C(pending_exception_address) \ |
| 125 C(external_caught_exception_address) | 127 C(external_caught_exception_address) |
| 126 | 128 |
| 127 #ifdef ENABLE_LOGGING_AND_PROFILING | 129 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 128 #define TOP_ADDRESS_LIST_PROF(C) \ | 130 #define TOP_ADDRESS_LIST_PROF(C) \ |
| 129 C(js_entry_sp_address) | 131 C(js_entry_sp_address) |
| 130 #else | 132 #else |
| 131 #define TOP_ADDRESS_LIST_PROF(C) | 133 #define TOP_ADDRESS_LIST_PROF(C) |
| 132 #endif | 134 #endif |
| 133 | 135 |
| 136 class TopPrivateData; |
| 137 |
| 138 class TopData { |
| 139 // The context that initiated this JS execution. |
| 140 ThreadLocalTop thread_local_; |
| 141 |
| 142 // Debug. |
| 143 // Mutex for serializing access to break control structures. |
| 144 Mutex* break_access_; |
| 145 |
| 146 TopPrivateData* top_private_data_; |
| 147 TopData(); |
| 148 |
| 149 friend class Top; |
| 150 friend class TopPrivateData; |
| 151 friend class ExecutionAccess; |
| 152 friend class V8Context; |
| 153 DISALLOW_COPY_AND_ASSIGN(TopData); |
| 154 }; |
| 134 | 155 |
| 135 class Top { | 156 class Top { |
| 136 public: | 157 public: |
| 137 enum AddressId { | 158 enum AddressId { |
| 138 #define C(name) k_##name, | 159 #define C(name) k_##name, |
| 139 TOP_ADDRESS_LIST(C) | 160 TOP_ADDRESS_LIST(C) |
| 140 TOP_ADDRESS_LIST_PROF(C) | 161 TOP_ADDRESS_LIST_PROF(C) |
| 141 #undef C | 162 #undef C |
| 142 k_top_address_count | 163 k_top_address_count |
| 143 }; | 164 }; |
| 144 | 165 |
| 145 static Address get_address_from_id(AddressId id); | 166 static Address get_address_from_id(AddressId id); |
| 146 | 167 |
| 147 // Access to top context (where the current function object was created). | 168 // Access to top context (where the current function object was created). |
| 148 static Context* context() { return thread_local_.context_; } | 169 static Context* context() { |
| 170 return v8_context()->top_data_.thread_local_.context_; |
| 171 } |
| 149 static void set_context(Context* context) { | 172 static void set_context(Context* context) { |
| 150 thread_local_.context_ = context; | 173 v8_context()->top_data_.thread_local_.context_ = context; |
| 151 } | 174 } |
| 152 static Context** context_address() { return &thread_local_.context_; } | 175 static Context** context_address() { |
| 176 return &v8_context()->top_data_.thread_local_.context_; |
| 177 } |
| 153 | 178 |
| 154 static SaveContext* save_context() {return thread_local_.save_context_; } | 179 static SaveContext* save_context() { |
| 180 return v8_context()->top_data_.thread_local_.save_context_; |
| 181 } |
| 155 static void set_save_context(SaveContext* save) { | 182 static void set_save_context(SaveContext* save) { |
| 156 thread_local_.save_context_ = save; | 183 v8_context()->top_data_.thread_local_.save_context_ = save; |
| 157 } | 184 } |
| 158 | 185 |
| 159 // Access to current thread id. | 186 // Access to current thread id. |
| 160 static int thread_id() { return thread_local_.thread_id_; } | 187 static int thread_id() { |
| 161 static void set_thread_id(int id) { thread_local_.thread_id_ = id; } | 188 return v8_context()->top_data_.thread_local_.thread_id_; |
| 189 } |
| 190 static void set_thread_id(int id) { |
| 191 v8_context()->top_data_.thread_local_.thread_id_ = id; |
| 192 } |
| 162 | 193 |
| 163 // Interface to pending exception. | 194 // Interface to pending exception. |
| 164 static Object* pending_exception() { | 195 static Object* pending_exception() { |
| 165 ASSERT(has_pending_exception()); | 196 ASSERT(has_pending_exception()); |
| 166 return thread_local_.pending_exception_; | 197 return v8_context()->top_data_.thread_local_.pending_exception_; |
| 167 } | 198 } |
| 168 static bool external_caught_exception() { | 199 static bool external_caught_exception() { |
| 169 return thread_local_.external_caught_exception_; | 200 return v8_context()->top_data_.thread_local_.external_caught_exception_; |
| 170 } | 201 } |
| 171 static void set_pending_exception(Object* exception) { | 202 static void set_pending_exception(Object* exception) { |
| 172 thread_local_.pending_exception_ = exception; | 203 v8_context()->top_data_.thread_local_.pending_exception_ = exception; |
| 173 } | 204 } |
| 174 static void clear_pending_exception() { | 205 static void clear_pending_exception() { |
| 175 thread_local_.pending_exception_ = Heap::the_hole_value(); | 206 v8_context()->top_data_.thread_local_.pending_exception_ = |
| 207 Heap::the_hole_value(); |
| 176 } | 208 } |
| 177 | 209 |
| 178 static Object** pending_exception_address() { | 210 static Object** pending_exception_address() { |
| 179 return &thread_local_.pending_exception_; | 211 return &v8_context()->top_data_.thread_local_.pending_exception_; |
| 180 } | 212 } |
| 181 static bool has_pending_exception() { | 213 static bool has_pending_exception() { |
| 182 return !thread_local_.pending_exception_->IsTheHole(); | 214 return !v8_context()->top_data_.thread_local_.pending_exception_-> |
| 215 IsTheHole(); |
| 183 } | 216 } |
| 184 static void clear_pending_message() { | 217 static void clear_pending_message() { |
| 185 thread_local_.has_pending_message_ = false; | 218 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 186 thread_local_.pending_message_ = NULL; | 219 thread_local.has_pending_message_ = false; |
| 187 thread_local_.pending_message_obj_ = Heap::the_hole_value(); | 220 thread_local.pending_message_ = NULL; |
| 188 thread_local_.pending_message_script_ = NULL; | 221 thread_local.pending_message_obj_ = Heap::the_hole_value(); |
| 222 thread_local.pending_message_script_ = NULL; |
| 189 } | 223 } |
| 190 static v8::TryCatch* try_catch_handler() { | 224 static v8::TryCatch* try_catch_handler() { |
| 191 return thread_local_.TryCatchHandler(); | 225 return v8_context()->top_data_.thread_local_.TryCatchHandler(); |
| 192 } | 226 } |
| 193 static Address try_catch_handler_address() { | 227 static Address try_catch_handler_address() { |
| 194 return thread_local_.try_catch_handler_address(); | 228 return v8_context()->top_data_.thread_local_.try_catch_handler_address(); |
| 195 } | 229 } |
| 196 // This method is called by the api after operations that may throw | 230 // This method is called by the api after operations that may throw |
| 197 // exceptions. If an exception was thrown and not handled by an external | 231 // exceptions. If an exception was thrown and not handled by an external |
| 198 // handler the exception is scheduled to be rethrown when we return to running | 232 // handler the exception is scheduled to be rethrown when we return to running |
| 199 // JavaScript code. If an exception is scheduled true is returned. | 233 // JavaScript code. If an exception is scheduled true is returned. |
| 200 static bool OptionalRescheduleException(bool is_bottom_call); | 234 static bool OptionalRescheduleException(bool is_bottom_call); |
| 201 | 235 |
| 202 | 236 |
| 203 static bool* external_caught_exception_address() { | 237 static bool* external_caught_exception_address() { |
| 204 return &thread_local_.external_caught_exception_; | 238 return &v8_context()->top_data_.thread_local_.external_caught_exception_; |
| 205 } | 239 } |
| 206 | 240 |
| 207 static Object** scheduled_exception_address() { | 241 static Object** scheduled_exception_address() { |
| 208 return &thread_local_.scheduled_exception_; | 242 return &v8_context()->top_data_.thread_local_.scheduled_exception_; |
| 209 } | 243 } |
| 210 | 244 |
| 211 static Object* scheduled_exception() { | 245 static Object* scheduled_exception() { |
| 212 ASSERT(has_scheduled_exception()); | 246 ASSERT(has_scheduled_exception()); |
| 213 return thread_local_.scheduled_exception_; | 247 return v8_context()->top_data_.thread_local_.scheduled_exception_; |
| 214 } | 248 } |
| 215 static bool has_scheduled_exception() { | 249 static bool has_scheduled_exception() { |
| 216 return !thread_local_.scheduled_exception_->IsTheHole(); | 250 return !v8_context()->top_data_.thread_local_.scheduled_exception_-> |
| 251 IsTheHole(); |
| 217 } | 252 } |
| 218 static void clear_scheduled_exception() { | 253 static void clear_scheduled_exception() { |
| 219 thread_local_.scheduled_exception_ = Heap::the_hole_value(); | 254 v8_context()->top_data_.thread_local_.scheduled_exception_ = |
| 255 Heap::the_hole_value(); |
| 220 } | 256 } |
| 221 | 257 |
| 222 static void setup_external_caught() { | 258 static void setup_external_caught() { |
| 223 thread_local_.external_caught_exception_ = | 259 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 260 thread_local.external_caught_exception_ = |
| 224 has_pending_exception() && | 261 has_pending_exception() && |
| 225 (thread_local_.catcher_ != NULL) && | 262 (thread_local.catcher_ != NULL) && |
| 226 (try_catch_handler() == thread_local_.catcher_); | 263 (try_catch_handler() == thread_local.catcher_); |
| 227 } | 264 } |
| 228 | 265 |
| 229 // Tells whether the current context has experienced an out of memory | 266 // Tells whether the current context has experienced an out of memory |
| 230 // exception. | 267 // exception. |
| 231 static bool is_out_of_memory(); | 268 static bool is_out_of_memory(); |
| 232 | 269 |
| 233 // JS execution stack (see frames.h). | 270 // JS execution stack (see frames.h). |
| 234 static Address c_entry_fp(ThreadLocalTop* thread) { | 271 static Address c_entry_fp(ThreadLocalTop* thread) { |
| 235 return thread->c_entry_fp_; | 272 return thread->c_entry_fp_; |
| 236 } | 273 } |
| 237 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } | 274 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } |
| 238 | 275 |
| 239 static inline Address* c_entry_fp_address() { | 276 static inline Address* c_entry_fp_address() { |
| 240 return &thread_local_.c_entry_fp_; | 277 return &v8_context()->top_data_.thread_local_.c_entry_fp_; |
| 241 } | 278 } |
| 242 static inline Address* handler_address() { return &thread_local_.handler_; } | 279 static inline Address* handler_address() { |
| 280 return &v8_context()->top_data_.thread_local_.handler_; |
| 281 } |
| 243 | 282 |
| 244 #ifdef ENABLE_LOGGING_AND_PROFILING | 283 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 245 // Bottom JS entry (see StackTracer::Trace in log.cc). | 284 // Bottom JS entry (see StackTracer::Trace in log.cc). |
| 246 static Address js_entry_sp(ThreadLocalTop* thread) { | 285 static Address js_entry_sp(ThreadLocalTop* thread) { |
| 247 return thread->js_entry_sp_; | 286 return thread->js_entry_sp_; |
| 248 } | 287 } |
| 249 static inline Address* js_entry_sp_address() { | 288 static inline Address* js_entry_sp_address() { |
| 250 return &thread_local_.js_entry_sp_; | 289 return &v8_context()->top_data_.thread_local_.js_entry_sp_; |
| 251 } | 290 } |
| 252 #endif | 291 #endif |
| 253 | 292 |
| 254 // Generated code scratch locations. | 293 // Generated code scratch locations. |
| 255 static void* formal_count_address() { return &thread_local_.formal_count_; } | 294 static void* formal_count_address() { |
| 295 return &v8_context()->top_data_.thread_local_.formal_count_; |
| 296 } |
| 256 | 297 |
| 257 static void MarkCompactPrologue(bool is_compacting); | 298 static void MarkCompactPrologue(bool is_compacting); |
| 258 static void MarkCompactEpilogue(bool is_compacting); | 299 static void MarkCompactEpilogue(bool is_compacting); |
| 259 static void MarkCompactPrologue(bool is_compacting, | 300 static void MarkCompactPrologue(bool is_compacting, |
| 260 char* archived_thread_data); | 301 char* archived_thread_data); |
| 261 static void MarkCompactEpilogue(bool is_compacting, | 302 static void MarkCompactEpilogue(bool is_compacting, |
| 262 char* archived_thread_data); | 303 char* archived_thread_data); |
| 263 static void PrintCurrentStackTrace(FILE* out); | 304 static void PrintCurrentStackTrace(FILE* out); |
| 264 static void PrintStackTrace(FILE* out, char* thread_data); | 305 static void PrintStackTrace(FILE* out, char* thread_data); |
| 265 static void PrintStack(StringStream* accumulator); | 306 static void PrintStack(StringStream* accumulator); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 } | 373 } |
| 333 | 374 |
| 334 // Returns the current global context. | 375 // Returns the current global context. |
| 335 static Handle<Context> global_context(); | 376 static Handle<Context> global_context(); |
| 336 | 377 |
| 337 // Returns the global context of the calling JavaScript code. That | 378 // Returns the global context of the calling JavaScript code. That |
| 338 // is, the global context of the top-most JavaScript frame. | 379 // is, the global context of the top-most JavaScript frame. |
| 339 static Handle<Context> GetCallingGlobalContext(); | 380 static Handle<Context> GetCallingGlobalContext(); |
| 340 | 381 |
| 341 static Handle<JSBuiltinsObject> builtins() { | 382 static Handle<JSBuiltinsObject> builtins() { |
| 342 return Handle<JSBuiltinsObject>(thread_local_.context_->builtins()); | 383 return Handle<JSBuiltinsObject>( |
| 384 v8_context()->top_data_.thread_local_.context_->builtins()); |
| 343 } | 385 } |
| 344 | 386 |
| 345 static Object* LookupSpecialFunction(JSObject* receiver, | 387 static Object* LookupSpecialFunction(JSObject* receiver, |
| 346 JSObject* prototype, | 388 JSObject* prototype, |
| 347 JSFunction* value); | 389 JSFunction* value); |
| 348 | 390 |
| 349 static void RegisterTryCatchHandler(v8::TryCatch* that); | 391 static void RegisterTryCatchHandler(v8::TryCatch* that); |
| 350 static void UnregisterTryCatchHandler(v8::TryCatch* that); | 392 static void UnregisterTryCatchHandler(v8::TryCatch* that); |
| 351 | 393 |
| 352 #define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \ | 394 #define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \ |
| 353 static Handle<type> name() { \ | 395 static Handle<type> name() { \ |
| 354 return Handle<type>(context()->global_context()->name()); \ | 396 return Handle<type>(context()->global_context()->name()); \ |
| 355 } | 397 } |
| 356 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR) | 398 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR) |
| 357 #undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR | 399 #undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR |
| 358 | 400 |
| 359 static inline ThreadLocalTop* GetCurrentThread() { return &thread_local_; } | 401 static inline ThreadLocalTop* GetCurrentThread() { |
| 402 return &v8_context()->top_data_.thread_local_; |
| 403 } |
| 360 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } | 404 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } |
| 361 static char* ArchiveThread(char* to); | 405 static char* ArchiveThread(char* to); |
| 362 static char* RestoreThread(char* from); | 406 static char* RestoreThread(char* from); |
| 363 static void FreeThreadResources() { thread_local_.Free(); } | 407 static void FreeThreadResources() { |
| 408 v8_context()->top_data_.thread_local_.Free(); |
| 409 } |
| 364 | 410 |
| 365 static const char* kStackOverflowMessage; | 411 static const char* kStackOverflowMessage; |
| 366 | 412 |
| 367 private: | 413 private: |
| 368 // The context that initiated this JS execution. | |
| 369 static ThreadLocalTop thread_local_; | |
| 370 static void InitializeThreadLocal(); | 414 static void InitializeThreadLocal(); |
| 371 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread); | 415 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread); |
| 372 static void MarkCompactPrologue(bool is_compacting, | 416 static void MarkCompactPrologue(bool is_compacting, |
| 373 ThreadLocalTop* archived_thread_data); | 417 ThreadLocalTop* archived_thread_data); |
| 374 static void MarkCompactEpilogue(bool is_compacting, | 418 static void MarkCompactEpilogue(bool is_compacting, |
| 375 ThreadLocalTop* archived_thread_data); | 419 ThreadLocalTop* archived_thread_data); |
| 376 | 420 |
| 377 // Debug. | |
| 378 // Mutex for serializing access to break control structures. | |
| 379 static Mutex* break_access_; | |
| 380 | |
| 381 friend class SaveContext; | 421 friend class SaveContext; |
| 382 friend class AssertNoContextChange; | 422 friend class AssertNoContextChange; |
| 383 friend class ExecutionAccess; | 423 friend class ExecutionAccess; |
| 384 | 424 |
| 425 static void PostConstruct(); |
| 426 static void PreDestroy(); |
| 385 static void FillCache(); | 427 static void FillCache(); |
| 428 |
| 429 friend class V8Context; |
| 386 }; | 430 }; |
| 387 | 431 |
| 388 | 432 |
| 389 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the | 433 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the |
| 390 // class as a work around for a bug in the generated code found with these | 434 // class as a work around for a bug in the generated code found with these |
| 391 // versions of GCC. See V8 issue 122 for details. | 435 // versions of GCC. See V8 issue 122 for details. |
| 392 class SaveContext BASE_EMBEDDED { | 436 class SaveContext BASE_EMBEDDED { |
| 393 public: | 437 public: |
| 394 SaveContext() | 438 SaveContext() |
| 395 : context_(Top::context()), | 439 : context_(Top::context()), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 | 494 |
| 451 class ExecutionAccess BASE_EMBEDDED { | 495 class ExecutionAccess BASE_EMBEDDED { |
| 452 public: | 496 public: |
| 453 ExecutionAccess(); | 497 ExecutionAccess(); |
| 454 ~ExecutionAccess(); | 498 ~ExecutionAccess(); |
| 455 }; | 499 }; |
| 456 | 500 |
| 457 } } // namespace v8::internal | 501 } } // namespace v8::internal |
| 458 | 502 |
| 459 #endif // V8_TOP_H_ | 503 #endif // V8_TOP_H_ |
| OLD | NEW |