1 // 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.
5 #include "src/execution.h"
7 #include "src/bootstrapper.h"
8 #include "src/codegen.h"
9 #include "src/deoptimizer.h"
10 #include "src/messages.h"
11 #include "src/vm-state-inl.h"
16 StackGuard::StackGuard()
21 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
22 DCHECK(isolate_ != NULL);
23 thread_local_.set_jslimit(kInterruptLimit);
24 thread_local_.set_climit(kInterruptLimit);
25 isolate_->heap()->SetStackLimits();
29 void StackGuard::reset_limits(const ExecutionAccess& lock) {
30 DCHECK(isolate_ != NULL);
31 thread_local_.set_jslimit(thread_local_.real_jslimit_);
32 thread_local_.set_climit(thread_local_.real_climit_);
33 isolate_->heap()->SetStackLimits();
37 static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
38 if (function->code() == function->shared()->code() &&
39 function->shared()->deserialized()) {
40 PrintF("[Running deserialized script");
41 Object* script = function->shared()->script();
42 if (script->IsScript()) {
43 Object* name = Script::cast(script)->name();
44 if (name->IsString()) {
45 PrintF(": %s", String::cast(name)->ToCString().get());
53 MUST_USE_RESULT static MaybeHandle<Object> Invoke(
55 Handle<JSFunction> function,
56 Handle<Object> receiver,
58 Handle<Object> args[]) {
59 Isolate* isolate = function->GetIsolate();
61 // api callbacks can be called directly.
62 if (!is_construct && function->shared()->IsApiFunction()) {
63 SaveContext save(isolate);
64 isolate->set_context(function->context());
65 if (receiver->IsGlobalObject()) {
66 receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
68 DCHECK(function->context()->global_object()->IsGlobalObject());
69 auto value = Builtins::InvokeApiFunction(function, receiver, argc, args);
70 bool has_exception = value.is_null();
71 DCHECK(has_exception == isolate->has_pending_exception());
73 isolate->ReportPendingMessages();
74 return MaybeHandle<Object>();
76 isolate->clear_pending_message();
81 // Entering JavaScript.
82 VMState<JS> state(isolate);
83 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
84 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
85 isolate->ThrowIllegalOperation();
86 isolate->ReportPendingMessages();
87 return MaybeHandle<Object>();
90 // Placeholder for return value.
93 typedef Object* (*JSEntryFunction)(byte* entry,
99 Handle<Code> code = is_construct
100 ? isolate->factory()->js_construct_entry_code()
101 : isolate->factory()->js_entry_code();
103 // Convert calls on global objects to be calls on the global
104 // receiver instead to avoid having a 'this' pointer which refers
105 // directly to a global object.
106 if (receiver->IsGlobalObject()) {
107 receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
110 // Make sure that the global object of the context we're about to
111 // make the current one is indeed a global object.
112 DCHECK(function->context()->global_object()->IsGlobalObject());
115 // Save and restore context around invocation and block the
116 // allocation of handles without explicit handle scopes.
117 SaveContext save(isolate);
118 SealHandleScope shs(isolate);
119 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
121 // Call the function through the right JS entry stub.
122 byte* function_entry = function->code()->entry();
123 JSFunction* func = *function;
124 Object* recv = *receiver;
125 Object*** argv = reinterpret_cast<Object***>(args);
126 if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function);
128 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
132 if (FLAG_verify_heap) {
133 value->ObjectVerify();
137 // Update the pending exception flag and return the value.
138 bool has_exception = value->IsException();
139 DCHECK(has_exception == isolate->has_pending_exception());
141 isolate->ReportPendingMessages();
142 // Reset stepping state when script exits with uncaught exception.
143 if (isolate->debug()->is_active()) {
144 isolate->debug()->ClearStepping();
146 return MaybeHandle<Object>();
148 isolate->clear_pending_message();
151 return Handle<Object>(value, isolate);
155 MaybeHandle<Object> Execution::Call(Isolate* isolate,
156 Handle<Object> callable,
157 Handle<Object> receiver,
159 Handle<Object> argv[],
160 bool convert_receiver) {
161 if (!callable->IsJSFunction()) {
162 ASSIGN_RETURN_ON_EXCEPTION(
163 isolate, callable, TryGetFunctionDelegate(isolate, callable), Object);
165 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
167 // In sloppy mode, convert receiver.
168 if (convert_receiver && !receiver->IsJSReceiver() &&
169 !func->shared()->native() && is_sloppy(func->shared()->language_mode())) {
170 if (receiver->IsUndefined() || receiver->IsNull()) {
171 receiver = handle(func->global_proxy());
172 DCHECK(!receiver->IsJSBuiltinsObject());
174 ASSIGN_RETURN_ON_EXCEPTION(
175 isolate, receiver, ToObject(isolate, receiver), Object);
179 return Invoke(false, func, receiver, argc, argv);
183 MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
185 Handle<Object> argv[]) {
186 return Invoke(true, func, handle(func->global_proxy()), argc, argv);
190 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
191 Handle<Object> receiver, int argc,
192 Handle<Object> args[],
193 MaybeHandle<Object>* exception_out) {
194 bool is_termination = false;
195 Isolate* isolate = func->GetIsolate();
196 MaybeHandle<Object> maybe_result;
197 if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
198 // Enter a try-block while executing the JavaScript code. To avoid
199 // duplicate error printing it must be non-verbose. Also, to avoid
200 // creating message objects during stack overflow we shouldn't
203 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
204 catcher.SetVerbose(false);
205 catcher.SetCaptureMessage(false);
207 maybe_result = Invoke(false, func, receiver, argc, args);
209 if (maybe_result.is_null()) {
210 DCHECK(catcher.HasCaught());
211 DCHECK(isolate->has_pending_exception());
212 DCHECK(isolate->external_caught_exception());
213 if (isolate->pending_exception() ==
214 isolate->heap()->termination_exception()) {
215 is_termination = true;
217 if (exception_out != NULL) {
218 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
221 isolate->OptionalRescheduleException(true);
224 DCHECK(!isolate->has_pending_exception());
227 // Re-request terminate execution interrupt to trigger later.
228 if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
234 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
235 Handle<Object> object) {
236 DCHECK(!object->IsJSFunction());
237 Factory* factory = isolate->factory();
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.
242 // 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();
247 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
249 // Objects created through the API can have an instance-call handler
250 // that should be used when calling the object as a function.
251 if (fun->IsHeapObject() &&
252 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
253 return Handle<JSFunction>(
254 isolate->native_context()->call_as_function_delegate());
257 return factory->undefined_value();
261 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
262 Handle<Object> object) {
263 DCHECK(!object->IsJSFunction());
265 // If object is a function proxy, get its handler. Iterate if necessary.
266 Object* fun = *object;
267 while (fun->IsJSFunctionProxy()) {
268 fun = JSFunctionProxy::cast(fun)->call_trap();
270 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
272 // Objects created through the API can have an instance-call handler
273 // that should be used when calling the object as a function.
274 if (fun->IsHeapObject() &&
275 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
276 return Handle<JSFunction>(
277 isolate->native_context()->call_as_function_delegate());
280 // If the Object doesn't have an instance-call handler we should
281 // throw a non-callable exception.
282 THROW_NEW_ERROR(isolate,
283 NewTypeError(MessageTemplate::kCalledNonCallable, object),
288 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
289 Handle<Object> object) {
290 DCHECK(!object->IsJSFunction());
292 // If you return a function from here, it will be called when an
293 // attempt is made to call the given object as a constructor.
295 // If object is a function proxies, get its handler. Iterate if necessary.
296 Object* fun = *object;
297 while (fun->IsJSFunctionProxy()) {
298 fun = JSFunctionProxy::cast(fun)->call_trap();
300 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
302 // Objects created through the API can have an instance-call handler
303 // that should be used when calling the object as a function.
304 if (fun->IsHeapObject() &&
305 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
306 return Handle<JSFunction>(
307 isolate->native_context()->call_as_constructor_delegate());
310 return isolate->factory()->undefined_value();
314 MaybeHandle<Object> Execution::TryGetConstructorDelegate(
315 Isolate* isolate, Handle<Object> object) {
316 DCHECK(!object->IsJSFunction());
318 // If you return a function from here, it will be called when an
319 // attempt is made to call the given object as a constructor.
321 // If object is a function proxies, get its handler. Iterate if necessary.
322 Object* fun = *object;
323 while (fun->IsJSFunctionProxy()) {
324 fun = JSFunctionProxy::cast(fun)->call_trap();
326 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
328 // Objects created through the API can have an instance-call handler
329 // that should be used when calling the object as a function.
330 if (fun->IsHeapObject() &&
331 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
332 return Handle<JSFunction>(
333 isolate->native_context()->call_as_constructor_delegate());
336 // If the Object doesn't have an instance-call handler we should
337 // throw a non-callable exception.
338 THROW_NEW_ERROR(isolate,
339 NewTypeError(MessageTemplate::kCalledNonCallable, object),
344 void StackGuard::SetStackLimit(uintptr_t limit) {
345 ExecutionAccess access(isolate_);
346 // If the current limits are special (e.g. due to a pending interrupt) then
348 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
349 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
350 thread_local_.set_jslimit(jslimit);
352 if (thread_local_.climit() == thread_local_.real_climit_) {
353 thread_local_.set_climit(limit);
355 thread_local_.real_climit_ = limit;
356 thread_local_.real_jslimit_ = jslimit;
360 void StackGuard::AdjustStackLimitForSimulator() {
361 ExecutionAccess access(isolate_);
362 uintptr_t climit = thread_local_.real_climit_;
363 // If the current limits are special (e.g. due to a pending interrupt) then
365 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, climit);
366 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
367 thread_local_.set_jslimit(jslimit);
368 isolate_->heap()->SetStackLimits();
373 void StackGuard::EnableInterrupts() {
374 ExecutionAccess access(isolate_);
375 if (has_pending_interrupts(access)) {
376 set_interrupt_limits(access);
381 void StackGuard::DisableInterrupts() {
382 ExecutionAccess access(isolate_);
383 reset_limits(access);
387 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
388 ExecutionAccess access(isolate_);
389 // Intercept already requested interrupts.
390 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
391 scope->intercepted_flags_ = intercepted;
392 thread_local_.interrupt_flags_ &= ~intercepted;
393 if (!has_pending_interrupts(access)) reset_limits(access);
394 // Add scope to the chain.
395 scope->prev_ = thread_local_.postpone_interrupts_;
396 thread_local_.postpone_interrupts_ = scope;
400 void StackGuard::PopPostponeInterruptsScope() {
401 ExecutionAccess access(isolate_);
402 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
403 // Make intercepted interrupts active.
404 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
405 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
406 if (has_pending_interrupts(access)) set_interrupt_limits(access);
407 // Remove scope from chain.
408 thread_local_.postpone_interrupts_ = top->prev_;
412 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
413 ExecutionAccess access(isolate_);
414 return thread_local_.interrupt_flags_ & flag;
418 void StackGuard::RequestInterrupt(InterruptFlag flag) {
419 ExecutionAccess access(isolate_);
420 // Check the chain of PostponeInterruptsScopes for interception.
421 if (thread_local_.postpone_interrupts_ &&
422 thread_local_.postpone_interrupts_->Intercept(flag)) {
426 // Not intercepted. Set as active interrupt flag.
427 thread_local_.interrupt_flags_ |= flag;
428 set_interrupt_limits(access);
430 // If this isolate is waiting in a futex, notify it to wake up.
431 isolate_->futex_wait_list_node()->NotifyWake();
435 void StackGuard::ClearInterrupt(InterruptFlag flag) {
436 ExecutionAccess access(isolate_);
437 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
438 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
440 current = current->prev_) {
441 current->intercepted_flags_ &= ~flag;
444 // Clear the interrupt flag from the active interrupt flags.
445 thread_local_.interrupt_flags_ &= ~flag;
446 if (!has_pending_interrupts(access)) reset_limits(access);
450 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
451 ExecutionAccess access(isolate_);
452 bool result = (thread_local_.interrupt_flags_ & flag);
453 thread_local_.interrupt_flags_ &= ~flag;
454 if (!has_pending_interrupts(access)) reset_limits(access);
459 char* StackGuard::ArchiveStackGuard(char* to) {
460 ExecutionAccess access(isolate_);
461 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
464 // Set the stack limits using the old thread_local_.
465 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
466 // (as the ctor called SetStackLimits, which looked at the
467 // current thread_local_ from StackGuard)-- but is this
468 // really what was intended?
469 isolate_->heap()->SetStackLimits();
470 thread_local_ = blank;
472 return to + sizeof(ThreadLocal);
476 char* StackGuard::RestoreStackGuard(char* from) {
477 ExecutionAccess access(isolate_);
478 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
479 isolate_->heap()->SetStackLimits();
480 return from + sizeof(ThreadLocal);
484 void StackGuard::FreeThreadResources() {
485 Isolate::PerIsolateThreadData* per_thread =
486 isolate_->FindOrAllocatePerThreadDataForThisThread();
487 per_thread->set_stack_limit(thread_local_.real_climit_);
491 void StackGuard::ThreadLocal::Clear() {
492 real_jslimit_ = kIllegalLimit;
493 set_jslimit(kIllegalLimit);
494 real_climit_ = kIllegalLimit;
495 set_climit(kIllegalLimit);
496 postpone_interrupts_ = NULL;
497 interrupt_flags_ = 0;
501 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
502 bool should_set_stack_limits = false;
503 if (real_climit_ == kIllegalLimit) {
504 const uintptr_t kLimitSize = FLAG_stack_size * KB;
505 DCHECK(GetCurrentStackPosition() > kLimitSize);
506 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
507 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
508 set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
509 real_climit_ = limit;
511 should_set_stack_limits = true;
513 postpone_interrupts_ = NULL;
514 interrupt_flags_ = 0;
515 return should_set_stack_limits;
519 void StackGuard::ClearThread(const ExecutionAccess& lock) {
520 thread_local_.Clear();
521 isolate_->heap()->SetStackLimits();
525 void StackGuard::InitThread(const ExecutionAccess& lock) {
526 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
527 Isolate::PerIsolateThreadData* per_thread =
528 isolate_->FindOrAllocatePerThreadDataForThisThread();
529 uintptr_t stored_limit = per_thread->stack_limit();
530 // You should hold the ExecutionAccess lock when you call this.
531 if (stored_limit != 0) {
532 SetStackLimit(stored_limit);
537 // --- C a l l s t o n a t i v e s ---
539 #define RETURN_NATIVE_CALL(name, args) \
541 Handle<Object> argv[] = args; \
542 return Call(isolate, isolate->name##_fun(), \
543 isolate->factory()->undefined_value(), arraysize(argv), argv); \
547 MaybeHandle<Object> Execution::ToNumber(
548 Isolate* isolate, Handle<Object> obj) {
549 RETURN_NATIVE_CALL(to_number, { obj });
553 MaybeHandle<Object> Execution::ToString(
554 Isolate* isolate, Handle<Object> obj) {
555 RETURN_NATIVE_CALL(to_string, { obj });
559 MaybeHandle<Object> Execution::ToDetailString(
560 Isolate* isolate, Handle<Object> obj) {
561 RETURN_NATIVE_CALL(to_detail_string, { obj });
565 MaybeHandle<Object> Execution::ToInteger(
566 Isolate* isolate, Handle<Object> obj) {
567 RETURN_NATIVE_CALL(to_integer, { obj });
571 MaybeHandle<Object> Execution::ToLength(
572 Isolate* isolate, Handle<Object> obj) {
573 RETURN_NATIVE_CALL(to_length, { obj });
577 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
578 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
579 RETURN_NATIVE_CALL(create_date, { time_obj });
583 #undef RETURN_NATIVE_CALL
586 MaybeHandle<Object> Execution::ToInt32(Isolate* isolate, Handle<Object> obj) {
587 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Execution::ToNumber(isolate, obj),
589 return isolate->factory()->NewNumberFromInt(DoubleToInt32(obj->Number()));
593 MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
594 Handle<JSReceiver> receiver;
595 if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
599 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
603 MaybeHandle<Object> Execution::ToUint32(Isolate* isolate, Handle<Object> obj) {
604 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Execution::ToNumber(isolate, obj),
606 return isolate->factory()->NewNumberFromUint(DoubleToUint32(obj->Number()));
610 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
611 Handle<String> flags) {
612 Isolate* isolate = pattern->GetIsolate();
613 Handle<JSFunction> function = Handle<JSFunction>(
614 isolate->native_context()->regexp_function());
615 Handle<Object> re_obj;
616 ASSIGN_RETURN_ON_EXCEPTION(
618 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
620 return Handle<JSRegExp>::cast(re_obj);
624 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
625 Handle<JSFunction> fun,
627 Handle<Object> is_global) {
628 Isolate* isolate = fun->GetIsolate();
629 Handle<Object> args[] = { recv, fun, pos, is_global };
630 MaybeHandle<Object> maybe_result =
631 TryCall(isolate->get_stack_trace_line_fun(),
632 isolate->factory()->undefined_value(), arraysize(args), args);
633 Handle<Object> result;
634 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
635 return isolate->factory()->empty_string();
638 return Handle<String>::cast(result);
642 void StackGuard::HandleGCInterrupt() {
643 if (CheckAndClearInterrupt(GC_REQUEST)) {
644 isolate_->heap()->HandleGCRequest();
649 Object* StackGuard::HandleInterrupts() {
650 if (CheckAndClearInterrupt(GC_REQUEST)) {
651 isolate_->heap()->HandleGCRequest();
654 if (CheckDebugBreak() || CheckDebugCommand()) {
655 isolate_->debug()->HandleDebugBreak();
658 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
659 return isolate_->TerminateExecution();
662 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
663 isolate_->heap()->DeoptMarkedAllocationSites();
666 if (CheckAndClearInterrupt(INSTALL_CODE)) {
667 DCHECK(isolate_->concurrent_recompilation_enabled());
668 isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
671 if (CheckAndClearInterrupt(API_INTERRUPT)) {
672 // Callbacks must be invoked outside of ExecusionAccess lock.
673 isolate_->InvokeApiInterruptCallbacks();
676 isolate_->counters()->stack_interrupts()->Increment();
677 isolate_->counters()->runtime_profiler_ticks()->Increment();
678 isolate_->runtime_profiler()->OptimizeNow();
680 return isolate_->heap()->undefined_value();
683 } // namespace internal