feat: 支持位运算字节码与 ToInt32/ToUint32
This commit is contained in:
@@ -34,6 +34,23 @@ pub fn to_number(val: JsValue, string_forge: &StringForge) -> f64 {
|
||||
f64::NAN
|
||||
}
|
||||
|
||||
pub fn to_uint32(val: JsValue, string_forge: &StringForge) -> u32 {
|
||||
let n = to_number(val, string_forge);
|
||||
if n == 0.0 || !n.is_finite() {
|
||||
return 0;
|
||||
}
|
||||
n.trunc().rem_euclid(4_294_967_296.0) as u32
|
||||
}
|
||||
|
||||
pub fn to_int32(val: JsValue, string_forge: &StringForge) -> i32 {
|
||||
let int = to_uint32(val, string_forge);
|
||||
if int > i32::MAX as u32 {
|
||||
(int as i64 - 4_294_967_296i64) as i32
|
||||
} else {
|
||||
int as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(string_forge: &StringForge, val: JsValue) -> String {
|
||||
if val.is_int() {
|
||||
return val.as_int().to_string();
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
use crate::coercion;
|
||||
use crate::vm::Vm;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
impl Vm {
|
||||
#[inline(always)]
|
||||
fn write_ushr_result(&mut self, rd: usize, result: u32) {
|
||||
if result <= i32::MAX as u32 {
|
||||
self.regs[rd] = JsValue::int(result as i32);
|
||||
} else {
|
||||
self.regs[rd] = JsValue::float(result as f64);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_bit_and(&mut self, rd: usize, a: usize, b: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(coercion::to_int32(self.regs[a], sf) & coercion::to_int32(self.regs[b], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_bit_or(&mut self, rd: usize, a: usize, b: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(coercion::to_int32(self.regs[a], sf) | coercion::to_int32(self.regs[b], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_bit_xor(&mut self, rd: usize, a: usize, b: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(coercion::to_int32(self.regs[a], sf) ^ coercion::to_int32(self.regs[b], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_shl(&mut self, rd: usize, a: usize, b: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
let lhs = coercion::to_int32(self.regs[a], sf);
|
||||
let shift = coercion::to_uint32(self.regs[b], sf) & 0x1F;
|
||||
self.regs[rd] = JsValue::int(lhs.wrapping_shl(shift));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_shr(&mut self, rd: usize, a: usize, b: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
let lhs = coercion::to_int32(self.regs[a], sf);
|
||||
let shift = coercion::to_uint32(self.regs[b], sf) & 0x1F;
|
||||
self.regs[rd] = JsValue::int(lhs >> shift);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_ushr(&mut self, rd: usize, a: usize, b: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
let lhs = coercion::to_uint32(self.regs[a], sf);
|
||||
let shift = coercion::to_uint32(self.regs[b], sf) & 0x1F;
|
||||
self.write_ushr_result(rd, lhs >> shift);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_bit_not(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(!coercion::to_int32(self.regs[a], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_compound_bit_and(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(coercion::to_int32(self.regs[rd], sf) & coercion::to_int32(self.regs[a], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_compound_bit_or(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(coercion::to_int32(self.regs[rd], sf) | coercion::to_int32(self.regs[a], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_compound_bit_xor(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
self.regs[rd] = JsValue::int(coercion::to_int32(self.regs[rd], sf) ^ coercion::to_int32(self.regs[a], sf));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_compound_shl(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
let lhs = coercion::to_int32(self.regs[rd], sf);
|
||||
let shift = coercion::to_uint32(self.regs[a], sf) & 0x1F;
|
||||
self.regs[rd] = JsValue::int(lhs.wrapping_shl(shift));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_compound_shr(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
let lhs = coercion::to_int32(self.regs[rd], sf);
|
||||
let shift = coercion::to_uint32(self.regs[a], sf) & 0x1F;
|
||||
self.regs[rd] = JsValue::int(lhs >> shift);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_compound_ushr(&mut self, rd: usize, a: usize) {
|
||||
let sf = self.kernel.string_forge().as_ref();
|
||||
let lhs = coercion::to_uint32(self.regs[rd], sf);
|
||||
let shift = coercion::to_uint32(self.regs[a], sf) & 0x1F;
|
||||
self.write_ushr_result(rd, lhs >> shift);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub(crate) mod arithmetic;
|
||||
pub(crate) mod bitwise;
|
||||
pub(crate) mod call;
|
||||
pub(crate) mod comparison;
|
||||
pub(crate) mod control_flow;
|
||||
|
||||
@@ -657,6 +657,34 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(-v);
|
||||
}
|
||||
|
||||
OpCode::BIT_AND => {
|
||||
self.dispatch_bit_and(rd, a, b);
|
||||
}
|
||||
|
||||
OpCode::BIT_OR => {
|
||||
self.dispatch_bit_or(rd, a, b);
|
||||
}
|
||||
|
||||
OpCode::BIT_XOR => {
|
||||
self.dispatch_bit_xor(rd, a, b);
|
||||
}
|
||||
|
||||
OpCode::SHL => {
|
||||
self.dispatch_shl(rd, a, b);
|
||||
}
|
||||
|
||||
OpCode::SHR => {
|
||||
self.dispatch_shr(rd, a, b);
|
||||
}
|
||||
|
||||
OpCode::USHR => {
|
||||
self.dispatch_ushr(rd, a, b);
|
||||
}
|
||||
|
||||
OpCode::BIT_NOT => {
|
||||
self.dispatch_bit_not(rd, a);
|
||||
}
|
||||
|
||||
OpCode::EQ => {
|
||||
self.dispatch_eq(rd, a, b);
|
||||
}
|
||||
@@ -1277,6 +1305,30 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::float(l.powf(r));
|
||||
}
|
||||
|
||||
OpCode::COMPOUND_AND => {
|
||||
self.dispatch_compound_bit_and(rd, a);
|
||||
}
|
||||
|
||||
OpCode::COMPOUND_OR => {
|
||||
self.dispatch_compound_bit_or(rd, a);
|
||||
}
|
||||
|
||||
OpCode::COMPOUND_XOR => {
|
||||
self.dispatch_compound_bit_xor(rd, a);
|
||||
}
|
||||
|
||||
OpCode::COMPOUND_SHL => {
|
||||
self.dispatch_compound_shl(rd, a);
|
||||
}
|
||||
|
||||
OpCode::COMPOUND_SHR => {
|
||||
self.dispatch_compound_shr(rd, a);
|
||||
}
|
||||
|
||||
OpCode::COMPOUND_USHR => {
|
||||
self.dispatch_compound_ushr(rd, a);
|
||||
}
|
||||
|
||||
OpCode::TYPEOF => {
|
||||
self.dispatch_typeof(rd, a);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user