blob: bb5f804506883b6d77e2b28c995d8cd7450ae2d2 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 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,
44 RUNTIME_PROFILER_TICK = 1 << 5
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045};
46
47class Execution : public AllStatic {
48 public:
49 // Call a function, the caller supplies a receiver and an array
50 // of arguments. Arguments are Object* type. After function returns,
51 // pointers in 'args' might be invalid.
52 //
53 // *pending_exception tells whether the invoke resulted in
54 // a pending exception.
55 //
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +000056 static Handle<Object> Call(Handle<Object> callable,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000057 Handle<Object> receiver,
58 int argc,
59 Object*** args,
60 bool* pending_exception);
61
62 // Construct object from function, the caller supplies an array of
63 // arguments. Arguments are Object* type. After function returns,
64 // pointers in 'args' might be invalid.
65 //
66 // *pending_exception tells whether the invoke resulted in
67 // a pending exception.
68 //
69 static Handle<Object> New(Handle<JSFunction> func,
70 int argc,
71 Object*** args,
72 bool* pending_exception);
73
74 // Call a function, just like Call(), but make sure to silently catch
75 // any thrown exceptions. The return value is either the result of
76 // calling the function (if caught exception is false) or the exception
77 // that occurred (if caught exception is true).
78 static Handle<Object> TryCall(Handle<JSFunction> func,
79 Handle<Object> receiver,
80 int argc,
81 Object*** args,
82 bool* caught_exception);
83
84 // ECMA-262 9.2
85 static Handle<Object> ToBoolean(Handle<Object> obj);
86
87 // ECMA-262 9.3
88 static Handle<Object> ToNumber(Handle<Object> obj, bool* exc);
89
90 // ECMA-262 9.4
91 static Handle<Object> ToInteger(Handle<Object> obj, bool* exc);
92
93 // ECMA-262 9.5
94 static Handle<Object> ToInt32(Handle<Object> obj, bool* exc);
95
96 // ECMA-262 9.6
97 static Handle<Object> ToUint32(Handle<Object> obj, bool* exc);
98
99 // ECMA-262 9.8
100 static Handle<Object> ToString(Handle<Object> obj, bool* exc);
101
102 // ECMA-262 9.8
103 static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc);
104
105 // ECMA-262 9.9
106 static Handle<Object> ToObject(Handle<Object> obj, bool* exc);
107
108 // Create a new date object from 'time'.
109 static Handle<Object> NewDate(double time, bool* exc);
110
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000111 // Create a new regular expression object from 'pattern' and 'flags'.
112 static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern,
113 Handle<String> flags,
114 bool* exc);
115
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116 // Used to implement [] notation on strings (calls JS code)
117 static Handle<Object> CharAt(Handle<String> str, uint32_t index);
118
119 static Handle<Object> GetFunctionFor();
120 static Handle<JSFunction> InstantiateFunction(
121 Handle<FunctionTemplateInfo> data, bool* exc);
122 static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data,
123 bool* exc);
124 static void ConfigureInstance(Handle<Object> instance,
125 Handle<Object> data,
126 bool* exc);
127 static Handle<String> GetStackTraceLine(Handle<Object> recv,
128 Handle<JSFunction> fun,
129 Handle<Object> pos,
130 Handle<Object> is_global);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000131#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000132 static Object* DebugBreakHelper();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000133 static void ProcessDebugMesssages(bool debug_command_only);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000134#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000135
136 // If the stack guard is triggered, but it is not an actual
137 // stack overflow, then handle the interruption accordingly.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000138 MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000139
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140 // Get a function delegate (or undefined) for the given non-function
141 // object. Used for support calling objects as functions.
142 static Handle<Object> GetFunctionDelegate(Handle<Object> object);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000143 static Handle<Object> TryGetFunctionDelegate(Handle<Object> object,
144 bool* has_pending_exception);
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000145
146 // Get a function delegate (or undefined) for the given non-function
147 // object. Used for support calling objects as constructors.
148 static Handle<Object> GetConstructorDelegate(Handle<Object> object);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000149 static Handle<Object> TryGetConstructorDelegate(Handle<Object> object,
150 bool* has_pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151};
152
153
154class ExecutionAccess;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000155class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000156
157
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000158// StackGuard contains the handling of the limits that are used to limit the
159// number of nested invocations of JavaScript and the stack size used in each
160// invocation.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000161class StackGuard {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000163 // Pass the address beyond which the stack should not grow. The stack
164 // is assumed to grow downwards.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000165 void SetStackLimit(uintptr_t limit);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000167 // Threading support.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000168 char* ArchiveStackGuard(char* to);
169 char* RestoreStackGuard(char* from);
170 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
171 void FreeThreadResources();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000172 // Sets up the default stack guard for this thread if it has not
173 // already been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000174 void InitThread(const ExecutionAccess& lock);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000175 // Clears the stack guard for this thread so it does not look as if
176 // it has been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000177 void ClearThread(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000179 bool IsStackOverflow();
180 bool IsPreempted();
181 void Preempt();
182 bool IsInterrupted();
183 void Interrupt();
184 bool IsTerminateExecution();
185 void TerminateExecution();
186 bool IsRuntimeProfilerTick();
187 void RequestRuntimeProfilerTick();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000188#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000189 bool IsDebugBreak();
190 void DebugBreak();
191 bool IsDebugCommand();
192 void DebugCommand();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000193#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000194 void Continue(InterruptFlag after_what);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000196 // This provides an asynchronous read of the stack limits for the current
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000197 // thread. There are no locks protecting this, but it is assumed that you
198 // have the global V8 lock if you are using multiple V8 threads.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 uintptr_t climit() {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000200 return thread_local_.climit_;
201 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000202 uintptr_t real_climit() {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000203 return thread_local_.real_climit_;
204 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000205 uintptr_t jslimit() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000206 return thread_local_.jslimit_;
207 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000208 uintptr_t real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000209 return thread_local_.real_jslimit_;
210 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000211 Address address_of_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000212 return reinterpret_cast<Address>(&thread_local_.jslimit_);
213 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000214 Address address_of_real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000215 return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
216 }
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000217
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000219 StackGuard();
220
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000222 bool has_pending_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000223 // Sanity check: We shouldn't be asking about pending interrupts
224 // unless we're not postponing them anymore.
225 ASSERT(!should_postpone_interrupts(lock));
226 return thread_local_.interrupt_flags_ != 0;
227 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000230 bool should_postpone_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000231 return thread_local_.postpone_interrupts_nesting_ > 0;
232 }
233
234 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000235 inline void set_interrupt_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000237 // Reset limits to actual values. For example after handling interrupt.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000239 inline void reset_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240
kasper.lund44510672008-07-25 07:37:58 +0000241 // Enable or disable interrupts.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000242 void EnableInterrupts();
243 void DisableInterrupts();
kasper.lund44510672008-07-25 07:37:58 +0000244
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000245#ifdef V8_TARGET_ARCH_X64
246 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000247 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000248#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249 static const uintptr_t kInterruptLimit = 0xfffffffe;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000250 static const uintptr_t kIllegalLimit = 0xfffffff8;
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000251#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000252
253 class ThreadLocal {
254 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000255 ThreadLocal() { Clear(); }
256 // You should hold the ExecutionAccess lock when you call Initialize or
257 // Clear.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000258 void Clear();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000259
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000260 // Returns true if the heap's stack limits should be set, false if not.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000261 bool Initialize(Isolate* isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000262
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000263 // The stack limit is split into a JavaScript and a C++ stack limit. These
264 // two are the same except when running on a simulator where the C++ and
265 // JavaScript stacks are separate. Each of the two stack limits have two
266 // values. The one eith the real_ prefix is the actual stack limit
267 // set for the VM. The one without the real_ prefix has the same value as
268 // the actual stack limit except when there is an interruption (e.g. debug
269 // break or preemption) in which case it is lowered to make stack checks
270 // fail. Both the generated code and the runtime system check against the
271 // one without the real_ prefix.
272 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273 uintptr_t jslimit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000274 uintptr_t real_climit_; // Actual C++ stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000275 uintptr_t climit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000276
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000277 int nesting_;
kasper.lund44510672008-07-25 07:37:58 +0000278 int postpone_interrupts_nesting_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279 int interrupt_flags_;
280 };
kasper.lund44510672008-07-25 07:37:58 +0000281
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000282 // TODO(isolates): Technically this could be calculated directly from a
283 // pointer to StackGuard.
284 Isolate* isolate_;
285 ThreadLocal thread_local_;
kasper.lund44510672008-07-25 07:37:58 +0000286
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000287 friend class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288 friend class StackLimitCheck;
kasper.lund44510672008-07-25 07:37:58 +0000289 friend class PostponeInterruptsScope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000290
291 DISALLOW_COPY_AND_ASSIGN(StackGuard);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292};
293
294
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000295} } // namespace v8::internal
296
297#endif // V8_EXECUTION_H_