mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
wip
This commit is contained in:
@@ -131,13 +131,7 @@ impl std::fmt::Display for FnMeta {
|
||||
match &self.content_hashable {
|
||||
ContentHashable::Empty => {}
|
||||
ContentHashable::Src(src_hash, deps) => {
|
||||
write!(f, " srcHash: 0x")?;
|
||||
|
||||
for b in src_hash {
|
||||
write!(f, "{:02x}", b)?;
|
||||
}
|
||||
|
||||
writeln!(f, ",")?;
|
||||
writeln!(f, " srcHash: {},", src_hash)?;
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
@@ -147,14 +141,8 @@ impl std::fmt::Display for FnMeta {
|
||||
}
|
||||
)?;
|
||||
}
|
||||
ContentHashable::Hash(content_hash) => {
|
||||
write!(f, " contentHash: 0x")?;
|
||||
|
||||
for b in content_hash {
|
||||
write!(f, "{:02x}", b)?;
|
||||
}
|
||||
|
||||
writeln!(f, ",")?;
|
||||
ContentHashable::Content(content_hash) => {
|
||||
writeln!(f, " contentHash: {},", content_hash)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,12 +150,29 @@ impl std::fmt::Display for FnMeta {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Hash(pub [u8; 32]);
|
||||
|
||||
impl std::fmt::Display for Hash {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "#")?;
|
||||
|
||||
let Hash(data) = self;
|
||||
|
||||
for b in data {
|
||||
write!(f, "{:02x}", b)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub enum ContentHashable {
|
||||
#[default]
|
||||
Empty,
|
||||
Src([u8; 32], Vec<Value>),
|
||||
Hash([u8; 32]),
|
||||
Src(Hash, Vec<Value>),
|
||||
Content(Hash),
|
||||
}
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)]
|
||||
|
||||
@@ -9,7 +9,7 @@ use valuescript_common::BuiltinName;
|
||||
|
||||
use crate::asm::{
|
||||
Array, Builtin, Class, ContentHashable, Definition, DefinitionContent, FnLine, FnMeta, Function,
|
||||
Instruction, Label, LabelRef, Lazy, Module, Number, Object, Pointer, Register, Value,
|
||||
Hash, Instruction, Label, LabelRef, Lazy, Module, Number, Object, Pointer, Register, Value,
|
||||
};
|
||||
|
||||
pub fn assemble(module: &Module) -> Vec<u8> {
|
||||
@@ -142,7 +142,9 @@ impl Assembler {
|
||||
ContentHashable::Src(src_hash, deps) => {
|
||||
self.output.push(0x01);
|
||||
|
||||
for b in src_hash {
|
||||
let Hash(src_hash_data) = src_hash;
|
||||
|
||||
for b in src_hash_data {
|
||||
self.output.push(*b);
|
||||
}
|
||||
|
||||
@@ -152,10 +154,12 @@ impl Assembler {
|
||||
self.value(dep);
|
||||
}
|
||||
}
|
||||
ContentHashable::Hash(content_hash) => {
|
||||
ContentHashable::Content(content_hash) => {
|
||||
self.output.push(0x02);
|
||||
|
||||
for b in content_hash {
|
||||
let Hash(content_hash_data) = content_hash;
|
||||
|
||||
for b in content_hash_data {
|
||||
self.output.push(*b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ use valuescript_common::{InstructionByte, BUILTIN_NAMES};
|
||||
|
||||
use crate::asm::{
|
||||
Array, Builtin, Class, ContentHashable, Definition, DefinitionContent, ExportStar, FnLine,
|
||||
FnMeta, Function, Instruction, Label, LabelRef, Module, Number, Object, Pointer, Register, Value,
|
||||
FnMeta, Function, Hash, Instruction, Label, LabelRef, Module, Number, Object, Pointer, Register,
|
||||
Value,
|
||||
};
|
||||
|
||||
pub struct AssemblyParser<'a> {
|
||||
@@ -561,7 +562,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
self.parse_exact(",");
|
||||
self.parse_optional_whitespace();
|
||||
|
||||
break 'b ContentHashable::Hash(content_hash);
|
||||
break 'b ContentHashable::Content(content_hash);
|
||||
}
|
||||
|
||||
panic!("{}", self.render_pos(-1, "Expected ContentHashable"));
|
||||
@@ -1124,8 +1125,8 @@ impl<'a> AssemblyParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble_hash(&mut self) -> [u8; 32] {
|
||||
self.parse_exact("0x");
|
||||
fn assemble_hash(&mut self) -> Hash {
|
||||
self.parse_exact("#");
|
||||
|
||||
let mut res = [0u8; 32];
|
||||
|
||||
@@ -1136,7 +1137,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
res
|
||||
Hash(res)
|
||||
}
|
||||
|
||||
fn assemble_hex_byte(&mut self) -> Option<u8> {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::mem::swap;
|
||||
use std::mem::{swap, take};
|
||||
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
||||
use crate::asm::{
|
||||
Definition, DefinitionContent, ExportStar, FnLine, Instruction, Object, Pointer, Value,
|
||||
Builtin, ContentHashable, Definition, DefinitionContent, ExportStar, FnLine, FnMeta, Hash,
|
||||
Instruction, Object, Pointer, Value,
|
||||
};
|
||||
use crate::gather_modules::PathAndModule;
|
||||
use crate::import_pattern::{ImportKind, ImportPattern};
|
||||
@@ -109,6 +112,9 @@ pub fn link_module(
|
||||
&mut result.diagnostics,
|
||||
);
|
||||
|
||||
collapse_pointers_of_pointers(&mut path_and_module.module);
|
||||
calculate_content_hashes(&mut path_and_module.module, &mut result.diagnostics);
|
||||
|
||||
optimize(&mut path_and_module.module, &mut pointer_allocator);
|
||||
|
||||
result.module = Some(path_and_module.module);
|
||||
@@ -346,3 +352,218 @@ fn flatten_export_star(
|
||||
|
||||
obj
|
||||
}
|
||||
|
||||
pub fn collapse_pointers_of_pointers(module: &mut Module) {
|
||||
let mut double_pointer_map = HashMap::<Pointer, Pointer>::new();
|
||||
|
||||
for definition in &mut module.definitions {
|
||||
let pointer = match &definition.content {
|
||||
DefinitionContent::Value(Value::Pointer(pointer)) => pointer,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
double_pointer_map.insert(definition.pointer.clone(), pointer.clone());
|
||||
}
|
||||
|
||||
visit_pointers(module, |visitation| match visitation {
|
||||
PointerVisitation::Definition(_) => {}
|
||||
PointerVisitation::Export(pointer) | PointerVisitation::Reference(_, pointer) => {
|
||||
let mut mapped_pointer: &Pointer = pointer;
|
||||
|
||||
loop {
|
||||
if let Some(new_pointer) = double_pointer_map.get(mapped_pointer) {
|
||||
mapped_pointer = new_pointer;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
*pointer = mapped_pointer.clone();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(clippy::ptr_arg)]
|
||||
fn calculate_content_hashes(module: &mut Module, _diagnostics: &mut Vec<Diagnostic>) {
|
||||
let mut fn_to_meta = HashMap::<Pointer, Pointer>::new();
|
||||
let mut meta_to_fn = HashMap::<Pointer, Pointer>::new();
|
||||
let mut src_and_deps_map = HashMap::<Pointer, (Hash, Vec<Value>)>::new();
|
||||
|
||||
for defn in &module.definitions {
|
||||
match &defn.content {
|
||||
DefinitionContent::Function(fn_) => {
|
||||
if let Some(metadata) = &fn_.metadata {
|
||||
fn_to_meta.insert(defn.pointer.clone(), metadata.clone());
|
||||
meta_to_fn.insert(metadata.clone(), defn.pointer.clone());
|
||||
}
|
||||
}
|
||||
DefinitionContent::FnMeta(fn_meta) => match &fn_meta.content_hashable {
|
||||
ContentHashable::Empty => {}
|
||||
ContentHashable::Src(src_hash, deps) => {
|
||||
src_and_deps_map.insert(defn.pointer.clone(), (src_hash.clone(), deps.clone()));
|
||||
}
|
||||
ContentHashable::Content(_) => {}
|
||||
},
|
||||
DefinitionContent::Value(_) => {}
|
||||
DefinitionContent::Lazy(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
for defn in &mut module.definitions {
|
||||
match &mut defn.content {
|
||||
DefinitionContent::Function(_) => {}
|
||||
DefinitionContent::FnMeta(fn_meta) => {
|
||||
let fn_ptr = meta_to_fn.get(&defn.pointer).unwrap().clone();
|
||||
|
||||
let mut full_deps = vec![PointerOrBuiltin::Pointer(fn_ptr.clone())];
|
||||
let mut deps_included = HashSet::<PointerOrBuiltin>::new();
|
||||
deps_included.insert(PointerOrBuiltin::Pointer(fn_ptr.clone()));
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
while i < full_deps.len() {
|
||||
let dep = full_deps[i].clone();
|
||||
|
||||
let ptr_dep = match dep {
|
||||
PointerOrBuiltin::Pointer(p) => p,
|
||||
PointerOrBuiltin::Builtin(_) => {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let meta_ptr = fn_to_meta.get(&ptr_dep).unwrap();
|
||||
let (_, sub_deps) = src_and_deps_map.get(meta_ptr).unwrap();
|
||||
|
||||
for sub_dep in sub_deps {
|
||||
match sub_dep {
|
||||
Value::Pointer(p) => {
|
||||
if deps_included.insert(PointerOrBuiltin::Pointer(p.clone())) {
|
||||
full_deps.push(PointerOrBuiltin::Pointer(p.clone()));
|
||||
}
|
||||
}
|
||||
Value::Builtin(b) => {
|
||||
if deps_included.insert(PointerOrBuiltin::Builtin(b.clone())) {
|
||||
full_deps.push(PointerOrBuiltin::Builtin(b.clone()));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("Expected sub_dep to be pointer or builtin")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let mut dep_to_index = HashMap::<PointerOrBuiltin, usize>::new();
|
||||
|
||||
for (i, dep) in full_deps.iter().enumerate() {
|
||||
dep_to_index.insert(dep.clone(), i);
|
||||
}
|
||||
|
||||
let mut links = Vec::<Vec<usize>>::new();
|
||||
|
||||
for dep in &full_deps {
|
||||
let mut link = Vec::<usize>::new();
|
||||
|
||||
match dep {
|
||||
PointerOrBuiltin::Pointer(ptr_dep) => {
|
||||
let meta_ptr = fn_to_meta.get(ptr_dep).unwrap();
|
||||
let (_, sub_deps) = src_and_deps_map.get(meta_ptr).unwrap();
|
||||
|
||||
for sub_dep in sub_deps {
|
||||
match sub_dep {
|
||||
Value::Pointer(p) => {
|
||||
let index = dep_to_index
|
||||
.get(&PointerOrBuiltin::Pointer(p.clone()))
|
||||
.unwrap();
|
||||
|
||||
link.push(*index);
|
||||
}
|
||||
Value::Builtin(b) => {
|
||||
let index = dep_to_index
|
||||
.get(&PointerOrBuiltin::Builtin(b.clone()))
|
||||
.unwrap();
|
||||
|
||||
link.push(*index);
|
||||
}
|
||||
_ => {
|
||||
panic!("Expected sub_dep to be pointer or builtin")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PointerOrBuiltin::Builtin(_) => {}
|
||||
};
|
||||
|
||||
links.push(link);
|
||||
}
|
||||
|
||||
let mut content_trace = "{deps:".to_string();
|
||||
|
||||
content_trace.push_str(&make_array_string(&full_deps, |dep| match dep {
|
||||
PointerOrBuiltin::Pointer(ptr_dep) => {
|
||||
let meta_ptr = fn_to_meta.get(ptr_dep).unwrap();
|
||||
let (src_hash, _) = src_and_deps_map.get(meta_ptr).unwrap();
|
||||
src_hash.to_string()
|
||||
}
|
||||
PointerOrBuiltin::Builtin(b) => b.to_string(),
|
||||
}));
|
||||
|
||||
content_trace.push_str(",links:");
|
||||
|
||||
content_trace.push_str(&make_array_string(&links, |link| {
|
||||
make_array_string(link, |i| i.to_string())
|
||||
}));
|
||||
|
||||
content_trace.push('}');
|
||||
|
||||
// dbg!((fn_ptr, full_deps, links, content_trace));
|
||||
|
||||
let mut k = Keccak::v256();
|
||||
k.update(content_trace.as_bytes());
|
||||
|
||||
let mut content_hash_data = [0u8; 32];
|
||||
k.finalize(&mut content_hash_data);
|
||||
|
||||
let content_hash = Hash(content_hash_data);
|
||||
|
||||
*fn_meta = FnMeta {
|
||||
name: take(&mut fn_meta.name),
|
||||
content_hashable: ContentHashable::Content(content_hash),
|
||||
};
|
||||
}
|
||||
DefinitionContent::Value(_) => {}
|
||||
DefinitionContent::Lazy(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq, Clone, Debug)]
|
||||
enum PointerOrBuiltin {
|
||||
Pointer(Pointer),
|
||||
Builtin(Builtin),
|
||||
}
|
||||
|
||||
fn make_array_string<T, F, S>(seq: S, to_string_fn: F) -> String
|
||||
where
|
||||
S: IntoIterator<Item = T>,
|
||||
F: Fn(T) -> String,
|
||||
{
|
||||
let mut result = "[".to_string();
|
||||
let mut iter = seq.into_iter();
|
||||
|
||||
if let Some(first_item) = iter.next() {
|
||||
result.push_str(&to_string_fn(first_item));
|
||||
|
||||
for item in iter {
|
||||
result.push(',');
|
||||
result.push_str(&to_string_fn(item));
|
||||
}
|
||||
}
|
||||
|
||||
result.push(']');
|
||||
result
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
asm::{DefinitionContent, Module, Pointer, Value},
|
||||
visit_pointers::{visit_pointers, PointerVisitation},
|
||||
};
|
||||
|
||||
pub fn collapse_pointers_of_pointers(module: &mut Module) {
|
||||
let mut double_pointer_map = HashMap::<Pointer, Pointer>::new();
|
||||
|
||||
for definition in &mut module.definitions {
|
||||
let pointer = match &definition.content {
|
||||
DefinitionContent::Value(Value::Pointer(pointer)) => pointer,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
double_pointer_map.insert(definition.pointer.clone(), pointer.clone());
|
||||
}
|
||||
|
||||
visit_pointers(module, |visitation| match visitation {
|
||||
PointerVisitation::Definition(_) => {}
|
||||
PointerVisitation::Export(pointer) | PointerVisitation::Reference(_, pointer) => {
|
||||
let mut mapped_pointer: &Pointer = pointer;
|
||||
|
||||
loop {
|
||||
if let Some(new_pointer) = double_pointer_map.get(mapped_pointer) {
|
||||
mapped_pointer = new_pointer;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
*pointer = mapped_pointer.clone();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
mod collapse_pointers_of_pointers;
|
||||
mod extract_constants;
|
||||
pub mod kal;
|
||||
mod optimize;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::asm::Module;
|
||||
use crate::name_allocator::NameAllocator;
|
||||
|
||||
use super::collapse_pointers_of_pointers::collapse_pointers_of_pointers;
|
||||
use super::extract_constants::extract_constants;
|
||||
use super::reduce_instructions::reduce_instructions;
|
||||
use super::remove_meta_lines::remove_meta_lines;
|
||||
@@ -12,7 +11,6 @@ use super::simplify::simplify;
|
||||
use super::simplify_jumps::simplify_jumps;
|
||||
|
||||
pub fn optimize(module: &mut Module, pointer_allocator: &mut NameAllocator) {
|
||||
collapse_pointers_of_pointers(module);
|
||||
shake_tree(module);
|
||||
|
||||
let passes = 3;
|
||||
|
||||
@@ -2017,7 +2017,7 @@ impl ScopeAnalysis {
|
||||
for (_span, ref_) in self.refs.range(start..end) {
|
||||
let name = self.names.get(&ref_.name_id).unwrap();
|
||||
|
||||
if let Value::Register(_) = &name.value {
|
||||
if let Value::Undefined | Value::Register(_) = &name.value {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
use swc_common::BytePos;
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
||||
pub fn src_hash(source: &str, span: swc_common::Span) -> [u8; 32] {
|
||||
use crate::asm::Hash;
|
||||
|
||||
pub fn src_hash(source: &str, span: swc_common::Span) -> Hash {
|
||||
let BytePos(start) = span.lo;
|
||||
let BytePos(end) = span.hi;
|
||||
|
||||
@@ -16,5 +18,5 @@ pub fn src_hash(source: &str, span: swc_common::Span) -> [u8; 32] {
|
||||
let mut output = [0u8; 32];
|
||||
k.finalize(&mut output);
|
||||
|
||||
output
|
||||
Hash(output)
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ where
|
||||
self.value(Some(&definition.pointer), dep);
|
||||
}
|
||||
}
|
||||
ContentHashable::Hash(_) => {}
|
||||
ContentHashable::Content(_) => {}
|
||||
},
|
||||
DefinitionContent::Value(value) => {
|
||||
self.value(Some(&definition.pointer), value);
|
||||
|
||||
Reference in New Issue
Block a user