feat: 对小整数做额外枚举以优化性能
This commit is contained in:
@@ -8,6 +8,10 @@ pub use oxide_parser::{BinaryOperator, Expression, Statement, UnaryOperator};
|
|||||||
|
|
||||||
pub struct Compiler;
|
pub struct Compiler;
|
||||||
|
|
||||||
|
fn is_int_literal(value: f64) -> bool {
|
||||||
|
value.fract() == 0.0 && value >= i32::MIN as f64 && value <= i32::MAX as f64
|
||||||
|
}
|
||||||
|
|
||||||
struct CompileCtx {
|
struct CompileCtx {
|
||||||
bytecode: Vec<opcode::Instr>,
|
bytecode: Vec<opcode::Instr>,
|
||||||
constants: Vec<Constant>,
|
constants: Vec<Constant>,
|
||||||
@@ -312,7 +316,11 @@ impl Compiler {
|
|||||||
fn emit_expression(&self, expr: &Expression, ctx: &mut CompileCtx) -> Result<u8, String> {
|
fn emit_expression(&self, expr: &Expression, ctx: &mut CompileCtx) -> Result<u8, String> {
|
||||||
match expr {
|
match expr {
|
||||||
Expression::NumericLiteral(n) => {
|
Expression::NumericLiteral(n) => {
|
||||||
let idx = ctx.add_constant(Constant::Number(n.value));
|
let idx = if is_int_literal(n.value) {
|
||||||
|
ctx.add_constant(Constant::Int(n.value as i32))
|
||||||
|
} else {
|
||||||
|
ctx.add_constant(Constant::Number(n.value))
|
||||||
|
};
|
||||||
let r = ctx.alloc_reg();
|
let r = ctx.alloc_reg();
|
||||||
ctx.emit(opcode::encode(
|
ctx.emit(opcode::encode(
|
||||||
OpCode::LOAD_CONST,
|
OpCode::LOAD_CONST,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use crate::opcode::{self, OpCode};
|
|||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Constant {
|
pub enum Constant {
|
||||||
Number(f64),
|
Number(f64),
|
||||||
|
Int(i32),
|
||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Null,
|
Null,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fn compile_constants() {
|
|||||||
assert!(!module.constants.is_empty());
|
assert!(!module.constants.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
module.constants[0],
|
module.constants[0],
|
||||||
oxide_compiler::compiler::Constant::Number(42.0)
|
oxide_compiler::compiler::Constant::Int(42)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ fn compile_var_declaration() {
|
|||||||
assert!(!module.bytecode.is_empty());
|
assert!(!module.bytecode.is_empty());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
module.constants[0],
|
module.constants[0],
|
||||||
oxide_compiler::compiler::Constant::Number(42.0)
|
oxide_compiler::compiler::Constant::Int(42)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ impl Vm {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|c| match c {
|
.map(|c| match c {
|
||||||
Constant::Number(v) => JsValue::float(*v),
|
Constant::Number(v) => JsValue::float(*v),
|
||||||
|
Constant::Int(v) => JsValue::int(*v),
|
||||||
Constant::String(s) => self.intern(s),
|
Constant::String(s) => self.intern(s),
|
||||||
Constant::Boolean(b) => JsValue::bool(*b),
|
Constant::Boolean(b) => JsValue::bool(*b),
|
||||||
Constant::Null => JsValue::null(),
|
Constant::Null => JsValue::null(),
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fn object_create_and_read() {
|
|||||||
assert!(obj.is_object());
|
assert!(obj.is_object());
|
||||||
let obj_ref = unsafe { &*obj.as_js_object_ptr() };
|
let obj_ref = unsafe { &*obj.as_js_object_ptr() };
|
||||||
assert_eq!(obj_ref.prop_count(), 1, "object should have 1 property");
|
assert_eq!(obj_ref.prop_count(), 1, "object should have 1 property");
|
||||||
assert!(obj_ref.get_inline_prop(0).is_double());
|
assert!(obj_ref.get_inline_prop(0).is_int());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user