// Copyright 2014 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/execution/execution.h" #include "src/api/api-inl.h" #include "src/debug/debug.h" #include "src/execution/frames.h" #include "src/execution/isolate-inl.h" #include "src/execution/vm-state-inl.h" #include "src/logging/runtime-call-stats-scope.h" #if V8_ENABLE_WEBASSEMBLY #include "src/compiler/wasm-compiler.h" // Only for static asserts. #endif // V8_ENABLE_WEBASSEMBLY namespace v8 { namespace internal { namespace { Handle NormalizeReceiver(Isolate* isolate, Handle receiver) { // Convert calls on global objects to be calls on the global // receiver instead to avoid having a 'this' pointer which refers // directly to a global object. if (receiver->IsJSGlobalObject()) { return handle(Handle::cast(receiver)->global_proxy(), isolate); } return receiver; } struct InvokeParams { static InvokeParams SetUpForNew(Isolate* isolate, Handle constructor, Handle new_target, int argc, Handle* argv); static InvokeParams SetUpForCall(Isolate* isolate, Handle callable, Handle receiver, int argc, Handle* argv); static InvokeParams SetUpForTryCall( Isolate* isolate, Handle callable, Handle receiver, int argc, Handle* argv, Execution::MessageHandling message_handling, MaybeHandle* exception_out, bool reschedule_terminate); static InvokeParams SetUpForRunMicrotasks(Isolate* isolate, MicrotaskQueue* microtask_queue, MaybeHandle* exception_out); Handle target; Handle receiver; int argc; Handle* argv; Handle new_target; MicrotaskQueue* microtask_queue; Execution::MessageHandling message_handling; MaybeHandle* exception_out; bool is_construct; Execution::Target execution_target; bool reschedule_terminate; }; // static InvokeParams InvokeParams::SetUpForNew(Isolate* isolate, Handle constructor, Handle new_target, int argc, Handle* argv) { InvokeParams params; params.target = constructor; params.receiver = isolate->factory()->undefined_value(); params.argc = argc; params.argv = argv; params.new_target = new_target; params.microtask_queue = nullptr; params.message_handling = Execution::MessageHandling::kReport; params.exception_out = nullptr; params.is_construct = true; params.execution_target = Execution::Target::kCallable; params.reschedule_terminate = true; return params; } // static InvokeParams InvokeParams::SetUpForCall(Isolate* isolate, Handle callable, Handle receiver, int argc, Handle* argv) { InvokeParams params; params.target = callable; params.receiver = NormalizeReceiver(isolate, receiver); params.argc = argc; params.argv = argv; params.new_target = isolate->factory()->undefined_value(); params.microtask_queue = nullptr; params.message_handling = Execution::MessageHandling::kReport; params.exception_out = nullptr; params.is_construct = false; params.execution_target = Execution::Target::kCallable; params.reschedule_terminate = true; return params; } // static InvokeParams InvokeParams::SetUpForTryCall( Isolate* isolate, Handle callable, Handle receiver, int argc, Handle* argv, Execution::MessageHandling message_handling, MaybeHandle* exception_out, bool reschedule_terminate) { InvokeParams params; params.target = callable; params.receiver = NormalizeReceiver(isolate, receiver); params.argc = argc; params.argv = argv; params.new_target = isolate->factory()->undefined_value(); params.microtask_queue = nullptr; params.message_handling = message_handling; params.exception_out = exception_out; params.is_construct = false; params.execution_target = Execution::Target::kCallable; params.reschedule_terminate = reschedule_terminate; return params; } // static InvokeParams InvokeParams::SetUpForRunMicrotasks( Isolate* isolate, MicrotaskQueue* microtask_queue, MaybeHandle* exception_out) { auto undefined = isolate->factory()->undefined_value(); InvokeParams params; params.target = undefined; params.receiver = undefined; params.argc = 0; params.argv = nullptr; params.new_target = undefined; params.microtask_queue = microtask_queue; params.message_handling = Execution::MessageHandling::kReport; params.exception_out = exception_out; params.is_construct = false; params.execution_target = Execution::Target::kRunMicrotasks; params.reschedule_terminate = true; return params; } Handle JSEntry(Isolate* isolate, Execution::Target execution_target, bool is_construct) { if (is_construct) { DCHECK_EQ(Execution::Target::kCallable, execution_target); return BUILTIN_CODE(isolate, JSConstructEntry); } else if (execution_target == Execution::Target::kCallable) { DCHECK(!is_construct); return BUILTIN_CODE(isolate, JSEntry); } else if (execution_target == Execution::Target::kRunMicrotasks) { DCHECK(!is_construct); return BUILTIN_CODE(isolate, JSRunMicrotasksEntry); } UNREACHABLE(); } MaybeHandle NewScriptContext(Isolate* isolate, Handle function) { // Creating a script context is a side effect, so abort if that's not // allowed. if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) { isolate->Throw(*isolate->factory()->NewEvalError( MessageTemplate::kNoSideEffectDebugEvaluate)); return MaybeHandle(); } SaveAndSwitchContext save(isolate, function->context()); SharedFunctionInfo sfi = function->shared(); Handle