Skip to content

Commit

Permalink
Context independent CodeBlocks
Browse files Browse the repository at this point in the history
This allows us to share `CodeBlock`s between `Context`, which makes
functions sharable between `Context`s.
  • Loading branch information
HalidOdat committed Nov 10, 2023
1 parent baa4f98 commit eeecbfc
Show file tree
Hide file tree
Showing 38 changed files with 703 additions and 570 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion boa_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ rust-version.workspace = true
boa_engine = { workspace = true, features = ["deser", "flowgraph", "trace"] }
boa_parser.workspace = true
boa_gc.workspace = true
boa_interner.workspace = true
boa_runtime.workspace = true
rustyline = { version = "12.0.0", features = ["derive"]}
clap = { workspace = true, features = ["derive"] }
Expand Down
7 changes: 3 additions & 4 deletions boa_cli/src/debug/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use boa_engine::{
vm::flowgraph::{Direction, Graph},
Context, JsArgs, JsNativeError, JsObject, JsResult, JsValue, NativeFunction,
};
use boa_interner::ToInternedString;

use crate::FlowgraphFormat;

Expand Down Expand Up @@ -92,7 +91,7 @@ fn flowgraph(_this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResu
let code = function.codeblock();

let mut graph = Graph::new(direction);
code.to_graph(context.interner(), graph.subgraph(String::default()));
code.to_graph(graph.subgraph(String::default()));
let result = match format {
FlowgraphFormat::Graphviz => graph.to_graphviz_format(),
FlowgraphFormat::Mermaid => graph.to_mermaid_format(),
Expand All @@ -101,7 +100,7 @@ fn flowgraph(_this: &JsValue, args: &[JsValue], context: &mut Context) -> JsResu
Ok(JsValue::new(js_string!(result)))
}

fn bytecode(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
fn bytecode(_: &JsValue, args: &[JsValue], _: &mut Context) -> JsResult<JsValue> {
let Some(value) = args.get(0) else {
return Err(JsNativeError::typ()
.with_message("expected function argument")
Expand All @@ -121,7 +120,7 @@ fn bytecode(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<Js
};
let code = function.codeblock();

Ok(js_string!(code.to_interned_string(context.interner())).into())
Ok(js_string!(code.to_string()).into())
}

fn set_trace_flag_in_function_object(object: &JsObject, value: bool) -> JsResult<()> {
Expand Down
2 changes: 1 addition & 1 deletion boa_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn generate_flowgraph(
};

let mut graph = Graph::new(direction);
code.to_graph(context.interner(), graph.subgraph(String::default()));
code.to_graph(graph.subgraph(String::default()));
let result = match format {
FlowgraphFormat::Graphviz => graph.to_graphviz_format(),
FlowgraphFormat::Mermaid => graph.to_mermaid_format(),
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

use crate::{
builtins::BuiltInObject,
bytecompiler::ByteCompiler,
bytecompiler::{ByteCompiler, ToJsString},
context::intrinsics::Intrinsics,
environments::Environment,
error::JsNativeError,
Expand Down Expand Up @@ -228,7 +228,7 @@ impl Eval {
let mut var_env = var_environment.compile_env();

let mut compiler = ByteCompiler::new(
Sym::MAIN,
Sym::MAIN.to_js_string(context.interner()),
body.strict(),
false,
var_env.clone(),
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

use crate::{
builtins::{BuiltInBuilder, BuiltInConstructor, BuiltInObject, IntrinsicObject},
bytecompiler::FunctionCompiler,
bytecompiler::{FunctionCompiler, ToJsString},
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
environments::{EnvironmentStack, PrivateEnvironment},
error::JsNativeError,
Expand Down Expand Up @@ -557,7 +557,7 @@ impl BuiltInFunctionObject {
};

let code = FunctionCompiler::new()
.name(Sym::ANONYMOUS)
.name(Sym::ANONYMOUS.to_js_string(context.interner()))
.generator(generator)
.r#async(r#async)
.compile(
Expand Down
4 changes: 2 additions & 2 deletions boa_engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use itertools::Itertools;

use crate::{
builtins::BuiltInObject,
bytecompiler::ByteCompiler,
bytecompiler::{ByteCompiler, ToJsString},
context::intrinsics::Intrinsics,
error::JsNativeError,
js_string,
Expand Down Expand Up @@ -114,7 +114,7 @@ impl Json {
let script = parser.parse_script(context.interner_mut())?;
let code_block = {
let mut compiler = ByteCompiler::new(
Sym::MAIN,
Sym::MAIN.to_js_string(context.interner()),
script.strict(),
true,
context.realm().environment().compile_env(),
Expand Down
47 changes: 26 additions & 21 deletions boa_engine/src/bytecompiler/class.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::{ByteCompiler, Literal, Operand};
use crate::vm::{BindingOpcode, CodeBlock, CodeBlockFlags, Opcode};
use super::{ByteCompiler, Literal, Operand, ToJsString};
use crate::{
js_string,
vm::{BindingOpcode, CodeBlock, CodeBlockFlags, Opcode},
};
use boa_ast::{
expression::Identifier,
function::{Class, ClassElement, FormalParameterList},
Expand Down Expand Up @@ -29,22 +32,24 @@ impl ByteCompiler<'_> {
let strict = self.strict();
self.code_block_flags |= CodeBlockFlags::STRICT;

let class_name = class.name().map_or(Sym::EMPTY_STRING, Identifier::sym);

let old_lex_env = match class.name() {
Some(name) if class.has_binding_identifier() => {
let old_lex_env = self.lexical_environment.clone();
let env_index = self.push_compile_environment(false);
self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
self.lexical_environment
.create_immutable_binding(name, true);
Some(old_lex_env)
}
_ => None,
let class_name = class
.name()
.map_or(Sym::EMPTY_STRING, Identifier::sym)
.to_js_string(self.interner());

let old_lex_env = if class.has_binding_identifier() {
let old_lex_env = self.lexical_environment.clone();
let env_index = self.push_compile_environment(false);
self.emit_with_varying_operand(Opcode::PushDeclarativeEnvironment, env_index);
self.lexical_environment
.create_immutable_binding(class_name.clone(), true);
Some(old_lex_env)
} else {
None
};

let mut compiler = ByteCompiler::new(
class_name,
class_name.clone(),
true,
self.json_parse,
self.variable_environment.clone(),
Expand Down Expand Up @@ -122,7 +127,7 @@ impl ByteCompiler<'_> {

if old_lex_env.is_some() {
self.emit_opcode(Opcode::Dup);
self.emit_binding(BindingOpcode::InitLexical, class_name.into());
self.emit_binding(BindingOpcode::InitLexical, class_name.clone());
}

// TODO: set function name for getter and setters
Expand Down Expand Up @@ -277,7 +282,7 @@ impl ByteCompiler<'_> {
}
}
let mut field_compiler = ByteCompiler::new(
Sym::EMPTY_STRING,
js_string!(),
true,
self.json_parse,
self.variable_environment.clone(),
Expand Down Expand Up @@ -305,7 +310,7 @@ impl ByteCompiler<'_> {
self.emit_opcode(Opcode::Dup);
let name_index = self.get_or_insert_private_name(*name);
let mut field_compiler = ByteCompiler::new(
class_name,
class_name.clone(),
true,
self.json_parse,
self.variable_environment.clone(),
Expand Down Expand Up @@ -343,7 +348,7 @@ impl ByteCompiler<'_> {
}
};
let mut field_compiler = ByteCompiler::new(
class_name,
class_name.clone(),
true,
self.json_parse,
self.variable_environment.clone(),
Expand Down Expand Up @@ -377,7 +382,7 @@ impl ByteCompiler<'_> {
}
ClassElement::StaticBlock(body) => {
let mut compiler = ByteCompiler::new(
Sym::EMPTY_STRING,
Sym::EMPTY_STRING.to_js_string(self.interner()),
true,
false,
self.variable_environment.clone(),
Expand Down Expand Up @@ -580,7 +585,7 @@ impl ByteCompiler<'_> {
self.emit_opcode(Opcode::PopPrivateEnvironment);

if !expression {
self.emit_binding(BindingOpcode::InitVar, class_name.into());
self.emit_binding(BindingOpcode::InitVar, class_name);
}

// NOTE: Reset strict mode to before class declaration/expression evalutation.
Expand Down
10 changes: 5 additions & 5 deletions boa_engine/src/bytecompiler/declaration/declaration_pattern.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
bytecompiler::{Access, ByteCompiler, Literal, Operand},
bytecompiler::{Access, ByteCompiler, Literal, Operand, ToJsString},
vm::{BindingOpcode, Opcode},
};
use boa_ast::{
Expand Down Expand Up @@ -61,7 +61,7 @@ impl ByteCompiler<'_> {
self.compile_expr(init, true);
self.patch_jump(skip);
}
self.emit_binding(def, *ident);
self.emit_binding(def, ident.to_js_string(self.interner()));

if rest_exits && name.computed().is_some() {
self.emit_opcode(Opcode::Swap);
Expand All @@ -88,7 +88,7 @@ impl ByteCompiler<'_> {
Operand::Varying(additional_excluded_keys_count),
],
);
self.emit_binding(def, *ident);
self.emit_binding(def, ident.to_js_string(self.interner()));
}
AssignmentRestPropertyAccess {
access,
Expand Down Expand Up @@ -250,7 +250,7 @@ impl ByteCompiler<'_> {
self.compile_expr(init, true);
self.patch_jump(skip);
}
self.emit_binding(def, *ident);
self.emit_binding(def, ident.to_js_string(self.interner()));
}
PropertyAccess { access } => {
self.access_set(Access::Property { access }, false, |compiler, _level| {
Expand All @@ -277,7 +277,7 @@ impl ByteCompiler<'_> {
// BindingRestElement : ... BindingIdentifier
SingleNameRest { ident } => {
self.emit_opcode(Opcode::IteratorToArray);
self.emit_binding(def, *ident);
self.emit_binding(def, ident.to_js_string(self.interner()));
}
PropertyAccessRest { access } => {
self.access_set(Access::Property { access }, false, |compiler, _level| {
Expand Down
Loading

0 comments on commit eeecbfc

Please sign in to comment.