blob: 705faa55480247897bd693351824c17800dfc740 [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.
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000103 ASSERT(function->context()->global_object()->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);
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000109 NoHandleAllocation na(isolate);
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
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +0000121#ifdef VERIFY_HEAP
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000122 value->Verify();
123#endif
124
125 // Update the pending exception flag and return the value.
126 *has_pending_exception = value->IsException();
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000127 ASSERT(*has_pending_exception == isolate->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();
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000130 if (isolate->pending_exception()->IsOutOfMemory()) {
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()) {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000168 Object* global = func->context()->global_object()->global_receiver();
lrn@chromium.org34e60782011-09-15 07:25:40 +0000169 // Under some circumstances, 'global' can be the JSBuiltinsObject
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000170 // In that case, don't rewrite. (FWIW, the same holds for
171 // GetIsolate()->global_object()->global_receiver().)
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000172 if (!global->IsJSBuiltinsObject()) {
173 receiver = Handle<Object>(global, func->GetIsolate());
174 }
lrn@chromium.org34e60782011-09-15 07:25:40 +0000175 } else {
176 receiver = ToObject(receiver, pending_exception);
177 }
178 if (*pending_exception) return callable;
179 }
180
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000181 return Invoke(false, func, receiver, argc, argv, pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182}
183
184
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000185Handle<Object> Execution::New(Handle<JSFunction> func,
186 int argc,
187 Handle<Object> argv[],
188 bool* pending_exception) {
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000189 return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000190 pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191}
192
193
194Handle<Object> Execution::TryCall(Handle<JSFunction> func,
195 Handle<Object> receiver,
196 int argc,
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000197 Handle<Object> args[],
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198 bool* caught_exception) {
199 // Enter a try-block while executing the JavaScript code. To avoid
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000200 // duplicate error printing it must be non-verbose. Also, to avoid
201 // creating message objects during stack overflow we shouldn't
202 // capture messages.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000203 v8::TryCatch catcher;
204 catcher.SetVerbose(false);
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000205 catcher.SetCaptureMessage(false);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000206 *caught_exception = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207
208 Handle<Object> result = Invoke(false, func, receiver, argc, args,
209 caught_exception);
210
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000211 Isolate* isolate = func->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 if (*caught_exception) {
213 ASSERT(catcher.HasCaught());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000214 ASSERT(isolate->has_pending_exception());
215 ASSERT(isolate->external_caught_exception());
mmassi@chromium.org49a44672012-12-04 13:52:03 +0000216 if (isolate->is_out_of_memory() && !isolate->ignore_out_of_memory()) {
217 V8::FatalProcessOutOfMemory("OOM during Execution::TryCall");
218 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000219 if (isolate->pending_exception() ==
220 isolate->heap()->termination_exception()) {
221 result = isolate->factory()->termination_exception();
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000222 } else {
223 result = v8::Utils::OpenHandle(*catcher.Exception());
224 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000225 isolate->OptionalRescheduleException(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226 }
227
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000228 ASSERT(!isolate->has_pending_exception());
229 ASSERT(!isolate->external_caught_exception());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230 return result;
231}
232
233
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
235 ASSERT(!object->IsJSFunction());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000236 Isolate* isolate = Isolate::Current();
237 Factory* factory = isolate->factory();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238
239 // If you return a function from here, it will be called when an
240 // attempt is made to call the given object as a function.
241
lrn@chromium.org34e60782011-09-15 07:25:40 +0000242 // If object is a function proxy, get its handler. Iterate if necessary.
243 Object* fun = *object;
244 while (fun->IsJSFunctionProxy()) {
245 fun = JSFunctionProxy::cast(fun)->call_trap();
246 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000247 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249 // Objects created through the API can have an instance-call handler
250 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000251 if (fun->IsHeapObject() &&
252 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253 return Handle<JSFunction>(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000254 isolate->native_context()->call_as_function_delegate());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000255 }
256
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000257 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000258}
259
260
lrn@chromium.org1c092762011-05-09 09:42:16 +0000261Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object,
262 bool* has_pending_exception) {
263 ASSERT(!object->IsJSFunction());
264 Isolate* isolate = Isolate::Current();
265
lrn@chromium.org34e60782011-09-15 07:25:40 +0000266 // If object is a function proxy, get its handler. Iterate if necessary.
267 Object* fun = *object;
268 while (fun->IsJSFunctionProxy()) {
269 fun = JSFunctionProxy::cast(fun)->call_trap();
270 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000271 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000272
lrn@chromium.org1c092762011-05-09 09:42:16 +0000273 // Objects created through the API can have an instance-call handler
274 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000275 if (fun->IsHeapObject() &&
276 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000277 return Handle<JSFunction>(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000278 isolate->native_context()->call_as_function_delegate());
lrn@chromium.org1c092762011-05-09 09:42:16 +0000279 }
280
281 // If the Object doesn't have an instance-call handler we should
282 // throw a non-callable exception.
283 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
284 "called_non_callable", i::HandleVector<i::Object>(&object, 1));
285 isolate->Throw(*error_obj);
286 *has_pending_exception = true;
287
288 return isolate->factory()->undefined_value();
289}
290
291
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000292Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) {
293 ASSERT(!object->IsJSFunction());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000294 Isolate* isolate = Isolate::Current();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000295
296 // If you return a function from here, it will be called when an
297 // attempt is made to call the given object as a constructor.
298
lrn@chromium.org34e60782011-09-15 07:25:40 +0000299 // If object is a function proxies, get its handler. Iterate if necessary.
300 Object* fun = *object;
301 while (fun->IsJSFunctionProxy()) {
302 fun = JSFunctionProxy::cast(fun)->call_trap();
303 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000304 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000305
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000306 // Objects created through the API can have an instance-call handler
307 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000308 if (fun->IsHeapObject() &&
309 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000310 return Handle<JSFunction>(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000311 isolate->native_context()->call_as_constructor_delegate());
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000312 }
313
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000314 return isolate->factory()->undefined_value();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +0000315}
316
317
lrn@chromium.org1c092762011-05-09 09:42:16 +0000318Handle<Object> Execution::TryGetConstructorDelegate(
319 Handle<Object> object,
320 bool* has_pending_exception) {
321 ASSERT(!object->IsJSFunction());
322 Isolate* isolate = Isolate::Current();
323
324 // If you return a function from here, it will be called when an
325 // attempt is made to call the given object as a constructor.
326
lrn@chromium.org34e60782011-09-15 07:25:40 +0000327 // If object is a function proxies, get its handler. Iterate if necessary.
328 Object* fun = *object;
329 while (fun->IsJSFunctionProxy()) {
330 fun = JSFunctionProxy::cast(fun)->call_trap();
331 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000332 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
lrn@chromium.org34e60782011-09-15 07:25:40 +0000333
lrn@chromium.org1c092762011-05-09 09:42:16 +0000334 // Objects created through the API can have an instance-call handler
335 // that should be used when calling the object as a function.
lrn@chromium.org34e60782011-09-15 07:25:40 +0000336 if (fun->IsHeapObject() &&
337 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000338 return Handle<JSFunction>(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000339 isolate->native_context()->call_as_constructor_delegate());
lrn@chromium.org1c092762011-05-09 09:42:16 +0000340 }
341
342 // If the Object doesn't have an instance-call handler we should
343 // throw a non-callable exception.
344 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
345 "called_non_callable", i::HandleVector<i::Object>(&object, 1));
346 isolate->Throw(*error_obj);
347 *has_pending_exception = true;
348
349 return isolate->factory()->undefined_value();
350}
351
352
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353bool StackGuard::IsStackOverflow() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000354 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355 return (thread_local_.jslimit_ != kInterruptLimit &&
356 thread_local_.climit_ != kInterruptLimit);
357}
358
359
360void StackGuard::EnableInterrupts() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000361 ExecutionAccess access(isolate_);
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000362 if (has_pending_interrupts(access)) {
363 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000364 }
365}
366
367
368void StackGuard::SetStackLimit(uintptr_t limit) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000369 ExecutionAccess access(isolate_);
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000370 // If the current limits are special (e.g. due to a pending interrupt) then
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000371 // leave them alone.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000372 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000373 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000374 thread_local_.jslimit_ = jslimit;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000375 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000376 if (thread_local_.climit_ == thread_local_.real_climit_) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000377 thread_local_.climit_ = limit;
378 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000379 thread_local_.real_climit_ = limit;
380 thread_local_.real_jslimit_ = jslimit;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000381}
382
383
384void StackGuard::DisableInterrupts() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000385 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000386 reset_limits(access);
387}
388
389
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000390bool StackGuard::ShouldPostponeInterrupts() {
391 ExecutionAccess access(isolate_);
392 return should_postpone_interrupts(access);
393}
394
395
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396bool StackGuard::IsInterrupted() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000397 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000398 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399}
400
401
402void StackGuard::Interrupt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000403 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404 thread_local_.interrupt_flags_ |= INTERRUPT;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000405 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000406}
407
408
409bool StackGuard::IsPreempted() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000410 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000411 return thread_local_.interrupt_flags_ & PREEMPT;
412}
413
414
415void StackGuard::Preempt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000416 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417 thread_local_.interrupt_flags_ |= PREEMPT;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000418 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000419}
420
421
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000422bool StackGuard::IsTerminateExecution() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000423 ExecutionAccess access(isolate_);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000424 return (thread_local_.interrupt_flags_ & TERMINATE) != 0;
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000425}
426
427
428void StackGuard::TerminateExecution() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000429 ExecutionAccess access(isolate_);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000430 thread_local_.interrupt_flags_ |= TERMINATE;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000431 set_interrupt_limits(access);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000432}
433
434
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000435void StackGuard::RequestCodeReadyEvent() {
436 ASSERT(FLAG_parallel_recompilation);
437 if (ExecutionAccess::TryLock(isolate_)) {
438 thread_local_.interrupt_flags_ |= CODE_READY;
439 if (thread_local_.postpone_interrupts_nesting_ == 0) {
440 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
441 isolate_->heap()->SetStackLimits();
442 }
443 ExecutionAccess::Unlock(isolate_);
444 }
445}
446
447
448bool StackGuard::IsCodeReadyEvent() {
449 ExecutionAccess access(isolate_);
450 return (thread_local_.interrupt_flags_ & CODE_READY) != 0;
451}
452
453
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000454bool StackGuard::IsGCRequest() {
455 ExecutionAccess access(isolate_);
456 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0;
457}
458
459
460void StackGuard::RequestGC() {
461 ExecutionAccess access(isolate_);
462 thread_local_.interrupt_flags_ |= GC_REQUEST;
463 if (thread_local_.postpone_interrupts_nesting_ == 0) {
464 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
465 isolate_->heap()->SetStackLimits();
466 }
467}
468
469
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000470#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000471bool StackGuard::IsDebugBreak() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000472 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000473 return thread_local_.interrupt_flags_ & DEBUGBREAK;
474}
475
kasper.lund44510672008-07-25 07:37:58 +0000476
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000477void StackGuard::DebugBreak() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000478 ExecutionAccess access(isolate_);
kasper.lund7276f142008-07-30 08:49:36 +0000479 thread_local_.interrupt_flags_ |= DEBUGBREAK;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000480 set_interrupt_limits(access);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000481}
482
483
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000484bool StackGuard::IsDebugCommand() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000485 ExecutionAccess access(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000486 return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
487}
488
489
490void StackGuard::DebugCommand() {
491 if (FLAG_debugger_auto_break) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000492 ExecutionAccess access(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000493 thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000494 set_interrupt_limits(access);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000495 }
496}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000497#endif
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000498
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499void StackGuard::Continue(InterruptFlag after_what) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000500 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +0000502 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000503 reset_limits(access);
504 }
505}
506
507
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508char* StackGuard::ArchiveStackGuard(char* to) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000509 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000510 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
511 ThreadLocal blank;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000512
513 // Set the stack limits using the old thread_local_.
514 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
515 // (as the ctor called SetStackLimits, which looked at the
516 // current thread_local_ from StackGuard)-- but is this
517 // really what was intended?
518 isolate_->heap()->SetStackLimits();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519 thread_local_ = blank;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000520
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521 return to + sizeof(ThreadLocal);
522}
523
524
525char* StackGuard::RestoreStackGuard(char* from) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000526 ExecutionAccess access(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000528 isolate_->heap()->SetStackLimits();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529 return from + sizeof(ThreadLocal);
530}
531
532
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000533void StackGuard::FreeThreadResources() {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000534 Isolate::PerIsolateThreadData* per_thread =
535 isolate_->FindOrAllocatePerThreadDataForThisThread();
536 per_thread->set_stack_limit(thread_local_.real_climit_);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000537}
538
539
540void StackGuard::ThreadLocal::Clear() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000541 real_jslimit_ = kIllegalLimit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000542 jslimit_ = kIllegalLimit;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000543 real_climit_ = kIllegalLimit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000544 climit_ = kIllegalLimit;
545 nesting_ = 0;
546 postpone_interrupts_nesting_ = 0;
547 interrupt_flags_ = 0;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000548}
549
550
lrn@chromium.org1c092762011-05-09 09:42:16 +0000551bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000552 bool should_set_stack_limits = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000553 if (real_climit_ == kIllegalLimit) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000554 // Takes the address of the limit variable in order to find out where
555 // the top of stack is right now.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000556 const uintptr_t kLimitSize = FLAG_stack_size * KB;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000557 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;
558 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
lrn@chromium.org1c092762011-05-09 09:42:16 +0000559 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
560 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000561 real_climit_ = limit;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000562 climit_ = limit;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000563 should_set_stack_limits = true;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000564 }
565 nesting_ = 0;
566 postpone_interrupts_nesting_ = 0;
567 interrupt_flags_ = 0;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000568 return should_set_stack_limits;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000569}
570
571
572void StackGuard::ClearThread(const ExecutionAccess& lock) {
573 thread_local_.Clear();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000574 isolate_->heap()->SetStackLimits();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000575}
576
577
578void StackGuard::InitThread(const ExecutionAccess& lock) {
lrn@chromium.org1c092762011-05-09 09:42:16 +0000579 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
580 Isolate::PerIsolateThreadData* per_thread =
581 isolate_->FindOrAllocatePerThreadDataForThisThread();
582 uintptr_t stored_limit = per_thread->stack_limit();
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000583 // You should hold the ExecutionAccess lock when you call this.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000584 if (stored_limit != 0) {
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000585 SetStackLimit(stored_limit);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000586 }
587}
588
589
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000590// --- C a l l s t o n a t i v e s ---
591
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000592#define RETURN_NATIVE_CALL(name, args, has_pending_exception) \
593 do { \
594 Isolate* isolate = Isolate::Current(); \
595 Handle<Object> argv[] = args; \
596 ASSERT(has_pending_exception != NULL); \
597 return Call(isolate->name##_fun(), \
598 isolate->js_builtins_object(), \
599 ARRAY_SIZE(argv), argv, \
600 has_pending_exception); \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000601 } while (false)
602
603
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000604Handle<Object> Execution::ToBoolean(Isolate* isolate, Handle<Object> obj) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605 // See the similar code in runtime.js:ToBoolean.
606 if (obj->IsBoolean()) return obj;
607 bool result = true;
608 if (obj->IsString()) {
609 result = Handle<String>::cast(obj)->length() != 0;
610 } else if (obj->IsNull() || obj->IsUndefined()) {
611 result = false;
612 } else if (obj->IsNumber()) {
613 double value = obj->Number();
614 result = !((value == 0) || isnan(value));
615 }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000616 return Handle<Object>(isolate->heap()->ToBoolean(result), isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617}
618
619
620Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000621 RETURN_NATIVE_CALL(to_number, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000622}
623
624
625Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000626 RETURN_NATIVE_CALL(to_string, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000627}
628
629
630Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000631 RETURN_NATIVE_CALL(to_detail_string, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000632}
633
634
635Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
lrn@chromium.org34e60782011-09-15 07:25:40 +0000636 if (obj->IsSpecObject()) return obj;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000637 RETURN_NATIVE_CALL(to_object, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000638}
639
640
641Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000642 RETURN_NATIVE_CALL(to_integer, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643}
644
645
646Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000647 RETURN_NATIVE_CALL(to_uint32, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000648}
649
650
651Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000652 RETURN_NATIVE_CALL(to_int32, { obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000653}
654
655
656Handle<Object> Execution::NewDate(double time, bool* exc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000657 Handle<Object> time_obj = FACTORY->NewNumber(time);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000658 RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000659}
660
661
662#undef RETURN_NATIVE_CALL
663
664
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000665Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
666 Handle<String> flags,
667 bool* exc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000668 Handle<JSFunction> function = Handle<JSFunction>(
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000669 pattern->GetIsolate()->native_context()->regexp_function());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000670 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000671 function, pattern, flags, exc);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000672 if (*exc) return Handle<JSRegExp>();
673 return Handle<JSRegExp>::cast(re_obj);
674}
675
676
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000677Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000678 Isolate* isolate = string->GetIsolate();
679 Factory* factory = isolate->factory();
680
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000681 int int_index = static_cast<int>(index);
682 if (int_index < 0 || int_index >= string->length()) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000683 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684 }
685
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000686 Handle<Object> char_at = GetProperty(
687 isolate, isolate->js_builtins_object(), factory->char_at_string());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000688 if (!char_at->IsJSFunction()) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000689 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690 }
691
692 bool caught_exception;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000693 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000694 Handle<Object> index_arg[] = { index_object };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
696 string,
697 ARRAY_SIZE(index_arg),
698 index_arg,
699 &caught_exception);
700 if (caught_exception) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000701 return factory->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702 }
703 return result;
704}
705
706
707Handle<JSFunction> Execution::InstantiateFunction(
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000708 Handle<FunctionTemplateInfo> data,
709 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000710 Isolate* isolate = data->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711 // Fast case: see if the function has already been instantiated
712 int serial_number = Smi::cast(data->serial_number())->value();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000713 Object* elm =
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000714 isolate->native_context()->function_cache()->
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000715 GetElementNoExceptionThrown(serial_number);
ager@chromium.org32912102009-01-16 10:38:43 +0000716 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717 // The function has not yet been instantiated in this context; do it.
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000718 Handle<Object> args[] = { data };
719 Handle<Object> result = Call(isolate->instantiate_fun(),
720 isolate->js_builtins_object(),
721 ARRAY_SIZE(args),
722 args,
723 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000724 if (*exc) return Handle<JSFunction>::null();
725 return Handle<JSFunction>::cast(result);
726}
727
728
729Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
730 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000731 Isolate* isolate = data->GetIsolate();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000732 if (data->property_list()->IsUndefined() &&
733 !data->constructor()->IsUndefined()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000734 // Initialization to make gcc happy.
735 Object* result = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000736 {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000737 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000738 Handle<FunctionTemplateInfo> cons_template =
739 Handle<FunctionTemplateInfo>(
740 FunctionTemplateInfo::cast(data->constructor()));
741 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
742 if (*exc) return Handle<JSObject>::null();
743 Handle<Object> value = New(cons, 0, NULL, exc);
744 if (*exc) return Handle<JSObject>::null();
745 result = *value;
746 }
747 ASSERT(!*exc);
748 return Handle<JSObject>(JSObject::cast(result));
749 } else {
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000750 Handle<Object> args[] = { data };
751 Handle<Object> result = Call(isolate->instantiate_fun(),
752 isolate->js_builtins_object(),
753 ARRAY_SIZE(args),
754 args,
755 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756 if (*exc) return Handle<JSObject>::null();
757 return Handle<JSObject>::cast(result);
758 }
759}
760
761
762void Execution::ConfigureInstance(Handle<Object> instance,
763 Handle<Object> instance_template,
764 bool* exc) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000765 Isolate* isolate = Isolate::Current();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000766 Handle<Object> args[] = { instance, instance_template };
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000767 Execution::Call(isolate->configure_instance_fun(),
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000768 isolate->js_builtins_object(),
769 ARRAY_SIZE(args),
770 args,
771 exc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772}
773
774
775Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
776 Handle<JSFunction> fun,
777 Handle<Object> pos,
778 Handle<Object> is_global) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000779 Isolate* isolate = fun->GetIsolate();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000780 Handle<Object> args[] = { recv, fun, pos, is_global };
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000781 bool caught_exception;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000782 Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(),
783 isolate->js_builtins_object(),
784 ARRAY_SIZE(args),
785 args,
786 &caught_exception);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000787 if (caught_exception || !result->IsString()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000788 return isolate->factory()->empty_string();
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000789 }
790
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000791 return Handle<String>::cast(result);
792}
793
794
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000795static Object* RuntimePreempt() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000796 Isolate* isolate = Isolate::Current();
797
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000798 // Clear the preempt request flag.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000799 isolate->stack_guard()->Continue(PREEMPT);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000800
801 ContextSwitcher::PreemptionReceived();
802
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000803#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000804 if (isolate->debug()->InDebugger()) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000805 // If currently in the debugger don't do any actual preemption but record
806 // that preemption occoured while in the debugger.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000807 isolate->debug()->PreemptionWhileInDebugger();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000808 } else {
809 // Perform preemption.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000810 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000811 Thread::YieldCPU();
812 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000813#else
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000814 { // NOLINT
815 // Perform preemption.
lrn@chromium.org1c092762011-05-09 09:42:16 +0000816 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000817 Thread::YieldCPU();
818 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000819#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000820
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000821 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000822}
823
824
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000825#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000826Object* Execution::DebugBreakHelper() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000827 Isolate* isolate = Isolate::Current();
828
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000829 // Just continue if breaks are disabled.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000830 if (isolate->debug()->disable_break()) {
831 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000832 }
833
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000834 // Ignore debug break during bootstrapping.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000835 if (isolate->bootstrapper()->IsActive()) {
836 return isolate->heap()->undefined_value();
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000837 }
838
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000839 // Ignore debug break if debugger is not active.
840 if (!isolate->debugger()->IsDebuggerActive()) {
841 return isolate->heap()->undefined_value();
842 }
843
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000844 StackLimitCheck check(isolate);
845 if (check.HasOverflowed()) {
846 return isolate->heap()->undefined_value();
847 }
848
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000849 {
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000850 JavaScriptFrameIterator it(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000851 ASSERT(!it.done());
852 Object* fun = it.frame()->function();
853 if (fun && fun->IsJSFunction()) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000854 // Don't stop in builtin functions.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000855 if (JSFunction::cast(fun)->IsBuiltin()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000856 return isolate->heap()->undefined_value();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000857 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000858 GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000859 // Don't stop in debugger functions.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000860 if (isolate->debug()->IsDebugGlobal(global)) {
861 return isolate->heap()->undefined_value();
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000862 }
863 }
864 }
865
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000866 // Collect the break state before clearing the flags.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000867 bool debug_command_only =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000868 isolate->stack_guard()->IsDebugCommand() &&
869 !isolate->stack_guard()->IsDebugBreak();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000870
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000871 // Clear the debug break request flag.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000872 isolate->stack_guard()->Continue(DEBUGBREAK);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000873
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000874 ProcessDebugMessages(debug_command_only);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000875
876 // Return to continue execution.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000877 return isolate->heap()->undefined_value();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000878}
879
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000880void Execution::ProcessDebugMessages(bool debug_command_only) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000881 Isolate* isolate = Isolate::Current();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000882 // Clear the debug command request flag.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000883 isolate->stack_guard()->Continue(DEBUGCOMMAND);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000884
fschneider@chromium.org7d10be52012-04-10 12:30:14 +0000885 StackLimitCheck check(isolate);
886 if (check.HasOverflowed()) {
887 return;
888 }
889
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000890 HandleScope scope(isolate);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000891 // Enter the debugger. Just continue if we fail to enter the debugger.
892 EnterDebugger debugger;
893 if (debugger.FailedToEnter()) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000894 return;
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000895 }
896
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000897 // Notify the debug event listeners. Indicate auto continue if the break was
898 // a debug command break.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000899 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(),
900 debug_command_only);
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000901}
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000902
903
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000904#endif
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000905
ulan@chromium.org812308e2012-02-29 15:58:45 +0000906MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000907 StackGuard* stack_guard = isolate->stack_guard();
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000908 if (stack_guard->ShouldPostponeInterrupts()) {
909 return isolate->heap()->undefined_value();
910 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000911
912 if (stack_guard->IsGCRequest()) {
mstarzinger@chromium.org3233d2f2012-03-14 11:16:03 +0000913 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
914 "StackGuard GC request");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000915 stack_guard->Continue(GC_REQUEST);
916 }
917
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000918 if (stack_guard->IsCodeReadyEvent()) {
919 ASSERT(FLAG_parallel_recompilation);
920 if (FLAG_trace_parallel_recompilation) {
921 PrintF(" ** CODE_READY event received.\n");
922 }
923 stack_guard->Continue(CODE_READY);
924 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000925 if (!stack_guard->IsTerminateExecution() &&
926 !FLAG_manual_parallel_recompilation) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000927 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
928 }
929
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000930 isolate->counters()->stack_interrupts()->Increment();
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +0000931 isolate->counters()->runtime_profiler_ticks()->Increment();
rossberg@chromium.orgcddc71f2012-12-07 12:40:13 +0000932 isolate->runtime_profiler()->OptimizeNow();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000933#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000934 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000935 DebugBreakHelper();
936 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000937#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000938 if (stack_guard->IsPreempted()) RuntimePreempt();
939 if (stack_guard->IsTerminateExecution()) {
940 stack_guard->Continue(TERMINATE);
941 return isolate->TerminateExecution();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +0000942 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000943 if (stack_guard->IsInterrupted()) {
944 stack_guard->Continue(INTERRUPT);
945 return isolate->StackOverflow();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000946 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000947 return isolate->heap()->undefined_value();
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000948}
949
yangguo@chromium.org56454712012-02-16 15:33:53 +0000950
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000951} } // namespace v8::internal