Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions core/engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
realm::Realm,
spanned_source_text::SourceText,
string::StaticJsStrings,
vm::{CallFrame, CallFrameFlags, Constant, Registers},
vm::{CallFrame, CallFrameFlags, Constant},
Context, JsArgs, JsResult, JsString, JsValue, SpannedSourceText,
};
use boa_ast::{
Expand Down Expand Up @@ -333,8 +333,7 @@ impl Eval {

context.realm().resize_global_env();

let register_count = context.vm.frame().code_block().register_count;
let record = context.run(&mut Registers::new(register_count as usize));
let record = context.run();
context.vm.pop_frame();

record.consume()
Expand Down
23 changes: 14 additions & 9 deletions core/engine/src/builtins/function/bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,23 +109,28 @@ fn bound_function_exotic_call(
.downcast_ref::<BoundFunction>()
.expect("bound function exotic method should only be callable from bound function objects");

let arguments_start_index = context.vm.stack.len() - argument_count;

// 1. Let target be F.[[BoundTargetFunction]].
let target = bound_function.target_function();
context.vm.stack[arguments_start_index - 1] = target.clone().into();
context
.vm
.stack
.calling_convention_set_function(argument_count, target.clone().into());

// 2. Let boundThis be F.[[BoundThis]].
let bound_this = bound_function.this();
context.vm.stack[arguments_start_index - 2] = bound_this.clone();
context
.vm
.stack
.calling_convention_set_this(argument_count, bound_this.clone());

// 3. Let boundArgs be F.[[BoundArguments]].
let bound_args = bound_function.args();

// 4. Let args be the list-concatenation of boundArgs and argumentsList.
context
.vm
.insert_values_at(bound_args, arguments_start_index);
.stack
.calling_convention_insert_arguments(argument_count, bound_args);

// 5. Return ? Call(target, boundThis, args).
Ok(target.__call__(bound_args.len() + argument_count))
Expand All @@ -143,7 +148,7 @@ fn bound_function_exotic_construct(
argument_count: usize,
context: &mut Context,
) -> JsResult<CallValue> {
let new_target = context.vm.pop();
let new_target = context.vm.stack.pop();

debug_assert!(new_target.is_object(), "new.target should be an object");

Expand All @@ -160,10 +165,10 @@ fn bound_function_exotic_construct(
let bound_args = bound_function.args();

// 4. Let args be the list-concatenation of boundArgs and argumentsList.
let arguments_start_index = context.vm.stack.len() - argument_count;
context
.vm
.insert_values_at(bound_args, arguments_start_index);
.stack
.calling_convention_insert_arguments(argument_count, bound_args);

// 5. If SameValue(F, newTarget) is true, set newTarget to target.
let function_object: JsValue = function_object.clone().into();
Expand All @@ -174,6 +179,6 @@ fn bound_function_exotic_construct(
};

// 6. Return ? Construct(target, args, newTarget).
context.vm.push(new_target);
context.vm.stack.push(new_target);
Ok(target.__construct__(bound_args.len() + argument_count))
}
20 changes: 6 additions & 14 deletions core/engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,6 @@ pub(crate) fn function_call(
let code = function.code.clone();
let environments = function.environments.clone();
let script_or_module = function.script_or_module.clone();
let register_count = code.register_count as usize;

drop(function);

Expand All @@ -1007,7 +1006,7 @@ pub(crate) fn function_call(

context.vm.push_frame(frame);

let this = context.vm.frame().this(&context.vm);
let this = context.vm.stack.get_this(context.vm.frame());

let lexical_this_mode = code.this_mode == ThisMode::Lexical;

Expand Down Expand Up @@ -1044,7 +1043,7 @@ pub(crate) fn function_call(
);
}

Ok(CallValue::Ready { register_count })
Ok(CallValue::Ready)
}

/// Construct an instance of this object with the specified arguments.
Expand Down Expand Up @@ -1073,12 +1072,11 @@ fn function_construct(
let code = function.code.clone();
let environments = function.environments.clone();
let script_or_module = function.script_or_module.clone();
let register_count = code.register_count as usize;
drop(function);

let env_fp = environments.len() as u32;

let new_target = context.vm.pop();
let new_target = context.vm.stack.pop();

let this = if code.is_derived_constructor() {
None
Expand Down Expand Up @@ -1111,13 +1109,8 @@ fn function_construct(
.flags
.set(CallFrameFlags::THIS_VALUE_CACHED, this.is_some());

let len = context.vm.stack.len();

context.vm.push_frame(frame);

// NOTE(HalidOdat): +1 because we insert `this` value below.
context.vm.frame_mut().rp = len as u32 + 1;

let mut last_env = 0;

if code.has_binding_identifier() {
Expand Down Expand Up @@ -1146,11 +1139,10 @@ fn function_construct(
),
);

// Insert `this` value
context.vm.stack.insert(
len - argument_count - 1,
context.vm.stack.set_this(
&context.vm.frame,
this.map(JsValue::new).unwrap_or_default(),
);

Ok(CallValue::Ready { register_count })
Ok(CallValue::Ready)
}
33 changes: 12 additions & 21 deletions core/engine/src/builtins/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
string::StaticJsStrings,
symbol::JsSymbol,
value::JsValue,
vm::{CallFrame, CallFrameFlags, CompletionRecord, GeneratorResumeKind, Registers},
vm::{CallFrame, CallFrameFlags, CompletionRecord, GeneratorResumeKind, Stack},
Context, JsArgs, JsData, JsError, JsResult, JsString,
};
use boa_gc::{custom_trace, Finalize, Trace};
Expand Down Expand Up @@ -59,23 +59,17 @@ unsafe impl Trace for GeneratorState {
/// context/vm before the generator execution starts/resumes and after it has ended/yielded.
#[derive(Debug, Trace, Finalize)]
pub(crate) struct GeneratorContext {
pub(crate) stack: Vec<JsValue>,
pub(crate) stack: Stack,
pub(crate) call_frame: Option<CallFrame>,
registers: Registers,
}

impl GeneratorContext {
/// Creates a new `GeneratorContext` from the current `Context` state.
pub(crate) fn from_current(
context: &mut Context,
mut registers: Registers,
async_generator: Option<JsObject>,
) -> Self {
pub(crate) fn from_current(context: &mut Context, async_generator: Option<JsObject>) -> Self {
let mut frame = context.vm.frame().clone();
frame.environments = context.vm.environments.clone();
frame.realm = context.realm().clone();
let fp = frame.fp() as usize;
let stack = context.vm.stack.split_off(fp);
let mut stack = context.vm.stack.split_off_frame(&frame);

frame.rp = CallFrame::FUNCTION_PROLOGUE + frame.argument_count;

Expand All @@ -84,16 +78,12 @@ impl GeneratorContext {
frame.flags |= CallFrameFlags::REGISTERS_ALREADY_PUSHED;

if let Some(async_generator) = async_generator {
registers.set(
CallFrame::ASYNC_GENERATOR_OBJECT_REGISTER_INDEX,
async_generator.into(),
);
stack.set_async_generator_object(&frame, async_generator);
}

Self {
call_frame: Some(frame),
stack,
registers,
}
}

Expand All @@ -114,11 +104,11 @@ impl GeneratorContext {
frame.set_exit_early(true);

if let Some(value) = value {
context.vm.push(value);
context.vm.stack.push(value);
}
context.vm.push(resume_kind);
context.vm.stack.push(resume_kind);

let result = context.run(&mut self.registers);
let result = context.run();

std::mem::swap(&mut context.vm.stack, &mut self.stack);
self.call_frame = context.vm.pop_frame();
Expand All @@ -128,9 +118,10 @@ impl GeneratorContext {

/// Returns the async generator object, if the function that this [`GeneratorContext`] is from an async generator, [`None`] otherwise.
pub(crate) fn async_generator_object(&self) -> Option<JsObject> {
self.call_frame
.as_ref()
.and_then(|frame| frame.async_generator_object(&self.registers))
if let Some(frame) = &self.call_frame {
return self.stack.async_generator_object(frame);
}
None
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/engine/src/builtins/intl/number_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ impl BuiltInConstructor for NumberFormat {
// ChainNumberFormat ( numberFormat, newTarget, this )
// <https://tc39.es/ecma402/#sec-chainnumberformat>

let this = context.vm.frame().this(&context.vm);
let this = context.vm.stack.get_this(context.vm.frame());
let Some(this_obj) = this.as_object() else {
return Ok(number_format.into());
};
Expand Down
5 changes: 2 additions & 3 deletions core/engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
string::{CodePoint, StaticJsStrings},
symbol::JsSymbol,
value::IntegerOrInfinity,
vm::{CallFrame, CallFrameFlags, Registers},
vm::{CallFrame, CallFrameFlags},
Context, JsArgs, JsBigInt, JsResult, JsString, JsValue, SpannedSourceText,
};
use boa_gc::Gc;
Expand Down Expand Up @@ -147,8 +147,7 @@ impl Json {
);

context.realm().resize_global_env();
let register_count = context.vm.frame().code_block().register_count;
let record = context.run(&mut Registers::new(register_count as usize));
let record = context.run();
context.vm.pop_frame();

let unfiltered = record.consume()?;
Expand Down
31 changes: 19 additions & 12 deletions core/engine/src/builtins/proxy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,21 +1165,24 @@ fn proxy_exotic_call(
return Ok(target.__call__(argument_count));
};

let args = context.vm.pop_n_values(argument_count);
let args = context
.vm
.stack
.calling_convention_pop_arguments(argument_count);

// 7. Let argArray be ! CreateArrayFromList(argumentsList).
let arg_array = array::Array::create_array_from_list(args, context);

// 8. Return ? Call(trap, handler, « target, thisArgument, argArray »).
let _func = context.vm.pop();
let this = context.vm.pop();
let _func = context.vm.stack.pop();
let this = context.vm.stack.pop();

context.vm.push(handler); // This
context.vm.push(trap.clone()); // Function
context.vm.stack.push(handler); // This
context.vm.stack.push(trap.clone()); // Function

context.vm.push(target);
context.vm.push(this);
context.vm.push(arg_array);
context.vm.stack.push(target);
context.vm.stack.push(this);
context.vm.stack.push(arg_array);
Ok(trap.__call__(3))
}

Expand Down Expand Up @@ -1213,9 +1216,13 @@ fn proxy_exotic_construct(
return Ok(target.__construct__(argument_count));
};

let new_target = context.vm.pop();
let args = context.vm.pop_n_values(argument_count);
let _func = context.vm.pop();
let new_target = context.vm.stack.pop();
let args = context
.vm
.stack
.calling_convention_pop_arguments(argument_count);
let _func = context.vm.stack.pop();
let _this = context.vm.stack.pop();

// 8. Let argArray be ! CreateArrayFromList(argumentsList).
let arg_array = array::Array::create_array_from_list(args, context);
Expand All @@ -1233,6 +1240,6 @@ fn proxy_exotic_construct(
})?;

// 11. Return newObj.
context.vm.push(new_obj);
context.vm.stack.push(new_obj);
Ok(CallValue::Complete)
}
4 changes: 4 additions & 0 deletions core/engine/src/bytecompiler/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,13 @@ impl ByteCompiler<'_> {
self.compile_class(class.deref().into(), Some(dst));
}
Expression::SuperCall(super_call) => {
let this = self.register_allocator.alloc();
let value = self.register_allocator.alloc();
self.bytecode.emit_super_call_prepare(value.variable());
self.bytecode.emit_push_undefined(this.variable());
self.push_from_register(&this);
self.push_from_register(&value);
self.register_allocator.dealloc(this);
self.register_allocator.dealloc(value);

let contains_spread = super_call
Expand Down
13 changes: 8 additions & 5 deletions core/engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,22 +511,22 @@ impl<'ctx> ByteCompiler<'ctx> {

debug_assert_eq!(
promise_register.index(),
CallFrame::PROMISE_CAPABILITY_PROMISE_REGISTER_INDEX
CallFrame::PROMISE_CAPABILITY_PROMISE_REGISTER_INDEX as u32
);
debug_assert_eq!(
resolve_register.index(),
CallFrame::PROMISE_CAPABILITY_RESOLVE_REGISTER_INDEX
CallFrame::PROMISE_CAPABILITY_RESOLVE_REGISTER_INDEX as u32
);
debug_assert_eq!(
reject_register.index(),
CallFrame::PROMISE_CAPABILITY_REJECT_REGISTER_INDEX
CallFrame::PROMISE_CAPABILITY_REJECT_REGISTER_INDEX as u32
);

if is_generator {
let async_function_object_register = register_allocator.alloc_persistent();
debug_assert_eq!(
async_function_object_register.index(),
CallFrame::ASYNC_GENERATOR_OBJECT_REGISTER_INDEX
CallFrame::ASYNC_GENERATOR_OBJECT_REGISTER_INDEX as u32
);
}
}
Expand Down Expand Up @@ -1833,7 +1833,6 @@ impl<'ctx> ByteCompiler<'ctx> {
self.register_allocator.dealloc(this);
self.register_allocator.dealloc(dst);
}

Expression::Optional(opt) if kind == CallKind::Call => {
let this = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();
Expand Down Expand Up @@ -1883,9 +1882,13 @@ impl<'ctx> ByteCompiler<'ctx> {
self.register_allocator.dealloc(value);
}
expr => {
let this = self.register_allocator.alloc();
let value = self.register_allocator.alloc();
self.compile_expr(expr, &value);
self.bytecode.emit_push_undefined(this.variable());
self.push_from_register(&this);
self.push_from_register(&value);
self.register_allocator.dealloc(this);
self.register_allocator.dealloc(value);
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/engine/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ impl Context {
return self.vm.native_active_function.clone();
}

self.vm.frame.function(&self.vm)
self.vm.stack.get_function(self.vm.frame())
}
}

Expand Down
Loading
Loading