Skip to content

Commit

Permalink
Adjust compile and execute to avoid clones (#1778)
Browse files Browse the repository at this point in the history
It changes the following:

- Adjust the `context` methods `compile` and `execute` to avoid clones on `StatementList` and `CodeBlock`



Co-authored-by: raskad <32105367+raskad@users.noreply.github.com>
  • Loading branch information
Razican and raskad committed Jan 23, 2022
1 parent 48185f3 commit 80794e5
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 12 deletions.
8 changes: 4 additions & 4 deletions boa/benches/full.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ macro_rules! full_benchmarks {
let statement_list = Parser::new(CODE.as_bytes(), false).parse_all( &mut interner).expect("parsing failed");
c.bench_function(concat!($id, " (Compiler)"), move |b| {
b.iter(|| {
Context::compile(black_box(statement_list.clone()));
Context::compile(black_box(&statement_list));
})
});
}
Expand All @@ -47,9 +47,9 @@ macro_rules! full_benchmarks {
{
static CODE: &str = include_str!(concat!("bench_scripts/", stringify!($name), ".js"));
let mut interner = Interner::new();
let statement_list = Parser::new(CODE.as_bytes(), false).parse_all( &mut interner).expect("parsing failed");
let code_block = Context::compile(statement_list);
let mut context = Context::default();
let statement_list = Parser::new(CODE.as_bytes(), false).parse_all(&mut interner).expect("parsing failed");
let mut context = Context::new(interner);
let code_block = Context::compile(&statement_list);
c.bench_function(concat!($id, " (Execution)"), move |b| {
b.iter(|| {
context.execute(black_box(code_block.clone())).unwrap();
Expand Down
21 changes: 13 additions & 8 deletions boa/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ impl Context {
Err(e) => return self.throw_syntax_error(e),
};

let code_block = Context::compile(statement_list);
let code_block = Context::compile(&statement_list);
let result = self.execute(code_block);

// The main_timer needs to be dropped before the BoaProfiler is.
Expand All @@ -905,24 +905,29 @@ impl Context {
result
}

// Compile the AST into a CodeBlock ready to execute by the VM
/// Compile the AST into a `CodeBlock` ready to be executed by the VM.
#[inline]
pub fn compile(statement_list: StatementList) -> CodeBlock {
pub fn compile(statement_list: &StatementList) -> Gc<CodeBlock> {
let _ = BoaProfiler::global().start_event("Compilation", "Main");
let mut compiler = ByteCompiler::new(JsString::new("<main>"), statement_list.strict());
compiler.compile_statement_list(&statement_list, true);
compiler.finish()
compiler.compile_statement_list(statement_list, true);
Gc::new(compiler.finish())
}

// Call the VM with the codeblock and return the result
/// Call the VM with a `CodeBlock` and return the result.
///
/// Since this function receives a `Gc<CodeBlock>`, cloning the code is very cheap, since it's
/// just a pointer copy. Therefore, if you'd like to execute the same `CodeBlock` multiple
/// times, there is no need to re-compile it, and you can just call `clone()` on the
/// `Gc<CodeBlock>` returned by the [`Self::compile()`] function.
#[inline]
pub fn execute(&mut self, code_block: CodeBlock) -> JsResult<JsValue> {
pub fn execute(&mut self, code_block: Gc<CodeBlock>) -> JsResult<JsValue> {
let _ = BoaProfiler::global().start_event("Execute", "Main");
let global_object = self.global_object().into();

self.vm.push_frame(CallFrame {
prev: None,
code: Gc::new(code_block),
code: code_block,
this: global_object,
pc: 0,
catch: Vec::new(),
Expand Down

0 comments on commit 80794e5

Please sign in to comment.