diff --git a/Libraries/LibJS/Bytecode/Interpreter.cpp b/Libraries/LibJS/Bytecode/Interpreter.cpp index 82ba095d65e..b0976314eb1 100644 --- a/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -242,7 +242,8 @@ ThrowCompletionOr Interpreter::run(Script& script_record, GC::Ptr perform_eval(VM& vm, Value x, CallerMode strict_caller, executable->dump(); // 20. Let evalContext be a new ECMAScript code execution context. - auto eval_context = ExecutionContext::create(executable->number_of_registers + executable->constants.size() + executable->local_variable_names.size(), 0); + ExecutionContext* eval_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(eval_context, executable->number_of_registers + executable->constants.size() + executable->local_variable_names.size(), 0); // 21. Set evalContext's Function to null. // NOTE: This was done in the construction of eval_context. diff --git a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp index 814f1fca163..95866803f0e 100644 --- a/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp +++ b/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp @@ -501,7 +501,9 @@ ThrowCompletionOr ECMAScriptFunctionObject::internal_call(Value this_argu } u32 arguments_count = max(arguments_list.size(), formal_parameters().size()); - auto callee_context = ExecutionContext::create(m_bytecode_executable->number_of_registers + m_bytecode_executable->constants.size() + m_bytecode_executable->local_variable_names.size(), arguments_count); + auto registers_and_constants_and_locals_count = m_bytecode_executable->number_of_registers + m_bytecode_executable->constants.size() + m_bytecode_executable->local_variable_names.size(); + ExecutionContext* callee_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_constants_and_locals_count, arguments_count); // Non-standard auto arguments = callee_context->arguments(); @@ -571,7 +573,9 @@ ThrowCompletionOr> ECMAScriptFunctionObject::internal_construct( } u32 arguments_count = max(arguments_list.size(), formal_parameters().size()); - auto callee_context = ExecutionContext::create(m_bytecode_executable->number_of_registers + m_bytecode_executable->constants.size() + m_bytecode_executable->local_variable_names.size(), arguments_count); + auto registers_and_constants_and_locals_count = m_bytecode_executable->number_of_registers + m_bytecode_executable->constants.size() + m_bytecode_executable->local_variable_names.size(); + ExecutionContext* callee_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_constants_and_locals_count, arguments_count); // Non-standard auto arguments = callee_context->arguments(); diff --git a/Libraries/LibJS/Runtime/ExecutionContext.h b/Libraries/LibJS/Runtime/ExecutionContext.h index 5ae9f5cd838..c90d9be5ccc 100644 --- a/Libraries/LibJS/Runtime/ExecutionContext.h +++ b/Libraries/LibJS/Runtime/ExecutionContext.h @@ -43,9 +43,9 @@ struct ExecutionContext { private: friend class ExecutionContextAllocator; +public: ExecutionContext(u32 registers_and_constants_and_locals_count, u32 arguments_count); -public: void operator delete(void* ptr); GC::Ptr function; // [[Function]] @@ -123,6 +123,22 @@ private: u32 registers_and_constants_and_locals_and_arguments_count { 0 }; }; +#define ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(execution_context, \ + registers_and_constants_and_locals_count, \ + arguments_count) \ + auto execution_context_size = sizeof(JS::ExecutionContext) \ + + ((registers_and_constants_and_locals_count) + (arguments_count)) \ + * sizeof(JS::Value); \ + \ + void* execution_context_memory = alloca(execution_context_size); \ + \ + execution_context = new (execution_context_memory) \ + JS::ExecutionContext((registers_and_constants_and_locals_count), (arguments_count)); \ + \ + ScopeGuard run_execution_context_destructor([execution_context] { \ + execution_context->~ExecutionContext(); \ + }) + struct StackTraceElement { ExecutionContext* execution_context; RefPtr source_range; diff --git a/Libraries/LibJS/Runtime/NativeFunction.cpp b/Libraries/LibJS/Runtime/NativeFunction.cpp index 58cb2e11952..6b20c5487f4 100644 --- a/Libraries/LibJS/Runtime/NativeFunction.cpp +++ b/Libraries/LibJS/Runtime/NativeFunction.cpp @@ -119,7 +119,8 @@ ThrowCompletionOr NativeFunction::internal_call(Value this_argument, Read // 2. If callerContext is not already suspended, suspend callerContext. // 3. Let calleeContext be a new execution context. - auto callee_context = ExecutionContext::create(0, arguments_list.size()); + ExecutionContext* callee_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, 0, arguments_list.size()); // 4. Set the Function of calleeContext to F. callee_context->function = this; @@ -181,7 +182,8 @@ ThrowCompletionOr> NativeFunction::internal_construct(ReadonlySp // 2. If callerContext is not already suspended, suspend callerContext. // 3. Let calleeContext be a new execution context. - auto callee_context = ExecutionContext::create(0, arguments_list.size()); + ExecutionContext* callee_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, 0, arguments_list.size()); // 4. Set the Function of calleeContext to F. callee_context->function = this; diff --git a/Libraries/LibJS/Runtime/WrappedFunction.cpp b/Libraries/LibJS/Runtime/WrappedFunction.cpp index 3028ac3ef49..e3d0bcb3de4 100644 --- a/Libraries/LibJS/Runtime/WrappedFunction.cpp +++ b/Libraries/LibJS/Runtime/WrappedFunction.cpp @@ -62,7 +62,9 @@ ThrowCompletionOr WrappedFunction::internal_call(Value this_argument, Rea // NOTE: No-op, kept by the VM in its execution context stack. // 2. Let calleeContext be PrepareForWrappedFunctionCall(F). - auto callee_context = ExecutionContext::create(0, 0); + ExecutionContext* callee_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, 0, 0); + prepare_for_wrapped_function_call(*this, *callee_context); // 3. Assert: calleeContext is now the running execution context. diff --git a/Libraries/LibJS/SourceTextModule.cpp b/Libraries/LibJS/SourceTextModule.cpp index 7d93b7dc03a..30a547b4ccd 100644 --- a/Libraries/LibJS/SourceTextModule.cpp +++ b/Libraries/LibJS/SourceTextModule.cpp @@ -701,7 +701,8 @@ ThrowCompletionOr SourceTextModule::execute_module(VM& vm, GC::Ptris_strict_mode = true; diff --git a/Libraries/LibJS/SyntheticModule.cpp b/Libraries/LibJS/SyntheticModule.cpp index 4a637bdd0ac..444a4c555c7 100644 --- a/Libraries/LibJS/SyntheticModule.cpp +++ b/Libraries/LibJS/SyntheticModule.cpp @@ -81,7 +81,8 @@ ThrowCompletionOr SyntheticModule::evaluate(VM& vm) // NOTE: Done by the push on step 8. // 2. Let moduleContext be a new ECMAScript code execution context. - auto module_context = ExecutionContext::create(0, 0); + ExecutionContext* module_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(module_context, 0, 0); // 3. Set the Function of moduleContext to null. // Note: This is the default value. diff --git a/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Libraries/LibWeb/Bindings/MainThreadVM.cpp index 919ae05bbdd..003adef48f0 100644 --- a/Libraries/LibWeb/Bindings/MainThreadVM.cpp +++ b/Libraries/LibWeb/Bindings/MainThreadVM.cpp @@ -585,7 +585,8 @@ ErrorOr initialize_main_thread_vm(HTML::EventLoop::Type type) // 5. Perform FinishLoadingImportedModule(referrer, moduleRequest, payload, completion). // NON-STANDARD: To ensure that LibJS can find the module on the stack, we push a new execution context. - auto module_execution_context = JS::ExecutionContext::create(0, 0); + JS::ExecutionContext* module_execution_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(module_execution_context, 0, 0); module_execution_context->realm = realm; if (module) module_execution_context->script_or_module = GC::Ref { *module }; diff --git a/Libraries/LibWeb/HTML/Scripting/ModuleScript.cpp b/Libraries/LibWeb/HTML/Scripting/ModuleScript.cpp index b82aad276c3..d2102899729 100644 --- a/Libraries/LibWeb/HTML/Scripting/ModuleScript.cpp +++ b/Libraries/LibWeb/HTML/Scripting/ModuleScript.cpp @@ -102,7 +102,8 @@ JS::Promise* JavaScriptModuleScript::run(PreventErrorReporting) VERIFY(record); // NON-STANDARD: To ensure that LibJS can find the module on the stack, we push a new execution context. - auto module_execution_context = JS::ExecutionContext::create(0, 0); + JS::ExecutionContext* module_execution_context = nullptr; + ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(module_execution_context, 0, 0); module_execution_context->realm = &realm; module_execution_context->script_or_module = GC::Ref { *record }; vm().push_execution_context(*module_execution_context);