/* * Copyright (c) 2021-2025, Andreas Kling * Copyright (c) 2025, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace JS { using namespace Bytecode; // Defined in generated assembly (asmint_x86_64.S or asmint_aarch64.S) extern "C" void asm_interpreter_entry(u8 const* bytecode, u32 entry_point, Value* values, VM* vm); bool Bytecode::g_dump_bytecode = false; // 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation ThrowCompletionOr VM::run(Script& script_record, GC::Ptr lexical_environment_override) { auto& vm = this->vm(); // 1. Let globalEnv be scriptRecord.[[Realm]].[[GlobalEnv]]. auto& global_environment = script_record.realm().global_environment(); // NOTE: Spec steps are rearranged in order to compute number of registers+constants+locals before construction of the execution context. // 12. Let result be Completion(GlobalDeclarationInstantiation(script, globalEnv)). auto instantiation_result = script_record.global_declaration_instantiation(vm, global_environment); Completion result = instantiation_result.is_throw_completion() ? instantiation_result.throw_completion() : normal_completion(js_undefined()); // 11. Let script be scriptRecord.[[ECMAScriptCode]]. GC::Ptr executable = script_record.cached_executable(); if (executable && g_dump_bytecode) executable->dump(); u32 registers_and_locals_count = 0; ReadonlySpan constants; if (executable) { registers_and_locals_count = executable->registers_and_locals_count; constants = executable->constants; } // 2. Let scriptContext be a new ECMAScript code execution context. auto& stack = vm.interpreter_stack(); auto* stack_mark = stack.top(); auto* script_context = stack.allocate(registers_and_locals_count, constants, 0); if (!script_context) [[unlikely]] return vm.throw_completion(ErrorType::CallStackSizeExceeded); ScopeGuard deallocate_guard = [&stack, stack_mark] { stack.deallocate(stack_mark); }; // 3. Set the Function of scriptContext to null. // NOTE: This was done during execution context construction. // 4. Set the Realm of scriptContext to scriptRecord.[[Realm]]. script_context->realm = &script_record.realm(); // 5. Set the ScriptOrModule of scriptContext to scriptRecord. script_context->script_or_module = GC::Ref