feat: VM 复用 kernel 字符串共享池
This commit is contained in:
+22
-45
@@ -1,10 +1,13 @@
|
|||||||
use std::collections::HashMap;
|
#![allow(clippy::arc_with_non_send_sync)]
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use oxide_compiler::compiler::Constant;
|
use oxide_compiler::compiler::Constant;
|
||||||
use oxide_compiler::module::CompiledModule;
|
use oxide_compiler::module::CompiledModule;
|
||||||
use oxide_compiler::opcode::{self, OpCode};
|
use oxide_compiler::opcode::{self, OpCode};
|
||||||
|
|
||||||
use crate::coercion;
|
use crate::coercion;
|
||||||
|
use oxide_kernel::kernel::{KernelConfig, OxideKernel};
|
||||||
use oxide_types::mem::{Epoch, P};
|
use oxide_types::mem::{Epoch, P};
|
||||||
use oxide_types::object::JsObject;
|
use oxide_types::object::JsObject;
|
||||||
use oxide_types::shape::{self, EMPTY_SHAPE_ID};
|
use oxide_types::shape::{self, EMPTY_SHAPE_ID};
|
||||||
@@ -22,8 +25,8 @@ pub struct Vm {
|
|||||||
bytecode: Vec<opcode::Instr>,
|
bytecode: Vec<opcode::Instr>,
|
||||||
constants: Vec<JsValue>,
|
constants: Vec<JsValue>,
|
||||||
frames: Vec<CallFrame>,
|
frames: Vec<CallFrame>,
|
||||||
string_table: HashMap<String, u32>,
|
kernel: Arc<OxideKernel>,
|
||||||
string_reverse: Vec<String>,
|
interned_strings: Vec<u32>,
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
pub object_prototype: P<JsObject>,
|
pub object_prototype: P<JsObject>,
|
||||||
}
|
}
|
||||||
@@ -36,40 +39,41 @@ impl Vm {
|
|||||||
bytecode: Vec::new(),
|
bytecode: Vec::new(),
|
||||||
constants: Vec::new(),
|
constants: Vec::new(),
|
||||||
frames: Vec::with_capacity(128),
|
frames: Vec::with_capacity(128),
|
||||||
string_table: HashMap::with_capacity(64),
|
kernel: Arc::new(OxideKernel::new(KernelConfig::minimal())),
|
||||||
string_reverse: Vec::with_capacity(64),
|
interned_strings: Vec::new(),
|
||||||
epoch: Epoch::new(),
|
epoch: Epoch::new(),
|
||||||
object_prototype: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
|
object_prototype: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_kernel(kernel: Arc<OxideKernel>) -> Self {
|
||||||
|
let mut vm = Self::new();
|
||||||
|
vm.kernel = Arc::clone(&kernel);
|
||||||
|
vm.object_prototype = P::clone(&kernel.builtin_world().object_proto);
|
||||||
|
vm
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
self.regs = [JsValue::undefined(); 256];
|
self.regs = [JsValue::undefined(); 256];
|
||||||
self.pc = 0;
|
self.pc = 0;
|
||||||
self.bytecode.clear();
|
self.bytecode.clear();
|
||||||
self.constants.clear();
|
self.constants.clear();
|
||||||
self.frames.clear();
|
self.frames.clear();
|
||||||
self.string_table.clear();
|
|
||||||
self.string_reverse.clear();
|
|
||||||
self.epoch.reset();
|
self.epoch.reset();
|
||||||
|
self.interned_strings.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern(&mut self, s: &str) -> JsValue {
|
pub fn intern(&mut self, s: &str) -> JsValue {
|
||||||
if let Some(&idx) = self.string_table.get(s) {
|
let (idx, hash) = self.kernel.string_forge().intern(s);
|
||||||
return JsValue::string(idx, hash16(s));
|
self.interned_strings.push(idx);
|
||||||
}
|
JsValue::string(idx, hash)
|
||||||
let idx = self.string_reverse.len() as u32;
|
|
||||||
self.string_reverse.push(s.to_string());
|
|
||||||
self.string_table.insert(s.to_string(), idx);
|
|
||||||
JsValue::string(idx, hash16(s))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_str(&self, val: JsValue) -> Option<&str> {
|
pub fn lookup_str(&self, val: JsValue) -> Option<String> {
|
||||||
if !val.is_string() {
|
if !val.is_string() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let idx = val.as_string_index() as usize;
|
self.kernel.string_forge().lookup(val.as_string_index())
|
||||||
self.string_reverse.get(idx).map(|s| s.as_str())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> {
|
fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> {
|
||||||
@@ -95,32 +99,12 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, module: &CompiledModule) -> Result<JsValue, String> {
|
pub fn run(&mut self, module: &CompiledModule) -> Result<JsValue, String> {
|
||||||
self.string_table.clear();
|
|
||||||
self.string_reverse.clear();
|
|
||||||
|
|
||||||
let string_entries: Vec<String> = module
|
|
||||||
.constants
|
|
||||||
.iter()
|
|
||||||
.filter_map(|c| {
|
|
||||||
if let Constant::String(s) = c {
|
|
||||||
Some(s.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
for s in &string_entries {
|
|
||||||
self.intern(s);
|
|
||||||
}
|
|
||||||
self.constants = module
|
self.constants = module
|
||||||
.constants
|
.constants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| match c {
|
.map(|c| match c {
|
||||||
Constant::Number(v) => JsValue::float(*v),
|
Constant::Number(v) => JsValue::float(*v),
|
||||||
Constant::String(s) => {
|
Constant::String(s) => self.intern(s),
|
||||||
let idx = self.string_table.get(s.as_str()).copied().unwrap_or(0);
|
|
||||||
JsValue::string(idx, hash16(s))
|
|
||||||
}
|
|
||||||
Constant::Boolean(b) => JsValue::bool(*b),
|
Constant::Boolean(b) => JsValue::bool(*b),
|
||||||
Constant::Null => JsValue::null(),
|
Constant::Null => JsValue::null(),
|
||||||
Constant::Undefined => JsValue::undefined(),
|
Constant::Undefined => JsValue::undefined(),
|
||||||
@@ -505,10 +489,3 @@ impl Default for Vm {
|
|||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash16(s: &str) -> u16 {
|
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
let mut h = rustc_hash::FxHasher::default();
|
|
||||||
s.hash(&mut h);
|
|
||||||
(h.finish() >> 48) as u16
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user