84f106a49689954d8f2d33625c7b14226be68976
[platform/upstream/v8.git] / src / execution.h
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
3 // found in the LICENSE file.
4
5 #ifndef V8_EXECUTION_H_
6 #define V8_EXECUTION_H_
7
8 #include "src/allocation.h"
9 #include "src/base/atomicops.h"
10 #include "src/handles.h"
11 #include "src/utils.h"
12
13 namespace v8 {
14 namespace internal {
15
16 // Forward declarations.
17 class JSRegExp;
18
19 class Execution final : public AllStatic {
20  public:
21   // Call a function, the caller supplies a receiver and an array
22   // of arguments.
23   //
24   // When the function called is not in strict mode, receiver is
25   // converted to an object.
26   //
27   MUST_USE_RESULT static MaybeHandle<Object> Call(Isolate* isolate,
28                                                   Handle<Object> callable,
29                                                   Handle<Object> receiver,
30                                                   int argc,
31                                                   Handle<Object> argv[]);
32
33   // Construct object from function, the caller supplies an array of
34   // arguments.
35   MUST_USE_RESULT static MaybeHandle<Object> New(Handle<JSFunction> constructor,
36                                                  int argc,
37                                                  Handle<Object> argv[]);
38   MUST_USE_RESULT static MaybeHandle<Object> New(Isolate* isolate,
39                                                  Handle<Object> constructor,
40                                                  Handle<Object> new_target,
41                                                  int argc,
42                                                  Handle<Object> argv[]);
43
44   // Call a function, just like Call(), but make sure to silently catch
45   // any thrown exceptions. The return value is either the result of
46   // calling the function (if caught exception is false) or the exception
47   // that occurred (if caught exception is true).
48   // In the exception case, exception_out holds the caught exceptions, unless
49   // it is a termination exception.
50   static MaybeHandle<Object> TryCall(Handle<JSFunction> func,
51                                      Handle<Object> receiver, int argc,
52                                      Handle<Object> argv[],
53                                      MaybeHandle<Object>* exception_out = NULL);
54
55   // ECMA-262 9.8
56   MUST_USE_RESULT static MaybeHandle<Object> ToDetailString(
57       Isolate* isolate, Handle<Object> obj);
58
59   // ECMA-262 9.9
60   MUST_USE_RESULT static MaybeHandle<Object> ToObject(
61       Isolate* isolate, Handle<Object> obj);
62
63   // Create a new date object from 'time'.
64   MUST_USE_RESULT static MaybeHandle<Object> NewDate(
65       Isolate* isolate, double time);
66
67   // Create a new regular expression object from 'pattern' and 'flags'.
68   MUST_USE_RESULT static MaybeHandle<JSRegExp> NewJSRegExp(
69       Handle<String> pattern, Handle<String> flags);
70
71   static Handle<String> GetStackTraceLine(Handle<Object> recv,
72                                           Handle<JSFunction> fun,
73                                           Handle<Object> pos,
74                                           Handle<Object> is_global);
75 };
76
77
78 class ExecutionAccess;
79 class PostponeInterruptsScope;
80
81
82 // StackGuard contains the handling of the limits that are used to limit the
83 // number of nested invocations of JavaScript and the stack size used in each
84 // invocation.
85 class StackGuard final {
86  public:
87   // Pass the address beyond which the stack should not grow.  The stack
88   // is assumed to grow downwards.
89   void SetStackLimit(uintptr_t limit);
90
91   // The simulator uses a separate JS stack. Limits on the JS stack might have
92   // to be adjusted in order to reflect overflows of the C stack, because we
93   // cannot rely on the interleaving of frames on the simulator.
94   void AdjustStackLimitForSimulator();
95
96   // Threading support.
97   char* ArchiveStackGuard(char* to);
98   char* RestoreStackGuard(char* from);
99   static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
100   void FreeThreadResources();
101   // Sets up the default stack guard for this thread if it has not
102   // already been set up.
103   void InitThread(const ExecutionAccess& lock);
104   // Clears the stack guard for this thread so it does not look as if
105   // it has been set up.
106   void ClearThread(const ExecutionAccess& lock);
107
108 #define INTERRUPT_LIST(V)                                          \
109   V(DEBUGBREAK, DebugBreak, 0)                                     \
110   V(DEBUGCOMMAND, DebugCommand, 1)                                 \
111   V(TERMINATE_EXECUTION, TerminateExecution, 2)                    \
112   V(GC_REQUEST, GC, 3)                                             \
113   V(INSTALL_CODE, InstallCode, 4)                                  \
114   V(API_INTERRUPT, ApiInterrupt, 5)                                \
115   V(DEOPT_MARKED_ALLOCATION_SITES, DeoptMarkedAllocationSites, 6)
116
117 #define V(NAME, Name, id)                                          \
118   inline bool Check##Name() { return CheckInterrupt(NAME); }  \
119   inline void Request##Name() { RequestInterrupt(NAME); }     \
120   inline void Clear##Name() { ClearInterrupt(NAME); }
121   INTERRUPT_LIST(V)
122 #undef V
123
124   // Flag used to set the interrupt causes.
125   enum InterruptFlag {
126   #define V(NAME, Name, id) NAME = (1 << id),
127     INTERRUPT_LIST(V)
128   #undef V
129   #define V(NAME, Name, id) NAME |
130     ALL_INTERRUPTS = INTERRUPT_LIST(V) 0
131   #undef V
132   };
133
134   uintptr_t climit() { return thread_local_.climit(); }
135   uintptr_t jslimit() { return thread_local_.jslimit(); }
136   // This provides an asynchronous read of the stack limits for the current
137   // thread.  There are no locks protecting this, but it is assumed that you
138   // have the global V8 lock if you are using multiple V8 threads.
139   uintptr_t real_climit() {
140     return thread_local_.real_climit_;
141   }
142   uintptr_t real_jslimit() {
143     return thread_local_.real_jslimit_;
144   }
145   Address address_of_jslimit() {
146     return reinterpret_cast<Address>(&thread_local_.jslimit_);
147   }
148   Address address_of_real_jslimit() {
149     return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
150   }
151
152   // If the stack guard is triggered, but it is not an actual
153   // stack overflow, then handle the interruption accordingly.
154   Object* HandleInterrupts();
155   void HandleGCInterrupt();
156
157  private:
158   StackGuard();
159
160   bool CheckInterrupt(InterruptFlag flag);
161   void RequestInterrupt(InterruptFlag flag);
162   void ClearInterrupt(InterruptFlag flag);
163   bool CheckAndClearInterrupt(InterruptFlag flag);
164
165   // You should hold the ExecutionAccess lock when calling this method.
166   bool has_pending_interrupts(const ExecutionAccess& lock) {
167     return thread_local_.interrupt_flags_ != 0;
168   }
169
170   // You should hold the ExecutionAccess lock when calling this method.
171   inline void set_interrupt_limits(const ExecutionAccess& lock);
172
173   // Reset limits to actual values. For example after handling interrupt.
174   // You should hold the ExecutionAccess lock when calling this method.
175   inline void reset_limits(const ExecutionAccess& lock);
176
177   // Enable or disable interrupts.
178   void EnableInterrupts();
179   void DisableInterrupts();
180
181 #if V8_TARGET_ARCH_64_BIT
182   static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
183   static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
184 #else
185   static const uintptr_t kInterruptLimit = 0xfffffffe;
186   static const uintptr_t kIllegalLimit = 0xfffffff8;
187 #endif
188
189   void PushPostponeInterruptsScope(PostponeInterruptsScope* scope);
190   void PopPostponeInterruptsScope();
191
192   class ThreadLocal final {
193    public:
194     ThreadLocal() { Clear(); }
195     // You should hold the ExecutionAccess lock when you call Initialize or
196     // Clear.
197     void Clear();
198
199     // Returns true if the heap's stack limits should be set, false if not.
200     bool Initialize(Isolate* isolate);
201
202     // The stack limit is split into a JavaScript and a C++ stack limit. These
203     // two are the same except when running on a simulator where the C++ and
204     // JavaScript stacks are separate. Each of the two stack limits have two
205     // values. The one eith the real_ prefix is the actual stack limit
206     // set for the VM. The one without the real_ prefix has the same value as
207     // the actual stack limit except when there is an interruption (e.g. debug
208     // break or preemption) in which case it is lowered to make stack checks
209     // fail. Both the generated code and the runtime system check against the
210     // one without the real_ prefix.
211     uintptr_t real_jslimit_;  // Actual JavaScript stack limit set for the VM.
212     uintptr_t real_climit_;  // Actual C++ stack limit set for the VM.
213
214     // jslimit_ and climit_ can be read without any lock.
215     // Writing requires the ExecutionAccess lock.
216     base::AtomicWord jslimit_;
217     base::AtomicWord climit_;
218
219     uintptr_t jslimit() {
220       return bit_cast<uintptr_t>(base::NoBarrier_Load(&jslimit_));
221     }
222     void set_jslimit(uintptr_t limit) {
223       return base::NoBarrier_Store(&jslimit_,
224                                    static_cast<base::AtomicWord>(limit));
225     }
226     uintptr_t climit() {
227       return bit_cast<uintptr_t>(base::NoBarrier_Load(&climit_));
228     }
229     void set_climit(uintptr_t limit) {
230       return base::NoBarrier_Store(&climit_,
231                                    static_cast<base::AtomicWord>(limit));
232     }
233
234     PostponeInterruptsScope* postpone_interrupts_;
235     int interrupt_flags_;
236   };
237
238   // TODO(isolates): Technically this could be calculated directly from a
239   //                 pointer to StackGuard.
240   Isolate* isolate_;
241   ThreadLocal thread_local_;
242
243   friend class Isolate;
244   friend class StackLimitCheck;
245   friend class PostponeInterruptsScope;
246
247   DISALLOW_COPY_AND_ASSIGN(StackGuard);
248 };
249
250 } }  // namespace v8::internal
251
252 #endif  // V8_EXECUTION_H_