blob: 9d8aa8227fa3ff044daa534912c8fa7a68f3a053 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000031#include "atomicops.h"
32#include "compilation-cache.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "frames-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000034#include "runtime-profiler.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
ricow@chromium.org83aa5492011-02-07 12:42:56 +000039class Simulator;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000040
41#define RETURN_IF_SCHEDULED_EXCEPTION() \
42 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException()
43
44// Top has static variables used for JavaScript execution.
45
ager@chromium.org32912102009-01-16 10:38:43 +000046class SaveContext; // Forward declaration.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000047class ThreadVisitor; // Defined in v8threads.h
whesse@chromium.org4a5224e2010-10-20 12:37:07 +000048class VMState; // Defined in vm-state.h
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
50class ThreadLocalTop BASE_EMBEDDED {
51 public:
ager@chromium.orgc4c92722009-11-18 14:12:51 +000052 // Initialize the thread data.
53 void Initialize();
54
55 // Get the top C++ try catch handler or NULL if none are registered.
56 //
57 // This method is not guarenteed to return an address that can be
58 // used for comparison with addresses into the JS stack. If such an
59 // address is needed, use try_catch_handler_address.
60 v8::TryCatch* TryCatchHandler();
61
62 // Get the address of the top C++ try catch handler or NULL if
63 // none are registered.
64 //
65 // This method always returns an address that can be compared to
66 // pointers into the JavaScript stack. When running on actual
67 // hardware, try_catch_handler_address and TryCatchHandler return
68 // the same pointer. When running on a simulator with a separate JS
69 // stack, try_catch_handler_address returns a JS stack address that
70 // corresponds to the place on the JS stack where the C++ handler
71 // would have been if the stack were not separate.
72 inline Address try_catch_handler_address() {
73 return try_catch_handler_address_;
74 }
75
76 // Set the address of the top C++ try catch handler.
77 inline void set_try_catch_handler_address(Address address) {
78 try_catch_handler_address_ = address;
79 }
80
81 void Free() {
82 ASSERT(!has_pending_message_);
83 ASSERT(!external_caught_exception_);
84 ASSERT(try_catch_handler_address_ == NULL);
85 }
86
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000087 // The context where the current execution method is created and for variable
88 // lookups.
89 Context* context_;
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000090 int thread_id_;
lrn@chromium.org303ada72010-10-27 09:33:13 +000091 MaybeObject* pending_exception_;
ager@chromium.org8bb60582008-12-11 12:02:20 +000092 bool has_pending_message_;
93 const char* pending_message_;
94 Object* pending_message_obj_;
95 Script* pending_message_script_;
96 int pending_message_start_pos_;
97 int pending_message_end_pos_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000098 // Use a separate value for scheduled exceptions to preserve the
99 // invariants that hold about pending_exception. We may want to
100 // unify them later.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000101 MaybeObject* scheduled_exception_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102 bool external_caught_exception_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103 SaveContext* save_context_;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000104 v8::TryCatch* catcher_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105
106 // Stack.
107 Address c_entry_fp_; // the frame pointer of the top c entry frame
108 Address handler_; // try-blocks are chained through the stack
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000109
lrn@chromium.org303ada72010-10-27 09:33:13 +0000110#ifdef USE_SIMULATOR
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000111#ifdef V8_TARGET_ARCH_ARM
ager@chromium.org378b34e2011-01-28 08:04:38 +0000112 Simulator* simulator_;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000113#elif V8_TARGET_ARCH_MIPS
114 assembler::mips::Simulator* simulator_;
115#endif
lrn@chromium.org303ada72010-10-27 09:33:13 +0000116#endif // USE_SIMULATOR
117
ager@chromium.orge2902be2009-06-08 12:21:35 +0000118#ifdef ENABLE_LOGGING_AND_PROFILING
119 Address js_entry_sp_; // the stack pointer of the bottom js entry frame
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120 Address external_callback_; // the external callback we're currently in
ager@chromium.orge2902be2009-06-08 12:21:35 +0000121#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000123#ifdef ENABLE_VMSTATE_TRACKING
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000124 StateTag current_vm_state_;
125
126 // Used for communication with the runtime profiler thread.
127 // Possible values are specified in RuntimeProfilerState.
128 Atomic32 runtime_profiler_state_;
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000129#endif
130
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131 // Generated code scratch locations.
132 int32_t formal_count_;
133
134 // Call back function to report unsafe JS accesses.
135 v8::FailedAccessCheckCallback failed_access_check_callback_;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000136
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000137 private:
138 Address try_catch_handler_address_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000139};
140
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000141#define TOP_ADDRESS_LIST(C) \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000142 C(handler_address) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000143 C(c_entry_fp_address) \
144 C(context_address) \
145 C(pending_exception_address) \
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000146 C(external_caught_exception_address)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147
ager@chromium.orge2902be2009-06-08 12:21:35 +0000148#ifdef ENABLE_LOGGING_AND_PROFILING
149#define TOP_ADDRESS_LIST_PROF(C) \
150 C(js_entry_sp_address)
151#else
152#define TOP_ADDRESS_LIST_PROF(C)
153#endif
154
155
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156class Top {
157 public:
158 enum AddressId {
159#define C(name) k_##name,
160 TOP_ADDRESS_LIST(C)
ager@chromium.orge2902be2009-06-08 12:21:35 +0000161 TOP_ADDRESS_LIST_PROF(C)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162#undef C
163 k_top_address_count
164 };
165
166 static Address get_address_from_id(AddressId id);
167
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000168 // Access to top context (where the current function object was created).
169 static Context* context() { return thread_local_.context_; }
170 static void set_context(Context* context) {
171 thread_local_.context_ = context;
172 }
173 static Context** context_address() { return &thread_local_.context_; }
174
175 static SaveContext* save_context() {return thread_local_.save_context_; }
176 static void set_save_context(SaveContext* save) {
177 thread_local_.save_context_ = save;
178 }
179
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000180 // Access to current thread id.
181 static int thread_id() { return thread_local_.thread_id_; }
182 static void set_thread_id(int id) { thread_local_.thread_id_ = id; }
183
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184 // Interface to pending exception.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000185 static MaybeObject* pending_exception() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000186 ASSERT(has_pending_exception());
187 return thread_local_.pending_exception_;
188 }
189 static bool external_caught_exception() {
190 return thread_local_.external_caught_exception_;
191 }
lrn@chromium.org303ada72010-10-27 09:33:13 +0000192 static void set_pending_exception(MaybeObject* exception) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193 thread_local_.pending_exception_ = exception;
194 }
195 static void clear_pending_exception() {
196 thread_local_.pending_exception_ = Heap::the_hole_value();
197 }
198
lrn@chromium.org303ada72010-10-27 09:33:13 +0000199 static MaybeObject** pending_exception_address() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200 return &thread_local_.pending_exception_;
201 }
202 static bool has_pending_exception() {
203 return !thread_local_.pending_exception_->IsTheHole();
204 }
ager@chromium.org8bb60582008-12-11 12:02:20 +0000205 static void clear_pending_message() {
ager@chromium.org8bb60582008-12-11 12:02:20 +0000206 thread_local_.has_pending_message_ = false;
207 thread_local_.pending_message_ = NULL;
208 thread_local_.pending_message_obj_ = Heap::the_hole_value();
209 thread_local_.pending_message_script_ = NULL;
210 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000211 static v8::TryCatch* try_catch_handler() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000212 return thread_local_.TryCatchHandler();
213 }
214 static Address try_catch_handler_address() {
215 return thread_local_.try_catch_handler_address();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 }
217 // This method is called by the api after operations that may throw
218 // exceptions. If an exception was thrown and not handled by an external
219 // handler the exception is scheduled to be rethrown when we return to running
220 // JavaScript code. If an exception is scheduled true is returned.
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000221 static bool OptionalRescheduleException(bool is_bottom_call);
222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223
224 static bool* external_caught_exception_address() {
225 return &thread_local_.external_caught_exception_;
226 }
227
lrn@chromium.org303ada72010-10-27 09:33:13 +0000228 static MaybeObject** scheduled_exception_address() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000229 return &thread_local_.scheduled_exception_;
230 }
231
lrn@chromium.org303ada72010-10-27 09:33:13 +0000232 static MaybeObject* scheduled_exception() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233 ASSERT(has_scheduled_exception());
234 return thread_local_.scheduled_exception_;
235 }
236 static bool has_scheduled_exception() {
237 return !thread_local_.scheduled_exception_->IsTheHole();
238 }
239 static void clear_scheduled_exception() {
240 thread_local_.scheduled_exception_ = Heap::the_hole_value();
241 }
242
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000243 static void setup_external_caught() {
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000244 thread_local_.external_caught_exception_ =
ager@chromium.org71daaf62009-04-01 07:22:49 +0000245 has_pending_exception() &&
ager@chromium.org3a6061e2009-03-12 14:24:36 +0000246 (thread_local_.catcher_ != NULL) &&
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000247 (try_catch_handler() == thread_local_.catcher_);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000248 }
249
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000250 static void SetCaptureStackTraceForUncaughtExceptions(
251 bool capture,
252 int frame_limit,
253 StackTrace::StackTraceOptions options);
254
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000255 // Tells whether the current context has experienced an out of memory
256 // exception.
257 static bool is_out_of_memory();
258
259 // JS execution stack (see frames.h).
260 static Address c_entry_fp(ThreadLocalTop* thread) {
261 return thread->c_entry_fp_;
262 }
263 static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
264
265 static inline Address* c_entry_fp_address() {
266 return &thread_local_.c_entry_fp_;
267 }
268 static inline Address* handler_address() { return &thread_local_.handler_; }
269
ager@chromium.orge2902be2009-06-08 12:21:35 +0000270#ifdef ENABLE_LOGGING_AND_PROFILING
271 // Bottom JS entry (see StackTracer::Trace in log.cc).
272 static Address js_entry_sp(ThreadLocalTop* thread) {
273 return thread->js_entry_sp_;
274 }
275 static inline Address* js_entry_sp_address() {
276 return &thread_local_.js_entry_sp_;
277 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000278
279 static Address external_callback() {
280 return thread_local_.external_callback_;
281 }
282 static void set_external_callback(Address callback) {
283 thread_local_.external_callback_ = callback;
284 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000285#endif
286
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000287#ifdef ENABLE_VMSTATE_TRACKING
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000288 static StateTag current_vm_state() {
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000289 return thread_local_.current_vm_state_;
290 }
291
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292 static void SetCurrentVMState(StateTag state) {
293 if (RuntimeProfiler::IsEnabled()) {
294 if (state == JS) {
295 // JS or non-JS -> JS transition.
296 RuntimeProfilerState old_state = SwapRuntimeProfilerState(PROF_IN_JS);
297 if (old_state == PROF_NOT_IN_JS_WAITING_FOR_JS) {
298 // If the runtime profiler was waiting, we reset the eager
299 // optimizing data in the compilation cache to get a fresh
300 // start after not running JavaScript code for a while and
301 // signal the runtime profiler so it can resume.
302 CompilationCache::ResetEagerOptimizingData();
303 runtime_profiler_semaphore_->Signal();
304 }
305 } else if (thread_local_.current_vm_state_ == JS) {
306 // JS -> non-JS transition. Update the runtime profiler state.
307 ASSERT(IsInJSState());
308 SetRuntimeProfilerState(PROF_NOT_IN_JS);
309 }
310 }
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000311 thread_local_.current_vm_state_ = state;
312 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000313
314 // Called in the runtime profiler thread.
315 // Returns whether the current VM state is set to JS.
316 static bool IsInJSState() {
317 ASSERT(RuntimeProfiler::IsEnabled());
318 return static_cast<RuntimeProfilerState>(
319 NoBarrier_Load(&thread_local_.runtime_profiler_state_)) == PROF_IN_JS;
320 }
321
322 // Called in the runtime profiler thread.
323 // Waits for the VM state to transtion from non-JS to JS. Returns
324 // true when notified of the transition, false when the current
325 // state is not the expected non-JS state.
326 static bool WaitForJSState() {
327 ASSERT(RuntimeProfiler::IsEnabled());
328 // Try to switch to waiting state.
329 RuntimeProfilerState old_state = CompareAndSwapRuntimeProfilerState(
330 PROF_NOT_IN_JS, PROF_NOT_IN_JS_WAITING_FOR_JS);
331 if (old_state == PROF_NOT_IN_JS) {
332 runtime_profiler_semaphore_->Wait();
333 return true;
334 }
335 return false;
336 }
337
338 // When shutting down we join the profiler thread. Doing so while
339 // it's waiting on a semaphore will cause a deadlock, so we have to
340 // wake it up first.
341 static void WakeUpRuntimeProfilerThreadBeforeShutdown() {
342 runtime_profiler_semaphore_->Signal();
343 }
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000344#endif
345
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000346 // Generated code scratch locations.
347 static void* formal_count_address() { return &thread_local_.formal_count_; }
348
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349 static void PrintCurrentStackTrace(FILE* out);
350 static void PrintStackTrace(FILE* out, char* thread_data);
351 static void PrintStack(StringStream* accumulator);
352 static void PrintStack();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000353 static Handle<String> StackTraceString();
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000354 static Handle<JSArray> CaptureCurrentStackTrace(
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000355 int frame_limit,
356 StackTrace::StackTraceOptions options);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357
358 // Returns if the top context may access the given global object. If
359 // the result is false, the pending exception is guaranteed to be
360 // set.
361 static bool MayNamedAccess(JSObject* receiver,
362 Object* key,
363 v8::AccessType type);
364 static bool MayIndexedAccess(JSObject* receiver,
365 uint32_t index,
366 v8::AccessType type);
367
368 static void SetFailedAccessCheckCallback(
369 v8::FailedAccessCheckCallback callback);
370 static void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
371
372 // Exception throwing support. The caller should use the result
373 // of Throw() as its return value.
374 static Failure* Throw(Object* exception, MessageLocation* location = NULL);
375 // Re-throw an exception. This involves no error reporting since
376 // error reporting was handled when the exception was thrown
377 // originally.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000378 static Failure* ReThrow(MaybeObject* exception,
379 MessageLocation* location = NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380 static void ScheduleThrow(Object* exception);
ager@chromium.org8bb60582008-12-11 12:02:20 +0000381 static void ReportPendingMessages();
ager@chromium.org3e875802009-06-29 08:26:34 +0000382 static Failure* ThrowIllegalOperation();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000383
384 // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000385 static Failure* PromoteScheduledException();
386 static void DoThrow(MaybeObject* exception,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 MessageLocation* location,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000388 const char* message);
ager@chromium.org378b34e2011-01-28 08:04:38 +0000389 // Checks if exception should be reported and finds out if it's
390 // caught externally.
391 static bool ShouldReportException(bool* is_caught_externally,
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000392 bool catchable_by_javascript);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000394 // Attempts to compute the current source location, storing the
395 // result in the target out parameter.
396 static void ComputeLocation(MessageLocation* target);
397
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398 // Override command line flag.
399 static void TraceException(bool flag);
400
401 // Out of resource exception helpers.
402 static Failure* StackOverflow();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000403 static Failure* TerminateExecution();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404
405 // Administration
406 static void Initialize();
kasper.lundaf4734f2008-07-28 12:50:18 +0000407 static void TearDown();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000408 static void Iterate(ObjectVisitor* v);
409 static void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
410 static char* Iterate(ObjectVisitor* v, char* t);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000411 static void IterateThread(ThreadVisitor* v);
412 static void IterateThread(ThreadVisitor* v, char* t);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000414 // Returns the global object of the current context. It could be
415 // a builtin object, or a js global object.
416 static Handle<GlobalObject> global() {
417 return Handle<GlobalObject>(context()->global());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000418 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000419
420 // Returns the global proxy object of the current context.
421 static Object* global_proxy() {
422 return context()->global_proxy();
423 }
424
ager@chromium.org1bf0cd02009-05-20 11:34:19 +0000425 // Returns the current global context.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000426 static Handle<Context> global_context();
427
ager@chromium.org1bf0cd02009-05-20 11:34:19 +0000428 // Returns the global context of the calling JavaScript code. That
429 // is, the global context of the top-most JavaScript frame.
430 static Handle<Context> GetCallingGlobalContext();
431
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 static Handle<JSBuiltinsObject> builtins() {
433 return Handle<JSBuiltinsObject>(thread_local_.context_->builtins());
434 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000435
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000436 static void RegisterTryCatchHandler(v8::TryCatch* that);
437 static void UnregisterTryCatchHandler(v8::TryCatch* that);
438
439#define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \
440 static Handle<type> name() { \
441 return Handle<type>(context()->global_context()->name()); \
442 }
443 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR)
444#undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR
445
446 static inline ThreadLocalTop* GetCurrentThread() { return &thread_local_; }
447 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
448 static char* ArchiveThread(char* to);
449 static char* RestoreThread(char* from);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000450 static void FreeThreadResources() { thread_local_.Free(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000452 static const char* kStackOverflowMessage;
453
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000454 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000455#ifdef ENABLE_VMSTATE_TRACKING
456 // Set of states used when communicating with the runtime profiler.
457 //
458 // The set of possible transitions is divided between the VM and the
459 // profiler threads.
460 //
461 // The VM thread can perform these transitions:
462 // o IN_JS -> NOT_IN_JS
463 // o NOT_IN_JS -> IN_JS
464 // o NOT_IN_JS_WAITING_FOR_JS -> IN_JS notifying the profiler thread
465 // using the semaphore.
466 // All the above transitions are caused by VM state changes.
467 //
468 // The profiler thread can only perform a single transition
469 // NOT_IN_JS -> NOT_IN_JS_WAITING_FOR_JS before it starts waiting on
470 // the semaphore.
471 enum RuntimeProfilerState {
472 PROF_NOT_IN_JS,
473 PROF_NOT_IN_JS_WAITING_FOR_JS,
474 PROF_IN_JS
475 };
476
477 static void SetRuntimeProfilerState(RuntimeProfilerState state) {
478 NoBarrier_Store(&thread_local_.runtime_profiler_state_, state);
479 }
480
481 static RuntimeProfilerState SwapRuntimeProfilerState(
482 RuntimeProfilerState state) {
483 return static_cast<RuntimeProfilerState>(
484 NoBarrier_AtomicExchange(&thread_local_.runtime_profiler_state_,
485 state));
486 }
487
488 static RuntimeProfilerState CompareAndSwapRuntimeProfilerState(
489 RuntimeProfilerState old_state,
490 RuntimeProfilerState state) {
491 return static_cast<RuntimeProfilerState>(
492 NoBarrier_CompareAndSwap(&thread_local_.runtime_profiler_state_,
493 old_state,
494 state));
495 }
496
497 static Semaphore* runtime_profiler_semaphore_;
498#endif // ENABLE_VMSTATE_TRACKING
499
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000500 // The context that initiated this JS execution.
501 static ThreadLocalTop thread_local_;
502 static void InitializeThreadLocal();
503 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000504 static void MarkCompactPrologue(bool is_compacting,
505 ThreadLocalTop* archived_thread_data);
506 static void MarkCompactEpilogue(bool is_compacting,
507 ThreadLocalTop* archived_thread_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508
509 // Debug.
510 // Mutex for serializing access to break control structures.
511 static Mutex* break_access_;
512
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000513 friend class SaveContext;
514 friend class AssertNoContextChange;
515 friend class ExecutionAccess;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000516 friend class ThreadLocalTop;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517
518 static void FillCache();
519};
520
521
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000522// If the GCC version is 4.1.x or 4.2.x an additional field is added to the
ager@chromium.org32912102009-01-16 10:38:43 +0000523// class as a work around for a bug in the generated code found with these
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000524// versions of GCC. See V8 issue 122 for details.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525class SaveContext BASE_EMBEDDED {
526 public:
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000527 SaveContext()
528 : context_(Top::context()),
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000529#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000530 dummy_(Top::context()),
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000531#endif
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000532 prev_(Top::save_context()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000533 Top::set_save_context(this);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000534
535 // If there is no JS frame under the current C frame, use the value 0.
536 JavaScriptFrameIterator it;
537 js_sp_ = it.done() ? 0 : it.frame()->sp();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000538 }
539
540 ~SaveContext() {
541 Top::set_context(*context_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542 Top::set_save_context(prev_);
543 }
544
545 Handle<Context> context() { return context_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000546 SaveContext* prev() { return prev_; }
547
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000548 // Returns true if this save context is below a given JavaScript frame.
549 bool below(JavaScriptFrame* frame) {
550 return (js_sp_ == 0) || (frame->sp() < js_sp_);
551 }
552
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553 private:
554 Handle<Context> context_;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000555#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000556 Handle<Context> dummy_;
557#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558 SaveContext* prev_;
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000559 Address js_sp_; // The top JS frame's sp when saving context.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560};
561
562
563class AssertNoContextChange BASE_EMBEDDED {
564#ifdef DEBUG
565 public:
566 AssertNoContextChange() :
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000567 context_(Top::context()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 }
569
570 ~AssertNoContextChange() {
571 ASSERT(Top::context() == *context_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572 }
573
574 private:
575 HandleScope scope_;
576 Handle<Context> context_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000577#else
578 public:
579 AssertNoContextChange() { }
580#endif
581};
582
583
584class ExecutionAccess BASE_EMBEDDED {
585 public:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000586 ExecutionAccess() { Lock(); }
587 ~ExecutionAccess() { Unlock(); }
588
589 static void Lock() { Top::break_access_->Lock(); }
590 static void Unlock() { Top::break_access_->Unlock(); }
591
592 static bool TryLock() {
593 return Top::break_access_->TryLock();
594 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595};
596
597} } // namespace v8::internal
598
599#endif // V8_TOP_H_