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 |