blob: 01e4b9da4f7c6905d5cb72a21232499171f56690 [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,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000044 RUNTIME_PROFILER_TICK = 1 << 5,
45 GC_REQUEST = 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
94 // ECMA-262 9.2
95 static Handle<Object> ToBoolean(Handle<Object> obj);
96
97 // ECMA-262 9.3
98 static Handle<Object> ToNumber(Handle<Object> obj, bool* exc);
99
100 // ECMA-262 9.4
101 static Handle<Object> ToInteger(Handle<Object> obj, bool* exc);
102
103 // ECMA-262 9.5
104 static Handle<Object> ToInt32(Handle<Object> obj, bool* exc);
105
106 // ECMA-262 9.6
107 static Handle<Object> ToUint32(Handle<Object> obj, bool* exc);
108
109 // ECMA-262 9.8
110 static Handle<Object> ToString(Handle<Object> obj, bool* exc);
111
112 // ECMA-262 9.8
113 static Handle<Object> ToDetailString(Handle<Object> obj, bool* exc);
114
115 // ECMA-262 9.9
116 static Handle<Object> ToObject(Handle<Object> obj, bool* exc);
117
118 // Create a new date object from 'time'.
119 static Handle<Object> NewDate(double time, bool* exc);
120
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000121 // Create a new regular expression object from 'pattern' and 'flags'.
122 static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern,
123 Handle<String> flags,
124 bool* exc);
125
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126 // Used to implement [] notation on strings (calls JS code)
127 static Handle<Object> CharAt(Handle<String> str, uint32_t index);
128
129 static Handle<Object> GetFunctionFor();
130 static Handle<JSFunction> InstantiateFunction(
131 Handle<FunctionTemplateInfo> data, bool* exc);
132 static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data,
133 bool* exc);
134 static void ConfigureInstance(Handle<Object> instance,
135 Handle<Object> data,
136 bool* exc);
137 static Handle<String> GetStackTraceLine(Handle<Object> recv,
138 Handle<JSFunction> fun,
139 Handle<Object> pos,
140 Handle<Object> is_global);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000141#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000142 static Object* DebugBreakHelper();
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000143 static void ProcessDebugMessages(bool debug_command_only);
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000144#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000145
146 // If the stack guard is triggered, but it is not an actual
147 // stack overflow, then handle the interruption accordingly.
ulan@chromium.org812308e2012-02-29 15:58:45 +0000148 MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt(
149 Isolate* isolate);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000150
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151 // Get a function delegate (or undefined) for the given non-function
152 // object. Used for support calling objects as functions.
153 static Handle<Object> GetFunctionDelegate(Handle<Object> object);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000154 static Handle<Object> TryGetFunctionDelegate(Handle<Object> object,
155 bool* has_pending_exception);
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000156
157 // Get a function delegate (or undefined) for the given non-function
158 // object. Used for support calling objects as constructors.
159 static Handle<Object> GetConstructorDelegate(Handle<Object> object);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000160 static Handle<Object> TryGetConstructorDelegate(Handle<Object> object,
161 bool* has_pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162};
163
164
165class ExecutionAccess;
166
167
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000168// StackGuard contains the handling of the limits that are used to limit the
169// number of nested invocations of JavaScript and the stack size used in each
170// invocation.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000171class StackGuard {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000172 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000173 // Pass the address beyond which the stack should not grow. The stack
174 // is assumed to grow downwards.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000175 void SetStackLimit(uintptr_t limit);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 // Threading support.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000178 char* ArchiveStackGuard(char* to);
179 char* RestoreStackGuard(char* from);
180 static int ArchiveSpacePerThread() { return sizeof(ThreadLocal); }
181 void FreeThreadResources();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000182 // Sets up the default stack guard for this thread if it has not
183 // already been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000184 void InitThread(const ExecutionAccess& lock);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000185 // Clears the stack guard for this thread so it does not look as if
186 // it has been set up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000187 void ClearThread(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000189 bool IsStackOverflow();
190 bool IsPreempted();
191 void Preempt();
192 bool IsInterrupted();
193 void Interrupt();
194 bool IsTerminateExecution();
195 void TerminateExecution();
196 bool IsRuntimeProfilerTick();
197 void RequestRuntimeProfilerTick();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000198#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 bool IsDebugBreak();
200 void DebugBreak();
201 bool IsDebugCommand();
202 void DebugCommand();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000203#endif
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000204 bool IsGCRequest();
205 void RequestGC();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000206 void Continue(InterruptFlag after_what);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000208 // This provides an asynchronous read of the stack limits for the current
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000209 // thread. There are no locks protecting this, but it is assumed that you
210 // have the global V8 lock if you are using multiple V8 threads.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000211 uintptr_t climit() {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000212 return thread_local_.climit_;
213 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000214 uintptr_t real_climit() {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000215 return thread_local_.real_climit_;
216 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000217 uintptr_t jslimit() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000218 return thread_local_.jslimit_;
219 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000220 uintptr_t real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000221 return thread_local_.real_jslimit_;
222 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000223 Address address_of_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000224 return reinterpret_cast<Address>(&thread_local_.jslimit_);
225 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000226 Address address_of_real_jslimit() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000227 return reinterpret_cast<Address>(&thread_local_.real_jslimit_);
228 }
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000229 bool ShouldPostponeInterrupts();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000230
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000232 StackGuard();
233
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000235 bool has_pending_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000236 // Sanity check: We shouldn't be asking about pending interrupts
237 // unless we're not postponing them anymore.
238 ASSERT(!should_postpone_interrupts(lock));
239 return thread_local_.interrupt_flags_ != 0;
240 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000241
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000242 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000243 bool should_postpone_interrupts(const ExecutionAccess& lock) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000244 return thread_local_.postpone_interrupts_nesting_ > 0;
245 }
246
247 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000248 inline void set_interrupt_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000250 // Reset limits to actual values. For example after handling interrupt.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251 // You should hold the ExecutionAccess lock when calling this method.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000252 inline void reset_limits(const ExecutionAccess& lock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253
kasper.lund44510672008-07-25 07:37:58 +0000254 // Enable or disable interrupts.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000255 void EnableInterrupts();
256 void DisableInterrupts();
kasper.lund44510672008-07-25 07:37:58 +0000257
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000258#ifdef V8_TARGET_ARCH_X64
259 static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000260 static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000261#else
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000262 static const uintptr_t kInterruptLimit = 0xfffffffe;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000263 static const uintptr_t kIllegalLimit = 0xfffffff8;
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000264#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265
266 class ThreadLocal {
267 public:
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000268 ThreadLocal() { Clear(); }
269 // You should hold the ExecutionAccess lock when you call Initialize or
270 // Clear.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000271 void Clear();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000272
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000273 // Returns true if the heap's stack limits should be set, false if not.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000274 bool Initialize(Isolate* isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000275
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000276 // The stack limit is split into a JavaScript and a C++ stack limit. These
277 // two are the same except when running on a simulator where the C++ and
278 // JavaScript stacks are separate. Each of the two stack limits have two
279 // values. The one eith the real_ prefix is the actual stack limit
280 // set for the VM. The one without the real_ prefix has the same value as
281 // the actual stack limit except when there is an interruption (e.g. debug
282 // break or preemption) in which case it is lowered to make stack checks
283 // fail. Both the generated code and the runtime system check against the
284 // one without the real_ prefix.
285 uintptr_t real_jslimit_; // Actual JavaScript stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000286 uintptr_t jslimit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000287 uintptr_t real_climit_; // Actual C++ stack limit set for the VM.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000288 uintptr_t climit_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000289
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000290 int nesting_;
kasper.lund44510672008-07-25 07:37:58 +0000291 int postpone_interrupts_nesting_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000292 int interrupt_flags_;
293 };
kasper.lund44510672008-07-25 07:37:58 +0000294
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000295 // TODO(isolates): Technically this could be calculated directly from a
296 // pointer to StackGuard.
297 Isolate* isolate_;
298 ThreadLocal thread_local_;
kasper.lund44510672008-07-25 07:37:58 +0000299
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000300 friend class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000301 friend class StackLimitCheck;
kasper.lund44510672008-07-25 07:37:58 +0000302 friend class PostponeInterruptsScope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000303
304 DISALLOW_COPY_AND_ASSIGN(StackGuard);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305};
306
307
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308} } // namespace v8::internal
309
310#endif // V8_EXECUTION_H_