blob: 7aa4f3341d68a4bfd3c569f4537df3db8593f3a4 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/execution.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/bootstrapper.h"
8#include "src/codegen.h"
9#include "src/deoptimizer.h"
10#include "src/isolate-inl.h"
11#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000012
13namespace v8 {
14namespace internal {
15
Steve Block44f0eee2011-05-26 01:26:41 +010016StackGuard::StackGuard()
17 : isolate_(NULL) {
18}
19
20
21void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022 DCHECK(isolate_ != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010023 thread_local_.jslimit_ = kInterruptLimit;
24 thread_local_.climit_ = kInterruptLimit;
25 isolate_->heap()->SetStackLimits();
26}
27
28
29void StackGuard::reset_limits(const ExecutionAccess& lock) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030 DCHECK(isolate_ != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010031 thread_local_.jslimit_ = thread_local_.real_jslimit_;
32 thread_local_.climit_ = thread_local_.real_climit_;
33 isolate_->heap()->SetStackLimits();
34}
35
36
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037MUST_USE_RESULT static MaybeHandle<Object> Invoke(
38 bool is_construct,
39 Handle<JSFunction> function,
40 Handle<Object> receiver,
41 int argc,
42 Handle<Object> args[]) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010043 Isolate* isolate = function->GetIsolate();
Steve Block44f0eee2011-05-26 01:26:41 +010044
Steve Blocka7e24c12009-10-30 11:49:00 +000045 // Entering JavaScript.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 VMState<JS> state(isolate);
47 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
48 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
49 isolate->ThrowIllegalOperation();
50 isolate->ReportPendingMessages();
51 return MaybeHandle<Object>();
52 }
Steve Blocka7e24c12009-10-30 11:49:00 +000053
54 // Placeholder for return value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 Object* value = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +000056
Ben Murdoch3ef787d2012-04-12 10:51:47 +010057 typedef Object* (*JSEntryFunction)(byte* entry,
58 Object* function,
59 Object* receiver,
60 int argc,
61 Object*** args);
Steve Blocka7e24c12009-10-30 11:49:00 +000062
Ben Murdoch3ef787d2012-04-12 10:51:47 +010063 Handle<Code> code = is_construct
64 ? isolate->factory()->js_construct_entry_code()
65 : isolate->factory()->js_entry_code();
Steve Blocka7e24c12009-10-30 11:49:00 +000066
67 // Convert calls on global objects to be calls on the global
68 // receiver instead to avoid having a 'this' pointer which refers
69 // directly to a global object.
70 if (receiver->IsGlobalObject()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
Steve Blocka7e24c12009-10-30 11:49:00 +000072 }
73
Leon Clarkee46be812010-01-19 14:06:41 +000074 // Make sure that the global object of the context we're about to
75 // make the current one is indeed a global object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000076 DCHECK(function->context()->global_object()->IsGlobalObject());
Leon Clarkee46be812010-01-19 14:06:41 +000077
Steve Blocka7e24c12009-10-30 11:49:00 +000078 {
79 // Save and restore context around invocation and block the
80 // allocation of handles without explicit handle scopes.
Steve Block44f0eee2011-05-26 01:26:41 +010081 SaveContext save(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 SealHandleScope shs(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010083 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +000084
85 // Call the function through the right JS entry stub.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010086 byte* function_entry = function->code()->entry();
87 JSFunction* func = *function;
88 Object* recv = *receiver;
89 Object*** argv = reinterpret_cast<Object***>(args);
90 value =
91 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
Steve Blocka7e24c12009-10-30 11:49:00 +000092 }
93
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094#ifdef VERIFY_HEAP
95 value->ObjectVerify();
Steve Blocka7e24c12009-10-30 11:49:00 +000096#endif
97
98 // Update the pending exception flag and return the value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 bool has_exception = value->IsException();
100 DCHECK(has_exception == isolate->has_pending_exception());
101 if (has_exception) {
Steve Block44f0eee2011-05-26 01:26:41 +0100102 isolate->ReportPendingMessages();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 // Reset stepping state when script exits with uncaught exception.
104 if (isolate->debug()->is_active()) {
105 isolate->debug()->ClearStepping();
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100106 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 return MaybeHandle<Object>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100109 isolate->clear_pending_message();
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 }
111
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112 return Handle<Object>(value, isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000113}
114
115
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000116MaybeHandle<Object> Execution::Call(Isolate* isolate,
117 Handle<Object> callable,
118 Handle<Object> receiver,
119 int argc,
120 Handle<Object> argv[],
121 bool convert_receiver) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000122 if (!callable->IsJSFunction()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 ASSIGN_RETURN_ON_EXCEPTION(
124 isolate, callable, TryGetFunctionDelegate(isolate, callable), Object);
Ben Murdoch257744e2011-11-30 15:57:28 +0000125 }
126 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
Ben Murdoch589d6972011-11-30 16:04:58 +0000127
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 // In sloppy mode, convert receiver.
Ben Murdoch589d6972011-11-30 16:04:58 +0000129 if (convert_receiver && !receiver->IsJSReceiver() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 !func->shared()->native() &&
131 func->shared()->strict_mode() == SLOPPY) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000132 if (receiver->IsUndefined() || receiver->IsNull()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 receiver = handle(func->global_proxy());
134 DCHECK(!receiver->IsJSBuiltinsObject());
Ben Murdoch589d6972011-11-30 16:04:58 +0000135 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 ASSIGN_RETURN_ON_EXCEPTION(
137 isolate, receiver, ToObject(isolate, receiver), Object);
Ben Murdoch589d6972011-11-30 16:04:58 +0000138 }
Ben Murdoch589d6972011-11-30 16:04:58 +0000139 }
140
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 return Invoke(false, func, receiver, argc, argv);
Steve Blocka7e24c12009-10-30 11:49:00 +0000142}
143
144
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
146 int argc,
147 Handle<Object> argv[]) {
148 return Invoke(true, func, handle(func->global_proxy()), argc, argv);
Steve Blocka7e24c12009-10-30 11:49:00 +0000149}
150
151
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
153 Handle<Object> receiver, int argc,
154 Handle<Object> args[],
155 MaybeHandle<Object>* exception_out) {
156 bool is_termination = false;
157 Isolate* isolate = func->GetIsolate();
158 MaybeHandle<Object> maybe_result;
159 if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000160 // Enter a try-block while executing the JavaScript code. To avoid
161 // duplicate error printing it must be non-verbose. Also, to avoid
162 // creating message objects during stack overflow we shouldn't
163 // capture messages.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 {
165 v8::TryCatch catcher;
166 catcher.SetVerbose(false);
167 catcher.SetCaptureMessage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 maybe_result = Invoke(false, func, receiver, argc, args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000170
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 if (maybe_result.is_null()) {
172 DCHECK(catcher.HasCaught());
173 DCHECK(isolate->has_pending_exception());
174 DCHECK(isolate->external_caught_exception());
175 if (exception_out != NULL) {
176 if (isolate->pending_exception() ==
177 isolate->heap()->termination_exception()) {
178 is_termination = true;
179 } else {
180 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
181 }
182 }
183 isolate->OptionalRescheduleException(true);
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000185
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 DCHECK(!isolate->has_pending_exception());
187 DCHECK(!isolate->external_caught_exception());
188 }
189 if (is_termination) isolate->TerminateExecution();
190 return maybe_result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000191}
192
193
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
195 Handle<Object> object) {
196 DCHECK(!object->IsJSFunction());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100197 Factory* factory = isolate->factory();
Steve Blocka7e24c12009-10-30 11:49:00 +0000198
199 // If you return a function from here, it will be called when an
200 // attempt is made to call the given object as a function.
201
Ben Murdoch589d6972011-11-30 16:04:58 +0000202 // If object is a function proxy, get its handler. Iterate if necessary.
203 Object* fun = *object;
204 while (fun->IsJSFunctionProxy()) {
205 fun = JSFunctionProxy::cast(fun)->call_trap();
206 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
Ben Murdoch589d6972011-11-30 16:04:58 +0000208
Steve Blocka7e24c12009-10-30 11:49:00 +0000209 // Objects created through the API can have an instance-call handler
210 // that should be used when calling the object as a function.
Ben Murdoch589d6972011-11-30 16:04:58 +0000211 if (fun->IsHeapObject() &&
212 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000213 return Handle<JSFunction>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000214 isolate->native_context()->call_as_function_delegate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000215 }
216
Ben Murdoch8b112d22011-06-08 16:22:53 +0100217 return factory->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000218}
219
220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
222 Handle<Object> object) {
223 DCHECK(!object->IsJSFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +0000224
Ben Murdoch589d6972011-11-30 16:04:58 +0000225 // If object is a function proxy, get its handler. Iterate if necessary.
226 Object* fun = *object;
227 while (fun->IsJSFunctionProxy()) {
228 fun = JSFunctionProxy::cast(fun)->call_trap();
229 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
Ben Murdoch589d6972011-11-30 16:04:58 +0000231
Ben Murdoch257744e2011-11-30 15:57:28 +0000232 // Objects created through the API can have an instance-call handler
233 // that should be used when calling the object as a function.
Ben Murdoch589d6972011-11-30 16:04:58 +0000234 if (fun->IsHeapObject() &&
235 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000236 return Handle<JSFunction>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 isolate->native_context()->call_as_function_delegate());
Ben Murdoch257744e2011-11-30 15:57:28 +0000238 }
239
240 // If the Object doesn't have an instance-call handler we should
241 // throw a non-callable exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
243 i::HandleVector<i::Object>(&object, 1)),
244 Object);
Ben Murdoch257744e2011-11-30 15:57:28 +0000245}
246
247
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
249 Handle<Object> object) {
250 DCHECK(!object->IsJSFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +0000251
252 // If you return a function from here, it will be called when an
253 // attempt is made to call the given object as a constructor.
254
Ben Murdoch589d6972011-11-30 16:04:58 +0000255 // If object is a function proxies, get its handler. Iterate if necessary.
256 Object* fun = *object;
257 while (fun->IsJSFunctionProxy()) {
258 fun = JSFunctionProxy::cast(fun)->call_trap();
259 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
Ben Murdoch589d6972011-11-30 16:04:58 +0000261
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 // Objects created through the API can have an instance-call handler
263 // that should be used when calling the object as a function.
Ben Murdoch589d6972011-11-30 16:04:58 +0000264 if (fun->IsHeapObject() &&
265 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 return Handle<JSFunction>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 isolate->native_context()->call_as_constructor_delegate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 }
269
Ben Murdoch8b112d22011-06-08 16:22:53 +0100270 return isolate->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000271}
272
273
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274MaybeHandle<Object> Execution::TryGetConstructorDelegate(
275 Isolate* isolate, Handle<Object> object) {
276 DCHECK(!object->IsJSFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +0000277
278 // If you return a function from here, it will be called when an
279 // attempt is made to call the given object as a constructor.
280
Ben Murdoch589d6972011-11-30 16:04:58 +0000281 // If object is a function proxies, get its handler. Iterate if necessary.
282 Object* fun = *object;
283 while (fun->IsJSFunctionProxy()) {
284 fun = JSFunctionProxy::cast(fun)->call_trap();
285 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
Ben Murdoch589d6972011-11-30 16:04:58 +0000287
Ben Murdoch257744e2011-11-30 15:57:28 +0000288 // Objects created through the API can have an instance-call handler
289 // that should be used when calling the object as a function.
Ben Murdoch589d6972011-11-30 16:04:58 +0000290 if (fun->IsHeapObject() &&
291 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000292 return Handle<JSFunction>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 isolate->native_context()->call_as_constructor_delegate());
Ben Murdoch257744e2011-11-30 15:57:28 +0000294 }
295
296 // If the Object doesn't have an instance-call handler we should
297 // throw a non-callable exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
299 i::HandleVector<i::Object>(&object, 1)),
300 Object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000301}
302
303
304void StackGuard::EnableInterrupts() {
Steve Block44f0eee2011-05-26 01:26:41 +0100305 ExecutionAccess access(isolate_);
Steve Block6ded16b2010-05-10 14:33:55 +0100306 if (has_pending_interrupts(access)) {
307 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000308 }
309}
310
311
312void StackGuard::SetStackLimit(uintptr_t limit) {
Steve Block44f0eee2011-05-26 01:26:41 +0100313 ExecutionAccess access(isolate_);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100314 // If the current limits are special (e.g. due to a pending interrupt) then
Steve Blocka7e24c12009-10-30 11:49:00 +0000315 // leave them alone.
Ben Murdoch257744e2011-11-30 15:57:28 +0000316 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
Steve Blockd0582a62009-12-15 09:54:21 +0000317 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000318 thread_local_.jslimit_ = jslimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 }
Steve Blockd0582a62009-12-15 09:54:21 +0000320 if (thread_local_.climit_ == thread_local_.real_climit_) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000321 thread_local_.climit_ = limit;
322 }
Steve Blockd0582a62009-12-15 09:54:21 +0000323 thread_local_.real_climit_ = limit;
324 thread_local_.real_jslimit_ = jslimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000325}
326
327
328void StackGuard::DisableInterrupts() {
Steve Block44f0eee2011-05-26 01:26:41 +0100329 ExecutionAccess access(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 reset_limits(access);
331}
332
333
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100335 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 // Intercept already requested interrupts.
337 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
338 scope->intercepted_flags_ = intercepted;
339 thread_local_.interrupt_flags_ &= ~intercepted;
340 if (!has_pending_interrupts(access)) reset_limits(access);
341 // Add scope to the chain.
342 scope->prev_ = thread_local_.postpone_interrupts_;
343 thread_local_.postpone_interrupts_ = scope;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100344}
345
346
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347void StackGuard::PopPostponeInterruptsScope() {
Steve Block44f0eee2011-05-26 01:26:41 +0100348 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
350 // Make intercepted interrupts active.
351 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
352 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
353 if (has_pending_interrupts(access)) set_interrupt_limits(access);
354 // Remove scope from chain.
355 thread_local_.postpone_interrupts_ = top->prev_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000356}
357
358
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359bool StackGuard::CheckInterrupt(InterruptFlag flag) {
Steve Block44f0eee2011-05-26 01:26:41 +0100360 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 return thread_local_.interrupt_flags_ & flag;
362}
363
364
365void StackGuard::RequestInterrupt(InterruptFlag flag) {
366 ExecutionAccess access(isolate_);
367 // Check the chain of PostponeInterruptsScopes for interception.
368 if (thread_local_.postpone_interrupts_ &&
369 thread_local_.postpone_interrupts_->Intercept(flag)) {
370 return;
371 }
372
373 // Not intercepted. Set as active interrupt flag.
374 thread_local_.interrupt_flags_ |= flag;
Steve Block6ded16b2010-05-10 14:33:55 +0100375 set_interrupt_limits(access);
Steve Blocka7e24c12009-10-30 11:49:00 +0000376}
377
378
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000379void StackGuard::ClearInterrupt(InterruptFlag flag) {
Steve Block44f0eee2011-05-26 01:26:41 +0100380 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
382 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
383 current != NULL;
384 current = current->prev_) {
385 current->intercepted_flags_ &= ~flag;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100386 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387
388 // Clear the interrupt flag from the active interrupt flags.
389 thread_local_.interrupt_flags_ &= ~flag;
390 if (!has_pending_interrupts(access)) reset_limits(access);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100391}
392
393
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100395 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 bool result = (thread_local_.interrupt_flags_ & flag);
397 thread_local_.interrupt_flags_ &= ~flag;
398 if (!has_pending_interrupts(access)) reset_limits(access);
399 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000400}
401
402
Steve Blocka7e24c12009-10-30 11:49:00 +0000403char* StackGuard::ArchiveStackGuard(char* to) {
Steve Block44f0eee2011-05-26 01:26:41 +0100404 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 ThreadLocal blank;
Steve Block44f0eee2011-05-26 01:26:41 +0100407
408 // Set the stack limits using the old thread_local_.
409 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
410 // (as the ctor called SetStackLimits, which looked at the
411 // current thread_local_ from StackGuard)-- but is this
412 // really what was intended?
413 isolate_->heap()->SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000414 thread_local_ = blank;
Steve Block44f0eee2011-05-26 01:26:41 +0100415
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 return to + sizeof(ThreadLocal);
417}
418
419
420char* StackGuard::RestoreStackGuard(char* from) {
Steve Block44f0eee2011-05-26 01:26:41 +0100421 ExecutionAccess access(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
Steve Block44f0eee2011-05-26 01:26:41 +0100423 isolate_->heap()->SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000424 return from + sizeof(ThreadLocal);
425}
426
427
Steve Blocka7e24c12009-10-30 11:49:00 +0000428void StackGuard::FreeThreadResources() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000429 Isolate::PerIsolateThreadData* per_thread =
430 isolate_->FindOrAllocatePerThreadDataForThisThread();
431 per_thread->set_stack_limit(thread_local_.real_climit_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000432}
433
434
435void StackGuard::ThreadLocal::Clear() {
Steve Blockd0582a62009-12-15 09:54:21 +0000436 real_jslimit_ = kIllegalLimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 jslimit_ = kIllegalLimit;
Steve Blockd0582a62009-12-15 09:54:21 +0000438 real_climit_ = kIllegalLimit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 climit_ = kIllegalLimit;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 postpone_interrupts_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 interrupt_flags_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000442}
443
444
Ben Murdoch257744e2011-11-30 15:57:28 +0000445bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +0100446 bool should_set_stack_limits = false;
Steve Blockd0582a62009-12-15 09:54:21 +0000447 if (real_climit_ == kIllegalLimit) {
Steve Block1e0659c2011-05-24 12:43:12 +0100448 const uintptr_t kLimitSize = FLAG_stack_size * KB;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449 DCHECK(GetCurrentStackPosition() > kLimitSize);
450 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
Ben Murdoch257744e2011-11-30 15:57:28 +0000451 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
452 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
Steve Blockd0582a62009-12-15 09:54:21 +0000453 real_climit_ = limit;
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 climit_ = limit;
Steve Block44f0eee2011-05-26 01:26:41 +0100455 should_set_stack_limits = true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000456 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 postpone_interrupts_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 interrupt_flags_ = 0;
Steve Block44f0eee2011-05-26 01:26:41 +0100459 return should_set_stack_limits;
Steve Blocka7e24c12009-10-30 11:49:00 +0000460}
461
462
463void StackGuard::ClearThread(const ExecutionAccess& lock) {
464 thread_local_.Clear();
Steve Block44f0eee2011-05-26 01:26:41 +0100465 isolate_->heap()->SetStackLimits();
Steve Blocka7e24c12009-10-30 11:49:00 +0000466}
467
468
469void StackGuard::InitThread(const ExecutionAccess& lock) {
Ben Murdoch257744e2011-11-30 15:57:28 +0000470 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
471 Isolate::PerIsolateThreadData* per_thread =
472 isolate_->FindOrAllocatePerThreadDataForThisThread();
473 uintptr_t stored_limit = per_thread->stack_limit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 // You should hold the ExecutionAccess lock when you call this.
Steve Block44f0eee2011-05-26 01:26:41 +0100475 if (stored_limit != 0) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000476 SetStackLimit(stored_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 }
478}
479
480
481// --- C a l l s t o n a t i v e s ---
482
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483#define RETURN_NATIVE_CALL(name, args) \
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100484 do { \
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100485 Handle<Object> argv[] = args; \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486 return Call(isolate, \
487 isolate->name##_fun(), \
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100488 isolate->js_builtins_object(), \
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 arraysize(argv), argv); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 } while (false)
491
492
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000493MaybeHandle<Object> Execution::ToNumber(
494 Isolate* isolate, Handle<Object> obj) {
495 RETURN_NATIVE_CALL(to_number, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000496}
497
498
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499MaybeHandle<Object> Execution::ToString(
500 Isolate* isolate, Handle<Object> obj) {
501 RETURN_NATIVE_CALL(to_string, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000502}
503
504
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505MaybeHandle<Object> Execution::ToDetailString(
506 Isolate* isolate, Handle<Object> obj) {
507 RETURN_NATIVE_CALL(to_detail_string, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000508}
509
510
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511MaybeHandle<Object> Execution::ToObject(
512 Isolate* isolate, Handle<Object> obj) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000513 if (obj->IsSpecObject()) return obj;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 RETURN_NATIVE_CALL(to_object, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000515}
516
517
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518MaybeHandle<Object> Execution::ToInteger(
519 Isolate* isolate, Handle<Object> obj) {
520 RETURN_NATIVE_CALL(to_integer, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000521}
522
523
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524MaybeHandle<Object> Execution::ToUint32(
525 Isolate* isolate, Handle<Object> obj) {
526 RETURN_NATIVE_CALL(to_uint32, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000527}
528
529
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530MaybeHandle<Object> Execution::ToInt32(
531 Isolate* isolate, Handle<Object> obj) {
532 RETURN_NATIVE_CALL(to_int32, { obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000533}
534
535
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
537 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
538 RETURN_NATIVE_CALL(create_date, { time_obj });
Steve Blocka7e24c12009-10-30 11:49:00 +0000539}
540
541
542#undef RETURN_NATIVE_CALL
543
544
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
546 Handle<String> flags) {
547 Isolate* isolate = pattern->GetIsolate();
Steve Block44f0eee2011-05-26 01:26:41 +0100548 Handle<JSFunction> function = Handle<JSFunction>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549 isolate->native_context()->regexp_function());
550 Handle<Object> re_obj;
551 ASSIGN_RETURN_ON_EXCEPTION(
552 isolate, re_obj,
553 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
554 JSRegExp);
Ben Murdochf87a2032010-10-22 12:50:53 +0100555 return Handle<JSRegExp>::cast(re_obj);
556}
557
558
Steve Blocka7e24c12009-10-30 11:49:00 +0000559Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100560 Isolate* isolate = string->GetIsolate();
561 Factory* factory = isolate->factory();
562
Steve Blocka7e24c12009-10-30 11:49:00 +0000563 int int_index = static_cast<int>(index);
564 if (int_index < 0 || int_index >= string->length()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100565 return factory->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000566 }
567
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 Handle<Object> char_at = Object::GetProperty(
569 isolate->js_builtins_object(),
570 factory->char_at_string()).ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000571 if (!char_at->IsJSFunction()) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100572 return factory->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000573 }
574
Ben Murdoch8b112d22011-06-08 16:22:53 +0100575 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100576 Handle<Object> index_arg[] = { index_object };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 Handle<Object> result;
578 if (!TryCall(Handle<JSFunction>::cast(char_at),
579 string,
580 arraysize(index_arg),
581 index_arg).ToHandle(&result)) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100582 return factory->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 }
584 return result;
585}
586
587
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588MaybeHandle<JSFunction> Execution::InstantiateFunction(
589 Handle<FunctionTemplateInfo> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100590 Isolate* isolate = data->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 if (!data->do_not_cache()) {
592 // Fast case: see if the function has already been instantiated
593 int serial_number = Smi::cast(data->serial_number())->value();
594 Handle<JSObject> cache(isolate->native_context()->function_cache());
595 Handle<Object> elm =
596 Object::GetElement(isolate, cache, serial_number).ToHandleChecked();
597 if (elm->IsJSFunction()) return Handle<JSFunction>::cast(elm);
598 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 // The function has not yet been instantiated in this context; do it.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100600 Handle<Object> args[] = { data };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 Handle<Object> result;
602 ASSIGN_RETURN_ON_EXCEPTION(
603 isolate, result,
604 Call(isolate,
605 isolate->instantiate_fun(),
606 isolate->js_builtins_object(),
607 arraysize(args),
608 args),
609 JSFunction);
Steve Blocka7e24c12009-10-30 11:49:00 +0000610 return Handle<JSFunction>::cast(result);
611}
612
613
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614MaybeHandle<JSObject> Execution::InstantiateObject(
615 Handle<ObjectTemplateInfo> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100616 Isolate* isolate = data->GetIsolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 Handle<Object> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000618 if (data->property_list()->IsUndefined() &&
619 !data->constructor()->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 Handle<FunctionTemplateInfo> cons_template =
621 Handle<FunctionTemplateInfo>(
622 FunctionTemplateInfo::cast(data->constructor()));
623 Handle<JSFunction> cons;
624 ASSIGN_RETURN_ON_EXCEPTION(
625 isolate, cons, InstantiateFunction(cons_template), JSObject);
626 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, New(cons, 0, NULL), JSObject);
Steve Blocka7e24c12009-10-30 11:49:00 +0000627 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100628 Handle<Object> args[] = { data };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 ASSIGN_RETURN_ON_EXCEPTION(
630 isolate, result,
631 Call(isolate,
632 isolate->instantiate_fun(),
633 isolate->js_builtins_object(),
634 arraysize(args),
635 args),
636 JSObject);
Steve Blocka7e24c12009-10-30 11:49:00 +0000637 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 return Handle<JSObject>::cast(result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000639}
640
641
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000642MaybeHandle<Object> Execution::ConfigureInstance(
643 Isolate* isolate,
644 Handle<Object> instance,
645 Handle<Object> instance_template) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100646 Handle<Object> args[] = { instance, instance_template };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647 return Execution::Call(isolate,
648 isolate->configure_instance_fun(),
649 isolate->js_builtins_object(),
650 arraysize(args),
651 args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000652}
653
654
655Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
656 Handle<JSFunction> fun,
657 Handle<Object> pos,
658 Handle<Object> is_global) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100659 Isolate* isolate = fun->GetIsolate();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100660 Handle<Object> args[] = { recv, fun, pos, is_global };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000661 MaybeHandle<Object> maybe_result =
662 TryCall(isolate->get_stack_trace_line_fun(),
663 isolate->js_builtins_object(),
664 arraysize(args),
665 args);
666 Handle<Object> result;
667 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
668 return isolate->factory()->empty_string();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100669 }
670
Steve Blocka7e24c12009-10-30 11:49:00 +0000671 return Handle<String>::cast(result);
672}
673
674
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675Object* StackGuard::HandleInterrupts() {
676 if (CheckAndClearInterrupt(GC_REQUEST)) {
677 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
Steve Blocka7e24c12009-10-30 11:49:00 +0000678 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000679
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680 if (CheckDebugBreak() || CheckDebugCommand()) {
681 isolate_->debug()->HandleDebugBreak();
682 }
683
684 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
685 return isolate_->TerminateExecution();
686 }
687
688 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
689 isolate_->heap()->DeoptMarkedAllocationSites();
690 }
691
692 if (CheckAndClearInterrupt(INSTALL_CODE)) {
693 DCHECK(isolate_->concurrent_recompilation_enabled());
694 isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
695 }
696
697 if (CheckAndClearInterrupt(API_INTERRUPT)) {
698 // Callback must be invoked outside of ExecusionAccess lock.
699 isolate_->InvokeApiInterruptCallback();
700 }
701
702 isolate_->counters()->stack_interrupts()->Increment();
703 isolate_->counters()->runtime_profiler_ticks()->Increment();
704 isolate_->runtime_profiler()->OptimizeNow();
705
706 return isolate_->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000707}
708
Steve Blocka7e24c12009-10-30 11:49:00 +0000709} } // namespace v8::internal