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
33namespace v8 {
34namespace internal {
35
36
37// Flag used to set the interrupt causes.
38enum 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
50class Isolate;
51
52
53class 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
179class 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.
185class 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