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_EXECUTION_H_ 29 #define V8_EXECUTION_H_ 30 31 namespace v8 { 32 namespace internal { 33 34 35 // Flag used to set the interrupt causes. 36 enum InterruptFlag { 37 INTERRUPT = 1 << 0, 38 DEBUGBREAK = 1 << 1, 39 DEBUGCOMMAND = 1 << 2, 40 PREEMPT = 1 << 3, 41 TERMINATE = 1 << 4 42 }; 43 44 class Execution : public AllStatic { 45 public: 46 // Call a function, the caller supplies a receiver and an array 47 // of arguments. Arguments are Object* type. After function returns, 48 // pointers in 'args' might be invalid. 49 // 50 // *pending_exception tells whether the invoke resulted in 51 // a pending exception. 52 // 53 static Handle<Object> Call(Handle<JSFunction> func, 54 Handle<Object> receiver, 55 int argc, 56 Object*** args, 57 bool* pending_exception); 58 59 // Construct object from function, the caller supplies an array of 60 // arguments. Arguments are Object* type. After function returns, 61 // pointers in 'args' might be invalid. 62 // 63 // *pending_exception tells whether the invoke resulted in 64 // a pending exception. 65 // 66 static Handle<Object> New(Handle<JSFunction> func, 67 int argc, 68 Object*** args, 69 bool* pending_exception); 70 71 // Call a function, just like Call(), but make sure to silently catch 72 // any thrown exceptions. The return value is either the result of 73 // calling the function (if caught exception is false) or the exception 74 // that occurred (if caught exception is true). 75 static Handle<Object> TryCall(Handle<JSFunction> func, 76 Handle<Object> receiver, 77 int argc, 78 Object*** args, 79 bool* caught_exception); 80 81 // ECMA-262 9.2 82 static Handle<Object> ToBoolean(Handle<Object> obj); 83 84 // ECMA-262 9.3 85 static Handle<Object> ToNumber(Handle<Object> obj, bool* exc); 86 87 // ECMA-262 9.4 88 static Handle<Object> ToInteger(Handle<Object> obj, bool* exc); 89 90 // ECMA-262 9.5 91 static Handle<Object> ToInt32(Handle<Object> obj, bool* exc); 92 93 // ECMA-262 9.6 94 static Handle<Object> ToUint32(Handle<Object> obj, bool* exc); 95 96 // ECMA-262 9.8 97 static Handle<Object> ToString(Handle<Object> obj, bool* exc); 98 99 // ECMA-262 9.8 100 static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc); 101 102 // ECMA-262 9.9 103 static Handle<Object> ToObject(Handle<Object> obj, bool* exc); 104 105 // Create a new date object from 'time'. 106 static Handle<Object> NewDate(double time, bool* exc); 107 108 // Used to implement [] notation on strings (calls JS code) 109 static Handle<Object> CharAt(Handle<String> str, uint32_t index); 110 111 static Handle<Object> GetFunctionFor(); 112 static Handle<JSFunction> InstantiateFunction( 113 Handle<FunctionTemplateInfo> data, bool* exc); 114 static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data, 115 bool* exc); 116 static void ConfigureInstance(Handle<Object> instance, 117 Handle<Object> data, 118 bool* exc); 119 static Handle<String> GetStackTraceLine(Handle<Object> recv, 120 Handle<JSFunction> fun, 121 Handle<Object> pos, 122 Handle<Object> is_global); 123 #ifdef ENABLE_DEBUGGER_SUPPORT 124 static Object* DebugBreakHelper(); 125 #endif 126 127 // If the stack guard is triggered, but it is not an actual 128 // stack overflow, then handle the interruption accordingly. 129 static Object* HandleStackGuardInterrupt(); 130 131 // Get a function delegate (or undefined) for the given non-function 132 // object. Used for support calling objects as functions. 133 static Handle<Object> GetFunctionDelegate(Handle<Object> object); 134 135 // Get a function delegate (or undefined) for the given non-function 136 // object. Used for support calling objects as constructors. 137 static Handle<Object> GetConstructorDelegate(Handle<Object> object); 138 }; 139 140 141 class ExecutionAccess; 142 143 144 // Stack guards are used to limit the number of nested invocations of 145 // JavaScript and the stack size used in each invocation. 146 class StackGuard BASE_EMBEDDED { 147 public: 148 StackGuard(); 149 150 ~StackGuard(); 151 152 static void SetStackLimit(uintptr_t limit); 153 address_of_jslimit()154 static Address address_of_jslimit() { 155 return reinterpret_cast<Address>(&thread_local_.jslimit_); 156 } 157 158 // Threading support. 159 static char* ArchiveStackGuard(char* to); 160 static char* RestoreStackGuard(char* from); 161 static int ArchiveSpacePerThread(); 162 163 static bool IsStackOverflow(); 164 static bool IsPreempted(); 165 static void Preempt(); 166 static bool IsInterrupted(); 167 static void Interrupt(); 168 static bool IsTerminateExecution(); 169 static void TerminateExecution(); 170 #ifdef ENABLE_DEBUGGER_SUPPORT 171 static bool IsDebugBreak(); 172 static void DebugBreak(); 173 static bool IsDebugCommand(); 174 static void DebugCommand(); 175 #endif 176 static void Continue(InterruptFlag after_what); 177 jslimit()178 static uintptr_t jslimit() { 179 return thread_local_.jslimit_; 180 } 181 182 private: 183 // You should hold the ExecutionAccess lock when calling this method. 184 static bool IsSet(const ExecutionAccess& lock); 185 186 // This provides an asynchronous read of the stack limit for the current 187 // thread. There are no locks protecting this, but it is assumed that you 188 // have the global V8 lock if you are using multiple V8 threads. climit()189 static uintptr_t climit() { 190 return thread_local_.climit_; 191 } 192 193 // You should hold the ExecutionAccess lock when calling this method. set_limits(uintptr_t value,const ExecutionAccess & lock)194 static void set_limits(uintptr_t value, const ExecutionAccess& lock) { 195 Heap::SetStackLimit(value); 196 thread_local_.jslimit_ = value; 197 thread_local_.climit_ = value; 198 } 199 200 // Reset limits to initial values. For example after handling interrupt. 201 // You should hold the ExecutionAccess lock when calling this method. reset_limits(const ExecutionAccess & lock)202 static void reset_limits(const ExecutionAccess& lock) { 203 if (thread_local_.nesting_ == 0) { 204 // No limits have been set yet. 205 set_limits(kIllegalLimit, lock); 206 } else { 207 thread_local_.jslimit_ = thread_local_.initial_jslimit_; 208 Heap::SetStackLimit(thread_local_.jslimit_); 209 thread_local_.climit_ = thread_local_.initial_climit_; 210 } 211 } 212 213 // Enable or disable interrupts. 214 static void EnableInterrupts(); 215 static void DisableInterrupts(); 216 217 static const uintptr_t kLimitSize = kPointerSize * 128 * KB; 218 #ifdef V8_TARGET_ARCH_X64 219 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe); 220 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xffffffffffffffff); 221 #else 222 static const uintptr_t kInterruptLimit = 0xfffffffe; 223 static const uintptr_t kIllegalLimit = 0xffffffff; 224 #endif 225 226 class ThreadLocal { 227 public: ThreadLocal()228 ThreadLocal() 229 : initial_jslimit_(kIllegalLimit), 230 jslimit_(kIllegalLimit), 231 initial_climit_(kIllegalLimit), 232 climit_(kIllegalLimit), 233 nesting_(0), 234 postpone_interrupts_nesting_(0), 235 interrupt_flags_(0) { 236 Heap::SetStackLimit(kIllegalLimit); 237 } 238 uintptr_t initial_jslimit_; 239 uintptr_t jslimit_; 240 uintptr_t initial_climit_; 241 uintptr_t climit_; 242 int nesting_; 243 int postpone_interrupts_nesting_; 244 int interrupt_flags_; 245 }; 246 247 static ThreadLocal thread_local_; 248 249 friend class StackLimitCheck; 250 friend class PostponeInterruptsScope; 251 }; 252 253 254 // Support for checking for stack-overflows in C++ code. 255 class StackLimitCheck BASE_EMBEDDED { 256 public: HasOverflowed()257 bool HasOverflowed() const { 258 // Stack has overflowed in C++ code only if stack pointer exceeds the C++ 259 // stack guard and the limits are not set to interrupt values. 260 // TODO(214): Stack overflows are ignored if a interrupt is pending. This 261 // code should probably always use the initial C++ limit. 262 return (reinterpret_cast<uintptr_t>(this) < StackGuard::climit()) && 263 StackGuard::IsStackOverflow(); 264 } 265 }; 266 267 268 // Support for temporarily postponing interrupts. When the outermost 269 // postpone scope is left the interrupts will be re-enabled and any 270 // interrupts that occurred while in the scope will be taken into 271 // account. 272 class PostponeInterruptsScope BASE_EMBEDDED { 273 public: PostponeInterruptsScope()274 PostponeInterruptsScope() { 275 StackGuard::thread_local_.postpone_interrupts_nesting_++; 276 StackGuard::DisableInterrupts(); 277 } 278 ~PostponeInterruptsScope()279 ~PostponeInterruptsScope() { 280 if (--StackGuard::thread_local_.postpone_interrupts_nesting_ == 0) { 281 StackGuard::EnableInterrupts(); 282 } 283 } 284 }; 285 286 287 class GCExtension : public v8::Extension { 288 public: GCExtension()289 GCExtension() : v8::Extension("v8/gc", kSource) {} 290 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( 291 v8::Handle<v8::String> name); 292 static v8::Handle<v8::Value> GC(const v8::Arguments& args); 293 private: 294 static const char* kSource; 295 }; 296 297 298 } } // namespace v8::internal 299 300 #endif // V8_EXECUTION_H_ 301