Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Adjust compile and execute to avoid clones #1778

Closed
wants to merge 3 commits into from
Closed
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
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