Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/top.h

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/token.cc ('k') | src/top.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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_
OLDNEW
« no previous file with comments | « src/token.cc ('k') | src/top.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698