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 RUNTIME_PROFILER_TICK = 1 << 5 43 }; 44 45 class Execution : public AllStatic { 46 public: 47 // Call a function, the caller supplies a receiver and an array 48 // of arguments. Arguments are Object* type. After function returns, 49 // pointers in 'args' might be invalid. 50 // 51 // *pending_exception tells whether the invoke resulted in 52 // a pending exception. 53 // 54 static Handle<Object> Call(Handle<JSFunction> func, 55 Handle<Object> receiver, 56 int argc, 57 Object*** args, 58 bool* pending_exception); 59 60 // Construct object from function, the caller supplies an array of 61 // arguments. Arguments are Object* type. After function returns, 62 // pointers in 'args' might be invalid. 63 // 64 // *pending_exception tells whether the invoke resulted in 65 // a pending exception. 66 // 67 static Handle<Object> New(Handle<JSFunction> func, 68 int argc, 69 Object*** args, 70 bool* pending_exception); 71 72 // Call a function, just like Call(), but make sure to silently catch 73 // any thrown exceptions. The return value is either the result of 74 // calling the function (if caught exception is false) or the exception 75 // that occurred (if caught exception is true). 76 static Handle<Object> TryCall(Handle<JSFunction> func, 77 Handle<Object> receiver, 78 int argc, 79 Object*** args, 80 bool* caught_exception); 81 82 // ECMA-262 9.2 83 static Handle<Object> ToBoolean(Handle<Object> obj); 84 85 // ECMA-262 9.3 86 static Handle<Object> ToNumber(Handle<Object> obj, bool* exc); 87 88 // ECMA-262 9.4 89 static Handle<Object> ToInteger(Handle<Object> obj, bool* exc); 90 91 // ECMA-262 9.5 92 static Handle<Object> ToInt32(Handle<Object> obj, bool* exc); 93 94 // ECMA-262 9.6 95 static Handle<Object> ToUint32(Handle<Object> obj, bool* exc); 96 97 // ECMA-262 9.8 98 static Handle<Object> ToString(Handle<Object> obj, bool* exc); 99 100 // ECMA-262 9.8 101 static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc); 102 103 // ECMA-262 9.9 104 static Handle<Object> ToObject(Handle<Object> obj, bool* exc); 105 106 // Create a new date object from 'time'. 107 static Handle<Object> NewDate(double time, bool* exc); 108 109 // Create a new regular expression object from 'pattern' and 'flags'. 110 static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern, 111 Handle<String> flags, 112 bool* exc); 113 114 // Used to implement [] notation on strings (calls JS code) 115 static Handle<Object> CharAt(Handle<String> str, uint32_t index); 116 117 static Handle<Object> GetFunctionFor(); 118 static Handle<JSFunction> InstantiateFunction( 119 Handle<FunctionTemplateInfo> data, bool* exc); 120 static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data, 121 bool* exc); 122 static void ConfigureInstance(Handle<Object> instance, 123 Handle<Object> data, 124 bool* exc); 125 static Handle<String> GetStackTraceLine(Handle<Object> recv, 126 Handle<JSFunction> fun, 127 Handle<Object> pos, 128 Handle<Object> is_global); 129 #ifdef ENABLE_DEBUGGER_SUPPORT 130 static Object* DebugBreakHelper(); 131 static void ProcessDebugMesssages(bool debug_command_only); 132 #endif 133 134 // If the stack guard is triggered, but it is not an actual 135 // stack overflow, then handle the interruption accordingly. 136 MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt(); 137 138 // Get a function delegate (or undefined) for the given non-function 139 // object. Used for support calling objects as functions. 140 static Handle<Object> GetFunctionDelegate(Handle<Object> object); 141 142 // Get a function delegate (or undefined) for the given non-function 143 // object. Used for support calling objects as constructors. 144 static Handle<Object> GetConstructorDelegate(Handle<Object> object); 145 }; 146 147 148 class ExecutionAccess; 149 class Isolate; 150 151 152 // StackGuard contains the handling of the limits that are used to limit the 153 // number of nested invocations of JavaScript and the stack size used in each 154 // invocation. 155 class StackGuard { 156 public: 157 // Pass the address beyond which the stack should not grow. The stack 158 // is assumed to grow downwards. 159 void SetStackLimit(uintptr_t limit); 160 161 // Threading support. 162 char* ArchiveStackGuard(char* to); 163 char* RestoreStackGuard(char* from); 164 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); } 165 void FreeThreadResources(); 166 // Sets up the default stack guard for this thread if it has not 167 // already been set up. 168 void InitThread(const ExecutionAccess& lock); 169 // Clears the stack guard for this thread so it does not look as if 170 // it has been set up. 171 void ClearThread(const ExecutionAccess& lock); 172 173 bool IsStackOverflow(); 174 bool IsPreempted(); 175 void Preempt(); 176 bool IsInterrupted(); 177 void Interrupt(); 178 bool IsTerminateExecution(); 179 void TerminateExecution(); 180 bool IsRuntimeProfilerTick(); 181 void RequestRuntimeProfilerTick(); 182 #ifdef ENABLE_DEBUGGER_SUPPORT 183 bool IsDebugBreak(); 184 void DebugBreak(); 185 bool IsDebugCommand(); 186 void DebugCommand(); 187 #endif 188 void Continue(InterruptFlag after_what); 189 190 // This provides an asynchronous read of the stack limits for the current 191 // thread. There are no locks protecting this, but it is assumed that you 192 // have the global V8 lock if you are using multiple V8 threads. 193 uintptr_t climit() { 194 return thread_local_.climit_; 195 } 196 uintptr_t real_climit() { 197 return thread_local_.real_climit_; 198 } 199 uintptr_t jslimit() { 200 return thread_local_.jslimit_; 201 } 202 uintptr_t real_jslimit() { 203 return thread_local_.real_jslimit_; 204 } 205 Address address_of_jslimit() { 206 return reinterpret_cast<Address>(&thread_local_.jslimit_); 207 } 208 Address address_of_real_jslimit() { 209 return reinterpret_cast<Address>(&thread_local_.real_jslimit_); 210 } 211 212 private: 213 StackGuard(); 214 215 // You should hold the ExecutionAccess lock when calling this method. 216 bool has_pending_interrupts(const ExecutionAccess& lock) { 217 // Sanity check: We shouldn't be asking about pending interrupts 218 // unless we're not postponing them anymore. 219 ASSERT(!should_postpone_interrupts(lock)); 220 return thread_local_.interrupt_flags_ != 0; 221 } 222 223 // You should hold the ExecutionAccess lock when calling this method. 224 bool should_postpone_interrupts(const ExecutionAccess& lock) { 225 return thread_local_.postpone_interrupts_nesting_ > 0; 226 } 227 228 // You should hold the ExecutionAccess lock when calling this method. 229 inline void set_interrupt_limits(const ExecutionAccess& lock); 230 231 // Reset limits to actual values. For example after handling interrupt. 232 // You should hold the ExecutionAccess lock when calling this method. 233 inline void reset_limits(const ExecutionAccess& lock); 234 235 // Enable or disable interrupts. 236 void EnableInterrupts(); 237 void DisableInterrupts(); 238 239 #ifdef V8_TARGET_ARCH_X64 240 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe); 241 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8); 242 #else 243 static const uintptr_t kInterruptLimit = 0xfffffffe; 244 static const uintptr_t kIllegalLimit = 0xfffffff8; 245 #endif 246 247 class ThreadLocal { 248 public: 249 ThreadLocal() { Clear(); } 250 // You should hold the ExecutionAccess lock when you call Initialize or 251 // Clear. 252 void Clear(); 253 254 // Returns true if the heap's stack limits should be set, false if not. 255 bool Initialize(); 256 257 // The stack limit is split into a JavaScript and a C++ stack limit. These 258 // two are the same except when running on a simulator where the C++ and 259 // JavaScript stacks are separate. Each of the two stack limits have two 260 // values. The one eith the real_ prefix is the actual stack limit 261 // set for the VM. The one without the real_ prefix has the same value as 262 // the actual stack limit except when there is an interruption (e.g. debug 263 // break or preemption) in which case it is lowered to make stack checks 264 // fail. Both the generated code and the runtime system check against the 265 // one without the real_ prefix. 266 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM. 267 uintptr_t jslimit_; 268 uintptr_t real_climit_; // Actual C++ stack limit set for the VM. 269 uintptr_t climit_; 270 271 int nesting_; 272 int postpone_interrupts_nesting_; 273 int interrupt_flags_; 274 }; 275 276 // TODO(isolates): Technically this could be calculated directly from a 277 // pointer to StackGuard. 278 Isolate* isolate_; 279 ThreadLocal thread_local_; 280 281 friend class Isolate; 282 friend class StackLimitCheck; 283 friend class PostponeInterruptsScope; 284 285 DISALLOW_COPY_AND_ASSIGN(StackGuard); 286 }; 287 288 289 } } // namespace v8::internal 290 291 #endif // V8_EXECUTION_H_ 292