Skip to content

Instantly share code, notes, and snippets.

@dherman
Last active May 7, 2018 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dherman/b15a1a5b37963bd9bb15d9eb6b151a5e to your computer and use it in GitHub Desktop.
Save dherman/b15a1a5b37963bd9bb15d9eb6b151a5e to your computer and use it in GitHub Desktop.
a few variations on VM 2.0
// VARIANT A: SINGLE VM TRAIT WITH "VM" CONVENTION
// trait Vm<'a>: a context-sensitive view into the VM
// - Call<'a> impl Vm<'a>
// - MethodCall<'a, C: Class> impl Vm<'a>
// - ModuleInit<'a> impl Vm<'a>
// convention: name the Call `vm`
// all APIs that call into JS take an &mut impl Vm
// example:
fn f(mut vm: Call) -> JsResult<JsNumber> {
// note that `vm.argument(...)` reads weird
let b: Handle<JsArrayBuffer> = vm.argument(0)?;
let o1: Handle<JsObject> = vm.argument(1)?;
let o2: Handle<JsObject> = o1.get(vm, "foobar")?;
let x: u32 = {
let guard = vm.lock();
let data = b.borrow(&guard);
let slice = data.as_slice();
slice[0]
};
let y: Handle<JsNumber> = o2.get(vm, "quux")?;
vm.number((x + (y as u32)) as f64)
}
// VARIANT B: SINGLE VM TRAIT WITH "CX" CONVENTION
// trait Vm<'a>: a context-sensitive view into the VM
// - Call<'a> impl Vm<'a>
// - MethodCall<'a, C: Class> impl Vm<'a>
// - ModuleInit<'a> impl Vm<'a>
// convention: name the Call `cx`
// all APIs that call into JS take an &mut impl Vm
// example:
fn f(mut cx: Call) -> JsResult<JsNumber> {
let b: Handle<JsArrayBuffer> = cx.argument(0)?;
let o1: Handle<JsObject> = cx.argument(1)?;
// note that this loses the nice "model mutable access to the JS VM" property
let o2: Handle<JsObject> = o1.get(cx, "foobar")?;
let x: u32 = {
let guard = cx.lock_vm();
let data = b.borrow(&guard);
let slice = data.as_slice();
slice[0]
};
let y: Handle<JsNumber> = o2.get(cx, "quux")?;
cx.number((x + (y as u32)) as f64)
}
// VARIANT C: SEPARATE VM AND CONTEXT APIS WITH &MUT VM
// trait VmContext<'a>: a particular execution context in the VM
// - Call<'a> impl VmContext<'a>
// - MethodCall<'a, C: Class> impl VmContext<'a>
// - ModuleInit<'a> impl VmContext<'a>
// struct Vm<'a>: a context-sensitive view into the VM
// convention: name the Call `call`
// all APIs that call into JS take an &mut impl Vm
// the context hands you an &mut Vm when you call `cx.vm()`
// example:
fn f(mut call: Call) -> JsResult<JsNumber> {
let b: Handle<JsArrayBuffer> = call.argument(0)?;
let o1: Handle<JsObject> = call.argument(1)?;
// notice that this makes `call` inaccessible so in practice it's the last thing you do with `call`
let vm = call.vm();
let o2: Handle<JsObject> = o1.get(vm, "foobar")?;
let x: u32 = {
let guard = vm.lock();
let data = b.borrow(&guard);
let slice = data.as_slice();
slice[0]
};
let y: Handle<JsNumber> = o2.get(vm, "quux")?;
vm.number((x + (y as u32)) as f64)
}
// VARIANT C: SEPARATE VM AND CONTEXT APIS WITH TRANSFER TO VM
// trait VmContext<'a>: a particular execution context in the VM
// - Call<'a> impl VmContext<'a>
// - MethodCall<'a, C: Class> impl VmContext<'a>
// - ModuleInit<'a> impl VmContext<'a>
// struct Vm<'a>: a context-sensitive view into the VM
// convention: name the Call `call`
// all APIs that call into JS take an &mut impl Vm
// the context hands you an &mut Vm when you call `cx.vm()`
// example:
fn f(call: Call) -> JsResult<JsNumber> {
let b: Handle<JsArrayBuffer> = call.argument(0)?;
let o1: Handle<JsObject> = call.argument(1)?;
let mut vm = call.into_vm();
let o2: Handle<JsObject> = o1.get(&mut vm, "foobar")?;
let x: u32 = {
let guard = vm.lock();
let data = b.borrow(&guard);
let slice = data.as_slice();
slice[0]
};
let y: Handle<JsNumber> = o2.get(&mut vm, "quux")?;
vm.number((x + (y as u32)) as f64)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment