blob: 3cdbf63e9382b2b82b5d9f461e9441331ca6f0c4 [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,
45 FULL_DEOPT = 1 << 6
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046};
47
ulan@chromium.org812308e2012-02-29 15:58:45 +000048
49class Isolate;
50
51
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052class Execution : public AllStatic {
53 public:
54 // Call a function, the caller supplies a receiver and an array
55 // of arguments. Arguments are Object* type. After function returns,
56 // pointers in 'args' might be invalid.
57 //
58 // *pending_exception tells whether the invoke resulted in
59 // a pending exception.
60 //
lrn@chromium.org34e60782011-09-15 07:25:40 +000061 // When convert_receiver is set, and the receiver is not an object,
62 // and the function called is not in strict mode, receiver is converted to
63 // an object.
64 //
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +000065 static Handle<Object> Call(Handle<Object> callable,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000066 Handle<Object> receiver,
67 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000068 Handle<Object> argv[],
lrn@chromium.org34e60782011-09-15 07:25:40 +000069 bool* pending_exception,
70 bool convert_receiver = false);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071
72 // Construct object from function, the caller supplies an array of
73 // arguments. Arguments are Object* type. After function returns,
74 // pointers in 'args' might be invalid.
75 //
76 // *pending_exception tells whether the invoke resulted in
77 // a pending exception.
78 //
79 static Handle<Object> New(Handle<JSFunction> func,
80 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000081 Handle<Object> argv[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082 bool* pending_exception);
83
84 // Call a function, just like Call(), but make sure to silently catch
85 // any thrown exceptions. The return value is either the result of
86 // calling the function (if caught exception is false) or the exception
87 // that occurred (if caught exception is true).
88 static Handle<Object> TryCall(Handle<JSFunction> func,
89 Handle<Object> receiver,
90 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000091 Handle<Object> argv[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092 bool* caught_exception);
93
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094 // ECMA-262 9.3
95 static Handle<Object> ToNumber(Handle<Object> obj, bool* exc);
96
97 // ECMA-262 9.4
98 static Handle<Object> ToInteger(Handle<Object> obj, bool* exc);
99
100 // ECMA-262 9.5
101 static Handle<Object> ToInt32(Handle<Object> obj, bool* exc);
102
103 // ECMA-262 9.6
104 static Handle<Object> ToUint32(Handle<Object> obj, bool* exc);
105
106 // ECMA-262 9.8
107 static Handle<Object> ToString(Handle<Object> obj, bool* exc);
108
109 // ECMA-262 9.8
110 static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc);
111
112 // ECMA-262 9.9
113 static Handle<Object> ToObject(Handle<Object> obj, bool* exc);
114
115 // Create a new date object from 'time'.
116 static Handle<Object> NewDate(double time, bool* exc);
117
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000118 // Create a new regular expression object from 'pattern' and 'flags'.
119 static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern,
120 Handle<String> flags,
121 bool* exc);
122
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123 // Used to implement [] notation on strings (calls JS code)
124 static Handle<Object> CharAt(Handle<String> str, uint32_t index);
125
126 static Handle<Object> GetFunctionFor();
127 static Handle<JSFunction> InstantiateFunction(
128 Handle<FunctionTemplateInfo> data, bool* exc);
129 static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data,
130 bool* exc);
131 static void ConfigureInstance(Handle<Object> instance,
132 Handle<Object> data,
133 bool* exc);
134 static Handle<String> GetStackTraceLine(Handle<Object> recv,
135 Handle<JSFunction> fun,
136 Handle<Object> pos,
137 Handle<Object> is_global);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000138#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000139 static Object* DebugBreakHelper();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000140 static void ProcessDebugMessages(bool debug_command_only);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000141#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000142
143 // If the stack guard is triggered, but it is not an actual
144 // stack overflow, then handle the interruption accordingly.
ulan@chromium.org812308e2012-02-29 15:58:45 +0000145 MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt(
146 Isolate* isolate);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000147
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148 // Get a function delegate (or undefined) for the given non-function
149 // object. Used for support calling objects as functions.
150 static Handle<Object> GetFunctionDelegate(Handle<Object> object);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000151 static Handle<Object> TryGetFunctionDelegate(Handle<Object> object,
152 bool* has_pending_exception);
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000153
154 // Get a function delegate (or undefined) for the given non-function
155 // object. Used for support calling objects as constructors.
156 static Handle<Object> GetConstructorDelegate(Handle<Object> object);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000157 static Handle<Object> TryGetConstructorDelegate(Handle<Object> object,
158 bool* has_pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000159};
160
161
162class ExecutionAccess;
163
164
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000165// StackGuard contains the handling of the limits that are used to limit the
166// number of nested invocations of JavaScript and the stack size used in each
167// invocation.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000168class StackGuard {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000170 // Pass the address beyond which the stack should not grow. The stack
171 // is assumed to grow downwards.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000172 void SetStackLimit(uintptr_t limit);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 // Threading support.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000175 char* ArchiveStackGuard(char* to);
176 char* RestoreStackGuard(char* from);
177 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
178 void FreeThreadResources();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000179 // Sets up the default stack guard for this thread if it has not
180 // already been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000181 void InitThread(const ExecutionAccess& lock);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000182 // Clears the stack guard for this thread so it does not look as if
183 // it has been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000184 void ClearThread(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000186 bool IsStackOverflow();
187 bool IsPreempted();
188 void Preempt();
189 bool IsInterrupted();
190 void Interrupt();
191 bool IsTerminateExecution();
192 void TerminateExecution();
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000193 void CancelTerminateExecution();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000194#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000195 bool IsDebugBreak();
196 void DebugBreak();
197 bool IsDebugCommand();
198 void DebugCommand();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000199#endif
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000200 bool IsGCRequest();
201 void RequestGC();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000202 bool IsFullDeopt();
203 void FullDeopt();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000204 void Continue(InterruptFlag after_what);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000206 // This provides an asynchronous read of the stack limits for the current
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000207 // thread. There are no locks protecting this, but it is assumed that you
208 // have the global V8 lock if you are using multiple V8 threads.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000209 uintptr_t climit() {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000210 return thread_local_.climit_;
211 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000212 uintptr_t real_climit() {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000213 return thread_local_.real_climit_;
214 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000215 uintptr_t jslimit() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000216 return thread_local_.jslimit_;
217 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000218 uintptr_t real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000219 return thread_local_.real_jslimit_;
220 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000221 Address address_of_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000222 return reinterpret_cast<Address>(&thread_local_.jslimit_);
223 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000224 Address address_of_real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000225 return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
226 }
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000227 bool ShouldPostponeInterrupts();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000230 StackGuard();
231
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000232 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000233 bool has_pending_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000234 // Sanity check: We shouldn't be asking about pending interrupts
235 // unless we're not postponing them anymore.
236 ASSERT(!should_postpone_interrupts(lock));
237 return thread_local_.interrupt_flags_ != 0;
238 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000241 bool should_postpone_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000242 return thread_local_.postpone_interrupts_nesting_ > 0;
243 }
244
245 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000246 inline void set_interrupt_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000248 // Reset limits to actual values. For example after handling interrupt.
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 inline void reset_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251
kasper.lund44510672008-07-25 07:37:58 +0000252 // Enable or disable interrupts.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000253 void EnableInterrupts();
254 void DisableInterrupts();
kasper.lund44510672008-07-25 07:37:58 +0000255
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000256#ifdef V8_TARGET_ARCH_X64
257 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000258 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000259#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000260 static const uintptr_t kInterruptLimit = 0xfffffffe;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000261 static const uintptr_t kIllegalLimit = 0xfffffff8;
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000262#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263
264 class ThreadLocal {
265 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000266 ThreadLocal() { Clear(); }
267 // You should hold the ExecutionAccess lock when you call Initialize or
268 // Clear.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000269 void Clear();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000270
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000271 // Returns true if the heap's stack limits should be set, false if not.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000272 bool Initialize(Isolate* isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000273
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000274 // The stack limit is split into a JavaScript and a C++ stack limit. These
275 // two are the same except when running on a simulator where the C++ and
276 // JavaScript stacks are separate. Each of the two stack limits have two
277 // values. The one eith the real_ prefix is the actual stack limit
278 // set for the VM. The one without the real_ prefix has the same value as
279 // the actual stack limit except when there is an interruption (e.g. debug
280 // break or preemption) in which case it is lowered to make stack checks
281 // fail. Both the generated code and the runtime system check against the
282 // one without the real_ prefix.
283 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000284 uintptr_t jslimit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000285 uintptr_t real_climit_; // Actual C++ stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000286 uintptr_t climit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000287
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288 int nesting_;
kasper.lund44510672008-07-25 07:37:58 +0000289 int postpone_interrupts_nesting_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000290 int interrupt_flags_;
291 };
kasper.lund44510672008-07-25 07:37:58 +0000292
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000293 // TODO(isolates): Technically this could be calculated directly from a
294 // pointer to StackGuard.
295 Isolate* isolate_;
296 ThreadLocal thread_local_;
kasper.lund44510672008-07-25 07:37:58 +0000297
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000298 friend class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000299 friend class StackLimitCheck;
kasper.lund44510672008-07-25 07:37:58 +0000300 friend class PostponeInterruptsScope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000301
302 DISALLOW_COPY_AND_ASSIGN(StackGuard);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000303};
304
305
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306} } // namespace v8::internal
307
308#endif // V8_EXECUTION_H_