| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_EXECUTION_H_ | 5 #ifndef V8_EXECUTION_H_ |
| 6 #define V8_EXECUTION_H_ | 6 #define V8_EXECUTION_H_ |
| 7 | 7 |
| 8 #include "src/handles.h" | 8 #include "src/handles.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 // Get a function delegate (or undefined) for the given non-function | 115 // Get a function delegate (or undefined) for the given non-function |
| 116 // object. Used for support calling objects as constructors. | 116 // object. Used for support calling objects as constructors. |
| 117 static Handle<Object> GetConstructorDelegate(Isolate* isolate, | 117 static Handle<Object> GetConstructorDelegate(Isolate* isolate, |
| 118 Handle<Object> object); | 118 Handle<Object> object); |
| 119 static MaybeHandle<Object> TryGetConstructorDelegate(Isolate* isolate, | 119 static MaybeHandle<Object> TryGetConstructorDelegate(Isolate* isolate, |
| 120 Handle<Object> object); | 120 Handle<Object> object); |
| 121 }; | 121 }; |
| 122 | 122 |
| 123 | 123 |
| 124 class ExecutionAccess; | 124 class ExecutionAccess; |
| 125 class PostponeInterruptsScope; | |
| 126 | 125 |
| 127 | 126 |
| 128 // StackGuard contains the handling of the limits that are used to limit the | 127 // StackGuard contains the handling of the limits that are used to limit the |
| 129 // number of nested invocations of JavaScript and the stack size used in each | 128 // number of nested invocations of JavaScript and the stack size used in each |
| 130 // invocation. | 129 // invocation. |
| 131 class StackGuard V8_FINAL { | 130 class StackGuard V8_FINAL { |
| 132 public: | 131 public: |
| 133 // Pass the address beyond which the stack should not grow. The stack | 132 // Pass the address beyond which the stack should not grow. The stack |
| 134 // is assumed to grow downwards. | 133 // is assumed to grow downwards. |
| 135 void SetStackLimit(uintptr_t limit); | 134 void SetStackLimit(uintptr_t limit); |
| 136 | 135 |
| 137 // Threading support. | 136 // Threading support. |
| 138 char* ArchiveStackGuard(char* to); | 137 char* ArchiveStackGuard(char* to); |
| 139 char* RestoreStackGuard(char* from); | 138 char* RestoreStackGuard(char* from); |
| 140 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); } | 139 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); } |
| 141 void FreeThreadResources(); | 140 void FreeThreadResources(); |
| 142 // Sets up the default stack guard for this thread if it has not | 141 // Sets up the default stack guard for this thread if it has not |
| 143 // already been set up. | 142 // already been set up. |
| 144 void InitThread(const ExecutionAccess& lock); | 143 void InitThread(const ExecutionAccess& lock); |
| 145 // Clears the stack guard for this thread so it does not look as if | 144 // Clears the stack guard for this thread so it does not look as if |
| 146 // it has been set up. | 145 // it has been set up. |
| 147 void ClearThread(const ExecutionAccess& lock); | 146 void ClearThread(const ExecutionAccess& lock); |
| 148 | 147 |
| 149 #define INTERRUPT_LIST(V) \ | 148 #define INTERRUPT_LIST(V) \ |
| 150 V(DEBUGBREAK, DebugBreak, 0) \ | 149 V(DEBUGBREAK, DebugBreak) \ |
| 151 V(DEBUGCOMMAND, DebugCommand, 1) \ | 150 V(DEBUGCOMMAND, DebugCommand) \ |
| 152 V(TERMINATE_EXECUTION, TerminateExecution, 2) \ | 151 V(TERMINATE_EXECUTION, TerminateExecution) \ |
| 153 V(GC_REQUEST, GC, 3) \ | 152 V(GC_REQUEST, GC) \ |
| 154 V(INSTALL_CODE, InstallCode, 4) \ | 153 V(INSTALL_CODE, InstallCode) \ |
| 155 V(API_INTERRUPT, ApiInterrupt, 5) \ | 154 V(API_INTERRUPT, ApiInterrupt) \ |
| 156 V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites, 6) | 155 V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites) |
| 157 | 156 |
| 158 #define V(NAME, Name, id) \ | 157 #define V(NAME, Name) \ |
| 159 inline bool Check##Name() { return CheckInterrupt(NAME); } \ | 158 inline bool Check##Name() { return CheckInterrupt(1 << NAME); } \ |
| 160 inline void Request##Name() { RequestInterrupt(NAME); } \ | 159 inline void Request##Name() { RequestInterrupt(1 << NAME); } \ |
| 161 inline void Clear##Name() { ClearInterrupt(NAME); } | 160 inline void Clear##Name() { ClearInterrupt(1 << NAME); } |
| 162 INTERRUPT_LIST(V) | 161 INTERRUPT_LIST(V) |
| 163 #undef V | 162 #undef V |
| 164 | 163 |
| 165 // Flag used to set the interrupt causes. | |
| 166 enum InterruptFlag { | |
| 167 #define V(NAME, Name, id) NAME = (1 << id), | |
| 168 INTERRUPT_LIST(V) | |
| 169 #undef V | |
| 170 #define V(NAME, Name, id) NAME | | |
| 171 ALL_INTERRUPTS = INTERRUPT_LIST(V) 0 | |
| 172 #undef V | |
| 173 }; | |
| 174 | |
| 175 // This provides an asynchronous read of the stack limits for the current | 164 // This provides an asynchronous read of the stack limits for the current |
| 176 // thread. There are no locks protecting this, but it is assumed that you | 165 // thread. There are no locks protecting this, but it is assumed that you |
| 177 // have the global V8 lock if you are using multiple V8 threads. | 166 // have the global V8 lock if you are using multiple V8 threads. |
| 178 uintptr_t climit() { | 167 uintptr_t climit() { |
| 179 return thread_local_.climit_; | 168 return thread_local_.climit_; |
| 180 } | 169 } |
| 181 uintptr_t real_climit() { | 170 uintptr_t real_climit() { |
| 182 return thread_local_.real_climit_; | 171 return thread_local_.real_climit_; |
| 183 } | 172 } |
| 184 uintptr_t jslimit() { | 173 uintptr_t jslimit() { |
| 185 return thread_local_.jslimit_; | 174 return thread_local_.jslimit_; |
| 186 } | 175 } |
| 187 uintptr_t real_jslimit() { | 176 uintptr_t real_jslimit() { |
| 188 return thread_local_.real_jslimit_; | 177 return thread_local_.real_jslimit_; |
| 189 } | 178 } |
| 190 Address address_of_jslimit() { | 179 Address address_of_jslimit() { |
| 191 return reinterpret_cast<Address>(&thread_local_.jslimit_); | 180 return reinterpret_cast<Address>(&thread_local_.jslimit_); |
| 192 } | 181 } |
| 193 Address address_of_real_jslimit() { | 182 Address address_of_real_jslimit() { |
| 194 return reinterpret_cast<Address>(&thread_local_.real_jslimit_); | 183 return reinterpret_cast<Address>(&thread_local_.real_jslimit_); |
| 195 } | 184 } |
| 196 | 185 |
| 197 // If the stack guard is triggered, but it is not an actual | 186 // If the stack guard is triggered, but it is not an actual |
| 198 // stack overflow, then handle the interruption accordingly. | 187 // stack overflow, then handle the interruption accordingly. |
| 199 Object* HandleInterrupts(); | 188 Object* HandleInterrupts(); |
| 200 | 189 |
| 201 private: | 190 private: |
| 202 StackGuard(); | 191 StackGuard(); |
| 203 | 192 |
| 204 bool CheckInterrupt(InterruptFlag flag); | 193 // Flag used to set the interrupt causes. |
| 205 void RequestInterrupt(InterruptFlag flag); | 194 enum InterruptFlag { |
| 206 void ClearInterrupt(InterruptFlag flag); | 195 #define V(NAME, Name) NAME, |
| 196 INTERRUPT_LIST(V) |
| 197 #undef V |
| 198 NUMBER_OF_INTERRUPTS |
| 199 }; |
| 200 |
| 201 bool CheckInterrupt(int flagbit); |
| 202 void RequestInterrupt(int flagbit); |
| 203 void ClearInterrupt(int flagbit); |
| 207 bool CheckAndClearInterrupt(InterruptFlag flag); | 204 bool CheckAndClearInterrupt(InterruptFlag flag); |
| 208 | 205 |
| 209 // You should hold the ExecutionAccess lock when calling this method. | 206 // You should hold the ExecutionAccess lock when calling this method. |
| 210 bool has_pending_interrupts(const ExecutionAccess& lock) { | 207 bool has_pending_interrupts(const ExecutionAccess& lock) { |
| 208 // Sanity check: We shouldn't be asking about pending interrupts |
| 209 // unless we're not postponing them anymore. |
| 210 ASSERT(!should_postpone_interrupts(lock)); |
| 211 return thread_local_.interrupt_flags_ != 0; | 211 return thread_local_.interrupt_flags_ != 0; |
| 212 } | 212 } |
| 213 | 213 |
| 214 // You should hold the ExecutionAccess lock when calling this method. | 214 // You should hold the ExecutionAccess lock when calling this method. |
| 215 bool should_postpone_interrupts(const ExecutionAccess& lock) { |
| 216 return thread_local_.postpone_interrupts_nesting_ > 0; |
| 217 } |
| 218 |
| 219 // You should hold the ExecutionAccess lock when calling this method. |
| 215 inline void set_interrupt_limits(const ExecutionAccess& lock); | 220 inline void set_interrupt_limits(const ExecutionAccess& lock); |
| 216 | 221 |
| 217 // Reset limits to actual values. For example after handling interrupt. | 222 // Reset limits to actual values. For example after handling interrupt. |
| 218 // You should hold the ExecutionAccess lock when calling this method. | 223 // You should hold the ExecutionAccess lock when calling this method. |
| 219 inline void reset_limits(const ExecutionAccess& lock); | 224 inline void reset_limits(const ExecutionAccess& lock); |
| 220 | 225 |
| 221 // Enable or disable interrupts. | 226 // Enable or disable interrupts. |
| 222 void EnableInterrupts(); | 227 void EnableInterrupts(); |
| 223 void DisableInterrupts(); | 228 void DisableInterrupts(); |
| 224 | 229 |
| 225 #if V8_TARGET_ARCH_64_BIT | 230 #if V8_TARGET_ARCH_64_BIT |
| 226 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe); | 231 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe); |
| 227 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8); | 232 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8); |
| 228 #else | 233 #else |
| 229 static const uintptr_t kInterruptLimit = 0xfffffffe; | 234 static const uintptr_t kInterruptLimit = 0xfffffffe; |
| 230 static const uintptr_t kIllegalLimit = 0xfffffff8; | 235 static const uintptr_t kIllegalLimit = 0xfffffff8; |
| 231 #endif | 236 #endif |
| 232 | 237 |
| 233 void PushPostponeInterruptsScope(PostponeInterruptsScope* scope); | |
| 234 void PopPostponeInterruptsScope(); | |
| 235 | |
| 236 class ThreadLocal V8_FINAL { | 238 class ThreadLocal V8_FINAL { |
| 237 public: | 239 public: |
| 238 ThreadLocal() { Clear(); } | 240 ThreadLocal() { Clear(); } |
| 239 // You should hold the ExecutionAccess lock when you call Initialize or | 241 // You should hold the ExecutionAccess lock when you call Initialize or |
| 240 // Clear. | 242 // Clear. |
| 241 void Clear(); | 243 void Clear(); |
| 242 | 244 |
| 243 // Returns true if the heap's stack limits should be set, false if not. | 245 // Returns true if the heap's stack limits should be set, false if not. |
| 244 bool Initialize(Isolate* isolate); | 246 bool Initialize(Isolate* isolate); |
| 245 | 247 |
| 246 // The stack limit is split into a JavaScript and a C++ stack limit. These | 248 // The stack limit is split into a JavaScript and a C++ stack limit. These |
| 247 // two are the same except when running on a simulator where the C++ and | 249 // two are the same except when running on a simulator where the C++ and |
| 248 // JavaScript stacks are separate. Each of the two stack limits have two | 250 // JavaScript stacks are separate. Each of the two stack limits have two |
| 249 // values. The one eith the real_ prefix is the actual stack limit | 251 // values. The one eith the real_ prefix is the actual stack limit |
| 250 // set for the VM. The one without the real_ prefix has the same value as | 252 // set for the VM. The one without the real_ prefix has the same value as |
| 251 // the actual stack limit except when there is an interruption (e.g. debug | 253 // the actual stack limit except when there is an interruption (e.g. debug |
| 252 // break or preemption) in which case it is lowered to make stack checks | 254 // break or preemption) in which case it is lowered to make stack checks |
| 253 // fail. Both the generated code and the runtime system check against the | 255 // fail. Both the generated code and the runtime system check against the |
| 254 // one without the real_ prefix. | 256 // one without the real_ prefix. |
| 255 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM. | 257 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM. |
| 256 uintptr_t jslimit_; | 258 uintptr_t jslimit_; |
| 257 uintptr_t real_climit_; // Actual C++ stack limit set for the VM. | 259 uintptr_t real_climit_; // Actual C++ stack limit set for the VM. |
| 258 uintptr_t climit_; | 260 uintptr_t climit_; |
| 259 | 261 |
| 260 PostponeInterruptsScope* postpone_interrupts_; | 262 int nesting_; |
| 263 int postpone_interrupts_nesting_; |
| 261 int interrupt_flags_; | 264 int interrupt_flags_; |
| 262 }; | 265 }; |
| 263 | 266 |
| 264 class StackPointer { | 267 class StackPointer { |
| 265 public: | 268 public: |
| 266 inline uintptr_t address() { return reinterpret_cast<uintptr_t>(this); } | 269 inline uintptr_t address() { return reinterpret_cast<uintptr_t>(this); } |
| 267 }; | 270 }; |
| 268 | 271 |
| 269 // TODO(isolates): Technically this could be calculated directly from a | 272 // TODO(isolates): Technically this could be calculated directly from a |
| 270 // pointer to StackGuard. | 273 // pointer to StackGuard. |
| 271 Isolate* isolate_; | 274 Isolate* isolate_; |
| 272 ThreadLocal thread_local_; | 275 ThreadLocal thread_local_; |
| 273 | 276 |
| 274 friend class Isolate; | 277 friend class Isolate; |
| 275 friend class StackLimitCheck; | 278 friend class StackLimitCheck; |
| 276 friend class PostponeInterruptsScope; | 279 friend class PostponeInterruptsScope; |
| 277 | 280 |
| 278 DISALLOW_COPY_AND_ASSIGN(StackGuard); | 281 DISALLOW_COPY_AND_ASSIGN(StackGuard); |
| 279 }; | 282 }; |
| 280 | 283 |
| 281 } } // namespace v8::internal | 284 } } // namespace v8::internal |
| 282 | 285 |
| 283 #endif // V8_EXECUTION_H_ | 286 #endif // V8_EXECUTION_H_ |
| OLD | NEW |