Skip to content

Commit

Permalink
WIP Register VM
Browse files Browse the repository at this point in the history
- Add todo for storing fp in CallFrame
- Start on moving to register VM
- Add more binary ops
- Add helpter transition methods
- Register based logical ops
- Register InPrivate
- Register GetFunction
- Some class opcodes
- Register post and pre increment and decrement
  • Loading branch information
HalidOdat committed Jul 5, 2024
1 parent 961d7b4 commit 1e0bf01
Show file tree
Hide file tree
Showing 37 changed files with 2,124 additions and 620 deletions.
2 changes: 1 addition & 1 deletion core/engine/src/builtins/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ impl Array {
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-createarrayfromlist
pub(crate) fn create_array_from_list<I>(elements: I, context: &mut Context) -> JsObject
pub(crate) fn create_array_from_list<I>(elements: I, context: &Context) -> JsObject
where
I: IntoIterator<Item = JsValue>,
{
Expand Down
2 changes: 2 additions & 0 deletions core/engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ impl Eval {
false,
var_env.clone(),
lex_env.clone(),
false,
false,
context.interner_mut(),
in_with,
);
Expand Down
2 changes: 2 additions & 0 deletions core/engine/src/builtins/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ impl Json {
true,
context.realm().environment().compile_env(),
context.realm().environment().compile_env(),
false,
false,
context.interner_mut(),
in_with,
);
Expand Down
86 changes: 70 additions & 16 deletions core/engine/src/bytecompiler/class.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{ByteCompiler, Literal, Operand, ToJsString};
use super::{ByteCompiler, InstructionOperand, Literal, Operand, Operand2, ToJsString};
use crate::{
js_string,
vm::{BindingOpcode, CodeBlock, CodeBlockFlags, Opcode},
Expand Down Expand Up @@ -54,6 +54,8 @@ impl ByteCompiler<'_> {
self.json_parse,
self.variable_environment.clone(),
self.lexical_environment.clone(),
false,
false,
self.interner,
self.in_with,
);
Expand Down Expand Up @@ -84,7 +86,7 @@ impl ByteCompiler<'_> {
} else {
compiler.emit_opcode(Opcode::PushUndefined);
}
compiler.emit_opcode(Opcode::SetReturnValue);
compiler.emit_opcode(Opcode::SetAccumulatorFromStack);

// 17. If ClassHeritageopt is present, set F.[[ConstructorKind]] to derived.
compiler.code_block_flags.set(
Expand All @@ -94,19 +96,43 @@ impl ByteCompiler<'_> {

let code = Gc::new(compiler.finish());
let index = self.push_function_to_constants(code);
self.emit_with_varying_operand(Opcode::GetFunction, index);

self.emit_opcode(Opcode::Dup);
let class_register = self.register_allocator.alloc();
self.emit_get_function(&class_register, index);

let prototype_register = self.register_allocator.alloc();

if let Some(node) = class.super_ref() {
self.compile_expr(node, true);
self.emit_opcode(Opcode::PushClassPrototype);
self.pop_into_register(&prototype_register);

self.emit2(
Opcode::PushClassPrototype,
&[
Operand2::Register(&prototype_register),
Operand2::Operand(InstructionOperand::Register(&class_register)),
Operand2::Operand(InstructionOperand::Register(&prototype_register)),
],
);
} else {
self.emit_opcode(Opcode::PushUndefined);
self.pop_into_register(&prototype_register);
}
self.emit_opcode(Opcode::SetClassPrototype);
self.emit_opcode(Opcode::Swap);

let count_label = self.emit_opcode_with_operand(Opcode::PushPrivateEnvironment);
let proto_register = self.register_allocator.alloc();

self.emit2(
Opcode::SetClassPrototype,
&[
Operand2::Register(&proto_register),
Operand2::Operand(InstructionOperand::Register(&prototype_register)),
Operand2::Operand(InstructionOperand::Register(&class_register)),
],
);
self.register_allocator.dealloc(prototype_register);

let count_label =
self.emit_push_private_environment(InstructionOperand::Register(&class_register));
let mut count = 0;
for element in class.elements() {
match element {
Expand All @@ -127,10 +153,16 @@ impl ByteCompiler<'_> {
let mut static_field_name_count = 0;

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

self.push_from_register(&proto_register);
self.push_from_register(&class_register);

self.register_allocator.dealloc(proto_register);
self.register_allocator.dealloc(class_register);

// TODO: set function name for getter and setters
for element in class.elements() {
match element {
Expand Down Expand Up @@ -288,6 +320,8 @@ impl ByteCompiler<'_> {
self.json_parse,
self.variable_environment.clone(),
self.lexical_environment.clone(),
false,
false,
self.interner,
self.in_with,
);
Expand All @@ -299,13 +333,18 @@ impl ByteCompiler<'_> {
} else {
field_compiler.emit_opcode(Opcode::PushUndefined);
}
field_compiler.emit_opcode(Opcode::SetReturnValue);
field_compiler.emit_opcode(Opcode::SetAccumulatorFromStack);

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

let code = Gc::new(field_compiler.finish());
let index = self.push_function_to_constants(code);
self.emit_with_varying_operand(Opcode::GetFunction, index);

let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);

self.emit_opcode(Opcode::PushClassField);
}
ClassElement::PrivateFieldDefinition(name, field) => {
Expand All @@ -317,6 +356,8 @@ impl ByteCompiler<'_> {
self.json_parse,
self.variable_environment.clone(),
self.lexical_environment.clone(),
false,
false,
self.interner,
self.in_with,
);
Expand All @@ -326,13 +367,16 @@ impl ByteCompiler<'_> {
} else {
field_compiler.emit_opcode(Opcode::PushUndefined);
}
field_compiler.emit_opcode(Opcode::SetReturnValue);
field_compiler.emit_opcode(Opcode::SetAccumulatorFromStack);

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

let code = Gc::new(field_compiler.finish());
let index = self.push_function_to_constants(code);
self.emit_with_varying_operand(Opcode::GetFunction, index);
let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);
self.emit_with_varying_operand(Opcode::PushClassFieldPrivate, name_index);
}
ClassElement::StaticFieldDefinition(name, field) => {
Expand All @@ -356,6 +400,8 @@ impl ByteCompiler<'_> {
self.json_parse,
self.variable_environment.clone(),
self.lexical_environment.clone(),
false,
false,
self.interner,
self.in_with,
);
Expand All @@ -365,7 +411,7 @@ impl ByteCompiler<'_> {
} else {
field_compiler.emit_opcode(Opcode::PushUndefined);
}
field_compiler.emit_opcode(Opcode::SetReturnValue);
field_compiler.emit_opcode(Opcode::SetAccumulatorFromStack);

field_compiler.code_block_flags |= CodeBlockFlags::IN_CLASS_FIELD_INITIALIZER;

Expand All @@ -391,6 +437,8 @@ impl ByteCompiler<'_> {
false,
self.variable_environment.clone(),
self.lexical_environment.clone(),
false,
false,
self.interner,
self.in_with,
);
Expand Down Expand Up @@ -555,7 +603,10 @@ impl ByteCompiler<'_> {
StaticElement::StaticBlock(code) => {
self.emit_opcode(Opcode::Dup);
let index = self.push_function_to_constants(code);
self.emit_with_varying_operand(Opcode::GetFunction, index);
let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);
self.emit_opcode(Opcode::SetHomeObject);
self.emit_with_varying_operand(Opcode::Call, 0);
self.emit_opcode(Opcode::Pop);
Expand All @@ -564,7 +615,10 @@ impl ByteCompiler<'_> {
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
let index = self.push_function_to_constants(code);
self.emit_with_varying_operand(Opcode::GetFunction, index);
let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);
self.emit_opcode(Opcode::SetHomeObject);
self.emit_with_varying_operand(Opcode::Call, 0);
if let Some(name_index) = name_index {
Expand Down
17 changes: 13 additions & 4 deletions core/engine/src/bytecompiler/declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,10 +597,13 @@ impl ByteCompiler<'_> {
);

// Ensures global functions are printed when generating the global flowgraph.
let function_index = self.push_function_to_constants(code.clone());
let function_index = self.push_function_to_constants(code);

// b. Let fo be InstantiateFunctionObject of f with arguments env and privateEnv.
self.emit_with_varying_operand(Opcode::GetFunction, function_index);
let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, function_index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);

// c. Perform ? env.CreateGlobalFunctionBinding(fn, fo, false).
let name_index = self.get_or_insert_name(name);
Expand Down Expand Up @@ -971,7 +974,10 @@ impl ByteCompiler<'_> {
let index = self.push_function_to_constants(code.clone());

// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
self.emit_with_varying_operand(Opcode::GetFunction, index);
let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);

// i. Perform ? varEnv.CreateGlobalFunctionBinding(fn, fo, true).
let name_index = self.get_or_insert_name(name);
Expand All @@ -984,7 +990,10 @@ impl ByteCompiler<'_> {
else {
// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
let index = self.push_function_to_constants(code);
self.emit_with_varying_operand(Opcode::GetFunction, index);
let dst = self.register_allocator.alloc();
self.emit_get_function(&dst, index);
self.push_from_register(&dst);
self.register_allocator.dealloc(dst);

let name = name.to_js_string(self.interner());

Expand Down
Loading

0 comments on commit 1e0bf01

Please sign in to comment.