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 "frames-inl.h" | |
32 #include "isolate.h" | |
33 | |
34 namespace v8 { | |
35 namespace internal { | |
36 | |
37 | |
38 #define RETURN_IF_SCHEDULED_EXCEPTION() \ | |
39 if (Top::has_scheduled_exception()) return Top::PromoteScheduledException() | |
40 | |
41 // Top has static variables used for JavaScript execution. | |
42 | |
43 class SaveContext; // Forward declaration. | |
44 class ThreadVisitor; // Defined in v8threads.h | |
45 | |
46 #define TOP_ADDRESS_LIST(C) \ | |
47 C(handler_address) \ | |
48 C(c_entry_fp_address) \ | |
49 C(context_address) \ | |
50 C(pending_exception_address) \ | |
51 C(external_caught_exception_address) | |
52 | |
53 #ifdef ENABLE_LOGGING_AND_PROFILING | |
54 #define TOP_ADDRESS_LIST_PROF(C) \ | |
55 C(js_entry_sp_address) | |
56 #else | |
57 #define TOP_ADDRESS_LIST_PROF(C) | |
58 #endif | |
59 | |
60 | |
61 class Top { | |
62 public: | |
63 enum AddressId { | |
64 #define C(name) k_##name, | |
65 TOP_ADDRESS_LIST(C) | |
66 TOP_ADDRESS_LIST_PROF(C) | |
67 #undef C | |
68 k_top_address_count | |
69 }; | |
70 | |
71 static Address get_address_from_id(AddressId id); | |
72 | |
73 // Access to top context (where the current function object was created). | |
74 static Context* context() { return thread_local()->context_; } | |
75 static void set_context(Context* context) { | |
76 thread_local()->context_ = context; | |
77 } | |
78 static Context** context_address() { return &thread_local()->context_; } | |
79 | |
80 static SaveContext* save_context() {return thread_local()->save_context_; } | |
81 static void set_save_context(SaveContext* save) { | |
82 thread_local()->save_context_ = save; | |
83 } | |
84 | |
85 // Access to current thread id. | |
86 static int thread_id() { return thread_local()->thread_id_; } | |
87 static void set_thread_id(int id) { thread_local()->thread_id_ = id; } | |
88 | |
89 // Interface to pending exception. | |
90 static Object* pending_exception() { | |
91 ASSERT(has_pending_exception()); | |
92 return thread_local()->pending_exception_; | |
93 } | |
94 static bool external_caught_exception() { | |
95 return thread_local()->external_caught_exception_; | |
96 } | |
97 static void set_pending_exception(Object* exception) { | |
98 thread_local()->pending_exception_ = exception; | |
99 } | |
100 static void clear_pending_exception() { | |
101 thread_local()->pending_exception_ = HEAP->the_hole_value(); | |
102 } | |
103 | |
104 static Object** pending_exception_address() { | |
105 return &thread_local()->pending_exception_; | |
106 } | |
107 static bool has_pending_exception() { | |
108 return !thread_local()->pending_exception_->IsTheHole(); | |
109 } | |
110 static void clear_pending_message() { | |
111 thread_local()->has_pending_message_ = false; | |
112 thread_local()->pending_message_ = NULL; | |
113 thread_local()->pending_message_obj_ = HEAP->the_hole_value(); | |
114 thread_local()->pending_message_script_ = NULL; | |
115 } | |
116 static v8::TryCatch* try_catch_handler() { | |
117 return thread_local()->TryCatchHandler(); | |
118 } | |
119 static Address try_catch_handler_address() { | |
120 return thread_local()->try_catch_handler_address(); | |
121 } | |
122 // This method is called by the api after operations that may throw | |
123 // exceptions. If an exception was thrown and not handled by an external | |
124 // handler the exception is scheduled to be rethrown when we return to running | |
125 // JavaScript code. If an exception is scheduled true is returned. | |
126 static bool OptionalRescheduleException(bool is_bottom_call); | |
127 | |
128 | |
129 static bool* external_caught_exception_address() { | |
130 return &thread_local()->external_caught_exception_; | |
131 } | |
132 | |
133 static Object** scheduled_exception_address() { | |
134 return &thread_local()->scheduled_exception_; | |
135 } | |
136 | |
137 static Object* scheduled_exception() { | |
138 ASSERT(has_scheduled_exception()); | |
139 return thread_local()->scheduled_exception_; | |
140 } | |
141 static bool has_scheduled_exception() { | |
142 return !thread_local()->scheduled_exception_->IsTheHole(); | |
143 } | |
144 static void clear_scheduled_exception() { | |
145 thread_local()->scheduled_exception_ = HEAP->the_hole_value(); | |
146 } | |
147 | |
148 static void setup_external_caught() { | |
149 thread_local()->external_caught_exception_ = | |
150 has_pending_exception() && | |
151 (thread_local()->catcher_ != NULL) && | |
152 (try_catch_handler() == thread_local()->catcher_); | |
153 } | |
154 | |
155 // Tells whether the current context has experienced an out of memory | |
156 // exception. | |
157 static bool is_out_of_memory(); | |
158 | |
159 // JS execution stack (see frames.h). | |
160 static Address c_entry_fp(ThreadLocalTop* thread) { | |
161 return thread->c_entry_fp_; | |
162 } | |
163 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } | |
164 | |
165 static inline Address* c_entry_fp_address() { | |
166 return &thread_local()->c_entry_fp_; | |
167 } | |
168 static inline Address* handler_address() { return &thread_local()->handler_; } | |
169 | |
170 #ifdef ENABLE_LOGGING_AND_PROFILING | |
171 // Bottom JS entry (see StackTracer::Trace in log.cc). | |
172 static Address js_entry_sp(ThreadLocalTop* thread) { | |
173 return thread->js_entry_sp_; | |
174 } | |
175 static inline Address* js_entry_sp_address() { | |
176 return &thread_local()->js_entry_sp_; | |
177 } | |
178 #endif | |
179 | |
180 // Generated code scratch locations. | |
181 static void* formal_count_address() { return &thread_local()->formal_count_; } | |
182 | |
183 static void MarkCompactPrologue(bool is_compacting); | |
184 static void MarkCompactEpilogue(bool is_compacting); | |
185 static void MarkCompactPrologue(bool is_compacting, | |
186 char* archived_thread_data); | |
187 static void MarkCompactEpilogue(bool is_compacting, | |
188 char* archived_thread_data); | |
189 static void PrintCurrentStackTrace(FILE* out); | |
190 static void PrintStackTrace(FILE* out, char* thread_data); | |
191 static void PrintStack(StringStream* accumulator); | |
192 static void PrintStack(); | |
193 static Handle<String> StackTraceString(); | |
194 static Local<StackTrace> CaptureCurrentStackTrace( | |
195 int frame_limit, | |
196 StackTrace::StackTraceOptions options); | |
197 | |
198 // Returns if the top context may access the given global object. If | |
199 // the result is false, the pending exception is guaranteed to be | |
200 // set. | |
201 static bool MayNamedAccess(JSObject* receiver, | |
202 Object* key, | |
203 v8::AccessType type); | |
204 static bool MayIndexedAccess(JSObject* receiver, | |
205 uint32_t index, | |
206 v8::AccessType type); | |
207 | |
208 static void SetFailedAccessCheckCallback( | |
209 v8::FailedAccessCheckCallback callback); | |
210 static void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type); | |
211 | |
212 // Exception throwing support. The caller should use the result | |
213 // of Throw() as its return value. | |
214 static Failure* Throw(Object* exception, MessageLocation* location = NULL); | |
215 // Re-throw an exception. This involves no error reporting since | |
216 // error reporting was handled when the exception was thrown | |
217 // originally. | |
218 static Failure* ReThrow(Object* exception, MessageLocation* location = NULL); | |
219 static void ScheduleThrow(Object* exception); | |
220 static void ReportPendingMessages(); | |
221 static Failure* ThrowIllegalOperation(); | |
222 | |
223 // Promote a scheduled exception to pending. Asserts has_scheduled_exception. | |
224 static Object* PromoteScheduledException(); | |
225 static void DoThrow(Object* exception, | |
226 MessageLocation* location, | |
227 const char* message); | |
228 static bool ShouldReturnException(bool* is_caught_externally, | |
229 bool catchable_by_javascript); | |
230 static void ReportUncaughtException(Handle<Object> exception, | |
231 MessageLocation* location, | |
232 Handle<String> stack_trace); | |
233 | |
234 // Attempts to compute the current source location, storing the | |
235 // result in the target out parameter. | |
236 static void ComputeLocation(MessageLocation* target); | |
237 | |
238 // Override command line flag. | |
239 static void TraceException(bool flag); | |
240 | |
241 // Out of resource exception helpers. | |
242 static Failure* StackOverflow(); | |
243 static Failure* TerminateExecution(); | |
244 | |
245 // Administration | |
246 static void Initialize(); | |
247 static void TearDown(); | |
248 static void Iterate(ObjectVisitor* v); | |
249 static void Iterate(ObjectVisitor* v, ThreadLocalTop* t); | |
250 static char* Iterate(ObjectVisitor* v, char* t); | |
251 static void IterateThread(ThreadVisitor* v); | |
252 static void IterateThread(ThreadVisitor* v, char* t); | |
253 | |
254 // Returns the global object of the current context. It could be | |
255 // a builtin object, or a js global object. | |
256 static Handle<GlobalObject> global() { | |
257 return Handle<GlobalObject>(context()->global()); | |
258 } | |
259 | |
260 // Returns the global proxy object of the current context. | |
261 static Object* global_proxy() { | |
262 return context()->global_proxy(); | |
263 } | |
264 | |
265 // Returns the current global context. | |
266 static Handle<Context> global_context(); | |
267 | |
268 // Returns the global context of the calling JavaScript code. That | |
269 // is, the global context of the top-most JavaScript frame. | |
270 static Handle<Context> GetCallingGlobalContext(); | |
271 | |
272 static Handle<JSBuiltinsObject> builtins() { | |
273 return Handle<JSBuiltinsObject>(thread_local()->context_->builtins()); | |
274 } | |
275 | |
276 static void RegisterTryCatchHandler(v8::TryCatch* that); | |
277 static void UnregisterTryCatchHandler(v8::TryCatch* that); | |
278 | |
279 #define TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \ | |
280 static Handle<type> name() { \ | |
281 return Handle<type>(context()->global_context()->name()); \ | |
282 } | |
283 GLOBAL_CONTEXT_FIELDS(TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR) | |
284 #undef TOP_GLOBAL_CONTEXT_FIELD_ACCESSOR | |
285 | |
286 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } | |
287 static char* ArchiveThread(char* to); | |
288 static char* RestoreThread(char* from); | |
289 static void FreeThreadResources() { thread_local()->Free(); } | |
290 | |
291 static const char* kStackOverflowMessage; | |
292 | |
293 private: | |
294 // The context that initiated this JS execution. | |
295 static ThreadLocalTop* thread_local() { | |
296 return Isolate::Current()->thread_local_top(); | |
297 } | |
298 static void InitializeThreadLocal(); | |
299 static void PrintStackTrace(FILE* out, ThreadLocalTop* thread); | |
300 static void MarkCompactPrologue(bool is_compacting, | |
301 ThreadLocalTop* archived_thread_data); | |
302 static void MarkCompactEpilogue(bool is_compacting, | |
303 ThreadLocalTop* archived_thread_data); | |
304 | |
305 friend class SaveContext; | |
306 friend class AssertNoContextChange; | |
307 friend class ExecutionAccess; | |
308 | |
309 static void FillCache(); | |
310 }; | |
311 | |
312 | |
313 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the | |
314 // class as a work around for a bug in the generated code found with these | |
315 // versions of GCC. See V8 issue 122 for details. | |
316 class SaveContext BASE_EMBEDDED { | |
317 public: | |
318 SaveContext() | |
319 : context_(Top::context()), | |
320 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300 | |
321 dummy_(Top::context()), | |
322 #endif | |
323 prev_(Top::save_context()) { | |
324 Top::set_save_context(this); | |
325 | |
326 // If there is no JS frame under the current C frame, use the value 0. | |
327 JavaScriptFrameIterator it; | |
328 js_sp_ = it.done() ? 0 : it.frame()->sp(); | |
329 } | |
330 | |
331 ~SaveContext() { | |
332 Top::set_context(*context_); | |
333 Top::set_save_context(prev_); | |
334 } | |
335 | |
336 Handle<Context> context() { return context_; } | |
337 SaveContext* prev() { return prev_; } | |
338 | |
339 // Returns true if this save context is below a given JavaScript frame. | |
340 bool below(JavaScriptFrame* frame) { | |
341 return (js_sp_ == 0) || (frame->sp() < js_sp_); | |
342 } | |
343 | |
344 private: | |
345 Handle<Context> context_; | |
346 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300 | |
347 Handle<Context> dummy_; | |
348 #endif | |
349 SaveContext* prev_; | |
350 Address js_sp_; // The top JS frame's sp when saving context. | |
351 }; | |
352 | |
353 | |
354 class AssertNoContextChange BASE_EMBEDDED { | |
355 #ifdef DEBUG | |
356 public: | |
357 AssertNoContextChange() : | |
358 context_(Top::context()) { | |
359 } | |
360 | |
361 ~AssertNoContextChange() { | |
362 ASSERT(Top::context() == *context_); | |
363 } | |
364 | |
365 private: | |
366 HandleScope scope_; | |
367 Handle<Context> context_; | |
368 #else | |
369 public: | |
370 AssertNoContextChange() { } | |
371 #endif | |
372 }; | |
373 | |
374 | |
375 class ExecutionAccess BASE_EMBEDDED { | |
376 public: | |
377 ExecutionAccess(); | |
378 ~ExecutionAccess(); | |
379 }; | |
380 | |
381 } } // namespace v8::internal | |
382 | |
383 #endif // V8_TOP_H_ | |
OLD | NEW |