blob: 371ea309d6cb9bca24e409596a94b6aea66d6b43 [file] [log] [blame]
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
32
kasperl@chromium.org71affb52009-05-26 05:44:31 +000033namespace v8 {
34namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
36
37// Flag used to set the interrupt causes.
38enum InterruptFlag {
39 INTERRUPT = 1 << 0,
40 DEBUGBREAK = 1 << 1,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000041 DEBUGCOMMAND = 1 << 2,
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000042 PREEMPT = 1 << 3,
kasperl@chromium.orga5551262010-12-07 12:49:48 +000043 TERMINATE = 1 << 4,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000044 GC_REQUEST = 1 << 5,
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +000045 FULL_DEOPT = 1 << 6,
46 INSTALL_CODE = 1 << 7
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047};
48
ulan@chromium.org812308e2012-02-29 15:58:45 +000049
50class Isolate;
51
52
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000053class 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 //
lrn@chromium.org34e60782011-09-15 07:25:40 +000062 // 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 //
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +000066 static Handle<Object> Call(Isolate* isolate,
67 Handle<Object> callable,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068 Handle<Object> receiver,
69 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000070 Handle<Object> argv[],
lrn@chromium.org34e60782011-09-15 07:25:40 +000071 bool* pending_exception,
72 bool convert_receiver = false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000073
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,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000083 Handle<Object> argv[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000084 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,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000093 Handle<Object> argv[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094 bool* caught_exception);
95
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096 // ECMA-262 9.3
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000097 static Handle<Object> ToNumber(
98 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099
100 // ECMA-262 9.4
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000101 static Handle<Object> ToInteger(
102 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103
104 // ECMA-262 9.5
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000105 static Handle<Object> ToInt32(
106 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107
108 // ECMA-262 9.6
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000109 static Handle<Object> ToUint32(
110 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111
112 // ECMA-262 9.8
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000113 static Handle<Object> ToString(
114 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115
116 // ECMA-262 9.8
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000117 static Handle<Object> ToDetailString(
118 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119
120 // ECMA-262 9.9
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000121 static Handle<Object> ToObject(
122 Isolate* isolate, Handle<Object> obj, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123
124 // Create a new date object from 'time'.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000125 static Handle<Object> NewDate(
126 Isolate* isolate, double time, bool* exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000127
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000128 // 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000133 // 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);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000141 static void ConfigureInstance(Isolate* isolate,
142 Handle<Object> instance,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000143 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);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000149#ifdef ENABLE_DEBUGGER_SUPPORT
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000150 static Object* DebugBreakHelper(Isolate* isolate);
151 static void ProcessDebugMessages(Isolate* isolate, bool debug_command_only);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000152#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000153
154 // If the stack guard is triggered, but it is not an actual
155 // stack overflow, then handle the interruption accordingly.
ulan@chromium.org812308e2012-02-29 15:58:45 +0000156 MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt(
157 Isolate* isolate);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000158
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000159 // Get a function delegate (or undefined) for the given non-function
160 // object. Used for support calling objects as functions.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000161 static Handle<Object> GetFunctionDelegate(Isolate* isolate,
162 Handle<Object> object);
163 static Handle<Object> TryGetFunctionDelegate(Isolate* isolate,
164 Handle<Object> object,
lrn@chromium.org1c092762011-05-09 09:42:16 +0000165 bool* has_pending_exception);
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000166
167 // Get a function delegate (or undefined) for the given non-function
168 // object. Used for support calling objects as constructors.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +0000169 static Handle<Object> GetConstructorDelegate(Isolate* isolate,
170 Handle<Object> object);
171 static Handle<Object> TryGetConstructorDelegate(Isolate* isolate,
172 Handle<Object> object,
lrn@chromium.org1c092762011-05-09 09:42:16 +0000173 bool* has_pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174};
175
176
177class ExecutionAccess;
178
179
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000180// StackGuard contains the handling of the limits that are used to limit the
181// number of nested invocations of JavaScript and the stack size used in each
182// invocation.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000183class StackGuard {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000185 // Pass the address beyond which the stack should not grow. The stack
186 // is assumed to grow downwards.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000187 void SetStackLimit(uintptr_t limit);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189 // Threading support.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000190 char* ArchiveStackGuard(char* to);
191 char* RestoreStackGuard(char* from);
192 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
193 void FreeThreadResources();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000194 // Sets up the default stack guard for this thread if it has not
195 // already been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000196 void InitThread(const ExecutionAccess& lock);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000197 // Clears the stack guard for this thread so it does not look as if
198 // it has been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 void ClearThread(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000201 bool IsStackOverflow();
202 bool IsPreempted();
203 void Preempt();
204 bool IsInterrupted();
205 void Interrupt();
206 bool IsTerminateExecution();
207 void TerminateExecution();
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000208 void CancelTerminateExecution();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000209#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000210 bool IsDebugBreak();
211 void DebugBreak();
212 bool IsDebugCommand();
213 void DebugCommand();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000214#endif
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000215 bool IsGCRequest();
216 void RequestGC();
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000217 bool IsInstallCodeRequest();
218 void RequestInstallCode();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000219 bool IsFullDeopt();
220 void FullDeopt();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000221 void Continue(InterruptFlag after_what);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000223 // This provides an asynchronous read of the stack limits for the current
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000224 // thread. There are no locks protecting this, but it is assumed that you
225 // have the global V8 lock if you are using multiple V8 threads.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000226 uintptr_t climit() {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000227 return thread_local_.climit_;
228 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000229 uintptr_t real_climit() {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000230 return thread_local_.real_climit_;
231 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000232 uintptr_t jslimit() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000233 return thread_local_.jslimit_;
234 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000235 uintptr_t real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000236 return thread_local_.real_jslimit_;
237 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000238 Address address_of_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000239 return reinterpret_cast<Address>(&thread_local_.jslimit_);
240 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000241 Address address_of_real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000242 return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
243 }
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000244 bool ShouldPostponeInterrupts();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000245
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000246 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000247 StackGuard();
248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000250 bool has_pending_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000251 // Sanity check: We shouldn't be asking about pending interrupts
252 // unless we're not postponing them anymore.
253 ASSERT(!should_postpone_interrupts(lock));
254 return thread_local_.interrupt_flags_ != 0;
255 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000256
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000258 bool should_postpone_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000259 return thread_local_.postpone_interrupts_nesting_ > 0;
260 }
261
262 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000263 inline void set_interrupt_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000264
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000265 // Reset limits to actual values. For example after handling interrupt.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000266 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000267 inline void reset_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000268
kasper.lund44510672008-07-25 07:37:58 +0000269 // Enable or disable interrupts.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000270 void EnableInterrupts();
271 void DisableInterrupts();
kasper.lund44510672008-07-25 07:37:58 +0000272
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +0000273#if V8_TARGET_ARCH_X64
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000274 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000275 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000276#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277 static const uintptr_t kInterruptLimit = 0xfffffffe;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000278 static const uintptr_t kIllegalLimit = 0xfffffff8;
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000279#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000280
281 class ThreadLocal {
282 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000283 ThreadLocal() { Clear(); }
284 // You should hold the ExecutionAccess lock when you call Initialize or
285 // Clear.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000286 void Clear();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000287
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000288 // Returns true if the heap's stack limits should be set, false if not.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000289 bool Initialize(Isolate* isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000290
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000291 // The stack limit is split into a JavaScript and a C++ stack limit. These
292 // two are the same except when running on a simulator where the C++ and
293 // JavaScript stacks are separate. Each of the two stack limits have two
294 // values. The one eith the real_ prefix is the actual stack limit
295 // set for the VM. The one without the real_ prefix has the same value as
296 // the actual stack limit except when there is an interruption (e.g. debug
297 // break or preemption) in which case it is lowered to make stack checks
298 // fail. Both the generated code and the runtime system check against the
299 // one without the real_ prefix.
300 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000301 uintptr_t jslimit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000302 uintptr_t real_climit_; // Actual C++ stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000303 uintptr_t climit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000304
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 int nesting_;
kasper.lund44510672008-07-25 07:37:58 +0000306 int postpone_interrupts_nesting_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000307 int interrupt_flags_;
308 };
kasper.lund44510672008-07-25 07:37:58 +0000309
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000310 // TODO(isolates): Technically this could be calculated directly from a
311 // pointer to StackGuard.
312 Isolate* isolate_;
313 ThreadLocal thread_local_;
kasper.lund44510672008-07-25 07:37:58 +0000314
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000315 friend class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316 friend class StackLimitCheck;
kasper.lund44510672008-07-25 07:37:58 +0000317 friend class PostponeInterruptsScope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000318
319 DISALLOW_COPY_AND_ASSIGN(StackGuard);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320};
321
322
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000323} } // namespace v8::internal
324
325#endif // V8_EXECUTION_H_