| 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 |