blob: 2613c20f0f4ed1b23e47e211fa8839ca7a22af58 [file] [log] [blame]
yangguo@chromium.org56454712012-02-16 15:33:53 +00001// Copyright 2012 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#include <stdlib.h>
29
30#include "v8.h"
31
32#include "api.h"
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000033#include "bootstrapper.h"
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000034#include "codegen.h"
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000035#include "debug.h"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000036#include "isolate-inl.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000037#include "runtime-profiler.h"
ager@chromium.orgc4c92722009-11-18 14:12:51 +000038#include "simulator.h"
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000039#include "v8threads.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000040#include "vm-state-inl.h"
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000041
kasperl@chromium.org71affb52009-05-26 05:44:31 +000042namespace v8 {
43namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044
45
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000046StackGuard::StackGuard()
47 : isolate_(NULL) {
48}
49
50
51void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
52 ASSERT(isolate_ != NULL);
53 // Ignore attempts to interrupt when interrupts are postponed.
54 if (should_postpone_interrupts(lock)) return;
55 thread_local_.jslimit_ = kInterruptLimit;
56 thread_local_.climit_ = kInterruptLimit;
57 isolate_->heap()->SetStackLimits();
58}
59
60
61void StackGuard::reset_limits(const ExecutionAccess& lock) {
62 ASSERT(isolate_ != NULL);
63 thread_local_.jslimit_ = thread_local_.real_jslimit_;
64 thread_local_.climit_ = thread_local_.real_climit_;
65 isolate_->heap()->SetStackLimits();
66}
67
68
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000069static Handle<Object> Invoke(bool is_construct,
70 Handle<JSFunction> function,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071 Handle<Object> receiver,
72 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000073 Handle<Object> args[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000074 bool* has_pending_exception) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000075 Isolate* isolate = function->GetIsolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000076
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077 // Entering JavaScript.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000078 VMState state(isolate, JS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000079
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000080 // Placeholder for return value.
lrn@chromium.org303ada72010-10-27 09:33:13 +000081 MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000083 typedef Object* (*JSEntryFunction)(byte* entry,
84 Object* function,
85 Object* receiver,
86 int argc,
87 Object*** args);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000088
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +000089 Handle<Code> code = is_construct
90 ? isolate->factory()->js_construct_entry_code()
91 : isolate->factory()->js_entry_code();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092
sgjesse@chromium.org8d96e6d2009-08-07 10:18:15 +000093 // Convert calls on global objects to be calls on the global
94 // receiver instead to avoid having a 'this' pointer which refers
95 // directly to a global object.
96 if (receiver->IsGlobalObject()) {
97 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
98 receiver = Handle<JSObject>(global->global_receiver());
99 }
100
kasperl@chromium.org7b9eafd2009-12-21 15:20:30 +0000101 // Make sure that the global object of the context we're about to
102 // make the current one is indeed a global object.
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000103 ASSERT(function->context()->global()->IsGlobalObject());
kasperl@chromium.org7b9eafd2009-12-21 15:20:30 +0000104
kasper.lund44510672008-07-25 07:37:58 +0000105 {
106 // Save and restore context around invocation and block the
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107 // allocation of handles without explicit handle scopes.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000108 SaveContext save(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000109 NoHandleAllocation na;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000110 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111
112 // Call the function through the right JS entry stub.
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000113 byte* function_entry = function->code()->entry();
114 JSFunction* func = *function;
115 Object* recv = *receiver;
116 Object*** argv = reinterpret_cast<Object***>(args);
117 value =
118 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000119 }
120
121#ifdef DEBUG
122 value->Verify();
123#endif
124
125 // Update the pending exception flag and return the value.
126 *has_pending_exception = value->IsException();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000127 ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000128 if (*has_pending_exception) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000129 isolate->ReportPendingMessages();
130 if (isolate->pending_exception() == Failure::OutOfMemoryException()) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +0000131 if (!isolate->ignore_out_of_memory()) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000132 V8::FatalProcessOutOfMemory("JS", true);
133 }
134 }
danno@chromium.org81cac2b2012-07-10 11:28:27 +0000135#ifdef ENABLE_DEBUGGER_SUPPORT
136 // Reset stepping state when script exits with uncaught exception.
137 if (isolate->debugger()->IsDebuggerActive()) {
138 isolate->debug()->ClearStepping();
139 }
140#endif // ENABLE_DEBUGGER_SUPPORT
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000141 return Handle<Object>();
ager@chromium.org8bb60582008-12-11 12:02:20 +0000142 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000143 isolate->clear_pending_message();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000144 }
145
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000146 return Handle<Object>(value->ToObjectUnchecked(), isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147}
148
149
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000150Handle<Object> Execution::Call(Handle<Object> callable,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151 Handle<Object> receiver,
152 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000153 Handle<Object> argv[],
lrn@chromium.org34e60782011-09-15 07:25:40 +0000154 bool* pending_exception,
155 bool convert_receiver) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000156 *pending_exception = false;
157
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000158 if (!callable->IsJSFunction()) {
159 callable = TryGetFunctionDelegate(callable, pending_exception);
160 if (*pending_exception) return callable;
161 }
162 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000163
164 // In non-strict mode, convert receiver.
165 if (convert_receiver && !receiver->IsJSReceiver() &&
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000166 !func->shared()->native() && func->shared()->is_classic_mode()) {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000167 if (receiver->IsUndefined() || receiver->IsNull()) {
168 Object* global = func->context()->global()->global_receiver();
169 // Under some circumstances, 'global' can be the JSBuiltinsObject
170 // In that case, don't rewrite.
171 // (FWIW, the same holds for GetIsolate()->global()->global_receiver().)
172 if (!global->IsJSBuiltinsObject()) receiver = Handle<Object>(global);
173 } else {
174 receiver = ToObject(receiver, pending_exception);
175 }
176 if (*pending_exception) return callable;
177 }
178
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000179 return Invoke(false, func, receiver, argc, argv, pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000180}
181
182
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000183Handle<Object> Execution::New(Handle<JSFunction> func,
184 int argc,
185 Handle<Object> argv[],
186 bool* pending_exception) {
187 return Invoke(true, func, Isolate::Current()->global(), argc, argv,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000188 pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000189}
190
191
192Handle<Object> Execution::TryCall(Handle<JSFunction> func,
193 Handle<Object> receiver,
194 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000195 Handle<Object> args[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196 bool* caught_exception) {
197 // Enter a try-block while executing the JavaScript code. To avoid
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000198 // duplicate error printing it must be non-verbose. Also, to avoid
199 // creating message objects during stack overflow we shouldn't
200 // capture messages.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201 v8::TryCatch catcher;
202 catcher.SetVerbose(false);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000203 catcher.SetCaptureMessage(false);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000204 *caught_exception = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205
206 Handle<Object> result = Invoke(false, func, receiver, argc, args,
207 caught_exception);
208
209 if (*caught_exception) {
210 ASSERT(catcher.HasCaught());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000211 Isolate* isolate = Isolate::Current();
212 ASSERT(isolate->has_pending_exception());
213 ASSERT(isolate->external_caught_exception());
214 if (isolate->pending_exception() ==
215 isolate->heap()->termination_exception()) {
216 result = isolate->factory()->termination_exception();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000217 } else {
218 result = v8::Utils::OpenHandle(*catcher.Exception());
219 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000220 isolate->OptionalRescheduleException(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221 }
222
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000223 ASSERT(!Isolate::Current()->has_pending_exception());
224 ASSERT(!Isolate::Current()->external_caught_exception());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000225 return result;
226}
227
228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
230 ASSERT(!object->IsJSFunction());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000231 Isolate* isolate = Isolate::Current();
232 Factory* factory = isolate->factory();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233
234 // If you return a function from here, it will be called when an
235 // attempt is made to call the given object as a function.
236
lrn@chromium.org34e60782011-09-15 07:25:40 +0000237 // If object is a function proxy, get its handler. Iterate if necessary.
238 Object* fun = *object;
239 while (fun->IsJSFunctionProxy()) {
240 fun = JSFunctionProxy::cast(fun)->call_trap();
241 }
242 if (fun->IsJSFunction()) return Handle<Object>(fun);
243
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244 // Objects created through the API can have an instance-call handler
245 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000246 if (fun->IsHeapObject() &&
247 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000248 return Handle<JSFunction>(
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000249 isolate->global_context()->call_as_function_delegate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000250 }
251
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000252 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253}
254
255
lrn@chromium.org1c092762011-05-09 09:42:16 +0000256Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
257 bool* has_pending_exception) {
258 ASSERT(!object->IsJSFunction());
259 Isolate* isolate = Isolate::Current();
260
lrn@chromium.org34e60782011-09-15 07:25:40 +0000261 // If object is a function proxy, get its handler. Iterate if necessary.
262 Object* fun = *object;
263 while (fun->IsJSFunctionProxy()) {
264 fun = JSFunctionProxy::cast(fun)->call_trap();
265 }
266 if (fun->IsJSFunction()) return Handle<Object>(fun);
267
lrn@chromium.org1c092762011-05-09 09:42:16 +0000268 // Objects created through the API can have an instance-call handler
269 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000270 if (fun->IsHeapObject() &&
271 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000272 return Handle<JSFunction>(
273 isolate->global_context()->call_as_function_delegate());
274 }
275
276 // If the Object doesn't have an instance-call handler we should
277 // throw a non-callable exception.
278 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
279 "called_non_callable", i::HandleVector<i::Object>(&object, 1));
280 isolate->Throw(*error_obj);
281 *has_pending_exception = true;
282
283 return isolate->factory()->undefined_value();
284}
285
286
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000287Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
288 ASSERT(!object->IsJSFunction());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000289 Isolate* isolate = Isolate::Current();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000290
291 // If you return a function from here, it will be called when an
292 // attempt is made to call the given object as a constructor.
293
lrn@chromium.org34e60782011-09-15 07:25:40 +0000294 // If object is a function proxies, get its handler. Iterate if necessary.
295 Object* fun = *object;
296 while (fun->IsJSFunctionProxy()) {
297 fun = JSFunctionProxy::cast(fun)->call_trap();
298 }
299 if (fun->IsJSFunction()) return Handle<Object>(fun);
300
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000301 // Objects created through the API can have an instance-call handler
302 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000303 if (fun->IsHeapObject() &&
304 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000305 return Handle<JSFunction>(
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000306 isolate->global_context()->call_as_constructor_delegate());
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000307 }
308
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000309 return isolate->factory()->undefined_value();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000310}
311
312
lrn@chromium.org1c092762011-05-09 09:42:16 +0000313Handle<Object> Execution::TryGetConstructorDelegate(
314 Handle<Object> object,
315 bool* has_pending_exception) {
316 ASSERT(!object->IsJSFunction());
317 Isolate* isolate = Isolate::Current();
318
319 // If you return a function from here, it will be called when an
320 // attempt is made to call the given object as a constructor.
321
lrn@chromium.org34e60782011-09-15 07:25:40 +0000322 // If object is a function proxies, get its handler. Iterate if necessary.
323 Object* fun = *object;
324 while (fun->IsJSFunctionProxy()) {
325 fun = JSFunctionProxy::cast(fun)->call_trap();
326 }
327 if (fun->IsJSFunction()) return Handle<Object>(fun);
328
lrn@chromium.org1c092762011-05-09 09:42:16 +0000329 // Objects created through the API can have an instance-call handler
330 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000331 if (fun->IsHeapObject() &&
332 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000333 return Handle<JSFunction>(
334 isolate->global_context()->call_as_constructor_delegate());
335 }
336
337 // If the Object doesn't have an instance-call handler we should
338 // throw a non-callable exception.
339 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
340 "called_non_callable", i::HandleVector<i::Object>(&object, 1));
341 isolate->Throw(*error_obj);
342 *has_pending_exception = true;
343
344 return isolate->factory()->undefined_value();
345}
346
347
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000348bool StackGuard::IsStackOverflow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000349 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000350 return (thread_local_.jslimit_ != kInterruptLimit &&
351 thread_local_.climit_ != kInterruptLimit);
352}
353
354
355void StackGuard::EnableInterrupts() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000356 ExecutionAccess access(isolate_);
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000357 if (has_pending_interrupts(access)) {
358 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000359 }
360}
361
362
363void StackGuard::SetStackLimit(uintptr_t limit) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000364 ExecutionAccess access(isolate_);
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000365 // If the current limits are special (e.g. due to a pending interrupt) then
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000366 // leave them alone.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000367 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000368 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000369 thread_local_.jslimit_ = jslimit;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000371 if (thread_local_.climit_ == thread_local_.real_climit_) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000372 thread_local_.climit_ = limit;
373 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000374 thread_local_.real_climit_ = limit;
375 thread_local_.real_jslimit_ = jslimit;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000376}
377
378
379void StackGuard::DisableInterrupts() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000380 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000381 reset_limits(access);
382}
383
384
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000385bool StackGuard::ShouldPostponeInterrupts() {
386 ExecutionAccess access(isolate_);
387 return should_postpone_interrupts(access);
388}
389
390
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000391bool StackGuard::IsInterrupted() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000392 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000393 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394}
395
396
397void StackGuard::Interrupt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000398 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399 thread_local_.interrupt_flags_ |= INTERRUPT;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000400 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401}
402
403
404bool StackGuard::IsPreempted() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000405 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000406 return thread_local_.interrupt_flags_ & PREEMPT;
407}
408
409
410void StackGuard::Preempt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000411 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000412 thread_local_.interrupt_flags_ |= PREEMPT;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000413 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000414}
415
416
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000417bool StackGuard::IsTerminateExecution() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000418 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000419 return (thread_local_.interrupt_flags_ & TERMINATE) != 0;
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000420}
421
422
423void StackGuard::TerminateExecution() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000424 ExecutionAccess access(isolate_);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000425 thread_local_.interrupt_flags_ |= TERMINATE;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000426 set_interrupt_limits(access);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000427}
428
429
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000430bool StackGuard::IsRuntimeProfilerTick() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000431 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000432 return (thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK) != 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000433}
434
435
436void StackGuard::RequestRuntimeProfilerTick() {
437 // Ignore calls if we're not optimizing or if we can't get the lock.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000438 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000439 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
440 if (thread_local_.postpone_interrupts_nesting_ == 0) {
441 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000442 isolate_->heap()->SetStackLimits();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000443 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000444 ExecutionAccess::Unlock(isolate_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000445 }
446}
447
448
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000449bool StackGuard::IsGCRequest() {
450 ExecutionAccess access(isolate_);
451 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0;
452}
453
454
455void StackGuard::RequestGC() {
456 ExecutionAccess access(isolate_);
457 thread_local_.interrupt_flags_ |= GC_REQUEST;
458 if (thread_local_.postpone_interrupts_nesting_ == 0) {
459 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
460 isolate_->heap()->SetStackLimits();
461 }
462}
463
464
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000465#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466bool StackGuard::IsDebugBreak() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000467 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468 return thread_local_.interrupt_flags_ & DEBUGBREAK;
469}
470
kasper.lund44510672008-07-25 07:37:58 +0000471
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000472void StackGuard::DebugBreak() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000473 ExecutionAccess access(isolate_);
kasper.lund7276f142008-07-30 08:49:36 +0000474 thread_local_.interrupt_flags_ |= DEBUGBREAK;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000475 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000476}
477
478
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000479bool StackGuard::IsDebugCommand() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000480 ExecutionAccess access(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000481 return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
482}
483
484
485void StackGuard::DebugCommand() {
486 if (FLAG_debugger_auto_break) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000487 ExecutionAccess access(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000488 thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000489 set_interrupt_limits(access);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000490 }
491}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000492#endif
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000493
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000494void StackGuard::Continue(InterruptFlag after_what) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000495 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000497 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000498 reset_limits(access);
499 }
500}
501
502
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503char* StackGuard::ArchiveStackGuard(char* to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000504 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
506 ThreadLocal blank;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000507
508 // Set the stack limits using the old thread_local_.
509 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
510 // (as the ctor called SetStackLimits, which looked at the
511 // current thread_local_ from StackGuard)-- but is this
512 // really what was intended?
513 isolate_->heap()->SetStackLimits();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000514 thread_local_ = blank;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000515
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000516 return to + sizeof(ThreadLocal);
517}
518
519
520char* StackGuard::RestoreStackGuard(char* from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000521 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000522 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000523 isolate_->heap()->SetStackLimits();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524 return from + sizeof(ThreadLocal);
525}
526
527
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000528void StackGuard::FreeThreadResources() {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000529 Isolate::PerIsolateThreadData* per_thread =
530 isolate_->FindOrAllocatePerThreadDataForThisThread();
531 per_thread->set_stack_limit(thread_local_.real_climit_);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000532}
533
534
535void StackGuard::ThreadLocal::Clear() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000536 real_jslimit_ = kIllegalLimit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000537 jslimit_ = kIllegalLimit;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000538 real_climit_ = kIllegalLimit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000539 climit_ = kIllegalLimit;
540 nesting_ = 0;
541 postpone_interrupts_nesting_ = 0;
542 interrupt_flags_ = 0;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000543}
544
545
lrn@chromium.org1c092762011-05-09 09:42:16 +0000546bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000547 bool should_set_stack_limits = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000548 if (real_climit_ == kIllegalLimit) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000549 // Takes the address of the limit variable in order to find out where
550 // the top of stack is right now.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000551 const uintptr_t kLimitSize = FLAG_stack_size * KB;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000552 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
553 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000554 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
555 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000556 real_climit_ = limit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000557 climit_ = limit;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000558 should_set_stack_limits = true;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000559 }
560 nesting_ = 0;
561 postpone_interrupts_nesting_ = 0;
562 interrupt_flags_ = 0;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000563 return should_set_stack_limits;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000564}
565
566
567void StackGuard::ClearThread(const ExecutionAccess& lock) {
568 thread_local_.Clear();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000569 isolate_->heap()->SetStackLimits();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000570}
571
572
573void StackGuard::InitThread(const ExecutionAccess& lock) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000574 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
575 Isolate::PerIsolateThreadData* per_thread =
576 isolate_->FindOrAllocatePerThreadDataForThisThread();
577 uintptr_t stored_limit = per_thread->stack_limit();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000578 // You should hold the ExecutionAccess lock when you call this.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000579 if (stored_limit != 0) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000580 SetStackLimit(stored_limit);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000581 }
582}
583
584
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000585// --- C a l l s t o n a t i v e s ---
586
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000587#define RETURN_NATIVE_CALL(name, args, has_pending_exception) \
588 do { \
589 Isolate* isolate = Isolate::Current(); \
590 Handle<Object> argv[] = args; \
591 ASSERT(has_pending_exception != NULL); \
592 return Call(isolate->name##_fun(), \
593 isolate->js_builtins_object(), \
594 ARRAY_SIZE(argv), argv, \
595 has_pending_exception); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596 } while (false)
597
598
599Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
600 // See the similar code in runtime.js:ToBoolean.
601 if (obj->IsBoolean()) return obj;
602 bool result = true;
603 if (obj->IsString()) {
604 result = Handle<String>::cast(obj)->length() != 0;
605 } else if (obj->IsNull() || obj->IsUndefined()) {
606 result = false;
607 } else if (obj->IsNumber()) {
608 double value = obj->Number();
609 result = !((value == 0) || isnan(value));
610 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000611 return Handle<Object>(HEAP->ToBoolean(result));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612}
613
614
615Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000616 RETURN_NATIVE_CALL(to_number, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617}
618
619
620Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000621 RETURN_NATIVE_CALL(to_string, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000622}
623
624
625Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000626 RETURN_NATIVE_CALL(to_detail_string, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627}
628
629
630Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000631 if (obj->IsSpecObject()) return obj;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000632 RETURN_NATIVE_CALL(to_object, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000633}
634
635
636Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000637 RETURN_NATIVE_CALL(to_integer, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000638}
639
640
641Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000642 RETURN_NATIVE_CALL(to_uint32, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643}
644
645
646Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000647 RETURN_NATIVE_CALL(to_int32, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000648}
649
650
651Handle<Object> Execution::NewDate(double time, bool* exc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000652 Handle<Object> time_obj = FACTORY->NewNumber(time);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000653 RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654}
655
656
657#undef RETURN_NATIVE_CALL
658
659
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000660Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
661 Handle<String> flags,
662 bool* exc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000663 Handle<JSFunction> function = Handle<JSFunction>(
664 pattern->GetIsolate()->global_context()->regexp_function());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000665 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000666 function, pattern, flags, exc);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000667 if (*exc) return Handle<JSRegExp>();
668 return Handle<JSRegExp>::cast(re_obj);
669}
670
671
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000672Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000673 Isolate* isolate = string->GetIsolate();
674 Factory* factory = isolate->factory();
675
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676 int int_index = static_cast<int>(index);
677 if (int_index < 0 || int_index >= string->length()) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000678 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679 }
680
681 Handle<Object> char_at =
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000682 GetProperty(isolate->js_builtins_object(),
683 factory->char_at_symbol());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684 if (!char_at->IsJSFunction()) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000685 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000686 }
687
688 bool caught_exception;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000689 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000690 Handle<Object> index_arg[] = { index_object };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000691 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
692 string,
693 ARRAY_SIZE(index_arg),
694 index_arg,
695 &caught_exception);
696 if (caught_exception) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000697 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000698 }
699 return result;
700}
701
702
703Handle<JSFunction> Execution::InstantiateFunction(
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000704 Handle<FunctionTemplateInfo> data,
705 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000706 Isolate* isolate = data->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707 // Fast case: see if the function has already been instantiated
708 int serial_number = Smi::cast(data->serial_number())->value();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000709 Object* elm =
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000710 isolate->global_context()->function_cache()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000711 GetElementNoExceptionThrown(serial_number);
ager@chromium.org32912102009-01-16 10:38:43 +0000712 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713 // The function has not yet been instantiated in this context; do it.
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000714 Handle<Object> args[] = { data };
715 Handle<Object> result = Call(isolate->instantiate_fun(),
716 isolate->js_builtins_object(),
717 ARRAY_SIZE(args),
718 args,
719 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000720 if (*exc) return Handle<JSFunction>::null();
721 return Handle<JSFunction>::cast(result);
722}
723
724
725Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
726 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000727 Isolate* isolate = data->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728 if (data->property_list()->IsUndefined() &&
729 !data->constructor()->IsUndefined()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000730 // Initialization to make gcc happy.
731 Object* result = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000732 {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000733 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000734 Handle<FunctionTemplateInfo> cons_template =
735 Handle<FunctionTemplateInfo>(
736 FunctionTemplateInfo::cast(data->constructor()));
737 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
738 if (*exc) return Handle<JSObject>::null();
739 Handle<Object> value = New(cons, 0, NULL, exc);
740 if (*exc) return Handle<JSObject>::null();
741 result = *value;
742 }
743 ASSERT(!*exc);
744 return Handle<JSObject>(JSObject::cast(result));
745 } else {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000746 Handle<Object> args[] = { data };
747 Handle<Object> result = Call(isolate->instantiate_fun(),
748 isolate->js_builtins_object(),
749 ARRAY_SIZE(args),
750 args,
751 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752 if (*exc) return Handle<JSObject>::null();
753 return Handle<JSObject>::cast(result);
754 }
755}
756
757
758void Execution::ConfigureInstance(Handle<Object> instance,
759 Handle<Object> instance_template,
760 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000761 Isolate* isolate = Isolate::Current();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000762 Handle<Object> args[] = { instance, instance_template };
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000763 Execution::Call(isolate->configure_instance_fun(),
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000764 isolate->js_builtins_object(),
765 ARRAY_SIZE(args),
766 args,
767 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000768}
769
770
771Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
772 Handle<JSFunction> fun,
773 Handle<Object> pos,
774 Handle<Object> is_global) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000775 Isolate* isolate = fun->GetIsolate();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000776 Handle<Object> args[] = { recv, fun, pos, is_global };
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000777 bool caught_exception;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000778 Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(),
779 isolate->js_builtins_object(),
780 ARRAY_SIZE(args),
781 args,
782 &caught_exception);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000783 if (caught_exception || !result->IsString()) {
784 return isolate->factory()->empty_symbol();
785 }
786
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000787 return Handle<String>::cast(result);
788}
789
790
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000791static Object* RuntimePreempt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000792 Isolate* isolate = Isolate::Current();
793
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000794 // Clear the preempt request flag.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000795 isolate->stack_guard()->Continue(PREEMPT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000796
797 ContextSwitcher::PreemptionReceived();
798
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000799#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000800 if (isolate->debug()->InDebugger()) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000801 // If currently in the debugger don't do any actual preemption but record
802 // that preemption occoured while in the debugger.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000803 isolate->debug()->PreemptionWhileInDebugger();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000804 } else {
805 // Perform preemption.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000806 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000807 Thread::YieldCPU();
808 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000809#else
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000810 { // NOLINT
811 // Perform preemption.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000812 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000813 Thread::YieldCPU();
814 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000815#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000816
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000817 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000818}
819
820
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000821#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000822Object* Execution::DebugBreakHelper() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000823 Isolate* isolate = Isolate::Current();
824
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000825 // Just continue if breaks are disabled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000826 if (isolate->debug()->disable_break()) {
827 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000828 }
829
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000830 // Ignore debug break during bootstrapping.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000831 if (isolate->bootstrapper()->IsActive()) {
832 return isolate->heap()->undefined_value();
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000833 }
834
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000835 // Ignore debug break if debugger is not active.
836 if (!isolate->debugger()->IsDebuggerActive()) {
837 return isolate->heap()->undefined_value();
838 }
839
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000840 StackLimitCheck check(isolate);
841 if (check.HasOverflowed()) {
842 return isolate->heap()->undefined_value();
843 }
844
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000845 {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000846 JavaScriptFrameIterator it(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000847 ASSERT(!it.done());
848 Object* fun = it.frame()->function();
849 if (fun && fun->IsJSFunction()) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000850 // Don't stop in builtin functions.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000851 if (JSFunction::cast(fun)->IsBuiltin()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000852 return isolate->heap()->undefined_value();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000853 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000854 GlobalObject* global = JSFunction::cast(fun)->context()->global();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000855 // Don't stop in debugger functions.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000856 if (isolate->debug()->IsDebugGlobal(global)) {
857 return isolate->heap()->undefined_value();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000858 }
859 }
860 }
861
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000862 // Collect the break state before clearing the flags.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000863 bool debug_command_only =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000864 isolate->stack_guard()->IsDebugCommand() &&
865 !isolate->stack_guard()->IsDebugBreak();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000866
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000867 // Clear the debug break request flag.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000868 isolate->stack_guard()->Continue(DEBUGBREAK);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000869
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000870 ProcessDebugMessages(debug_command_only);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000871
872 // Return to continue execution.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000873 return isolate->heap()->undefined_value();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000874}
875
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000876void Execution::ProcessDebugMessages(bool debug_command_only) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000877 Isolate* isolate = Isolate::Current();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000878 // Clear the debug command request flag.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000879 isolate->stack_guard()->Continue(DEBUGCOMMAND);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000880
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000881 StackLimitCheck check(isolate);
882 if (check.HasOverflowed()) {
883 return;
884 }
885
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000886 HandleScope scope(isolate);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000887 // Enter the debugger. Just continue if we fail to enter the debugger.
888 EnterDebugger debugger;
889 if (debugger.FailedToEnter()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000890 return;
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000891 }
892
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000893 // Notify the debug event listeners. Indicate auto continue if the break was
894 // a debug command break.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000895 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
896 debug_command_only);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000897}
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000898
899
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000900#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000901
ulan@chromium.org812308e2012-02-29 15:58:45 +0000902MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000903 StackGuard* stack_guard = isolate->stack_guard();
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000904 if (stack_guard->ShouldPostponeInterrupts()) {
905 return isolate->heap()->undefined_value();
906 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000907
908 if (stack_guard->IsGCRequest()) {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000909 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
910 "StackGuard GC request");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000911 stack_guard->Continue(GC_REQUEST);
912 }
913
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000914 isolate->counters()->stack_interrupts()->Increment();
yangguo@chromium.org56454712012-02-16 15:33:53 +0000915 // If FLAG_count_based_interrupts, every interrupt is a profiler interrupt.
916 if (FLAG_count_based_interrupts ||
917 stack_guard->IsRuntimeProfilerTick()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000918 isolate->counters()->runtime_profiler_ticks()->Increment();
919 stack_guard->Continue(RUNTIME_PROFILER_TICK);
920 isolate->runtime_profiler()->OptimizeNow();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000921 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000922#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000923 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000924 DebugBreakHelper();
925 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000926#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000927 if (stack_guard->IsPreempted()) RuntimePreempt();
928 if (stack_guard->IsTerminateExecution()) {
929 stack_guard->Continue(TERMINATE);
930 return isolate->TerminateExecution();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000931 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000932 if (stack_guard->IsInterrupted()) {
933 stack_guard->Continue(INTERRUPT);
934 return isolate->StackOverflow();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000935 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000936 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000937}
938
yangguo@chromium.org56454712012-02-16 15:33:53 +0000939
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000940} } // namespace v8::internal