OLD | NEW |
| (Empty) |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | |
2 // Redistribution and use in source and binary forms, with or without | |
3 // modification, are permitted provided that the following conditions are | |
4 // met: | |
5 // | |
6 // * Redistributions of source code must retain the above copyright | |
7 // notice, this list of conditions and the following disclaimer. | |
8 // * Redistributions in binary form must reproduce the above | |
9 // copyright notice, this list of conditions and the following | |
10 // disclaimer in the documentation and/or other materials provided | |
11 // with the distribution. | |
12 // * Neither the name of Google Inc. nor the names of its | |
13 // contributors may be used to endorse or promote products derived | |
14 // from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | |
28 #ifndef V8_TOP_H_ | |
29 #define V8_TOP_H_ | |
30 | |
31 #include "atomicops.h" | |
32 #include "compilation-cache.h" | |
33 #include "frames-inl.h" | |
34 #include "runtime-profiler.h" | |
35 | |
36 namespace v8 { | |
37 namespace internal { | |
38 | |
39 class Simulator; | |
40 | |
41 #define RETURN_IF_SCHEDULED_EXCEPTION() \ | |
42 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException() | |
43 | |
44 #define RETURN_IF_EMPTY_HANDLE_VALUE(call, value) \ | |
45 if (call.is_null()) { \ | |
46 ASSERT(Top::has_pending_exception()); \ | |
47 return value; \ | |
48 } | |
49 | |
50 #define RETURN_IF_EMPTY_HANDLE(call) \ | |
51 RETURN_IF_EMPTY_HANDLE_VALUE(call, Failure::Exception()) | |
52 | |
53 // Top has static variables used for JavaScript execution. | |
54 | |
55 class SaveContext; // Forward declaration. | |
56 class ThreadVisitor; // Defined in v8threads.h | |
57 class VMState; // Defined in vm-state.h | |
58 | |
59 class ThreadLocalTop BASE_EMBEDDED { | |
60 public: | |
61 // Initialize the thread data. | |
62 void Initialize(); | |
63 | |
64 // Get the top C++ try catch handler or NULL if none are registered. | |
65 // | |
66 // This method is not guarenteed to return an address that can be | |
67 // used for comparison with addresses into the JS stack. If such an | |
68 // address is needed, use try_catch_handler_address. | |
69 v8::TryCatch* TryCatchHandler(); | |
70 | |
71 // Get the address of the top C++ try catch handler or NULL if | |
72 // none are registered. | |
73 // | |
74 // This method always returns an address that can be compared to | |
75 // pointers into the JavaScript stack. When running on actual | |
76 // hardware, try_catch_handler_address and TryCatchHandler return | |
77 // the same pointer. When running on a simulator with a separate JS | |
78 // stack, try_catch_handler_address returns a JS stack address that | |
79 // corresponds to the place on the JS stack where the C++ handler | |
80 // would have been if the stack were not separate. | |
81 inline Address try_catch_handler_address() { | |
82 return try_catch_handler_address_; | |
83 } | |
84 | |
85 // Set the address of the top C++ try catch handler. | |
86 inline void set_try_catch_handler_address(Address address) { | |
87 try_catch_handler_address_ = address; | |
88 } | |
89 | |
90 void Free() { | |
91 ASSERT(!has_pending_message_); | |
92 ASSERT(!external_caught_exception_); | |
93 ASSERT(try_catch_handler_address_ == NULL); | |
94 } | |
95 | |
96 // The context where the current execution method is created and for variable | |
97 // lookups. | |
98 Context* context_; | |
99 int thread_id_; | |
100 MaybeObject* pending_exception_; | |
101 bool has_pending_message_; | |
102 const char* pending_message_; | |
103 Object* pending_message_obj_; | |
104 Script* pending_message_script_; | |
105 int pending_message_start_pos_; | |
106 int pending_message_end_pos_; | |
107 // Use a separate value for scheduled exceptions to preserve the | |
108 // invariants that hold about pending_exception. We may want to | |
109 // unify them later. | |
110 MaybeObject* scheduled_exception_; | |
111 bool external_caught_exception_; | |
112 SaveContext* save_context_; | |
113 v8::TryCatch* catcher_; | |
114 | |
115 // Stack. | |
116 Address c_entry_fp_; // the frame pointer of the top c entry frame | |
117 Address handler_; // try-blocks are chained through the stack | |
118 | |
119 #ifdef USE_SIMULATOR | |
120 #ifdef V8_TARGET_ARCH_ARM | |
121 Simulator* simulator_; | |
122 #elif V8_TARGET_ARCH_MIPS | |
123 assembler::mips::Simulator* simulator_; | |
124 #endif | |
125 #endif // USE_SIMULATOR | |
126 | |
127 #ifdef ENABLE_LOGGING_AND_PROFILING | |
128 Address js_entry_sp_; // the stack pointer of the bottom js entry frame | |
129 Address external_callback_; // the external callback we're currently in | |
130 #endif | |
131 | |
132 #ifdef ENABLE_VMSTATE_TRACKING | |
133 StateTag current_vm_state_; | |
134 | |
135 // Used for communication with the runtime profiler thread. | |
136 // Possible values are specified in RuntimeProfilerState. | |
137 Atomic32 runtime_profiler_state_; | |
138 #endif | |
139 | |
140 // Generated code scratch locations. | |
141 int32_t formal_count_; | |
142 | |
143 // Call back function to report unsafe JS accesses. | |
144 v8::FailedAccessCheckCallback failed_access_check_callback_; | |
145 | |
146 private: | |
147 Address try_catch_handler_address_; | |
148 }; | |
149 | |
150 #define TOP_ADDRESS_LIST(C) \ | |
151 C(handler_address) \ | |
152 C(c_entry_fp_address) \ | |
153 C(context_address) \ | |
154 C(pending_exception_address) \ | |
155 C(external_caught_exception_address) | |
156 | |
157 #ifdef ENABLE_LOGGING_AND_PROFILING | |
158 #define TOP_ADDRESS_LIST_PROF(C) \ | |
159 C(js_entry_sp_address) | |
160 #else | |
161 #define TOP_ADDRESS_LIST_PROF(C) | |
162 #endif | |
163 | |
164 | |
165 class Top { | |
166 public: | |
167 enum AddressId { | |
168 #define C(name) k_##name, | |
169 TOP_ADDRESS_LIST(C) | |
170 TOP_ADDRESS_LIST_PROF(C) | |
171 #undef C | |
172 k_top_address_count | |
173 }; | |
174 | |
175 static Address get_address_from_id(AddressId id); | |
176 | |
177 // Access to top context (where the current function object was created). | |
178 static Context* context() { return thread_local_.context_; } | |
179 static void set_context(Context* context) { | |
180 thread_local_.context_ = context; | |
181 } | |
182 static Context** context_address() { return &thread_local_.context_; } | |
183 | |
184 static SaveContext* save_context() {return thread_local_.save_context_; } | |
185 static void set_save_context(SaveContext* save) { | |
186 thread_local_.save_context_ = save; | |
187 } | |
188 | |
189 // Access to current thread id. | |
190 static int thread_id() { return thread_local_.thread_id_; } | |
191 static void set_thread_id(int id) { thread_local_.thread_id_ = id; } | |
192 | |
193 // Interface to pending exception. | |
194 static MaybeObject* pending_exception() { | |
195 ASSERT(has_pending_exception()); | |
196 return thread_local_.pending_exception_; | |
197 } | |
198 static bool external_caught_exception() { | |
199 return thread_local_.external_caught_exception_; | |
200 } | |
201 static void set_pending_exception(MaybeObject* exception) { | |
202 thread_local_.pending_exception_ = exception; | |
203 } | |
204 static void clear_pending_exception() { | |
205 thread_local_.pending_exception_ = Heap::the_hole_value(); | |
206 } | |
207 | |
208 static MaybeObject** pending_exception_address() { | |
209 return &thread_local_.pending_exception_; | |
210 } | |
211 static bool has_pending_exception() { | |
212 return !thread_local_.pending_exception_->IsTheHole(); | |
213 } | |
214 static void clear_pending_message() { | |
215 thread_local_.has_pending_message_ = false; | |
216 thread_local_.pending_message_ = NULL; | |
217 thread_local_.pending_message_obj_ = Heap::the_hole_value(); | |
218 thread_local_.pending_message_script_ = NULL; | |
219 } | |
220 static v8::TryCatch* try_catch_handler() { | |
221 return thread_local_.TryCatchHandler(); | |
222 } | |
223 static Address try_catch_handler_address() { | |
224 return thread_local_.try_catch_handler_address(); | |
225 } | |
226 // This method is called by the api after operations that may throw | |
227 // exceptions. If an exception was thrown and not handled by an external | |
228 // handler the exception is scheduled to be rethrown when we return to running | |
229 // JavaScript code. If an exception is scheduled true is returned. | |
230 static bool OptionalRescheduleException(bool is_bottom_call); | |
231 | |
232 | |
233 static bool* external_caught_exception_address() { | |
234 return &thread_local_.external_caught_exception_; | |
235 } | |
236 | |
237 static MaybeObject** scheduled_exception_address() { | |
238 return &thread_local_.scheduled_exception_; | |
239 } | |
240 | |
241 static MaybeObject* scheduled_exception() { | |
242 ASSERT(has_scheduled_exception()); | |
243 return thread_local_.scheduled_exception_; | |
244 } | |
245 static bool has_scheduled_exception() { | |
246 return !thread_local_.scheduled_exception_->IsTheHole(); | |
247 } | |
248 static void clear_scheduled_exception() { | |
249 thread_local_.scheduled_exception_ = Heap::the_hole_value(); | |
250 } | |
251 | |
252 static bool IsExternallyCaught(); | |
253 | |
254 static void SetCaptureStackTraceForUncaughtExceptions( | |
255 bool capture, | |
256 int frame_limit, | |
257 StackTrace::StackTraceOptions options); | |
258 | |
259 // Tells whether the current context has experienced an out of memory | |
260 // exception. | |
261 static bool is_out_of_memory(); | |
262 | |
263 static bool is_catchable_by_javascript(MaybeObject* exception) { | |
264 return (exception != Failure::OutOfMemoryException()) && | |
265 (exception != Heap::termination_exception()); | |
266 } | |
267 | |
268 // JS execution stack (see frames.h). | |
269 static Address c_entry_fp(ThreadLocalTop* thread) { | |
270 return thread->c_entry_fp_; | |
271 } | |
272 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } | |
273 | |
274 static inline Address* c_entry_fp_address() { | |
275 return &thread_local_.c_entry_fp_; | |
276 } | |
277 static inline Address* handler_address() { return &thread_local_.handler_; } | |
278 | |
279 #ifdef ENABLE_LOGGING_AND_PROFILING | |
280 // Bottom JS entry (see StackTracer::Trace in log.cc). | |
281 static Address js_entry_sp(ThreadLocalTop* thread) { | |
282 return thread->js_entry_sp_; | |
283 } | |
284 static inline Address* js_entry_sp_address() { | |
285 return &thread_local_.js_entry_sp_; | |
286 } | |
287 | |
288 static Address external_callback() { | |
289 return thread_local_.external_callback_; | |
290 } | |
291 static void set_external_callback(Address callback) { | |
292 thread_local_.external_callback_ = callback; | |
293 } | |
294 #endif | |
295 | |
296 #ifdef ENABLE_VMSTATE_TRACKING | |
297 static StateTag current_vm_state() { | |
298 return thread_local_.current_vm_state_; | |
299 } | |
300 | |
301 static void SetCurrentVMState(StateTag state) { | |
302 if (RuntimeProfiler::IsEnabled()) { | |
303 if (state == JS) { | |
304 // JS or non-JS -> JS transition. | |
305 RuntimeProfilerState old_state = SwapRuntimeProfilerState(PROF_IN_JS); | |
306 if (old_state == PROF_NOT_IN_JS_WAITING_FOR_JS) { | |
307 // If the runtime profiler was waiting, we reset the eager | |
308 // optimizing data in the compilation cache to get a fresh | |
309 // start after not running JavaScript code for a while and | |
310 // signal the runtime profiler so it can resume. | |
311 CompilationCache::ResetEagerOptimizingData(); | |
312 runtime_profiler_semaphore_->Signal(); | |
313 } | |
314 } else if (thread_local_.current_vm_state_ == JS) { | |
315 // JS -> non-JS transition. Update the runtime profiler state. | |
316 ASSERT(IsInJSState()); | |
317 SetRuntimeProfilerState(PROF_NOT_IN_JS); | |
318 } | |
319 } | |
320 thread_local_.current_vm_state_ = state; | |
321 } | |
322 | |
323 // Called in the runtime profiler thread. | |
324 // Returns whether the current VM state is set to JS. | |
325 static bool IsInJSState() { | |
326 ASSERT(RuntimeProfiler::IsEnabled()); | |
327 return static_cast<RuntimeProfilerState>( | |
328 NoBarrier_Load(&thread_local_.runtime_profiler_state_)) == PROF_IN_JS; | |
329 } | |
330 | |
331 // Called in the runtime profiler thread. | |
332 // Waits for the VM state to transtion from non-JS to JS. Returns | |
333 // true when notified of the transition, false when the current | |
334 // state is not the expected non-JS state. | |
335 static bool WaitForJSState() { | |
336 ASSERT(RuntimeProfiler::IsEnabled()); | |
337 // Try to switch to waiting state. | |
338 RuntimeProfilerState old_state = CompareAndSwapRuntimeProfilerState( | |
339 PROF_NOT_IN_JS, PROF_NOT_IN_JS_WAITING_FOR_JS); | |
340 if (old_state == PROF_NOT_IN_JS) { | |
341 runtime_profiler_semaphore_->Wait(); | |
342 return true; | |
343 } | |
344 return false; | |
345 } | |
346 | |
347 // When shutting down we join the profiler thread. Doing so while | |
348 // it's waiting on a semaphore will cause a deadlock, so we have to | |
349 // wake it up first. | |
350 static void WakeUpRuntimeProfilerThreadBeforeShutdown() { | |
351 runtime_profiler_semaphore_->Signal(); | |
352 } | |
353 #endif | |
354 | |
355 // Generated code scratch locations. | |
356 static void* formal_count_address() { return &thread_local_.formal_count_; } | |
357 | |
358 static void PrintCurrentStackTrace(FILE* out); | |
359 static void PrintStackTrace(FILE* out, char* thread_data); | |
360 static void PrintStack(StringStream* accumulator); | |
361 static void PrintStack(); | |
362 static Handle<String> StackTraceString(); | |
363 static Handle<JSArray> CaptureCurrentStackTrace( | |
364 int frame_limit, | |
365 StackTrace::StackTraceOptions options); | |
366 | |
367 // Returns if the top context may access the given global object. If | |
368 // the result is false, the pending exception is guaranteed to be | |
369 // set. | |
370 static bool MayNamedAccess(JSObject* receiver, | |
371 Object* key, | |
372 v8::AccessType type); | |
373 static bool MayIndexedAccess(JSObject* receiver, | |
374 uint32_t index, | |
375 v8::AccessType type); | |
376 | |
377 static void SetFailedAccessCheckCallback( | |
378 v8::FailedAccessCheckCallback callback); | |
379 static void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type); | |
380 | |
381 // Exception throwing support. The caller should use the result | |
382 // of Throw() as its return value. | |
383 static Failure* Throw(Object* exception, MessageLocation* location = NULL); | |
384 // Re-throw an exception. This involves no error reporting since | |
385 // error reporting was handled when the exception was thrown | |
386 // originally. | |
387 static Failure* ReThrow(MaybeObject* exception, | |
388 MessageLocation* location = NULL); | |
389 static void ScheduleThrow(Object* exception); | |
390 static void ReportPendingMessages(); | |
391 static Failure* ThrowIllegalOperation(); | |
392 | |
393 // Promote a scheduled exception to pending. Asserts has_scheduled_exception. | |
394 static Failure* PromoteScheduledException(); | |
395 static void DoThrow(MaybeObject* exception, | |
396 MessageLocation* location, | |
397 const char* message); | |
398 // Checks if exception should be reported and finds out if it's | |
399 // caught externally. | |
400 static bool ShouldReportException(bool* can_be_caught_externally, | |
401 bool catchable_by_javascript); | |
402 | |
403 // Attempts to compute the current source location, storing the | |
404 // result in the target out parameter. | |
405 static void ComputeLocation(MessageLocation* target); | |
406 | |
407 // Override command line flag. | |
408 static void TraceException(bool flag); | |
409 | |
410 // Out of resource exception helpers. | |
411 static Failure* StackOverflow(); | |
412 static Failure* TerminateExecution(); | |
413 | |
414 // Administration | |
415 static void Initialize(); | |
416 static void TearDown(); | |
417 static void Iterate(ObjectVisitor* v); | |
418 static void Iterate(ObjectVisitor* v, ThreadLocalTop* t); | |
419 static char* Iterate(ObjectVisitor* v, char* t); | |
420 static void IterateThread(ThreadVisitor* v); | |
421 static void IterateThread(ThreadVisitor* v, char* t); | |
422 | |
423 // Returns the global object of the current context. It could be | |
424 // a builtin object, or a js global object. | |
425 static Handle<GlobalObject> global() { | |
426 return Handle<GlobalObject>(context()->global()); | |
427 } | |
428 | |
429 // Returns the global proxy object of the current context. | |
430 static Object* global_proxy() { | |
431 return context()->global_proxy(); | |
432 } | |
433 | |
434 // Returns the current global context. | |
435 static Handle<Context> global_context(); | |
436 | |
437 // Returns the global context of the calling JavaScript code. That | |
438 // is, the global context of the top-most JavaScript frame. | |
439 static Handle<Context> GetCallingGlobalContext(); | |
440 | |
441 static Handle<JSBuiltinsObject> builtins() { | |
442 return Handle<JSBuiltinsObject>(thread_local_.context_->builtins()); | |
443 } | |
444 | |
445 static void RegisterTryCatchHandler(v8::TryCatch* that); | |
446 static void UnregisterTryCatchHandler(v8::TryCatch* that); | |
447 | |
448 #define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \ | |
449 static Handle<type> name() { \ | |
450 return Handle<type>(context()->global_context()->name()); \ | |
451 } | |
452 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR) | |
453 #undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR | |
454 | |
455 static inline ThreadLocalTop* GetCurrentThread() { return &thread_local_; } | |
456 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } | |
457 static char* ArchiveThread(char* to); | |
458 static char* RestoreThread(char* from); | |
459 static void FreeThreadResources() { thread_local_.Free(); } | |
460 | |
461 static const char* kStackOverflowMessage; | |
462 | |
463 private: | |
464 #ifdef ENABLE_VMSTATE_TRACKING | |
465 // Set of states used when communicating with the runtime profiler. | |
466 // | |
467 // The set of possible transitions is divided between the VM and the | |
468 // profiler threads. | |
469 // | |
470 // The VM thread can perform these transitions: | |
471 // o IN_JS -> NOT_IN_JS | |
472 // o NOT_IN_JS -> IN_JS | |
473 // o NOT_IN_JS_WAITING_FOR_JS -> IN_JS notifying the profiler thread | |
474 // using the semaphore. | |
475 // All the above transitions are caused by VM state changes. | |
476 // | |
477 // The profiler thread can only perform a single transition | |
478 // NOT_IN_JS -> NOT_IN_JS_WAITING_FOR_JS before it starts waiting on | |
479 // the semaphore. | |
480 enum RuntimeProfilerState { | |
481 PROF_NOT_IN_JS, | |
482 PROF_NOT_IN_JS_WAITING_FOR_JS, | |
483 PROF_IN_JS | |
484 }; | |
485 | |
486 static void SetRuntimeProfilerState(RuntimeProfilerState state) { | |
487 NoBarrier_Store(&thread_local_.runtime_profiler_state_, state); | |
488 } | |
489 | |
490 static RuntimeProfilerState SwapRuntimeProfilerState( | |
491 RuntimeProfilerState state) { | |
492 return static_cast<RuntimeProfilerState>( | |
493 NoBarrier_AtomicExchange(&thread_local_.runtime_profiler_state_, | |
494 state)); | |
495 } | |
496 | |
497 static RuntimeProfilerState CompareAndSwapRuntimeProfilerState( | |
498 RuntimeProfilerState old_state, | |
499 RuntimeProfilerState state) { | |
500 return static_cast<RuntimeProfilerState>( | |
501 NoBarrier_CompareAndSwap(&thread_local_.runtime_profiler_state_, | |
502 old_state, | |
503 state)); | |
504 } | |
505 | |
506 static Semaphore* runtime_profiler_semaphore_; | |
507 #endif // ENABLE_VMSTATE_TRACKING | |
508 | |
509 // The context that initiated this JS execution. | |
510 static ThreadLocalTop thread_local_; | |
511 static void InitializeThreadLocal(); | |
512 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread); | |
513 static void MarkCompactPrologue(bool is_compacting, | |
514 ThreadLocalTop* archived_thread_data); | |
515 static void MarkCompactEpilogue(bool is_compacting, | |
516 ThreadLocalTop* archived_thread_data); | |
517 | |
518 // Debug. | |
519 // Mutex for serializing access to break control structures. | |
520 static Mutex* break_access_; | |
521 | |
522 friend class SaveContext; | |
523 friend class AssertNoContextChange; | |
524 friend class ExecutionAccess; | |
525 friend class ThreadLocalTop; | |
526 | |
527 static void FillCache(); | |
528 }; | |
529 | |
530 | |
531 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the | |
532 // class as a work around for a bug in the generated code found with these | |
533 // versions of GCC. See V8 issue 122 for details. | |
534 class SaveContext BASE_EMBEDDED { | |
535 public: | |
536 SaveContext() | |
537 : context_(Top::context()), | |
538 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300 | |
539 dummy_(Top::context()), | |
540 #endif | |
541 prev_(Top::save_context()) { | |
542 Top::set_save_context(this); | |
543 | |
544 // If there is no JS frame under the current C frame, use the value 0. | |
545 JavaScriptFrameIterator it; | |
546 js_sp_ = it.done() ? 0 : it.frame()->sp(); | |
547 } | |
548 | |
549 ~SaveContext() { | |
550 Top::set_context(*context_); | |
551 Top::set_save_context(prev_); | |
552 } | |
553 | |
554 Handle<Context> context() { return context_; } | |
555 SaveContext* prev() { return prev_; } | |
556 | |
557 // Returns true if this save context is below a given JavaScript frame. | |
558 bool below(JavaScriptFrame* frame) { | |
559 return (js_sp_ == 0) || (frame->sp() < js_sp_); | |
560 } | |
561 | |
562 private: | |
563 Handle<Context> context_; | |
564 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300 | |
565 Handle<Context> dummy_; | |
566 #endif | |
567 SaveContext* prev_; | |
568 Address js_sp_; // The top JS frame's sp when saving context. | |
569 }; | |
570 | |
571 | |
572 class AssertNoContextChange BASE_EMBEDDED { | |
573 #ifdef DEBUG | |
574 public: | |
575 AssertNoContextChange() : | |
576 context_(Top::context()) { | |
577 } | |
578 | |
579 ~AssertNoContextChange() { | |
580 ASSERT(Top::context() == *context_); | |
581 } | |
582 | |
583 private: | |
584 HandleScope scope_; | |
585 Handle<Context> context_; | |
586 #else | |
587 public: | |
588 AssertNoContextChange() { } | |
589 #endif | |
590 }; | |
591 | |
592 | |
593 class ExecutionAccess BASE_EMBEDDED { | |
594 public: | |
595 ExecutionAccess() { Lock(); } | |
596 ~ExecutionAccess() { Unlock(); } | |
597 | |
598 static void Lock() { Top::break_access_->Lock(); } | |
599 static void Unlock() { Top::break_access_->Unlock(); } | |
600 | |
601 static bool TryLock() { | |
602 return Top::break_access_->TryLock(); | |
603 } | |
604 }; | |
605 | |
606 } } // namespace v8::internal | |
607 | |
608 #endif // V8_TOP_H_ | |
OLD | NEW |