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