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::EnableInterrupts() {
345 ExecutionAccess access(isolate_);
346 if (has_pending_interrupts(access)) {
347 set_interrupt_limits(access);
352 void StackGuard::SetStackLimit(uintptr_t limit) {
353 ExecutionAccess access(isolate_);
354 // If the current limits are special (e.g. due to a pending interrupt) then
356 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
357 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
358 thread_local_.set_jslimit(jslimit);
360 if (thread_local_.climit() == thread_local_.real_climit_) {
361 thread_local_.set_climit(limit);
363 thread_local_.real_climit_ = limit;
364 thread_local_.real_jslimit_ = jslimit;
368 void StackGuard::DisableInterrupts() {
369 ExecutionAccess access(isolate_);
370 reset_limits(access);
374 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
375 ExecutionAccess access(isolate_);
376 // Intercept already requested interrupts.
377 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
378 scope->intercepted_flags_ = intercepted;
379 thread_local_.interrupt_flags_ &= ~intercepted;
380 if (!has_pending_interrupts(access)) reset_limits(access);
381 // Add scope to the chain.
382 scope->prev_ = thread_local_.postpone_interrupts_;
383 thread_local_.postpone_interrupts_ = scope;
387 void StackGuard::PopPostponeInterruptsScope() {
388 ExecutionAccess access(isolate_);
389 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
390 // Make intercepted interrupts active.
391 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
392 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
393 if (has_pending_interrupts(access)) set_interrupt_limits(access);
394 // Remove scope from chain.
395 thread_local_.postpone_interrupts_ = top->prev_;
399 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
400 ExecutionAccess access(isolate_);
401 return thread_local_.interrupt_flags_ & flag;
405 void StackGuard::RequestInterrupt(InterruptFlag flag) {
406 ExecutionAccess access(isolate_);
407 // Check the chain of PostponeInterruptsScopes for interception.
408 if (thread_local_.postpone_interrupts_ &&
409 thread_local_.postpone_interrupts_->Intercept(flag)) {
413 // Not intercepted. Set as active interrupt flag.
414 thread_local_.interrupt_flags_ |= flag;
415 set_interrupt_limits(access);
419 void StackGuard::ClearInterrupt(InterruptFlag flag) {
420 ExecutionAccess access(isolate_);
421 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
422 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
424 current = current->prev_) {
425 current->intercepted_flags_ &= ~flag;
428 // Clear the interrupt flag from the active interrupt flags.
429 thread_local_.interrupt_flags_ &= ~flag;
430 if (!has_pending_interrupts(access)) reset_limits(access);
434 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
435 ExecutionAccess access(isolate_);
436 bool result = (thread_local_.interrupt_flags_ & flag);
437 thread_local_.interrupt_flags_ &= ~flag;
438 if (!has_pending_interrupts(access)) reset_limits(access);
443 char* StackGuard::ArchiveStackGuard(char* to) {
444 ExecutionAccess access(isolate_);
445 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
448 // Set the stack limits using the old thread_local_.
449 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
450 // (as the ctor called SetStackLimits, which looked at the
451 // current thread_local_ from StackGuard)-- but is this
452 // really what was intended?
453 isolate_->heap()->SetStackLimits();
454 thread_local_ = blank;
456 return to + sizeof(ThreadLocal);
460 char* StackGuard::RestoreStackGuard(char* from) {
461 ExecutionAccess access(isolate_);
462 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
463 isolate_->heap()->SetStackLimits();
464 return from + sizeof(ThreadLocal);
468 void StackGuard::FreeThreadResources() {
469 Isolate::PerIsolateThreadData* per_thread =
470 isolate_->FindOrAllocatePerThreadDataForThisThread();
471 per_thread->set_stack_limit(thread_local_.real_climit_);
475 void StackGuard::ThreadLocal::Clear() {
476 real_jslimit_ = kIllegalLimit;
477 set_jslimit(kIllegalLimit);
478 real_climit_ = kIllegalLimit;
479 set_climit(kIllegalLimit);
480 postpone_interrupts_ = NULL;
481 interrupt_flags_ = 0;
485 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
486 bool should_set_stack_limits = false;
487 if (real_climit_ == kIllegalLimit) {
488 const uintptr_t kLimitSize = FLAG_stack_size * KB;
489 DCHECK(GetCurrentStackPosition() > kLimitSize);
490 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
491 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
492 set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
493 real_climit_ = limit;
495 should_set_stack_limits = true;
497 postpone_interrupts_ = NULL;
498 interrupt_flags_ = 0;
499 return should_set_stack_limits;
503 void StackGuard::ClearThread(const ExecutionAccess& lock) {
504 thread_local_.Clear();
505 isolate_->heap()->SetStackLimits();
509 void StackGuard::InitThread(const ExecutionAccess& lock) {
510 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
511 Isolate::PerIsolateThreadData* per_thread =
512 isolate_->FindOrAllocatePerThreadDataForThisThread();
513 uintptr_t stored_limit = per_thread->stack_limit();
514 // You should hold the ExecutionAccess lock when you call this.
515 if (stored_limit != 0) {
516 SetStackLimit(stored_limit);
521 // --- C a l l s t o n a t i v e s ---
523 #define RETURN_NATIVE_CALL(name, args) \
525 Handle<Object> argv[] = args; \
526 return Call(isolate, \
527 isolate->name##_fun(), \
528 isolate->js_builtins_object(), \
529 arraysize(argv), argv); \
533 MaybeHandle<Object> Execution::ToNumber(
534 Isolate* isolate, Handle<Object> obj) {
535 RETURN_NATIVE_CALL(to_number, { obj });
539 MaybeHandle<Object> Execution::ToString(
540 Isolate* isolate, Handle<Object> obj) {
541 RETURN_NATIVE_CALL(to_string, { obj });
545 MaybeHandle<Object> Execution::ToDetailString(
546 Isolate* isolate, Handle<Object> obj) {
547 RETURN_NATIVE_CALL(to_detail_string, { obj });
551 MaybeHandle<Object> Execution::ToObject(
552 Isolate* isolate, Handle<Object> obj) {
553 if (obj->IsSpecObject()) return obj;
554 // TODO(verwaest): Use Object::ToObject but throw an exception on failure.
555 RETURN_NATIVE_CALL(to_object, { obj });
559 MaybeHandle<Object> Execution::ToInteger(
560 Isolate* isolate, Handle<Object> obj) {
561 RETURN_NATIVE_CALL(to_integer, { obj });
565 MaybeHandle<Object> Execution::ToUint32(
566 Isolate* isolate, Handle<Object> obj) {
567 RETURN_NATIVE_CALL(to_uint32, { obj });
571 MaybeHandle<Object> Execution::ToInt32(
572 Isolate* isolate, Handle<Object> obj) {
573 RETURN_NATIVE_CALL(to_int32, { obj });
577 MaybeHandle<Object> Execution::ToLength(
578 Isolate* isolate, Handle<Object> obj) {
579 RETURN_NATIVE_CALL(to_length, { obj });
583 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
584 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
585 RETURN_NATIVE_CALL(create_date, { time_obj });
589 #undef RETURN_NATIVE_CALL
592 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
593 Handle<String> flags) {
594 Isolate* isolate = pattern->GetIsolate();
595 Handle<JSFunction> function = Handle<JSFunction>(
596 isolate->native_context()->regexp_function());
597 Handle<Object> re_obj;
598 ASSIGN_RETURN_ON_EXCEPTION(
600 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
602 return Handle<JSRegExp>::cast(re_obj);
606 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
607 Handle<JSFunction> fun,
609 Handle<Object> is_global) {
610 Isolate* isolate = fun->GetIsolate();
611 Handle<Object> args[] = { recv, fun, pos, is_global };
612 MaybeHandle<Object> maybe_result =
613 TryCall(isolate->get_stack_trace_line_fun(),
614 isolate->js_builtins_object(),
617 Handle<Object> result;
618 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
619 return isolate->factory()->empty_string();
622 return Handle<String>::cast(result);
626 void StackGuard::CheckAndHandleGCInterrupt() {
627 if (CheckAndClearInterrupt(GC_REQUEST)) {
628 isolate_->heap()->HandleGCRequest();
633 Object* StackGuard::HandleInterrupts() {
634 if (CheckAndClearInterrupt(GC_REQUEST)) {
635 isolate_->heap()->HandleGCRequest();
638 if (CheckDebugBreak() || CheckDebugCommand()) {
639 isolate_->debug()->HandleDebugBreak();
642 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
643 return isolate_->TerminateExecution();
646 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
647 isolate_->heap()->DeoptMarkedAllocationSites();
650 if (CheckAndClearInterrupt(INSTALL_CODE)) {
651 DCHECK(isolate_->concurrent_recompilation_enabled());
652 isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
655 if (CheckAndClearInterrupt(API_INTERRUPT)) {
656 // Callbacks must be invoked outside of ExecusionAccess lock.
657 isolate_->InvokeApiInterruptCallbacks();
660 isolate_->counters()->stack_interrupts()->Increment();
661 isolate_->counters()->runtime_profiler_ticks()->Increment();
662 isolate_->runtime_profiler()->OptimizeNow();
664 return isolate_->heap()->undefined_value();
667 } // namespace internal