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/isolate-inl.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_.jslimit_ = kInterruptLimit;
24 thread_local_.climit_ = kInterruptLimit;
25 isolate_->heap()->SetStackLimits();
29 void StackGuard::reset_limits(const ExecutionAccess& lock) {
30 DCHECK(isolate_ != NULL);
31 thread_local_.jslimit_ = thread_local_.real_jslimit_;
32 thread_local_.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;
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 (exception_out != NULL) {
214 if (isolate->pending_exception() ==
215 isolate->heap()->termination_exception()) {
216 is_termination = true;
218 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
221 isolate->OptionalRescheduleException(true);
224 DCHECK(!isolate->has_pending_exception());
225 DCHECK(!isolate->external_caught_exception());
227 if (is_termination) isolate->TerminateExecution();
232 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
233 Handle<Object> object) {
234 DCHECK(!object->IsJSFunction());
235 Factory* factory = isolate->factory();
237 // If you return a function from here, it will be called when an
238 // attempt is made to call the given object as a function.
240 // If object is a function proxy, get its handler. Iterate if necessary.
241 Object* fun = *object;
242 while (fun->IsJSFunctionProxy()) {
243 fun = JSFunctionProxy::cast(fun)->call_trap();
245 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
247 // Objects created through the API can have an instance-call handler
248 // that should be used when calling the object as a function.
249 if (fun->IsHeapObject() &&
250 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
251 return Handle<JSFunction>(
252 isolate->native_context()->call_as_function_delegate());
255 return factory->undefined_value();
259 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
260 Handle<Object> object) {
261 DCHECK(!object->IsJSFunction());
263 // If object is a function proxy, get its handler. Iterate if necessary.
264 Object* fun = *object;
265 while (fun->IsJSFunctionProxy()) {
266 fun = JSFunctionProxy::cast(fun)->call_trap();
268 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
270 // Objects created through the API can have an instance-call handler
271 // that should be used when calling the object as a function.
272 if (fun->IsHeapObject() &&
273 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
274 return Handle<JSFunction>(
275 isolate->native_context()->call_as_function_delegate());
278 // If the Object doesn't have an instance-call handler we should
279 // throw a non-callable exception.
280 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
281 i::HandleVector<i::Object>(&object, 1)),
286 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
287 Handle<Object> object) {
288 DCHECK(!object->IsJSFunction());
290 // If you return a function from here, it will be called when an
291 // attempt is made to call the given object as a constructor.
293 // If object is a function proxies, get its handler. Iterate if necessary.
294 Object* fun = *object;
295 while (fun->IsJSFunctionProxy()) {
296 fun = JSFunctionProxy::cast(fun)->call_trap();
298 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
300 // Objects created through the API can have an instance-call handler
301 // that should be used when calling the object as a function.
302 if (fun->IsHeapObject() &&
303 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
304 return Handle<JSFunction>(
305 isolate->native_context()->call_as_constructor_delegate());
308 return isolate->factory()->undefined_value();
312 MaybeHandle<Object> Execution::TryGetConstructorDelegate(
313 Isolate* isolate, Handle<Object> object) {
314 DCHECK(!object->IsJSFunction());
316 // If you return a function from here, it will be called when an
317 // attempt is made to call the given object as a constructor.
319 // If object is a function proxies, get its handler. Iterate if necessary.
320 Object* fun = *object;
321 while (fun->IsJSFunctionProxy()) {
322 fun = JSFunctionProxy::cast(fun)->call_trap();
324 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
326 // Objects created through the API can have an instance-call handler
327 // that should be used when calling the object as a function.
328 if (fun->IsHeapObject() &&
329 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
330 return Handle<JSFunction>(
331 isolate->native_context()->call_as_constructor_delegate());
334 // If the Object doesn't have an instance-call handler we should
335 // throw a non-callable exception.
336 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
337 i::HandleVector<i::Object>(&object, 1)),
342 void StackGuard::EnableInterrupts() {
343 ExecutionAccess access(isolate_);
344 if (has_pending_interrupts(access)) {
345 set_interrupt_limits(access);
350 void StackGuard::SetStackLimit(uintptr_t limit) {
351 ExecutionAccess access(isolate_);
352 // If the current limits are special (e.g. due to a pending interrupt) then
354 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
355 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
356 thread_local_.jslimit_ = jslimit;
358 if (thread_local_.climit_ == thread_local_.real_climit_) {
359 thread_local_.climit_ = limit;
361 thread_local_.real_climit_ = limit;
362 thread_local_.real_jslimit_ = jslimit;
366 void StackGuard::DisableInterrupts() {
367 ExecutionAccess access(isolate_);
368 reset_limits(access);
372 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
373 ExecutionAccess access(isolate_);
374 // Intercept already requested interrupts.
375 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
376 scope->intercepted_flags_ = intercepted;
377 thread_local_.interrupt_flags_ &= ~intercepted;
378 if (!has_pending_interrupts(access)) reset_limits(access);
379 // Add scope to the chain.
380 scope->prev_ = thread_local_.postpone_interrupts_;
381 thread_local_.postpone_interrupts_ = scope;
385 void StackGuard::PopPostponeInterruptsScope() {
386 ExecutionAccess access(isolate_);
387 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
388 // Make intercepted interrupts active.
389 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
390 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
391 if (has_pending_interrupts(access)) set_interrupt_limits(access);
392 // Remove scope from chain.
393 thread_local_.postpone_interrupts_ = top->prev_;
397 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
398 ExecutionAccess access(isolate_);
399 return thread_local_.interrupt_flags_ & flag;
403 void StackGuard::RequestInterrupt(InterruptFlag flag) {
404 ExecutionAccess access(isolate_);
405 // Check the chain of PostponeInterruptsScopes for interception.
406 if (thread_local_.postpone_interrupts_ &&
407 thread_local_.postpone_interrupts_->Intercept(flag)) {
411 // Not intercepted. Set as active interrupt flag.
412 thread_local_.interrupt_flags_ |= flag;
413 set_interrupt_limits(access);
417 void StackGuard::ClearInterrupt(InterruptFlag flag) {
418 ExecutionAccess access(isolate_);
419 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
420 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
422 current = current->prev_) {
423 current->intercepted_flags_ &= ~flag;
426 // Clear the interrupt flag from the active interrupt flags.
427 thread_local_.interrupt_flags_ &= ~flag;
428 if (!has_pending_interrupts(access)) reset_limits(access);
432 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
433 ExecutionAccess access(isolate_);
434 bool result = (thread_local_.interrupt_flags_ & flag);
435 thread_local_.interrupt_flags_ &= ~flag;
436 if (!has_pending_interrupts(access)) reset_limits(access);
441 char* StackGuard::ArchiveStackGuard(char* to) {
442 ExecutionAccess access(isolate_);
443 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
446 // Set the stack limits using the old thread_local_.
447 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
448 // (as the ctor called SetStackLimits, which looked at the
449 // current thread_local_ from StackGuard)-- but is this
450 // really what was intended?
451 isolate_->heap()->SetStackLimits();
452 thread_local_ = blank;
454 return to + sizeof(ThreadLocal);
458 char* StackGuard::RestoreStackGuard(char* from) {
459 ExecutionAccess access(isolate_);
460 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
461 isolate_->heap()->SetStackLimits();
462 return from + sizeof(ThreadLocal);
466 void StackGuard::FreeThreadResources() {
467 Isolate::PerIsolateThreadData* per_thread =
468 isolate_->FindOrAllocatePerThreadDataForThisThread();
469 per_thread->set_stack_limit(thread_local_.real_climit_);
473 void StackGuard::ThreadLocal::Clear() {
474 real_jslimit_ = kIllegalLimit;
475 jslimit_ = kIllegalLimit;
476 real_climit_ = kIllegalLimit;
477 climit_ = kIllegalLimit;
478 postpone_interrupts_ = NULL;
479 interrupt_flags_ = 0;
483 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
484 bool should_set_stack_limits = false;
485 if (real_climit_ == kIllegalLimit) {
486 const uintptr_t kLimitSize = FLAG_stack_size * KB;
487 DCHECK(GetCurrentStackPosition() > kLimitSize);
488 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
489 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
490 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
491 real_climit_ = limit;
493 should_set_stack_limits = true;
495 postpone_interrupts_ = NULL;
496 interrupt_flags_ = 0;
497 return should_set_stack_limits;
501 void StackGuard::ClearThread(const ExecutionAccess& lock) {
502 thread_local_.Clear();
503 isolate_->heap()->SetStackLimits();
507 void StackGuard::InitThread(const ExecutionAccess& lock) {
508 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
509 Isolate::PerIsolateThreadData* per_thread =
510 isolate_->FindOrAllocatePerThreadDataForThisThread();
511 uintptr_t stored_limit = per_thread->stack_limit();
512 // You should hold the ExecutionAccess lock when you call this.
513 if (stored_limit != 0) {
514 SetStackLimit(stored_limit);
519 // --- C a l l s t o n a t i v e s ---
521 #define RETURN_NATIVE_CALL(name, args) \
523 Handle<Object> argv[] = args; \
524 return Call(isolate, \
525 isolate->name##_fun(), \
526 isolate->js_builtins_object(), \
527 arraysize(argv), argv); \
531 MaybeHandle<Object> Execution::ToNumber(
532 Isolate* isolate, Handle<Object> obj) {
533 RETURN_NATIVE_CALL(to_number, { obj });
537 MaybeHandle<Object> Execution::ToString(
538 Isolate* isolate, Handle<Object> obj) {
539 RETURN_NATIVE_CALL(to_string, { obj });
543 MaybeHandle<Object> Execution::ToDetailString(
544 Isolate* isolate, Handle<Object> obj) {
545 RETURN_NATIVE_CALL(to_detail_string, { obj });
549 MaybeHandle<Object> Execution::ToObject(
550 Isolate* isolate, Handle<Object> obj) {
551 if (obj->IsSpecObject()) return obj;
552 RETURN_NATIVE_CALL(to_object, { obj });
556 MaybeHandle<Object> Execution::ToInteger(
557 Isolate* isolate, Handle<Object> obj) {
558 RETURN_NATIVE_CALL(to_integer, { obj });
562 MaybeHandle<Object> Execution::ToUint32(
563 Isolate* isolate, Handle<Object> obj) {
564 RETURN_NATIVE_CALL(to_uint32, { obj });
568 MaybeHandle<Object> Execution::ToInt32(
569 Isolate* isolate, Handle<Object> obj) {
570 RETURN_NATIVE_CALL(to_int32, { obj });
574 MaybeHandle<Object> Execution::ToLength(
575 Isolate* isolate, Handle<Object> obj) {
576 RETURN_NATIVE_CALL(to_length, { obj });
580 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
581 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
582 RETURN_NATIVE_CALL(create_date, { time_obj });
586 #undef RETURN_NATIVE_CALL
589 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
590 Handle<String> flags) {
591 Isolate* isolate = pattern->GetIsolate();
592 Handle<JSFunction> function = Handle<JSFunction>(
593 isolate->native_context()->regexp_function());
594 Handle<Object> re_obj;
595 ASSIGN_RETURN_ON_EXCEPTION(
597 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
599 return Handle<JSRegExp>::cast(re_obj);
603 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
604 Isolate* isolate = string->GetIsolate();
605 Factory* factory = isolate->factory();
607 int int_index = static_cast<int>(index);
608 if (int_index < 0 || int_index >= string->length()) {
609 return factory->undefined_value();
612 Handle<Object> char_at = Object::GetProperty(
613 isolate->js_builtins_object(),
614 factory->char_at_string()).ToHandleChecked();
615 if (!char_at->IsJSFunction()) {
616 return factory->undefined_value();
619 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
620 Handle<Object> index_arg[] = { index_object };
621 Handle<Object> result;
622 if (!TryCall(Handle<JSFunction>::cast(char_at),
624 arraysize(index_arg),
625 index_arg).ToHandle(&result)) {
626 return factory->undefined_value();
632 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
633 Handle<JSFunction> fun,
635 Handle<Object> is_global) {
636 Isolate* isolate = fun->GetIsolate();
637 Handle<Object> args[] = { recv, fun, pos, is_global };
638 MaybeHandle<Object> maybe_result =
639 TryCall(isolate->get_stack_trace_line_fun(),
640 isolate->js_builtins_object(),
643 Handle<Object> result;
644 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
645 return isolate->factory()->empty_string();
648 return Handle<String>::cast(result);
652 Object* StackGuard::HandleInterrupts() {
653 if (CheckAndClearInterrupt(GC_REQUEST)) {
654 isolate_->heap()->HandleGCRequest();
657 if (CheckDebugBreak() || CheckDebugCommand()) {
658 isolate_->debug()->HandleDebugBreak();
661 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
662 return isolate_->TerminateExecution();
665 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
666 isolate_->heap()->DeoptMarkedAllocationSites();
669 if (CheckAndClearInterrupt(INSTALL_CODE)) {
670 DCHECK(isolate_->concurrent_recompilation_enabled());
671 isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
674 if (CheckAndClearInterrupt(API_INTERRUPT)) {
675 // Callbacks must be invoked outside of ExecusionAccess lock.
676 isolate_->InvokeApiInterruptCallbacks();
679 isolate_->counters()->stack_interrupts()->Increment();
680 isolate_->counters()->runtime_profiler_ticks()->Increment();
681 isolate_->runtime_profiler()->OptimizeNow();
683 return isolate_->heap()->undefined_value();
686 } } // namespace v8::internal