• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 };
43 
44 class Execution : public AllStatic {
45  public:
46   // Call a function, the caller supplies a receiver and an array
47   // of arguments. Arguments are Object* type. After function returns,
48   // pointers in 'args' might be invalid.
49   //
50   // *pending_exception tells whether the invoke resulted in
51   // a pending exception.
52   //
53   static Handle<Object> Call(Handle<JSFunction> func,
54                              Handle<Object> receiver,
55                              int argc,
56                              Object*** args,
57                              bool* pending_exception);
58 
59   // Construct object from function, the caller supplies an array of
60   // arguments. Arguments are Object* type. After function returns,
61   // pointers in 'args' might be invalid.
62   //
63   // *pending_exception tells whether the invoke resulted in
64   // a pending exception.
65   //
66   static Handle<Object> New(Handle<JSFunction> func,
67                             int argc,
68                             Object*** args,
69                             bool* pending_exception);
70 
71   // Call a function, just like Call(), but make sure to silently catch
72   // any thrown exceptions. The return value is either the result of
73   // calling the function (if caught exception is false) or the exception
74   // that occurred (if caught exception is true).
75   static Handle<Object> TryCall(Handle<JSFunction> func,
76                                 Handle<Object> receiver,
77                                 int argc,
78                                 Object*** args,
79                                 bool* caught_exception);
80 
81   // ECMA-262 9.2
82   static Handle<Object> ToBoolean(Handle<Object> obj);
83 
84   // ECMA-262 9.3
85   static Handle<Object> ToNumber(Handle<Object> obj, bool* exc);
86 
87   // ECMA-262 9.4
88   static Handle<Object> ToInteger(Handle<Object> obj, bool* exc);
89 
90   // ECMA-262 9.5
91   static Handle<Object> ToInt32(Handle<Object> obj, bool* exc);
92 
93   // ECMA-262 9.6
94   static Handle<Object> ToUint32(Handle<Object> obj, bool* exc);
95 
96   // ECMA-262 9.8
97   static Handle<Object> ToString(Handle<Object> obj, bool* exc);
98 
99   // ECMA-262 9.8
100   static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc);
101 
102   // ECMA-262 9.9
103   static Handle<Object> ToObject(Handle<Object> obj, bool* exc);
104 
105   // Create a new date object from 'time'.
106   static Handle<Object> NewDate(double time, bool* exc);
107 
108   // Used to implement [] notation on strings (calls JS code)
109   static Handle<Object> CharAt(Handle<String> str, uint32_t index);
110 
111   static Handle<Object> GetFunctionFor();
112   static Handle<JSFunction> InstantiateFunction(
113       Handle<FunctionTemplateInfo> data, bool* exc);
114   static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data,
115                                             bool* exc);
116   static void ConfigureInstance(Handle<Object> instance,
117                                 Handle<Object> data,
118                                 bool* exc);
119   static Handle<String> GetStackTraceLine(Handle<Object> recv,
120                                           Handle<JSFunction> fun,
121                                           Handle<Object> pos,
122                                           Handle<Object> is_global);
123 #ifdef ENABLE_DEBUGGER_SUPPORT
124   static Object* DebugBreakHelper();
125 #endif
126 
127   // If the stack guard is triggered, but it is not an actual
128   // stack overflow, then handle the interruption accordingly.
129   static Object* HandleStackGuardInterrupt();
130 
131   // Get a function delegate (or undefined) for the given non-function
132   // object. Used for support calling objects as functions.
133   static Handle<Object> GetFunctionDelegate(Handle<Object> object);
134 
135   // Get a function delegate (or undefined) for the given non-function
136   // object. Used for support calling objects as constructors.
137   static Handle<Object> GetConstructorDelegate(Handle<Object> object);
138 };
139 
140 
141 class ExecutionAccess;
142 
143 
144 // Stack guards are used to limit the number of nested invocations of
145 // JavaScript and the stack size used in each invocation.
146 class StackGuard BASE_EMBEDDED {
147  public:
148   StackGuard();
149 
150   ~StackGuard();
151 
152   static void SetStackLimit(uintptr_t limit);
153 
address_of_jslimit()154   static Address address_of_jslimit() {
155     return reinterpret_cast<Address>(&thread_local_.jslimit_);
156   }
157 
158   // Threading support.
159   static char* ArchiveStackGuard(char* to);
160   static char* RestoreStackGuard(char* from);
161   static int ArchiveSpacePerThread();
162 
163   static bool IsStackOverflow();
164   static bool IsPreempted();
165   static void Preempt();
166   static bool IsInterrupted();
167   static void Interrupt();
168   static bool IsTerminateExecution();
169   static void TerminateExecution();
170 #ifdef ENABLE_DEBUGGER_SUPPORT
171   static bool IsDebugBreak();
172   static void DebugBreak();
173   static bool IsDebugCommand();
174   static void DebugCommand();
175 #endif
176   static void Continue(InterruptFlag after_what);
177 
jslimit()178   static uintptr_t jslimit() {
179     return thread_local_.jslimit_;
180   }
181 
182  private:
183   // You should hold the ExecutionAccess lock when calling this method.
184   static bool IsSet(const ExecutionAccess& lock);
185 
186   // This provides an asynchronous read of the stack limit for the current
187   // thread.  There are no locks protecting this, but it is assumed that you
188   // have the global V8 lock if you are using multiple V8 threads.
climit()189   static uintptr_t climit() {
190     return thread_local_.climit_;
191   }
192 
193   // You should hold the ExecutionAccess lock when calling this method.
set_limits(uintptr_t value,const ExecutionAccess & lock)194   static void set_limits(uintptr_t value, const ExecutionAccess& lock) {
195     Heap::SetStackLimit(value);
196     thread_local_.jslimit_ = value;
197     thread_local_.climit_ = value;
198   }
199 
200   // Reset limits to initial values. For example after handling interrupt.
201   // You should hold the ExecutionAccess lock when calling this method.
reset_limits(const ExecutionAccess & lock)202   static void reset_limits(const ExecutionAccess& lock) {
203     if (thread_local_.nesting_ == 0) {
204       // No limits have been set yet.
205       set_limits(kIllegalLimit, lock);
206     } else {
207       thread_local_.jslimit_ = thread_local_.initial_jslimit_;
208       Heap::SetStackLimit(thread_local_.jslimit_);
209       thread_local_.climit_ = thread_local_.initial_climit_;
210     }
211   }
212 
213   // Enable or disable interrupts.
214   static void EnableInterrupts();
215   static void DisableInterrupts();
216 
217   static const uintptr_t kLimitSize = kPointerSize * 128 * KB;
218 #ifdef V8_TARGET_ARCH_X64
219   static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
220   static const uintptr_t kIllegalLimit = V8_UINT64_C(0xffffffffffffffff);
221 #else
222   static const uintptr_t kInterruptLimit = 0xfffffffe;
223   static const uintptr_t kIllegalLimit = 0xffffffff;
224 #endif
225 
226   class ThreadLocal {
227    public:
ThreadLocal()228     ThreadLocal()
229       : initial_jslimit_(kIllegalLimit),
230         jslimit_(kIllegalLimit),
231         initial_climit_(kIllegalLimit),
232         climit_(kIllegalLimit),
233         nesting_(0),
234         postpone_interrupts_nesting_(0),
235         interrupt_flags_(0) {
236       Heap::SetStackLimit(kIllegalLimit);
237     }
238     uintptr_t initial_jslimit_;
239     uintptr_t jslimit_;
240     uintptr_t initial_climit_;
241     uintptr_t climit_;
242     int nesting_;
243     int postpone_interrupts_nesting_;
244     int interrupt_flags_;
245   };
246 
247   static ThreadLocal thread_local_;
248 
249   friend class StackLimitCheck;
250   friend class PostponeInterruptsScope;
251 };
252 
253 
254 // Support for checking for stack-overflows in C++ code.
255 class StackLimitCheck BASE_EMBEDDED {
256  public:
HasOverflowed()257   bool HasOverflowed() const {
258     // Stack has overflowed in C++ code only if stack pointer exceeds the C++
259     // stack guard and the limits are not set to interrupt values.
260     // TODO(214): Stack overflows are ignored if a interrupt is pending. This
261     // code should probably always use the initial C++ limit.
262     return (reinterpret_cast<uintptr_t>(this) < StackGuard::climit()) &&
263            StackGuard::IsStackOverflow();
264   }
265 };
266 
267 
268 // Support for temporarily postponing interrupts. When the outermost
269 // postpone scope is left the interrupts will be re-enabled and any
270 // interrupts that occurred while in the scope will be taken into
271 // account.
272 class PostponeInterruptsScope BASE_EMBEDDED {
273  public:
PostponeInterruptsScope()274   PostponeInterruptsScope() {
275     StackGuard::thread_local_.postpone_interrupts_nesting_++;
276     StackGuard::DisableInterrupts();
277   }
278 
~PostponeInterruptsScope()279   ~PostponeInterruptsScope() {
280     if (--StackGuard::thread_local_.postpone_interrupts_nesting_ == 0) {
281       StackGuard::EnableInterrupts();
282     }
283   }
284 };
285 
286 
287 class GCExtension : public v8::Extension {
288  public:
GCExtension()289   GCExtension() : v8::Extension("v8/gc", kSource) {}
290   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
291       v8::Handle<v8::String> name);
292   static v8::Handle<v8::Value> GC(const v8::Arguments& args);
293  private:
294   static const char* kSource;
295 };
296 
297 
298 } }  // namespace v8::internal
299 
300 #endif  // V8_EXECUTION_H_
301