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