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