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 MUST_USE_RESULT static MaybeHandle<Object> Invoke(
39 Handle<JSFunction> function,
40 Handle<Object> receiver,
42 Handle<Object> args[]) {
43 Isolate* isolate = function->GetIsolate();
45 // Entering JavaScript.
46 VMState<JS> state(isolate);
47 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
48 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
49 isolate->ThrowIllegalOperation();
50 isolate->ReportPendingMessages();
51 return MaybeHandle<Object>();
54 // Placeholder for return value.
57 typedef Object* (*JSEntryFunction)(byte* entry,
63 Handle<Code> code = is_construct
64 ? isolate->factory()->js_construct_entry_code()
65 : isolate->factory()->js_entry_code();
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()) {
71 receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy());
74 // Make sure that the global object of the context we're about to
75 // make the current one is indeed a global object.
76 DCHECK(function->context()->global_object()->IsGlobalObject());
79 // Save and restore context around invocation and block the
80 // allocation of handles without explicit handle scopes.
81 SaveContext save(isolate);
82 SealHandleScope shs(isolate);
83 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
85 // Call the function through the right JS entry stub.
86 byte* function_entry = function->code()->entry();
87 JSFunction* func = *function;
88 Object* recv = *receiver;
89 Object*** argv = reinterpret_cast<Object***>(args);
91 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv);
95 value->ObjectVerify();
98 // Update the pending exception flag and return the value.
99 bool has_exception = value->IsException();
100 DCHECK(has_exception == isolate->has_pending_exception());
102 isolate->ReportPendingMessages();
103 // Reset stepping state when script exits with uncaught exception.
104 if (isolate->debug()->is_active()) {
105 isolate->debug()->ClearStepping();
107 return MaybeHandle<Object>();
109 isolate->clear_pending_message();
112 return Handle<Object>(value, isolate);
116 MaybeHandle<Object> Execution::Call(Isolate* isolate,
117 Handle<Object> callable,
118 Handle<Object> receiver,
120 Handle<Object> argv[],
121 bool convert_receiver) {
122 if (!callable->IsJSFunction()) {
123 ASSIGN_RETURN_ON_EXCEPTION(
124 isolate, callable, TryGetFunctionDelegate(isolate, callable), Object);
126 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
128 // In sloppy mode, convert receiver.
129 if (convert_receiver && !receiver->IsJSReceiver() &&
130 !func->shared()->native() &&
131 func->shared()->strict_mode() == SLOPPY) {
132 if (receiver->IsUndefined() || receiver->IsNull()) {
133 receiver = handle(func->global_proxy());
134 DCHECK(!receiver->IsJSBuiltinsObject());
136 ASSIGN_RETURN_ON_EXCEPTION(
137 isolate, receiver, ToObject(isolate, receiver), Object);
141 return Invoke(false, func, receiver, argc, argv);
145 MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
147 Handle<Object> argv[]) {
148 return Invoke(true, func, handle(func->global_proxy()), argc, argv);
152 MaybeHandle<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>();
160 // 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
165 v8::TryCatch catcher;
166 catcher.SetVerbose(false);
167 catcher.SetCaptureMessage(false);
169 maybe_result = Invoke(false, func, receiver, argc, args);
171 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;
180 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
183 isolate->OptionalRescheduleException(true);
186 DCHECK(!isolate->has_pending_exception());
187 DCHECK(!isolate->external_caught_exception());
189 if (is_termination) isolate->TerminateExecution();
194 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate,
195 Handle<Object> object) {
196 DCHECK(!object->IsJSFunction());
197 Factory* factory = isolate->factory();
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.
202 // 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();
207 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
209 // Objects created through the API can have an instance-call handler
210 // that should be used when calling the object as a function.
211 if (fun->IsHeapObject() &&
212 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
213 return Handle<JSFunction>(
214 isolate->native_context()->call_as_function_delegate());
217 return factory->undefined_value();
221 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
222 Handle<Object> object) {
223 DCHECK(!object->IsJSFunction());
225 // 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();
230 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
232 // Objects created through the API can have an instance-call handler
233 // that should be used when calling the object as a function.
234 if (fun->IsHeapObject() &&
235 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
236 return Handle<JSFunction>(
237 isolate->native_context()->call_as_function_delegate());
240 // If the Object doesn't have an instance-call handler we should
241 // throw a non-callable exception.
242 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
243 i::HandleVector<i::Object>(&object, 1)),
248 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate,
249 Handle<Object> object) {
250 DCHECK(!object->IsJSFunction());
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.
255 // 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();
260 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
262 // Objects created through the API can have an instance-call handler
263 // that should be used when calling the object as a function.
264 if (fun->IsHeapObject() &&
265 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
266 return Handle<JSFunction>(
267 isolate->native_context()->call_as_constructor_delegate());
270 return isolate->factory()->undefined_value();
274 MaybeHandle<Object> Execution::TryGetConstructorDelegate(
275 Isolate* isolate, Handle<Object> object) {
276 DCHECK(!object->IsJSFunction());
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.
281 // 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();
286 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate);
288 // Objects created through the API can have an instance-call handler
289 // that should be used when calling the object as a function.
290 if (fun->IsHeapObject() &&
291 HeapObject::cast(fun)->map()->has_instance_call_handler()) {
292 return Handle<JSFunction>(
293 isolate->native_context()->call_as_constructor_delegate());
296 // If the Object doesn't have an instance-call handler we should
297 // throw a non-callable exception.
298 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable",
299 i::HandleVector<i::Object>(&object, 1)),
304 void StackGuard::EnableInterrupts() {
305 ExecutionAccess access(isolate_);
306 if (has_pending_interrupts(access)) {
307 set_interrupt_limits(access);
312 void StackGuard::SetStackLimit(uintptr_t limit) {
313 ExecutionAccess access(isolate_);
314 // If the current limits are special (e.g. due to a pending interrupt) then
316 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
317 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) {
318 thread_local_.jslimit_ = jslimit;
320 if (thread_local_.climit_ == thread_local_.real_climit_) {
321 thread_local_.climit_ = limit;
323 thread_local_.real_climit_ = limit;
324 thread_local_.real_jslimit_ = jslimit;
328 void StackGuard::DisableInterrupts() {
329 ExecutionAccess access(isolate_);
330 reset_limits(access);
334 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
335 ExecutionAccess access(isolate_);
336 // 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;
347 void StackGuard::PopPostponeInterruptsScope() {
348 ExecutionAccess access(isolate_);
349 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_;
359 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
360 ExecutionAccess access(isolate_);
361 return thread_local_.interrupt_flags_ & flag;
365 void 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)) {
373 // Not intercepted. Set as active interrupt flag.
374 thread_local_.interrupt_flags_ |= flag;
375 set_interrupt_limits(access);
379 void StackGuard::ClearInterrupt(InterruptFlag flag) {
380 ExecutionAccess access(isolate_);
381 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
382 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
384 current = current->prev_) {
385 current->intercepted_flags_ &= ~flag;
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);
394 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
395 ExecutionAccess access(isolate_);
396 bool result = (thread_local_.interrupt_flags_ & flag);
397 thread_local_.interrupt_flags_ &= ~flag;
398 if (!has_pending_interrupts(access)) reset_limits(access);
403 char* StackGuard::ArchiveStackGuard(char* to) {
404 ExecutionAccess access(isolate_);
405 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
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();
414 thread_local_ = blank;
416 return to + sizeof(ThreadLocal);
420 char* StackGuard::RestoreStackGuard(char* from) {
421 ExecutionAccess access(isolate_);
422 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
423 isolate_->heap()->SetStackLimits();
424 return from + sizeof(ThreadLocal);
428 void StackGuard::FreeThreadResources() {
429 Isolate::PerIsolateThreadData* per_thread =
430 isolate_->FindOrAllocatePerThreadDataForThisThread();
431 per_thread->set_stack_limit(thread_local_.real_climit_);
435 void StackGuard::ThreadLocal::Clear() {
436 real_jslimit_ = kIllegalLimit;
437 jslimit_ = kIllegalLimit;
438 real_climit_ = kIllegalLimit;
439 climit_ = kIllegalLimit;
440 postpone_interrupts_ = NULL;
441 interrupt_flags_ = 0;
445 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
446 bool should_set_stack_limits = false;
447 if (real_climit_ == kIllegalLimit) {
448 const uintptr_t kLimitSize = FLAG_stack_size * KB;
449 DCHECK(GetCurrentStackPosition() > kLimitSize);
450 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
451 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
452 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
453 real_climit_ = limit;
455 should_set_stack_limits = true;
457 postpone_interrupts_ = NULL;
458 interrupt_flags_ = 0;
459 return should_set_stack_limits;
463 void StackGuard::ClearThread(const ExecutionAccess& lock) {
464 thread_local_.Clear();
465 isolate_->heap()->SetStackLimits();
469 void StackGuard::InitThread(const ExecutionAccess& lock) {
470 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();
474 // You should hold the ExecutionAccess lock when you call this.
475 if (stored_limit != 0) {
476 SetStackLimit(stored_limit);
481 // --- C a l l s t o n a t i v e s ---
483 #define RETURN_NATIVE_CALL(name, args) \
485 Handle<Object> argv[] = args; \
486 return Call(isolate, \
487 isolate->name##_fun(), \
488 isolate->js_builtins_object(), \
489 arraysize(argv), argv); \
493 MaybeHandle<Object> Execution::ToNumber(
494 Isolate* isolate, Handle<Object> obj) {
495 RETURN_NATIVE_CALL(to_number, { obj });
499 MaybeHandle<Object> Execution::ToString(
500 Isolate* isolate, Handle<Object> obj) {
501 RETURN_NATIVE_CALL(to_string, { obj });
505 MaybeHandle<Object> Execution::ToDetailString(
506 Isolate* isolate, Handle<Object> obj) {
507 RETURN_NATIVE_CALL(to_detail_string, { obj });
511 MaybeHandle<Object> Execution::ToObject(
512 Isolate* isolate, Handle<Object> obj) {
513 if (obj->IsSpecObject()) return obj;
514 RETURN_NATIVE_CALL(to_object, { obj });
518 MaybeHandle<Object> Execution::ToInteger(
519 Isolate* isolate, Handle<Object> obj) {
520 RETURN_NATIVE_CALL(to_integer, { obj });
524 MaybeHandle<Object> Execution::ToUint32(
525 Isolate* isolate, Handle<Object> obj) {
526 RETURN_NATIVE_CALL(to_uint32, { obj });
530 MaybeHandle<Object> Execution::ToInt32(
531 Isolate* isolate, Handle<Object> obj) {
532 RETURN_NATIVE_CALL(to_int32, { obj });
536 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
537 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
538 RETURN_NATIVE_CALL(create_date, { time_obj });
542 #undef RETURN_NATIVE_CALL
545 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
546 Handle<String> flags) {
547 Isolate* isolate = pattern->GetIsolate();
548 Handle<JSFunction> function = Handle<JSFunction>(
549 isolate->native_context()->regexp_function());
550 Handle<Object> re_obj;
551 ASSIGN_RETURN_ON_EXCEPTION(
553 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
555 return Handle<JSRegExp>::cast(re_obj);
559 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
560 Isolate* isolate = string->GetIsolate();
561 Factory* factory = isolate->factory();
563 int int_index = static_cast<int>(index);
564 if (int_index < 0 || int_index >= string->length()) {
565 return factory->undefined_value();
568 Handle<Object> char_at = Object::GetProperty(
569 isolate->js_builtins_object(),
570 factory->char_at_string()).ToHandleChecked();
571 if (!char_at->IsJSFunction()) {
572 return factory->undefined_value();
575 Handle<Object> index_object = factory->NewNumberFromInt(int_index);
576 Handle<Object> index_arg[] = { index_object };
577 Handle<Object> result;
578 if (!TryCall(Handle<JSFunction>::cast(char_at),
580 arraysize(index_arg),
581 index_arg).ToHandle(&result)) {
582 return factory->undefined_value();
588 MaybeHandle<JSFunction> Execution::InstantiateFunction(
589 Handle<FunctionTemplateInfo> data) {
590 Isolate* isolate = data->GetIsolate();
591 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());
596 Object::GetElement(isolate, cache, serial_number).ToHandleChecked();
597 if (elm->IsJSFunction()) return Handle<JSFunction>::cast(elm);
599 // The function has not yet been instantiated in this context; do it.
600 Handle<Object> args[] = { data };
601 Handle<Object> result;
602 ASSIGN_RETURN_ON_EXCEPTION(
605 isolate->instantiate_fun(),
606 isolate->js_builtins_object(),
610 return Handle<JSFunction>::cast(result);
614 MaybeHandle<JSObject> Execution::InstantiateObject(
615 Handle<ObjectTemplateInfo> data) {
616 Isolate* isolate = data->GetIsolate();
617 Handle<Object> result;
618 if (data->property_list()->IsUndefined() &&
619 !data->constructor()->IsUndefined()) {
620 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);
628 Handle<Object> args[] = { data };
629 ASSIGN_RETURN_ON_EXCEPTION(
632 isolate->instantiate_fun(),
633 isolate->js_builtins_object(),
638 return Handle<JSObject>::cast(result);
642 MaybeHandle<Object> Execution::ConfigureInstance(
644 Handle<Object> instance,
645 Handle<Object> instance_template) {
646 Handle<Object> args[] = { instance, instance_template };
647 return Execution::Call(isolate,
648 isolate->configure_instance_fun(),
649 isolate->js_builtins_object(),
655 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
656 Handle<JSFunction> fun,
658 Handle<Object> is_global) {
659 Isolate* isolate = fun->GetIsolate();
660 Handle<Object> args[] = { recv, fun, pos, is_global };
661 MaybeHandle<Object> maybe_result =
662 TryCall(isolate->get_stack_trace_line_fun(),
663 isolate->js_builtins_object(),
666 Handle<Object> result;
667 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
668 return isolate->factory()->empty_string();
671 return Handle<String>::cast(result);
675 Object* StackGuard::HandleInterrupts() {
676 if (CheckAndClearInterrupt(GC_REQUEST)) {
677 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
680 if (CheckDebugBreak() || CheckDebugCommand()) {
681 isolate_->debug()->HandleDebugBreak();
684 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
685 return isolate_->TerminateExecution();
688 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
689 isolate_->heap()->DeoptMarkedAllocationSites();
692 if (CheckAndClearInterrupt(INSTALL_CODE)) {
693 DCHECK(isolate_->concurrent_recompilation_enabled());
694 isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
697 if (CheckAndClearInterrupt(API_INTERRUPT)) {
698 // Callback must be invoked outside of ExecusionAccess lock.
699 isolate_->InvokeApiInterruptCallback();
702 isolate_->counters()->stack_interrupts()->Increment();
703 isolate_->counters()->runtime_profiler_ticks()->Increment();
704 isolate_->runtime_profiler()->OptimizeNow();
706 return isolate_->heap()->undefined_value();
709 } } // namespace v8::internal