blob: 71e8ea34a1eb72b2050086889d812afa666c68cd [file] [log] [blame]
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +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#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 }
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000135 return Handle<Object>();
ager@chromium.org8bb60582008-12-11 12:02:20 +0000136 } else {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000137 isolate->clear_pending_message();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000138 }
139
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000140 return Handle<Object>(value->ToObjectUnchecked(), isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141}
142
143
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000144Handle<Object> Execution::Call(Handle<Object> callable,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000145 Handle<Object> receiver,
146 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000147 Handle<Object> argv[],
lrn@chromium.org34e60782011-09-15 07:25:40 +0000148 bool* pending_exception,
149 bool convert_receiver) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000150 *pending_exception = false;
151
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000152 if (!callable->IsJSFunction()) {
153 callable = TryGetFunctionDelegate(callable, pending_exception);
154 if (*pending_exception) return callable;
155 }
156 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000157
158 // In non-strict mode, convert receiver.
159 if (convert_receiver && !receiver->IsJSReceiver() &&
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000160 !func->shared()->native() && func->shared()->is_classic_mode()) {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000161 if (receiver->IsUndefined() || receiver->IsNull()) {
162 Object* global = func->context()->global()->global_receiver();
163 // Under some circumstances, 'global' can be the JSBuiltinsObject
164 // In that case, don't rewrite.
165 // (FWIW, the same holds for GetIsolate()->global()->global_receiver().)
166 if (!global->IsJSBuiltinsObject()) receiver = Handle<Object>(global);
167 } else {
168 receiver = ToObject(receiver, pending_exception);
169 }
170 if (*pending_exception) return callable;
171 }
172
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000173 return Invoke(false, func, receiver, argc, argv, pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174}
175
176
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000177Handle<Object> Execution::New(Handle<JSFunction> func,
178 int argc,
179 Handle<Object> argv[],
180 bool* pending_exception) {
181 return Invoke(true, func, Isolate::Current()->global(), argc, argv,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000182 pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000183}
184
185
186Handle<Object> Execution::TryCall(Handle<JSFunction> func,
187 Handle<Object> receiver,
188 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000189 Handle<Object> args[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000190 bool* caught_exception) {
191 // Enter a try-block while executing the JavaScript code. To avoid
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000192 // duplicate error printing it must be non-verbose. Also, to avoid
193 // creating message objects during stack overflow we shouldn't
194 // capture messages.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195 v8::TryCatch catcher;
196 catcher.SetVerbose(false);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000197 catcher.SetCaptureMessage(false);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000198 *caught_exception = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199
200 Handle<Object> result = Invoke(false, func, receiver, argc, args,
201 caught_exception);
202
203 if (*caught_exception) {
204 ASSERT(catcher.HasCaught());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000205 Isolate* isolate = Isolate::Current();
206 ASSERT(isolate->has_pending_exception());
207 ASSERT(isolate->external_caught_exception());
208 if (isolate->pending_exception() ==
209 isolate->heap()->termination_exception()) {
210 result = isolate->factory()->termination_exception();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000211 } else {
212 result = v8::Utils::OpenHandle(*catcher.Exception());
213 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000214 isolate->OptionalRescheduleException(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000215 }
216
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000217 ASSERT(!Isolate::Current()->has_pending_exception());
218 ASSERT(!Isolate::Current()->external_caught_exception());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000219 return result;
220}
221
222
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
224 ASSERT(!object->IsJSFunction());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000225 Isolate* isolate = Isolate::Current();
226 Factory* factory = isolate->factory();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000227
228 // If you return a function from here, it will be called when an
229 // attempt is made to call the given object as a function.
230
lrn@chromium.org34e60782011-09-15 07:25:40 +0000231 // If object is a function proxy, get its handler. Iterate if necessary.
232 Object* fun = *object;
233 while (fun->IsJSFunctionProxy()) {
234 fun = JSFunctionProxy::cast(fun)->call_trap();
235 }
236 if (fun->IsJSFunction()) return Handle<Object>(fun);
237
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238 // Objects created through the API can have an instance-call handler
239 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000240 if (fun->IsHeapObject() &&
241 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000242 return Handle<JSFunction>(
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000243 isolate->global_context()->call_as_function_delegate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244 }
245
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000246 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247}
248
249
lrn@chromium.org1c092762011-05-09 09:42:16 +0000250Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
251 bool* has_pending_exception) {
252 ASSERT(!object->IsJSFunction());
253 Isolate* isolate = Isolate::Current();
254
lrn@chromium.org34e60782011-09-15 07:25:40 +0000255 // If object is a function proxy, get its handler. Iterate if necessary.
256 Object* fun = *object;
257 while (fun->IsJSFunctionProxy()) {
258 fun = JSFunctionProxy::cast(fun)->call_trap();
259 }
260 if (fun->IsJSFunction()) return Handle<Object>(fun);
261
lrn@chromium.org1c092762011-05-09 09:42:16 +0000262 // Objects created through the API can have an instance-call handler
263 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000264 if (fun->IsHeapObject() &&
265 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000266 return Handle<JSFunction>(
267 isolate->global_context()->call_as_function_delegate());
268 }
269
270 // If the Object doesn't have an instance-call handler we should
271 // throw a non-callable exception.
272 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
273 "called_non_callable", i::HandleVector<i::Object>(&object, 1));
274 isolate->Throw(*error_obj);
275 *has_pending_exception = true;
276
277 return isolate->factory()->undefined_value();
278}
279
280
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000281Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
282 ASSERT(!object->IsJSFunction());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000283 Isolate* isolate = Isolate::Current();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000284
285 // If you return a function from here, it will be called when an
286 // attempt is made to call the given object as a constructor.
287
lrn@chromium.org34e60782011-09-15 07:25:40 +0000288 // If object is a function proxies, get its handler. Iterate if necessary.
289 Object* fun = *object;
290 while (fun->IsJSFunctionProxy()) {
291 fun = JSFunctionProxy::cast(fun)->call_trap();
292 }
293 if (fun->IsJSFunction()) return Handle<Object>(fun);
294
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000295 // Objects created through the API can have an instance-call handler
296 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000297 if (fun->IsHeapObject() &&
298 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000299 return Handle<JSFunction>(
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000300 isolate->global_context()->call_as_constructor_delegate());
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000301 }
302
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000303 return isolate->factory()->undefined_value();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000304}
305
306
lrn@chromium.org1c092762011-05-09 09:42:16 +0000307Handle<Object> Execution::TryGetConstructorDelegate(
308 Handle<Object> object,
309 bool* has_pending_exception) {
310 ASSERT(!object->IsJSFunction());
311 Isolate* isolate = Isolate::Current();
312
313 // If you return a function from here, it will be called when an
314 // attempt is made to call the given object as a constructor.
315
lrn@chromium.org34e60782011-09-15 07:25:40 +0000316 // If object is a function proxies, get its handler. Iterate if necessary.
317 Object* fun = *object;
318 while (fun->IsJSFunctionProxy()) {
319 fun = JSFunctionProxy::cast(fun)->call_trap();
320 }
321 if (fun->IsJSFunction()) return Handle<Object>(fun);
322
lrn@chromium.org1c092762011-05-09 09:42:16 +0000323 // Objects created through the API can have an instance-call handler
324 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000325 if (fun->IsHeapObject() &&
326 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000327 return Handle<JSFunction>(
328 isolate->global_context()->call_as_constructor_delegate());
329 }
330
331 // If the Object doesn't have an instance-call handler we should
332 // throw a non-callable exception.
333 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
334 "called_non_callable", i::HandleVector<i::Object>(&object, 1));
335 isolate->Throw(*error_obj);
336 *has_pending_exception = true;
337
338 return isolate->factory()->undefined_value();
339}
340
341
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342bool StackGuard::IsStackOverflow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000343 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 return (thread_local_.jslimit_ != kInterruptLimit &&
345 thread_local_.climit_ != kInterruptLimit);
346}
347
348
349void StackGuard::EnableInterrupts() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000350 ExecutionAccess access(isolate_);
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000351 if (has_pending_interrupts(access)) {
352 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353 }
354}
355
356
357void StackGuard::SetStackLimit(uintptr_t limit) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000358 ExecutionAccess access(isolate_);
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000359 // If the current limits are special (e.g. due to a pending interrupt) then
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360 // leave them alone.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000361 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000362 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000363 thread_local_.jslimit_ = jslimit;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000364 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000365 if (thread_local_.climit_ == thread_local_.real_climit_) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000366 thread_local_.climit_ = limit;
367 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000368 thread_local_.real_climit_ = limit;
369 thread_local_.real_jslimit_ = jslimit;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370}
371
372
373void StackGuard::DisableInterrupts() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000374 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000375 reset_limits(access);
376}
377
378
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000379bool StackGuard::IsInterrupted() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000380 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000381 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000382}
383
384
385void StackGuard::Interrupt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000386 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 thread_local_.interrupt_flags_ |= INTERRUPT;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000388 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000389}
390
391
392bool StackGuard::IsPreempted() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000393 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394 return thread_local_.interrupt_flags_ & PREEMPT;
395}
396
397
398void StackGuard::Preempt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000399 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000400 thread_local_.interrupt_flags_ |= PREEMPT;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000401 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000402}
403
404
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000405bool StackGuard::IsTerminateExecution() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000406 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000407 return (thread_local_.interrupt_flags_ & TERMINATE) != 0;
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000408}
409
410
411void StackGuard::TerminateExecution() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000412 ExecutionAccess access(isolate_);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000413 thread_local_.interrupt_flags_ |= TERMINATE;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000414 set_interrupt_limits(access);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000415}
416
417
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000418bool StackGuard::IsRuntimeProfilerTick() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000419 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000420 return (thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK) != 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000421}
422
423
424void StackGuard::RequestRuntimeProfilerTick() {
425 // Ignore calls if we're not optimizing or if we can't get the lock.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000426 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000427 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK;
428 if (thread_local_.postpone_interrupts_nesting_ == 0) {
429 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000430 isolate_->heap()->SetStackLimits();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000431 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000432 ExecutionAccess::Unlock(isolate_);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000433 }
434}
435
436
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000437bool StackGuard::IsGCRequest() {
438 ExecutionAccess access(isolate_);
439 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0;
440}
441
442
443void StackGuard::RequestGC() {
444 ExecutionAccess access(isolate_);
445 thread_local_.interrupt_flags_ |= GC_REQUEST;
446 if (thread_local_.postpone_interrupts_nesting_ == 0) {
447 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
448 isolate_->heap()->SetStackLimits();
449 }
450}
451
452
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000453#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000454bool StackGuard::IsDebugBreak() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000455 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456 return thread_local_.interrupt_flags_ & DEBUGBREAK;
457}
458
kasper.lund44510672008-07-25 07:37:58 +0000459
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000460void StackGuard::DebugBreak() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000461 ExecutionAccess access(isolate_);
kasper.lund7276f142008-07-30 08:49:36 +0000462 thread_local_.interrupt_flags_ |= DEBUGBREAK;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000463 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464}
465
466
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000467bool StackGuard::IsDebugCommand() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000468 ExecutionAccess access(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000469 return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
470}
471
472
473void StackGuard::DebugCommand() {
474 if (FLAG_debugger_auto_break) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000475 ExecutionAccess access(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000476 thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000477 set_interrupt_limits(access);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000478 }
479}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000480#endif
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000481
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482void StackGuard::Continue(InterruptFlag after_what) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000483 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000484 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000485 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000486 reset_limits(access);
487 }
488}
489
490
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491char* StackGuard::ArchiveStackGuard(char* to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000492 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000493 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
494 ThreadLocal blank;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000495
496 // Set the stack limits using the old thread_local_.
497 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
498 // (as the ctor called SetStackLimits, which looked at the
499 // current thread_local_ from StackGuard)-- but is this
500 // really what was intended?
501 isolate_->heap()->SetStackLimits();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502 thread_local_ = blank;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000503
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504 return to + sizeof(ThreadLocal);
505}
506
507
508char* StackGuard::RestoreStackGuard(char* from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000509 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000511 isolate_->heap()->SetStackLimits();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000512 return from + sizeof(ThreadLocal);
513}
514
515
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000516void StackGuard::FreeThreadResources() {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000517 Isolate::PerIsolateThreadData* per_thread =
518 isolate_->FindOrAllocatePerThreadDataForThisThread();
519 per_thread->set_stack_limit(thread_local_.real_climit_);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000520}
521
522
523void StackGuard::ThreadLocal::Clear() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000524 real_jslimit_ = kIllegalLimit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000525 jslimit_ = kIllegalLimit;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000526 real_climit_ = kIllegalLimit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000527 climit_ = kIllegalLimit;
528 nesting_ = 0;
529 postpone_interrupts_nesting_ = 0;
530 interrupt_flags_ = 0;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000531}
532
533
lrn@chromium.org1c092762011-05-09 09:42:16 +0000534bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000535 bool should_set_stack_limits = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000536 if (real_climit_ == kIllegalLimit) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000537 // Takes the address of the limit variable in order to find out where
538 // the top of stack is right now.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000539 const uintptr_t kLimitSize = FLAG_stack_size * KB;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000540 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
541 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000542 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
543 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000544 real_climit_ = limit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000545 climit_ = limit;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000546 should_set_stack_limits = true;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000547 }
548 nesting_ = 0;
549 postpone_interrupts_nesting_ = 0;
550 interrupt_flags_ = 0;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000551 return should_set_stack_limits;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000552}
553
554
555void StackGuard::ClearThread(const ExecutionAccess& lock) {
556 thread_local_.Clear();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000557 isolate_->heap()->SetStackLimits();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000558}
559
560
561void StackGuard::InitThread(const ExecutionAccess& lock) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000562 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
563 Isolate::PerIsolateThreadData* per_thread =
564 isolate_->FindOrAllocatePerThreadDataForThisThread();
565 uintptr_t stored_limit = per_thread->stack_limit();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000566 // You should hold the ExecutionAccess lock when you call this.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000567 if (stored_limit != 0) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000568 SetStackLimit(stored_limit);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000569 }
570}
571
572
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573// --- C a l l s t o n a t i v e s ---
574
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000575#define RETURN_NATIVE_CALL(name, args, has_pending_exception) \
576 do { \
577 Isolate* isolate = Isolate::Current(); \
578 Handle<Object> argv[] = args; \
579 ASSERT(has_pending_exception != NULL); \
580 return Call(isolate->name##_fun(), \
581 isolate->js_builtins_object(), \
582 ARRAY_SIZE(argv), argv, \
583 has_pending_exception); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584 } while (false)
585
586
587Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
588 // See the similar code in runtime.js:ToBoolean.
589 if (obj->IsBoolean()) return obj;
590 bool result = true;
591 if (obj->IsString()) {
592 result = Handle<String>::cast(obj)->length() != 0;
593 } else if (obj->IsNull() || obj->IsUndefined()) {
594 result = false;
595 } else if (obj->IsNumber()) {
596 double value = obj->Number();
597 result = !((value == 0) || isnan(value));
598 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000599 return Handle<Object>(HEAP->ToBoolean(result));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600}
601
602
603Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000604 RETURN_NATIVE_CALL(to_number, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605}
606
607
608Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000609 RETURN_NATIVE_CALL(to_string, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000610}
611
612
613Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000614 RETURN_NATIVE_CALL(to_detail_string, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000615}
616
617
618Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000619 if (obj->IsSpecObject()) return obj;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000620 RETURN_NATIVE_CALL(to_object, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000621}
622
623
624Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000625 RETURN_NATIVE_CALL(to_integer, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626}
627
628
629Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000630 RETURN_NATIVE_CALL(to_uint32, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000631}
632
633
634Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000635 RETURN_NATIVE_CALL(to_int32, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000636}
637
638
639Handle<Object> Execution::NewDate(double time, bool* exc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000640 Handle<Object> time_obj = FACTORY->NewNumber(time);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000641 RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000642}
643
644
645#undef RETURN_NATIVE_CALL
646
647
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000648Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
649 Handle<String> flags,
650 bool* exc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000651 Handle<JSFunction> function = Handle<JSFunction>(
652 pattern->GetIsolate()->global_context()->regexp_function());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000653 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000654 function, pattern, flags, exc);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000655 if (*exc) return Handle<JSRegExp>();
656 return Handle<JSRegExp>::cast(re_obj);
657}
658
659
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000661 Isolate* isolate = string->GetIsolate();
662 Factory* factory = isolate->factory();
663
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000664 int int_index = static_cast<int>(index);
665 if (int_index < 0 || int_index >= string->length()) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000666 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667 }
668
669 Handle<Object> char_at =
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000670 GetProperty(isolate->js_builtins_object(),
671 factory->char_at_symbol());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000672 if (!char_at->IsJSFunction()) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000673 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000674 }
675
676 bool caught_exception;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000677 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000678 Handle<Object> index_arg[] = { index_object };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000679 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
680 string,
681 ARRAY_SIZE(index_arg),
682 index_arg,
683 &caught_exception);
684 if (caught_exception) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000685 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000686 }
687 return result;
688}
689
690
691Handle<JSFunction> Execution::InstantiateFunction(
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000692 Handle<FunctionTemplateInfo> data,
693 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000694 Isolate* isolate = data->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695 // Fast case: see if the function has already been instantiated
696 int serial_number = Smi::cast(data->serial_number())->value();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000697 Object* elm =
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000698 isolate->global_context()->function_cache()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000699 GetElementNoExceptionThrown(serial_number);
ager@chromium.org32912102009-01-16 10:38:43 +0000700 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000701 // The function has not yet been instantiated in this context; do it.
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000702 Handle<Object> args[] = { data };
703 Handle<Object> result = Call(isolate->instantiate_fun(),
704 isolate->js_builtins_object(),
705 ARRAY_SIZE(args),
706 args,
707 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000708 if (*exc) return Handle<JSFunction>::null();
709 return Handle<JSFunction>::cast(result);
710}
711
712
713Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
714 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000715 Isolate* isolate = data->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000716 if (data->property_list()->IsUndefined() &&
717 !data->constructor()->IsUndefined()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000718 // Initialization to make gcc happy.
719 Object* result = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000720 {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000721 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722 Handle<FunctionTemplateInfo> cons_template =
723 Handle<FunctionTemplateInfo>(
724 FunctionTemplateInfo::cast(data->constructor()));
725 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
726 if (*exc) return Handle<JSObject>::null();
727 Handle<Object> value = New(cons, 0, NULL, exc);
728 if (*exc) return Handle<JSObject>::null();
729 result = *value;
730 }
731 ASSERT(!*exc);
732 return Handle<JSObject>(JSObject::cast(result));
733 } else {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000734 Handle<Object> args[] = { data };
735 Handle<Object> result = Call(isolate->instantiate_fun(),
736 isolate->js_builtins_object(),
737 ARRAY_SIZE(args),
738 args,
739 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000740 if (*exc) return Handle<JSObject>::null();
741 return Handle<JSObject>::cast(result);
742 }
743}
744
745
746void Execution::ConfigureInstance(Handle<Object> instance,
747 Handle<Object> instance_template,
748 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000749 Isolate* isolate = Isolate::Current();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000750 Handle<Object> args[] = { instance, instance_template };
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000751 Execution::Call(isolate->configure_instance_fun(),
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000752 isolate->js_builtins_object(),
753 ARRAY_SIZE(args),
754 args,
755 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756}
757
758
759Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
760 Handle<JSFunction> fun,
761 Handle<Object> pos,
762 Handle<Object> is_global) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000763 Isolate* isolate = fun->GetIsolate();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000764 Handle<Object> args[] = { recv, fun, pos, is_global };
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000765 bool caught_exception;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000766 Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(),
767 isolate->js_builtins_object(),
768 ARRAY_SIZE(args),
769 args,
770 &caught_exception);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000771 if (caught_exception || !result->IsString()) {
772 return isolate->factory()->empty_symbol();
773 }
774
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000775 return Handle<String>::cast(result);
776}
777
778
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000779static Object* RuntimePreempt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000780 Isolate* isolate = Isolate::Current();
781
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000782 // Clear the preempt request flag.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000783 isolate->stack_guard()->Continue(PREEMPT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000784
785 ContextSwitcher::PreemptionReceived();
786
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000787#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000788 if (isolate->debug()->InDebugger()) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000789 // If currently in the debugger don't do any actual preemption but record
790 // that preemption occoured while in the debugger.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000791 isolate->debug()->PreemptionWhileInDebugger();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000792 } else {
793 // Perform preemption.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000794 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000795 Thread::YieldCPU();
796 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000797#else
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000798 { // NOLINT
799 // Perform preemption.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000800 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000801 Thread::YieldCPU();
802 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000803#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000804
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000805 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000806}
807
808
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000809#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000810Object* Execution::DebugBreakHelper() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000811 Isolate* isolate = Isolate::Current();
812
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000813 // Just continue if breaks are disabled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000814 if (isolate->debug()->disable_break()) {
815 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000816 }
817
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000818 // Ignore debug break during bootstrapping.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000819 if (isolate->bootstrapper()->IsActive()) {
820 return isolate->heap()->undefined_value();
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000821 }
822
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000823 {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000824 JavaScriptFrameIterator it(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000825 ASSERT(!it.done());
826 Object* fun = it.frame()->function();
827 if (fun && fun->IsJSFunction()) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000828 // Don't stop in builtin functions.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000829 if (JSFunction::cast(fun)->IsBuiltin()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000830 return isolate->heap()->undefined_value();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000831 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000832 GlobalObject* global = JSFunction::cast(fun)->context()->global();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000833 // Don't stop in debugger functions.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000834 if (isolate->debug()->IsDebugGlobal(global)) {
835 return isolate->heap()->undefined_value();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000836 }
837 }
838 }
839
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000840 // Collect the break state before clearing the flags.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000841 bool debug_command_only =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000842 isolate->stack_guard()->IsDebugCommand() &&
843 !isolate->stack_guard()->IsDebugBreak();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000844
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000845 // Clear the debug break request flag.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000846 isolate->stack_guard()->Continue(DEBUGBREAK);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000847
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000848 ProcessDebugMessages(debug_command_only);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000849
850 // Return to continue execution.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000851 return isolate->heap()->undefined_value();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000852}
853
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000854void Execution::ProcessDebugMessages(bool debug_command_only) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000855 Isolate* isolate = Isolate::Current();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000856 // Clear the debug command request flag.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000857 isolate->stack_guard()->Continue(DEBUGCOMMAND);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000858
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000859 HandleScope scope(isolate);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000860 // Enter the debugger. Just continue if we fail to enter the debugger.
861 EnterDebugger debugger;
862 if (debugger.FailedToEnter()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000863 return;
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000864 }
865
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000866 // Notify the debug event listeners. Indicate auto continue if the break was
867 // a debug command break.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000868 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
869 debug_command_only);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000870}
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000871
872
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000873#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000874
lrn@chromium.org303ada72010-10-27 09:33:13 +0000875MaybeObject* Execution::HandleStackGuardInterrupt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000876 Isolate* isolate = Isolate::Current();
877 StackGuard* stack_guard = isolate->stack_guard();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000878
879 if (stack_guard->IsGCRequest()) {
rossberg@chromium.org994edf62012-02-06 10:12:55 +0000880 isolate->heap()->CollectAllGarbage(false, "StackGuard GC request");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000881 stack_guard->Continue(GC_REQUEST);
882 }
883
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000884 isolate->counters()->stack_interrupts()->Increment();
885 if (stack_guard->IsRuntimeProfilerTick()) {
886 isolate->counters()->runtime_profiler_ticks()->Increment();
887 stack_guard->Continue(RUNTIME_PROFILER_TICK);
888 isolate->runtime_profiler()->OptimizeNow();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000889 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000890#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000891 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000892 DebugBreakHelper();
893 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000894#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000895 if (stack_guard->IsPreempted()) RuntimePreempt();
896 if (stack_guard->IsTerminateExecution()) {
897 stack_guard->Continue(TERMINATE);
898 return isolate->TerminateExecution();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000899 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000900 if (stack_guard->IsInterrupted()) {
901 stack_guard->Continue(INTERRUPT);
902 return isolate->StackOverflow();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000903 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000904 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000905}
906
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907} } // namespace v8::internal