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/messages.h"
12 #include "src/parser.h"
13 #include "src/prettyprinter.h"
14 #include "src/vm-state-inl.h"
19 StackGuard::StackGuard()
24 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) {
25 DCHECK(isolate_ != NULL);
26 thread_local_.set_jslimit(kInterruptLimit);
27 thread_local_.set_climit(kInterruptLimit);
28 isolate_->heap()->SetStackLimits();
32 void StackGuard::reset_limits(const ExecutionAccess& lock) {
33 DCHECK(isolate_ != NULL);
34 thread_local_.set_jslimit(thread_local_.real_jslimit_);
35 thread_local_.set_climit(thread_local_.real_climit_);
36 isolate_->heap()->SetStackLimits();
40 static void PrintDeserializedCodeInfo(Handle<JSFunction> function) {
41 if (function->code() == function->shared()->code() &&
42 function->shared()->deserialized()) {
43 PrintF("[Running deserialized script");
44 Object* script = function->shared()->script();
45 if (script->IsScript()) {
46 Object* name = Script::cast(script)->name();
47 if (name->IsString()) {
48 PrintF(": %s", String::cast(name)->ToCString().get());
58 MUST_USE_RESULT MaybeHandle<Object> Invoke(bool is_construct,
59 Handle<JSFunction> function,
60 Handle<Object> receiver, int argc,
61 Handle<Object> args[]) {
62 Isolate* const isolate = function->GetIsolate();
64 // Convert calls on global objects to be calls on the global
65 // receiver instead to avoid having a 'this' pointer which refers
66 // directly to a global object.
67 if (receiver->IsGlobalObject()) {
69 handle(Handle<GlobalObject>::cast(receiver)->global_proxy(), isolate);
72 // api callbacks can be called directly.
73 if (!is_construct && function->shared()->IsApiFunction()) {
74 SaveContext save(isolate);
75 isolate->set_context(function->context());
76 DCHECK(function->context()->global_object()->IsGlobalObject());
77 auto value = Builtins::InvokeApiFunction(function, receiver, argc, args);
78 bool has_exception = value.is_null();
79 DCHECK(has_exception == isolate->has_pending_exception());
81 isolate->ReportPendingMessages();
82 return MaybeHandle<Object>();
84 isolate->clear_pending_message();
89 // Entering JavaScript.
90 VMState<JS> state(isolate);
91 CHECK(AllowJavascriptExecution::IsAllowed(isolate));
92 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
93 isolate->ThrowIllegalOperation();
94 isolate->ReportPendingMessages();
95 return MaybeHandle<Object>();
98 // Placeholder for return value.
101 typedef Object* (*JSEntryFunction)(byte* entry,
107 Handle<Code> code = is_construct
108 ? isolate->factory()->js_construct_entry_code()
109 : isolate->factory()->js_entry_code();
111 // Make sure that the global object of the context we're about to
112 // make the current one is indeed a global object.
113 DCHECK(function->context()->global_object()->IsGlobalObject());
116 // Save and restore context around invocation and block the
117 // allocation of handles without explicit handle scopes.
118 SaveContext save(isolate);
119 SealHandleScope shs(isolate);
120 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
122 // Call the function through the right JS entry stub.
123 byte* ignored = nullptr; // TODO(bmeurer): Remove this altogether.
124 JSFunction* func = *function;
125 Object* recv = *receiver;
126 Object*** argv = reinterpret_cast<Object***>(args);
127 if (FLAG_profile_deserialization) PrintDeserializedCodeInfo(function);
128 value = CALL_GENERATED_CODE(stub_entry, ignored, 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);
157 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable,
158 Handle<Object> receiver, int argc,
159 Handle<Object> argv[]) {
160 if (!callable->IsJSFunction()) {
161 ASSIGN_RETURN_ON_EXCEPTION(isolate, callable,
162 GetFunctionDelegate(isolate, callable), Object);
164 Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
166 return Invoke(false, func, receiver, argc, argv);
170 MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
172 Handle<Object> argv[]) {
173 return Invoke(true, func, handle(func->global_proxy()), argc, argv);
177 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
178 Handle<Object> receiver, int argc,
179 Handle<Object> args[],
180 MaybeHandle<Object>* exception_out) {
181 bool is_termination = false;
182 Isolate* isolate = func->GetIsolate();
183 MaybeHandle<Object> maybe_result;
184 if (exception_out != NULL) *exception_out = MaybeHandle<Object>();
185 // Enter a try-block while executing the JavaScript code. To avoid
186 // duplicate error printing it must be non-verbose. Also, to avoid
187 // creating message objects during stack overflow we shouldn't
190 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
191 catcher.SetVerbose(false);
192 catcher.SetCaptureMessage(false);
194 maybe_result = Call(isolate, func, receiver, argc, args);
196 if (maybe_result.is_null()) {
197 DCHECK(catcher.HasCaught());
198 DCHECK(isolate->has_pending_exception());
199 DCHECK(isolate->external_caught_exception());
200 if (isolate->pending_exception() ==
201 isolate->heap()->termination_exception()) {
202 is_termination = true;
204 if (exception_out != NULL) {
205 *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
208 isolate->OptionalRescheduleException(true);
211 DCHECK(!isolate->has_pending_exception());
214 // Re-request terminate execution interrupt to trigger later.
215 if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
222 MaybeHandle<JSFunction> Execution::GetFunctionDelegate(Isolate* isolate,
223 Handle<Object> object) {
224 DCHECK(!object->IsJSFunction());
225 if (object->IsHeapObject()) {
226 DisallowHeapAllocation no_gc;
228 // If object is a function proxy, get its handler. Iterate if necessary.
229 Object* fun = *object;
230 while (fun->IsJSFunctionProxy()) {
231 fun = JSFunctionProxy::cast(fun)->call_trap();
233 if (fun->IsJSFunction()) {
234 return handle(JSFunction::cast(fun), isolate);
237 // We can also have exotic objects with [[Call]] internal methods.
238 if (fun->IsCallable()) {
239 return handle(isolate->native_context()->call_as_function_delegate(),
244 // If the Object doesn't have an instance-call handler we should
245 // throw a non-callable exception.
246 Handle<String> callsite = RenderCallSite(isolate, object);
247 THROW_NEW_ERROR(isolate,
248 NewTypeError(MessageTemplate::kCalledNonCallable, callsite),
254 MaybeHandle<JSFunction> Execution::GetConstructorDelegate(
255 Isolate* isolate, Handle<Object> object) {
256 // If you return a function from here, it will be called when an
257 // attempt is made to call the given object as a constructor.
259 DCHECK(!object->IsJSFunction());
260 if (object->IsHeapObject()) {
261 DisallowHeapAllocation no_gc;
263 // If object is a function proxies, get its handler. Iterate if necessary.
264 Object* fun = *object;
265 while (fun->IsJSFunctionProxy()) {
266 // TODO(bmeurer): This should work based on [[Construct]]; our proxies
268 fun = JSFunctionProxy::cast(fun)->call_trap();
270 if (fun->IsJSFunction()) {
271 return handle(JSFunction::cast(fun), isolate);
274 // We can also have exotic objects with [[Construct]] internal methods.
275 // TODO(bmeurer): This should use IsConstructor() as dictacted by the spec.
276 if (fun->IsCallable()) {
277 return handle(isolate->native_context()->call_as_constructor_delegate(),
282 // If the Object doesn't have an instance-call handler we should
283 // throw a non-callable exception.
284 Handle<String> callsite = RenderCallSite(isolate, object);
285 THROW_NEW_ERROR(isolate,
286 NewTypeError(MessageTemplate::kCalledNonCallable, callsite),
292 Handle<String> Execution::RenderCallSite(Isolate* isolate,
293 Handle<Object> object) {
294 MessageLocation location;
295 if (isolate->ComputeLocation(&location)) {
297 base::SmartPointer<ParseInfo> info(
298 location.function()->shared()->is_function()
299 ? new ParseInfo(&zone, location.function())
300 : new ParseInfo(&zone, location.script()));
301 if (Parser::ParseStatic(info.get())) {
302 CallPrinter printer(isolate, &zone);
303 const char* string = printer.Print(info->literal(), location.start_pos());
304 return isolate->factory()->NewStringFromAsciiChecked(string);
306 isolate->clear_pending_exception();
309 return Object::TypeOf(isolate, object);
313 void StackGuard::SetStackLimit(uintptr_t limit) {
314 ExecutionAccess access(isolate_);
315 // If the current limits are special (e.g. due to a pending interrupt) then
317 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit);
318 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
319 thread_local_.set_jslimit(jslimit);
321 if (thread_local_.climit() == thread_local_.real_climit_) {
322 thread_local_.set_climit(limit);
324 thread_local_.real_climit_ = limit;
325 thread_local_.real_jslimit_ = jslimit;
329 void StackGuard::AdjustStackLimitForSimulator() {
330 ExecutionAccess access(isolate_);
331 uintptr_t climit = thread_local_.real_climit_;
332 // If the current limits are special (e.g. due to a pending interrupt) then
334 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, climit);
335 if (thread_local_.jslimit() == thread_local_.real_jslimit_) {
336 thread_local_.set_jslimit(jslimit);
337 isolate_->heap()->SetStackLimits();
342 void StackGuard::EnableInterrupts() {
343 ExecutionAccess access(isolate_);
344 if (has_pending_interrupts(access)) {
345 set_interrupt_limits(access);
350 void StackGuard::DisableInterrupts() {
351 ExecutionAccess access(isolate_);
352 reset_limits(access);
356 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) {
357 ExecutionAccess access(isolate_);
358 // Intercept already requested interrupts.
359 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_;
360 scope->intercepted_flags_ = intercepted;
361 thread_local_.interrupt_flags_ &= ~intercepted;
362 if (!has_pending_interrupts(access)) reset_limits(access);
363 // Add scope to the chain.
364 scope->prev_ = thread_local_.postpone_interrupts_;
365 thread_local_.postpone_interrupts_ = scope;
369 void StackGuard::PopPostponeInterruptsScope() {
370 ExecutionAccess access(isolate_);
371 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_;
372 // Make intercepted interrupts active.
373 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0);
374 thread_local_.interrupt_flags_ |= top->intercepted_flags_;
375 if (has_pending_interrupts(access)) set_interrupt_limits(access);
376 // Remove scope from chain.
377 thread_local_.postpone_interrupts_ = top->prev_;
381 bool StackGuard::CheckInterrupt(InterruptFlag flag) {
382 ExecutionAccess access(isolate_);
383 return thread_local_.interrupt_flags_ & flag;
387 void StackGuard::RequestInterrupt(InterruptFlag flag) {
388 ExecutionAccess access(isolate_);
389 // Check the chain of PostponeInterruptsScopes for interception.
390 if (thread_local_.postpone_interrupts_ &&
391 thread_local_.postpone_interrupts_->Intercept(flag)) {
395 // Not intercepted. Set as active interrupt flag.
396 thread_local_.interrupt_flags_ |= flag;
397 set_interrupt_limits(access);
399 // If this isolate is waiting in a futex, notify it to wake up.
400 isolate_->futex_wait_list_node()->NotifyWake();
404 void StackGuard::ClearInterrupt(InterruptFlag flag) {
405 ExecutionAccess access(isolate_);
406 // Clear the interrupt flag from the chain of PostponeInterruptsScopes.
407 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_;
409 current = current->prev_) {
410 current->intercepted_flags_ &= ~flag;
413 // Clear the interrupt flag from the active interrupt flags.
414 thread_local_.interrupt_flags_ &= ~flag;
415 if (!has_pending_interrupts(access)) reset_limits(access);
419 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
420 ExecutionAccess access(isolate_);
421 bool result = (thread_local_.interrupt_flags_ & flag);
422 thread_local_.interrupt_flags_ &= ~flag;
423 if (!has_pending_interrupts(access)) reset_limits(access);
428 char* StackGuard::ArchiveStackGuard(char* to) {
429 ExecutionAccess access(isolate_);
430 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
433 // Set the stack limits using the old thread_local_.
434 // TODO(isolates): This was the old semantics of constructing a ThreadLocal
435 // (as the ctor called SetStackLimits, which looked at the
436 // current thread_local_ from StackGuard)-- but is this
437 // really what was intended?
438 isolate_->heap()->SetStackLimits();
439 thread_local_ = blank;
441 return to + sizeof(ThreadLocal);
445 char* StackGuard::RestoreStackGuard(char* from) {
446 ExecutionAccess access(isolate_);
447 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
448 isolate_->heap()->SetStackLimits();
449 return from + sizeof(ThreadLocal);
453 void StackGuard::FreeThreadResources() {
454 Isolate::PerIsolateThreadData* per_thread =
455 isolate_->FindOrAllocatePerThreadDataForThisThread();
456 per_thread->set_stack_limit(thread_local_.real_climit_);
460 void StackGuard::ThreadLocal::Clear() {
461 real_jslimit_ = kIllegalLimit;
462 set_jslimit(kIllegalLimit);
463 real_climit_ = kIllegalLimit;
464 set_climit(kIllegalLimit);
465 postpone_interrupts_ = NULL;
466 interrupt_flags_ = 0;
470 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) {
471 bool should_set_stack_limits = false;
472 if (real_climit_ == kIllegalLimit) {
473 const uintptr_t kLimitSize = FLAG_stack_size * KB;
474 DCHECK(GetCurrentStackPosition() > kLimitSize);
475 uintptr_t limit = GetCurrentStackPosition() - kLimitSize;
476 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
477 set_jslimit(SimulatorStack::JsLimitFromCLimit(isolate, limit));
478 real_climit_ = limit;
480 should_set_stack_limits = true;
482 postpone_interrupts_ = NULL;
483 interrupt_flags_ = 0;
484 return should_set_stack_limits;
488 void StackGuard::ClearThread(const ExecutionAccess& lock) {
489 thread_local_.Clear();
490 isolate_->heap()->SetStackLimits();
494 void StackGuard::InitThread(const ExecutionAccess& lock) {
495 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits();
496 Isolate::PerIsolateThreadData* per_thread =
497 isolate_->FindOrAllocatePerThreadDataForThisThread();
498 uintptr_t stored_limit = per_thread->stack_limit();
499 // You should hold the ExecutionAccess lock when you call this.
500 if (stored_limit != 0) {
501 SetStackLimit(stored_limit);
506 // --- C a l l s t o n a t i v e s ---
508 #define RETURN_NATIVE_CALL(name, args) \
510 Handle<Object> argv[] = args; \
511 return Call(isolate, isolate->name##_fun(), \
512 isolate->factory()->undefined_value(), arraysize(argv), argv); \
516 MaybeHandle<Object> Execution::ToDetailString(
517 Isolate* isolate, Handle<Object> obj) {
518 RETURN_NATIVE_CALL(to_detail_string, { obj });
522 MaybeHandle<Object> Execution::ToInteger(
523 Isolate* isolate, Handle<Object> obj) {
524 RETURN_NATIVE_CALL(to_integer, { obj });
528 MaybeHandle<Object> Execution::ToLength(
529 Isolate* isolate, Handle<Object> obj) {
530 RETURN_NATIVE_CALL(to_length, { obj });
534 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
535 Handle<Object> time_obj = isolate->factory()->NewNumber(time);
536 RETURN_NATIVE_CALL(create_date, { time_obj });
540 #undef RETURN_NATIVE_CALL
543 MaybeHandle<Object> Execution::ToInt32(Isolate* isolate, Handle<Object> obj) {
544 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
545 return isolate->factory()->NewNumberFromInt(DoubleToInt32(obj->Number()));
549 MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
550 Handle<JSReceiver> receiver;
551 if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
555 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
559 MaybeHandle<Object> Execution::ToUint32(Isolate* isolate, Handle<Object> obj) {
560 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, Object::ToNumber(obj), Object);
561 return isolate->factory()->NewNumberFromUint(DoubleToUint32(obj->Number()));
565 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
566 Handle<String> flags) {
567 Isolate* isolate = pattern->GetIsolate();
568 Handle<JSFunction> function = Handle<JSFunction>(
569 isolate->native_context()->regexp_function());
570 Handle<Object> re_obj;
571 ASSIGN_RETURN_ON_EXCEPTION(
573 RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
575 return Handle<JSRegExp>::cast(re_obj);
579 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
580 Handle<JSFunction> fun,
582 Handle<Object> is_global) {
583 Isolate* isolate = fun->GetIsolate();
584 Handle<Object> args[] = { recv, fun, pos, is_global };
585 MaybeHandle<Object> maybe_result =
586 TryCall(isolate->get_stack_trace_line_fun(),
587 isolate->factory()->undefined_value(), arraysize(args), args);
588 Handle<Object> result;
589 if (!maybe_result.ToHandle(&result) || !result->IsString()) {
590 return isolate->factory()->empty_string();
593 return Handle<String>::cast(result);
597 void StackGuard::HandleGCInterrupt() {
598 if (CheckAndClearInterrupt(GC_REQUEST)) {
599 isolate_->heap()->HandleGCRequest();
604 Object* StackGuard::HandleInterrupts() {
605 if (CheckAndClearInterrupt(GC_REQUEST)) {
606 isolate_->heap()->HandleGCRequest();
609 if (CheckDebugBreak() || CheckDebugCommand()) {
610 isolate_->debug()->HandleDebugBreak();
613 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
614 return isolate_->TerminateExecution();
617 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
618 isolate_->heap()->DeoptMarkedAllocationSites();
621 if (CheckAndClearInterrupt(INSTALL_CODE)) {
622 DCHECK(isolate_->concurrent_recompilation_enabled());
623 isolate_->optimizing_compile_dispatcher()->InstallOptimizedFunctions();
626 if (CheckAndClearInterrupt(API_INTERRUPT)) {
627 // Callbacks must be invoked outside of ExecusionAccess lock.
628 isolate_->InvokeApiInterruptCallbacks();
631 isolate_->counters()->stack_interrupts()->Increment();
632 isolate_->counters()->runtime_profiler_ticks()->Increment();
633 isolate_->runtime_profiler()->OptimizeNow();
635 return isolate_->heap()->undefined_value();
638 } // namespace internal