Skip to content

Commit

Permalink
Move return_value to VM
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Aug 1, 2023
1 parent 04c8402 commit facc473
Show file tree
Hide file tree
Showing 11 changed files with 33 additions and 33 deletions.
2 changes: 0 additions & 2 deletions boa_engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,6 @@ impl Eval {
.push_frame(CallFrame::new(code_block).with_env_fp(env_fp));
context.realm().resize_global_env();

// Push return value.
context.vm.push(JsValue::undefined());
let record = context.run();
context.vm.pop_frame();

Expand Down
2 changes: 0 additions & 2 deletions boa_engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ impl Json {
.vm
.push_frame(CallFrame::new(code_block).with_env_fp(env_fp));
context.realm().resize_global_env();
// Push return value.
context.vm.push(JsValue::undefined());
let record = context.run();
context.vm.pop_frame();

Expand Down
3 changes: 1 addition & 2 deletions boa_engine/src/bytecompiler/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,7 @@ impl ByteCompiler<'_, '_> {
}
self.close_active_iterators();

self.emit_opcode(Opcode::SetReturnValue);
self.r#return();
self.r#return(true);

self.patch_jump(throw_method_undefined);
self.iterator_close(self.in_async());
Expand Down
7 changes: 7 additions & 0 deletions boa_engine/src/bytecompiler/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ impl FunctionCompiler {
// ExecuteAsyncModule ( module ): <https://tc39.es/ecma262/#sec-execute-async-module>
compiler.emit_opcode(Opcode::CreatePromiseCapability);

// Note: We set it to one so we don't pop return value when we return.
compiler.current_stack_value_count += 1;

// 2. Let declResult be Completion(FunctionDeclarationInstantiation(functionObject, argumentsList)).
//
// Note: We push an exception handler so we catch exceptions that are thrown by the
Expand All @@ -159,6 +162,10 @@ impl FunctionCompiler {
// Note: We do handle exceptions thrown by generator body in `AsyncGeneratorStart`.
if compiler.in_generator() {
assert!(compiler.async_handler.is_none());

// Note: We set it to one so we don't pop return value when we return.
compiler.current_stack_value_count += 1;

if compiler.in_async() {
// Patched in `ByteCompiler::finish()`.
compiler.async_handler = Some(compiler.push_handler());
Expand Down
11 changes: 9 additions & 2 deletions boa_engine/src/bytecompiler/jump_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub(crate) enum JumpRecordAction {
pub(crate) enum JumpRecordKind {
Break,
Continue,
Return,
Return { return_value_on_stack: bool },
}

/// This represents a local control flow handling. See [`JumpRecordKind`] for types.
Expand Down Expand Up @@ -122,7 +122,13 @@ impl JumpRecord {
match self.kind {
JumpRecordKind::Break => compiler.patch_jump(self.label),
JumpRecordKind::Continue => compiler.patch_jump_with_target(self.label, start_address),
JumpRecordKind::Return => {
JumpRecordKind::Return {
return_value_on_stack,
} => {
if return_value_on_stack {
compiler.emit_opcode(Opcode::SetReturnValue);
}

match (compiler.in_async(), compiler.in_generator()) {
// Taken from:
// - 27.6.3.2 AsyncGeneratorStart ( generator, generatorBody ): https://tc39.es/ecma262/#sec-asyncgeneratorstart
Expand All @@ -137,6 +143,7 @@ impl JumpRecord {
(true, false) => compiler.emit_opcode(Opcode::CompletePromiseCapability),
(_, _) => {}
}

compiler.emit_opcode(Opcode::Return);
}
}
Expand Down
6 changes: 2 additions & 4 deletions boa_engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
compile_environments: Vec::default(),
current_open_environments_count: 0,

// Note: We set it to one so we don't pop return value,
// which is allocated after frame pointer.
current_stack_value_count: 1,
current_stack_value_count: 0,
code_block_flags,
handlers: ThinVec::default(),

Expand Down Expand Up @@ -1422,7 +1420,7 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
if let Some(async_handler) = self.async_handler {
self.patch_handler(async_handler);
}
self.r#return();
self.r#return(false);

let name = self
.context
Expand Down
13 changes: 9 additions & 4 deletions boa_engine/src/bytecompiler/statement/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ impl ByteCompiler<'_, '_> {
} else {
self.emit_opcode(Opcode::PushUndefined);
}
self.emit_opcode(Opcode::SetReturnValue);

self.r#return();
self.r#return(true);
}
Statement::Try(t) => self.compile_try(t, use_expr),
Statement::Expression(expr) => {
Expand All @@ -88,10 +87,16 @@ impl ByteCompiler<'_, '_> {
}
}

pub(crate) fn r#return(&mut self) {
pub(crate) fn r#return(&mut self, return_value_on_stack: bool) {
let actions = self.return_jump_record_actions();

JumpRecord::new(JumpRecordKind::Return, actions).perform_actions(Self::DUMMY_ADDRESS, self);
JumpRecord::new(
JumpRecordKind::Return {
return_value_on_stack,
},
actions,
)
.perform_actions(Self::DUMMY_ADDRESS, self);
}

fn return_jump_record_actions(&self) -> Vec<JumpRecordAction> {
Expand Down
3 changes: 0 additions & 3 deletions boa_engine/src/module/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1763,9 +1763,6 @@ impl SourceTextModule {
// 10. Else,
// a. Assert: capability is a PromiseCapability Record.
// b. Perform AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext).

// Push return value.
context.vm.push(JsValue::undefined());
let result = context.run();

std::mem::swap(&mut context.vm.environments, &mut environments);
Expand Down
3 changes: 0 additions & 3 deletions boa_engine/src/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,6 @@ impl Script {

// TODO: Here should be https://tc39.es/ecma262/#sec-globaldeclarationinstantiation

// Push return value.
context.vm.push(JsValue::undefined());

self.realm().resize_global_env();
let record = context.run();
context.vm.pop_frame();
Expand Down
6 changes: 0 additions & 6 deletions boa_engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,9 +1241,6 @@ impl JsObject {

context.vm.push_frame(frame);

// Push return value.
context.vm.push(JsValue::undefined());

// Push function arguments to the stack.
for _ in argument_count..parameters_count {
context.vm.push(JsValue::undefined());
Expand Down Expand Up @@ -1443,9 +1440,6 @@ impl JsObject {
.with_env_fp(environments_len as u32),
);

// Push return value.
context.vm.push(JsValue::undefined());

// Push function arguments to the stack.
for _ in argument_count..parameters_count {
context.vm.push(JsValue::undefined());
Expand Down
10 changes: 5 additions & 5 deletions boa_engine/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ mod tests;
pub struct Vm {
pub(crate) frames: Vec<CallFrame>,
pub(crate) stack: Vec<JsValue>,
pub(crate) return_value: JsValue,

/// When an error is thrown, the pending exception is set.
///
Expand Down Expand Up @@ -94,6 +95,7 @@ impl Vm {
Self {
frames: Vec::with_capacity(16),
stack: Vec::with_capacity(1024),
return_value: JsValue::undefined(),
environments: EnvironmentStack::new(global),
pending_exception: None,
runtime_limits: RuntimeLimits::default(),
Expand Down Expand Up @@ -183,13 +185,11 @@ impl Vm {
}

pub(crate) fn get_return_value(&self) -> JsValue {
let fp = self.frame().fp;
self.stack[fp as usize].clone()
self.return_value.clone()
}

pub(crate) fn set_return_value(&mut self, value: JsValue) {
let fp = self.frame().fp;
self.stack[fp as usize] = value;
self.return_value = value;
}
}

Expand Down Expand Up @@ -338,8 +338,8 @@ impl Context<'_> {
match result {
Ok(CompletionType::Normal) => {}
Ok(CompletionType::Return) => {
let execution_result = self.vm.get_return_value();
self.vm.stack.truncate(self.vm.frame().fp as usize);
let execution_result = std::mem::take(&mut self.vm.return_value);
return CompletionRecord::Normal(execution_result);
}
Ok(CompletionType::Throw) => {
Expand Down

0 comments on commit facc473

Please sign in to comment.