-
Notifications
You must be signed in to change notification settings - Fork 22
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
feat: engine setup #24
Closed
Closed
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
3cc32c0
feat: engine setup
sno2 d1051f6
fix small string
sno2 b60617c
fix small string
sno2 25fddb8
fix small integer
sno2 b3b8105
more work
sno2 ec23e92
little empty string bonus
sno2 3705170
bank error in your favor. inherit $500
sno2 8e0b959
press CTRL+S to save
sno2 9af1511
get builtin flow working mid
sno2 a88e528
pattern-based equality
sno2 a7c9c7f
fix invalid truncating stuff
sno2 2bb7b94
checkpoint
sno2 a5bdae9
some work
sno2 ed2074a
more work towards builtins
sno2 8af1702
make intrinsics const functions
sno2 a50451b
remove double Option
sno2 61779ab
adjust for larger small bigint range
sno2 c03675a
update oxc deps
sno2 3ff1a73
update to stable and fix cli
sno2 a9b63f3
fmt
sno2 7a32683
i guess cargo fmt doesnt work
sno2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
mod array; | ||
mod builtin_function; | ||
|
||
pub use builtin_function::{ | ||
create_builtin_function, ArgumentsList, Behaviour, Builtin, BuiltinFunctionArgs, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
use super::{create_builtin_function, ArgumentsList, Behaviour, Builtin, BuiltinFunctionArgs}; | ||
use crate::{ | ||
execution::{Agent, JsResult, Realm}, | ||
types::{Object, Value}, | ||
}; | ||
|
||
struct ArrayConstructor; | ||
|
||
impl Builtin for ArrayConstructor { | ||
fn create(realm: &mut Realm) -> Object { | ||
let object = create_builtin_function( | ||
&mut realm.agent.clone().borrow_mut(), | ||
Behaviour::Regular(Self::behaviour), | ||
BuiltinFunctionArgs::new(1, "Array", realm), | ||
); | ||
|
||
object | ||
} | ||
} | ||
|
||
impl ArrayConstructor { | ||
fn behaviour(agent: &mut Agent, value: Value, arguments: ArgumentsList) -> JsResult<Value> { | ||
todo!(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
use crate::{ | ||
execution::{Agent, JsResult, Realm}, | ||
types::{Object, Value}, | ||
}; | ||
|
||
#[derive(Debug)] | ||
pub struct ArgumentsList; | ||
|
||
type RegularFn = fn(&mut Agent, Value, ArgumentsList) -> JsResult<Value>; | ||
type ConstructorFn = fn(&mut Agent, Value, ArgumentsList, Option<Object>) -> JsResult<Value>; | ||
|
||
#[derive(Debug)] | ||
pub enum Behaviour { | ||
Regular(RegularFn), | ||
Constructor(ConstructorFn), | ||
} | ||
|
||
pub trait Builtin { | ||
fn create(realm: &mut Realm) -> Object; | ||
} | ||
|
||
#[derive(Debug, Default)] | ||
pub struct BuiltinFunctionArgs<'a, 'ctx, 'host> { | ||
pub length: u32, | ||
pub name: &'static str, | ||
pub realm: Option<&'a mut Realm<'ctx, 'host>>, | ||
pub prototype: Option<Object>, | ||
pub prefix: Option<Object>, | ||
} | ||
|
||
impl<'a, 'ctx, 'host: 'ctx> BuiltinFunctionArgs<'a, 'ctx, 'host> { | ||
pub fn new(length: u32, name: &'static str, realm: &'a mut Realm<'ctx, 'host>) -> Self { | ||
Self { | ||
length, | ||
name, | ||
realm: Some(realm), | ||
..Default::default() | ||
} | ||
} | ||
} | ||
|
||
/// 10.3.3 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] ) | ||
/// https://tc39.es/ecma262/#sec-createbuiltinfunction | ||
pub fn create_builtin_function<'ctx, 'host: 'ctx>( | ||
agent: &mut Agent<'ctx, 'host>, | ||
behaviour: Behaviour, | ||
args: BuiltinFunctionArgs<'_, 'ctx, 'host>, | ||
) -> Object { | ||
// 1. If realm is not present, set realm to the current Realm Record. | ||
let realm = args.realm.unwrap(); // TODO: load record | ||
|
||
// 2. If prototype is not present, set prototype to realm.[[Intrinsics]].[[%Function.prototype%]]. | ||
let prototype = args | ||
.prototype | ||
.unwrap_or_else(|| realm.intrinsics.function_prototype()); | ||
|
||
// 3. Let internalSlotsList be a List containing the names of all the internal slots that 10.3 | ||
// requires for the built-in function object that is about to be created. | ||
// 4. Append to internalSlotsList the elements of additionalInternalSlotsList. | ||
|
||
// 5. Let func be a new built-in function object that, when called, performs the action | ||
// described by behaviour using the provided arguments as the values of the corresponding | ||
// parameters specified by behaviour. The new function object has internal slots whose names | ||
// are the elements of internalSlotsList, and an [[InitialName]] internal slot. | ||
|
||
// 10. Perform SetFunctionLength(func, length). | ||
|
||
// 11. If prefix is not present, then | ||
// a. Perform SetFunctionName(func, name). | ||
// 12. Else, | ||
// a. Perform SetFunctionName(func, name, prefix). | ||
|
||
// 13. Return func. | ||
todo!(); | ||
} | ||
|
||
pub fn define_builtin_function<'ctx, 'host: 'ctx>( | ||
object: Object, | ||
name: &'static str, | ||
behaviour: RegularFn, | ||
length: u32, | ||
realm: &'ctx mut Realm<'ctx, 'host>, | ||
) { | ||
let agent_mut = realm.agent.clone(); | ||
let mut agent = agent_mut.borrow_mut(); | ||
|
||
let function = create_builtin_function( | ||
&mut agent, | ||
Behaviour::Regular(behaviour), | ||
BuiltinFunctionArgs::new(length, name, realm), | ||
); | ||
|
||
define_builtin_property(object, name, Value::from(function)); | ||
} | ||
|
||
pub fn define_builtin_property(object: Object, name: &'static str, value: Value) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
pub mod agent; | ||
mod default_host_hooks; | ||
mod environments; | ||
mod execution_context; | ||
mod realm; | ||
|
||
pub use agent::{Agent, JsResult}; | ||
pub use environments::{ | ||
DeclarativeEnvironment, Environment, FunctionEnvironment, GlobalEnvironment, ObjectEnvironment, | ||
PrivateEnvironment, | ||
}; | ||
pub use execution_context::{ECMAScriptCode, ExecutionContext, ScriptOrModule}; | ||
pub use realm::Realm; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
use super::{ExecutionContext, Realm}; | ||
use crate::{ | ||
types::{Object, Symbol, Value}, | ||
Heap, | ||
}; | ||
use std::collections::HashMap; | ||
|
||
#[derive(Debug, Default)] | ||
pub struct Options { | ||
pub disable_gc: bool, | ||
pub print_ast: bool, | ||
pub print_bytecode: bool, | ||
} | ||
|
||
pub type JsResult<T> = std::result::Result<T, ()>; | ||
|
||
// #[derive(Debug)] | ||
// pub struct PreAllocated; | ||
|
||
#[derive(Debug)] | ||
pub struct HostHooks { | ||
pub host_ensure_can_compile_strings: fn(callee_realm: &mut Realm) -> JsResult<()>, | ||
pub host_has_source_text_available: fn(func: Object) -> bool, | ||
} | ||
|
||
/// 9.7 Agents | ||
/// https://tc39.es/ecma262/#sec-agents | ||
#[derive(Debug)] | ||
pub struct Agent<'ctx, 'host> { | ||
pub heap: Heap, | ||
pub options: Options, | ||
// pre_allocated: PreAllocated, | ||
pub exception: Option<Value>, | ||
pub symbol_id: usize, | ||
pub global_symbol_registry: HashMap<&'static str, Symbol>, | ||
pub host_hooks: HostHooks, | ||
pub execution_context_stack: Vec<ExecutionContext<'ctx, 'host>>, | ||
} | ||
|
||
impl Agent<'_, '_> { | ||
pub fn current_realm(&self) -> &mut Realm { | ||
todo!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use super::{JsResult, Realm}; | ||
use crate::types::Object; | ||
|
||
/// 19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm ) | ||
/// https://tc39.es/ecma262/#sec-hostensurecancompilestrings | ||
pub fn host_ensure_can_compile_strings(_: &mut Realm) -> JsResult<()> { | ||
Ok(()) | ||
} | ||
|
||
/// 20.2.5 HostHasSourceTextAvailable ( func ) | ||
/// https://tc39.es/ecma262/#sec-hosthassourcetextavailable | ||
pub fn host_has_source_text_available(_: Object) -> bool { | ||
// The default implementation of HostHasSourceTextAvailable is to return true. | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
//! 9.1 Environment Records | ||
//! https://tc39.es/ecma262/#sec-environment-records | ||
|
||
pub mod declarative_environment; | ||
pub mod function_environment; | ||
pub mod global_environment; | ||
pub mod object_environment; | ||
pub mod private_environment; | ||
|
||
pub use declarative_environment::DeclarativeEnvironment; | ||
pub use function_environment::FunctionEnvironment; | ||
pub use global_environment::GlobalEnvironment; | ||
pub use object_environment::ObjectEnvironment; | ||
pub use private_environment::PrivateEnvironment; | ||
use std::{cell::RefCell, rc::Rc}; | ||
|
||
/// 9.1.1 The Environment Record Type Hierarchy | ||
/// https://tc39.es/ecma262/#sec-the-environment-record-type-hierarchy | ||
#[derive(Debug)] | ||
pub enum Environment { | ||
DeclarativeEnvironment(Rc<RefCell<DeclarativeEnvironment>>), | ||
ObjectEnvironment(Rc<RefCell<ObjectEnvironment>>), | ||
FunctionEnvironment(Rc<RefCell<FunctionEnvironment>>), | ||
GlobalEnvironment(Rc<RefCell<GlobalEnvironment>>), | ||
} |
29 changes: 29 additions & 0 deletions
29
nova_vm/src/execution/environments/declarative_environment.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use super::Environment; | ||
use crate::types::Value; | ||
use std::collections::HashMap; | ||
|
||
/// 9.1.1.1 Declarative Environment Records | ||
/// https://tc39.es/ecma262/#sec-declarative-environment-records | ||
#[derive(Debug)] | ||
pub struct DeclarativeEnvironment { | ||
pub outer_env: Option<Environment>, | ||
pub bindings: HashMap<&'static str, Binding>, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct Binding { | ||
pub value: Option<Value>, | ||
pub strict: bool, | ||
pub mutable: bool, | ||
pub deletable: bool, | ||
} | ||
|
||
impl DeclarativeEnvironment { | ||
/// 9.1.1.1.1 HasBinding ( N ) | ||
/// https://tc39.es/ecma262/#sec-declarative-environment-records-hasbinding-n | ||
pub fn has_binding(self, name: &str) -> bool { | ||
// 1. If envRec has a binding for N, return true. | ||
// 2. Return false. | ||
return self.bindings.contains_key(name); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
nova_vm/src/execution/environments/function_environment.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use super::{DeclarativeEnvironment, Environment}; | ||
use crate::types::Value; | ||
use std::{cell::RefCell, rc::Rc}; | ||
|
||
#[derive(Debug)] | ||
pub enum ThisBindingStatus { | ||
Lexical, | ||
Initialized, | ||
Uninitialized, | ||
} | ||
|
||
#[derive(Debug)] | ||
struct ECMAScriptFunction; | ||
|
||
/// 9.1.1.3 Function Environment Records | ||
/// https://tc39.es/ecma262/#sec-function-environment-records | ||
#[derive(Debug)] | ||
pub struct FunctionEnvironment { | ||
/// [[ThisValue]] | ||
this_value: Value, | ||
|
||
/// [[ThisBindingStatus]] | ||
this_binding_status: ThisBindingStatus, | ||
|
||
/// [[FunctionObject]] | ||
function_object: ECMAScriptFunction, | ||
|
||
/// [[NewTarget]] | ||
new_target: Option<Value>, | ||
|
||
/// [[OuterEnv]] | ||
outer_env: Option<Environment>, | ||
|
||
// NOTE: This is how we implement the spec's inheritance of function | ||
// environments. | ||
declarative_environment: Rc<RefCell<DeclarativeEnvironment>>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
use super::{DeclarativeEnvironment, Environment, ObjectEnvironment}; | ||
use crate::types::Object; | ||
use std::{cell::RefCell, collections::HashMap, rc::Rc}; | ||
|
||
/// 9.1.1.4 Global Environment Records | ||
/// https://tc39.es/ecma262/#sec-global-environment-records | ||
#[derive(Debug)] | ||
pub struct GlobalEnvironment { | ||
// [[ObjectRecord]] | ||
object_record: Rc<RefCell<ObjectEnvironment>>, | ||
|
||
/// [[GlobalThisValue]] | ||
global_this_value: Object, | ||
|
||
/// [[DeclarativeRecord]] | ||
declarative_record: Rc<RefCell<DeclarativeEnvironment>>, | ||
|
||
/// [[VarNames]] | ||
var_names: HashMap<&'static str, ()>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Use a vector. |
||
|
||
/// [[OuterEnv]] | ||
outer_env: Option<Environment>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use super::Environment; | ||
use crate::types::Object; | ||
|
||
/// 9.1.1.2 Object Environment Records | ||
/// https://tc39.es/ecma262/#sec-object-environment-records | ||
#[derive(Debug)] | ||
pub struct ObjectEnvironment { | ||
/// [[BindingObject]] | ||
binding_object: Object, | ||
|
||
/// [[IsWithEnvironment]] | ||
is_with_environment: bool, | ||
|
||
/// [[OuterEnv]] | ||
outer_env: Option<Environment>, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use std::{cell::RefCell, collections::HashMap, rc::Rc}; | ||
|
||
/// 9.2 PrivateEnvironment Records | ||
/// https://tc39.es/ecma262/#sec-privateenvironment-records | ||
#[derive(Debug)] | ||
pub struct PrivateEnvironment { | ||
/// [[OuterPrivateEnvironment]] | ||
outer_private_environment: Option<Rc<RefCell<PrivateEnvironment>>>, | ||
|
||
/// [[Names]] | ||
names: HashMap<&'static str, ()>, // TODO: Implement private names | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment: I think the keys may benefit from being
Value::String
s. After all, often a binding key will also find its way into a map key etc.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: I'd actually personally probably set these up as ParallelVecs with one Vec for keys, one Vec for values and then probably one for the rest. It's quite possible that we end up with better perf iterating through a vector of keys than hopping through a HashMap linked list. This especially so since the iteration will likely be aggressively unrolled and SIMD'd.
And the reason for separating keys from values is that usually we're looking for a single item by key: If we iterate key-value pairs then all but once the value bytes are entirely wasted and we waste cache line space. Only once do we actually hit the right key and we know where we hit it by our iteration index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice suggestion. I had added the
&'static str
to avoid lifetimes while copying the spec entities but this would be better. Will work on implementing this.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
ParallelVec
s in question should be sorted, and all code should appropriately use logarithmic lookups (stdlib has us covered here with slice methods).If we're to do away with
HashMap
s entirely for some parts of the code*, we should have a generic type built onParallelVec
for reuse.* There are other hash map types and algorithms and allocator configurations? Maybe those would be more suitible? A
HashMap
in an arena allocator for example. I believe there are already libraries for this.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or BTrees? https://doc.rust-lang.org/std/collections/struct.BTreeMap.html