Skip to content

Commit

Permalink
Register post and pre increment and decrement
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat committed Apr 11, 2024
1 parent 0d8b706 commit 7351c87
Show file tree
Hide file tree
Showing 8 changed files with 356 additions and 155 deletions.
234 changes: 180 additions & 54 deletions core/engine/src/bytecompiler/expression/update.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
bytecompiler::{Access, ByteCompiler, Operand, ToJsString},
bytecompiler::{Access, ByteCompiler, Operand2, ToJsString},
environments::BindingLocatorError,
vm::Opcode,
};
Expand All @@ -11,10 +11,8 @@ use boa_ast::expression::{
impl ByteCompiler<'_> {
pub(crate) fn compile_update(&mut self, update: &Update, use_expr: bool) {
let opcode = match update.op() {
UpdateOp::IncrementPre => Opcode::Inc,
UpdateOp::DecrementPre => Opcode::Dec,
UpdateOp::IncrementPost => Opcode::IncPost,
UpdateOp::DecrementPost => Opcode::DecPost,
UpdateOp::IncrementPost | UpdateOp::IncrementPre => Opcode::Inc,
UpdateOp::DecrementPre | UpdateOp::DecrementPost => Opcode::Dec,
};
let post = matches!(
update.op(),
Expand All @@ -35,12 +33,26 @@ impl ByteCompiler<'_> {
self.emit_with_varying_operand(Opcode::GetNameAndLocator, index);
}

self.emit_opcode(opcode);
if post {
self.emit_opcode(Opcode::Swap);
} else {
self.emit_opcode(Opcode::Dup);
}
let src = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();

self.pop_into_register(&src);

self.emit2(
Opcode::ToNumeric,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(src.index()),
],
);
self.emit2(
opcode,
&[
Operand2::Varying(src.index()),
Operand2::Varying(dst.index()),
],
);
self.push_from_register(&src);

if binding.is_lexical() {
match self.lexical_environment.set_mutable_binding(name.clone()) {
Expand All @@ -59,60 +71,134 @@ impl ByteCompiler<'_> {
} else {
self.emit_opcode(Opcode::SetNameByLocator);
}
if post {
self.push_from_register(&dst);
} else {
self.push_from_register(&src);
}

self.register_allocator.dealloc(src);
self.register_allocator.dealloc(dst);
}
Access::Property { access } => match access {
PropertyAccess::Simple(access) => match access.field() {
PropertyAccessField::Const(name) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
PropertyAccess::Simple(access) => {
self.compile_expr(access.target(), true);

self.emit_get_property_by_name(*name);
self.emit_opcode(opcode);
if post {
self.emit(Opcode::RotateRight, &[Operand::U8(4)]);
}
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);

self.emit_set_property_by_name(*name);
if post {
self.emit_opcode(Opcode::Pop);
}
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(access.target(), true);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.emit_opcode(Opcode::Dup);
self.compile_expr(expr, true);
// Stack: value, value, value, value
match access.field() {
PropertyAccessField::Const(name) => {
self.emit_get_property_by_name(*name);

self.emit_opcode(Opcode::GetPropertyByValuePush);
self.emit_opcode(opcode);
if post {
self.emit(Opcode::RotateRight, &[Operand::U8(5)]);
let src = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();
self.pop_into_register(&src);

self.emit2(
Opcode::ToNumeric,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(src.index()),
],
);
self.emit2(
opcode,
&[
Operand2::Varying(src.index()),
Operand2::Varying(dst.index()),
],
);

self.push_from_register(&src);

self.emit_set_property_by_name(*name);

if post {
self.emit_opcode(Opcode::Pop);
self.push_from_register(&dst);
}

self.register_allocator.dealloc(src);
self.register_allocator.dealloc(dst);
}
PropertyAccessField::Expr(expr) => {
self.compile_expr(expr, true);

self.emit_opcode(Opcode::SetPropertyByValue);
if post {
self.emit_opcode(Opcode::Pop);
self.emit_opcode(Opcode::GetPropertyByValuePush);

let src = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();
self.pop_into_register(&src);

self.emit2(
Opcode::ToNumeric,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(src.index()),
],
);
self.emit2(
opcode,
&[
Operand2::Varying(src.index()),
Operand2::Varying(dst.index()),
],
);

self.push_from_register(&src);

self.emit_opcode(Opcode::SetPropertyByValue);

if post {
self.emit_opcode(Opcode::Pop);
self.push_from_register(&dst);
}

self.register_allocator.dealloc(src);
self.register_allocator.dealloc(dst);
}
}
},
}
PropertyAccess::Private(access) => {
let index = self.get_or_insert_private_name(access.field());
self.compile_expr(access.target(), true);

self.emit_opcode(Opcode::Dup);

self.emit_with_varying_operand(Opcode::GetPrivateField, index);
self.emit_opcode(opcode);
if post {
self.emit(Opcode::RotateRight, &[Operand::U8(3)]);
}

let src = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();
self.pop_into_register(&src);

self.emit2(
Opcode::ToNumeric,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(src.index()),
],
);
self.emit2(
opcode,
&[
Operand2::Varying(src.index()),
Operand2::Varying(dst.index()),
],
);

self.push_from_register(&src);

self.emit_with_varying_operand(Opcode::SetPrivateField, index);
if post {
self.emit_opcode(Opcode::Pop);
self.push_from_register(&dst);
}

self.register_allocator.dealloc(src);
self.register_allocator.dealloc(dst);
}
PropertyAccess::Super(access) => match access.field() {
PropertyAccessField::Const(name) => {
Expand All @@ -123,15 +209,36 @@ impl ByteCompiler<'_> {
self.emit_opcode(Opcode::This);

self.emit_get_property_by_name(*name);
self.emit_opcode(opcode);
if post {
self.emit(Opcode::RotateRight, &[Operand::U8(3)]);
}

let src = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();
self.pop_into_register(&src);

self.emit2(
Opcode::ToNumeric,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(src.index()),
],
);
self.emit2(
opcode,
&[
Operand2::Varying(src.index()),
Operand2::Varying(dst.index()),
],
);

self.push_from_register(&src);

self.emit_set_property_by_name(*name);
if post {
self.emit_opcode(Opcode::Pop);
self.push_from_register(&dst);
}

self.register_allocator.dealloc(src);
self.register_allocator.dealloc(dst);
}
PropertyAccessField::Expr(expr) => {
self.emit_opcode(Opcode::Super);
Expand All @@ -140,18 +247,37 @@ impl ByteCompiler<'_> {
self.compile_expr(expr, true);

self.emit_opcode(Opcode::GetPropertyByValuePush);
self.emit_opcode(opcode);
if post {
self.emit(Opcode::RotateRight, &[Operand::U8(2)]);
}

let src = self.register_allocator.alloc();
let dst = self.register_allocator.alloc();
self.pop_into_register(&src);

self.emit2(
Opcode::ToNumeric,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(src.index()),
],
);
self.emit2(
opcode,
&[
Operand2::Varying(src.index()),
Operand2::Varying(dst.index()),
],
);

self.emit_opcode(Opcode::This);
self.emit(Opcode::RotateRight, &[Operand::U8(2)]);
self.push_from_register(&src);

self.emit_opcode(Opcode::SetPropertyByValue);
if post {
self.emit_opcode(Opcode::Pop);
self.push_from_register(&dst);
}

self.register_allocator.dealloc(src);
self.register_allocator.dealloc(dst);
}
},
},
Expand Down
27 changes: 26 additions & 1 deletion core/engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,23 @@ impl<'ctx> ByteCompiler<'ctx> {
self.emit_u64(value as u64);
}
fn emit_get_property_by_name(&mut self, ident: Sym) {
let dst = self.register_allocator.alloc();
let receiver = self.register_allocator.alloc();
let value = self.register_allocator.alloc();

self.pop_into_register(&receiver);
self.pop_into_register(&value);

self.emit_get_property_by_name2(&dst, &receiver, &value, ident);

self.push_from_register(&dst);

self.register_allocator.dealloc(dst);
self.register_allocator.dealloc(receiver);
self.register_allocator.dealloc(value);
}

fn emit_get_property_by_name2(&mut self, dst: &Reg, receiver: &Reg, value: &Reg, ident: Sym) {
let ic_index = self.ic.len() as u32;

let name_index = self.get_or_insert_name(Identifier::new(ident));
Expand All @@ -706,7 +723,15 @@ impl<'ctx> ByteCompiler<'ctx> {
};
self.ic.push(InlineCache::new(name.clone()));

self.emit_with_varying_operand(Opcode::GetPropertyByName, ic_index);
self.emit2(
Opcode::GetPropertyByName,
&[
Operand2::Varying(dst.index()),
Operand2::Varying(receiver.index()),
Operand2::Varying(value.index()),
Operand2::Varying(ic_index),
],
);
}

fn emit_set_property_by_name(&mut self, ident: Sym) {
Expand Down
15 changes: 8 additions & 7 deletions core/engine/src/vm/code_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,10 @@ impl CodeBlock {
| Instruction::InstanceOf { .. }
| Instruction::StrictNotEq { .. }
| Instruction::StrictEq { .. }
| Instruction::InPrivate { .. } => "TODO: fix".to_string(),
| Instruction::InPrivate { .. }
| Instruction::Inc { .. }
| Instruction::Dec { .. }
| Instruction::ToNumeric { .. } => "TODO: fix".to_string(),
Instruction::PopIntoRegister { dst } => format!("R{}", dst.value()),
Instruction::PushFromRegister { src } => format!("R{}", src.value()),
Instruction::Move { dst: r1, src: r2 } => {
Expand Down Expand Up @@ -527,7 +530,8 @@ impl CodeBlock {
.to_std_string_escaped(),
)
}
Instruction::GetPropertyByName { index } | Instruction::SetPropertyByName { index } => {
Instruction::GetPropertyByName { index, .. }
| Instruction::SetPropertyByName { index } => {
let ic = &self.ic[index.value() as usize];
let slot = ic.slot();
format!(
Expand Down Expand Up @@ -588,10 +592,6 @@ impl CodeBlock {
| Instruction::LogicalNot
| Instruction::Pos
| Instruction::Neg
| Instruction::Inc
| Instruction::IncPost
| Instruction::Dec
| Instruction::DecPost
| Instruction::GetPropertyByValue
| Instruction::GetPropertyByValuePush
| Instruction::SetPropertyByValue
Expand Down Expand Up @@ -722,7 +722,8 @@ impl CodeBlock {
| Instruction::Reserved51
| Instruction::Reserved52
| Instruction::Reserved53
| Instruction::Reserved54 => unreachable!("Reserved opcodes are unrechable"),
| Instruction::Reserved54
| Instruction::Reserved55 => unreachable!("Reserved opcodes are unrechable"),
}
}
}
Expand Down
Loading

0 comments on commit 7351c87

Please sign in to comment.