Merge pull request #76 from mist-go/class-optimizations
Massive Class optimizations
This commit is contained in:
@@ -51,8 +51,10 @@ impl ClassProcessedData {
|
|||||||
if matches!(method.item.visibility, Visibility::Public) {
|
if matches!(method.item.visibility, Visibility::Public) {
|
||||||
match &method.item.is_override {
|
match &method.item.is_override {
|
||||||
None => {
|
None => {
|
||||||
|
if method.item.is_using_self() {
|
||||||
v_table.push(method.item.name.clone());
|
v_table.push(method.item.name.clone());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Some(override_spec) => {
|
Some(override_spec) => {
|
||||||
override_v_table
|
override_v_table
|
||||||
.entry(override_spec.clone())
|
.entry(override_spec.clone())
|
||||||
@@ -106,14 +108,12 @@ impl ClassProcessedData {
|
|||||||
));
|
));
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
cg.add_indentedln(
|
|
||||||
"pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),",
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(ref inherits) = self.inherits {
|
if let Some(ref inherits) = self.inherits {
|
||||||
cg.add_indented("pub _super: Box<");
|
cg.add_indented("pub _super: ");
|
||||||
cg.add(&get_type_from_path(inherits).get_rust());
|
cg.add(&get_type_from_path(inherits).get_rust());
|
||||||
cg.addln(">,");
|
cg.addln(",");
|
||||||
|
} else {
|
||||||
|
cg.add_indentedln("pub _vptr: &'static [*const std::ffi::c_void],");
|
||||||
}
|
}
|
||||||
|
|
||||||
for field in &self.fields {
|
for field in &self.fields {
|
||||||
@@ -133,9 +133,7 @@ impl ClassProcessedData {
|
|||||||
));
|
));
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
self.emit_v_table(cg);
|
self.emit_unified_vtable(cg);
|
||||||
|
|
||||||
self.emit_super_v_table(cg);
|
|
||||||
self.emit_super_v_tests(cg);
|
self.emit_super_v_tests(cg);
|
||||||
|
|
||||||
self.emit_constructor(ctx, cg);
|
self.emit_constructor(ctx, cg);
|
||||||
@@ -145,85 +143,96 @@ impl ClassProcessedData {
|
|||||||
cg.addln("}\n");
|
cg.addln("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_v_table(&self, cg: &mut RustCodegen) {
|
fn emit_unified_vtable(&self, cg: &mut RustCodegen) {
|
||||||
|
let has_parent = self.inherits.is_some();
|
||||||
|
let parent_path = self
|
||||||
|
.inherits
|
||||||
|
.as_ref()
|
||||||
|
.map(|p| p.get_rust())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
if has_parent {
|
||||||
|
cg.add_indentedln(&format!(
|
||||||
|
"pub const __PARENT_V_COUNT: usize = {}::__V_COUNT;",
|
||||||
|
parent_path
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
cg.add_indentedln("pub const __PARENT_V_COUNT: usize = 0;");
|
||||||
|
}
|
||||||
|
|
||||||
for (i, method_name) in self.v_table.iter().enumerate() {
|
for (i, method_name) in self.v_table.iter().enumerate() {
|
||||||
cg.add_indentedln(&format!(
|
cg.add_indentedln(&format!(
|
||||||
"pub const __FN_{}: usize = {i};",
|
"pub const __FN_{}: usize = Self::__PARENT_V_COUNT + {i};",
|
||||||
method_name.0.to_uppercase()
|
method_name.0.to_uppercase()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
cg.add_indentedln(&format!(
|
||||||
"pub const __V_TABLE: [*const std::ffi::c_void; {}] = [",
|
"pub const __V_COUNT: usize = Self::__PARENT_V_COUNT + {};",
|
||||||
self.v_table.len()
|
self.v_table.len()
|
||||||
));
|
));
|
||||||
|
|
||||||
|
cg.add_indentedln("pub const __V_TABLE: &'static [*const std::ffi::c_void] = &{");
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
for method_name in &self.v_table {
|
if has_parent {
|
||||||
cg.add_indented("Self::__m_");
|
|
||||||
cg.add(&method_name.get_rust());
|
|
||||||
cg.add(" as *const std::ffi::c_void");
|
|
||||||
cg.addln(",");
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.indent -= 1;
|
|
||||||
cg.add_indentedln("];");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_super_v_table(&self, cg: &mut RustCodegen) {
|
|
||||||
if self.override_v_table.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
cg.add_indentedln(&format!(
|
||||||
"pub const __SUPER_V_TABLES: [&'static [*const std::ffi::c_void]; {}] = [",
|
"let mut table = [std::ptr::null(); {}::__V_COUNT + {}];",
|
||||||
self.override_v_table.len()
|
parent_path,
|
||||||
|
self.v_table.len()
|
||||||
|
));
|
||||||
|
|
||||||
|
cg.add_indentedln(&format!("let parent_table = {}::__V_TABLE;", parent_path));
|
||||||
|
cg.add_indentedln(&format!(
|
||||||
|
"let mut i = 0; while i < {}::__V_COUNT {{ table[i] = parent_table[i]; i += 1; }}",
|
||||||
|
parent_path
|
||||||
));
|
));
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
for (override_tier, overriden_method_idents) in &self.override_v_table {
|
for (override_tier, overriden_method_idents) in &self.override_v_table {
|
||||||
let target_path = match &override_tier.0 {
|
let base_class_path = override_tier
|
||||||
Some(path) => path.clone(),
|
.0
|
||||||
None => {
|
.as_ref()
|
||||||
if let Some(parent_path) = &self.inherits {
|
.unwrap_or(self.inherits.as_ref().unwrap())
|
||||||
parent_path.clone()
|
.get_rust();
|
||||||
} else {
|
|
||||||
continue; // Safeguard if AST has a dangling override without inheritance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let target_rust_path = target_path.get_rust();
|
|
||||||
|
|
||||||
// 2. Emit the block for this specific index table
|
|
||||||
cg.add_indentedln("&{");
|
|
||||||
cg.indent += 1;
|
|
||||||
|
|
||||||
// Initialize this sub-table with the target parent class's base vtable
|
|
||||||
cg.add_indentedln(&format!("let mut table = {}::__V_TABLE;", target_rust_path));
|
|
||||||
|
|
||||||
// Patch the slots for every method registered under this specific override tier
|
|
||||||
for method_ident in &overriden_method_idents.item {
|
for method_ident in &overriden_method_idents.item {
|
||||||
cg.add_indentedln(&format!(
|
cg.add_indentedln(&format!(
|
||||||
"table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;",
|
"table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;",
|
||||||
target_rust_path,
|
base_class_path,
|
||||||
method_ident.0.to_uppercase(),
|
method_ident.0.to_uppercase(),
|
||||||
self.self_path.get_rust(),
|
self.self_path.get_rust(),
|
||||||
method_ident.get_rust()
|
method_ident.get_rust()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for method_name in &self.v_table {
|
||||||
|
cg.add_indentedln(&format!(
|
||||||
|
"table[Self::__FN_{}] = Self::__m_{} as *const std::ffi::c_void;",
|
||||||
|
method_name.0.to_uppercase(),
|
||||||
|
method_name.get_rust()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
cg.add_indentedln("table");
|
cg.add_indentedln("table");
|
||||||
|
} else {
|
||||||
|
cg.add_indentedln("[");
|
||||||
|
cg.indent += 1;
|
||||||
|
for method_name in &self.v_table {
|
||||||
|
cg.add_indentedln(&format!(
|
||||||
|
"Self::__m_{} as *const std::ffi::c_void,",
|
||||||
|
method_name.get_rust()
|
||||||
|
));
|
||||||
|
}
|
||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.add_indentedln("},");
|
cg.add_indentedln("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.add_indentedln("];");
|
cg.add_indentedln("};");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_super_v_tests(&self, cg: &mut RustCodegen) {
|
fn emit_super_v_tests(&self, cg: &mut RustCodegen) {
|
||||||
cg.add_indentedln(&format!("const fn __test_vt() {{"));
|
cg.add_indentedln(&format!("fn __test_vt() {{"));
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
for (override_tier, _) in self.override_v_table.iter() {
|
for (override_tier, _) in self.override_v_table.iter() {
|
||||||
@@ -234,7 +243,7 @@ impl ClassProcessedData {
|
|||||||
if let Some(parent_path) = &self.inherits {
|
if let Some(parent_path) = &self.inherits {
|
||||||
parent_path.clone()
|
parent_path.clone()
|
||||||
} else {
|
} else {
|
||||||
continue; // Safeguard if AST has a dangling override without inheritance
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -284,6 +293,19 @@ impl ClassProcessedData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deref tests for override targets
|
||||||
|
if self.inherits.is_some() && !self.override_v_table.is_empty() {
|
||||||
|
cg.add_indentedln("let this: &Self = &unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };");
|
||||||
|
|
||||||
|
for (override_tier, v) in &self.override_v_table {
|
||||||
|
if let Some(path) = &override_tier.0 {
|
||||||
|
cg.add_indentedln(&v.get_comment());
|
||||||
|
// This forces the compiler to statically verify that &Self can Deref into &Target
|
||||||
|
cg.add_indentedln(&format!("let _: &{} = this;", path.get_rust()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.add_indentedln("}");
|
cg.add_indentedln("}");
|
||||||
}
|
}
|
||||||
@@ -321,14 +343,12 @@ impl ClassProcessedData {
|
|||||||
param.gen_rust(ctx, cg);
|
param.gen_rust(ctx, cg);
|
||||||
}
|
}
|
||||||
|
|
||||||
cg.addln(") -> Box<Self> {");
|
cg.addln(") -> Self {");
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
cg.add_indentedln("let mut this = Box::new(unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() });");
|
cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };");
|
||||||
cg.add_indentedln("let this_ptr = &mut *this as *mut Self as *mut std::ffi::c_void;");
|
cg.add_indentedln("this._vptr = &Self::__V_TABLE;");
|
||||||
cg.add_indentedln("this._m_oop = (&Self::__V_TABLE, this_ptr);");
|
|
||||||
|
|
||||||
// Inline field declarations and initializers
|
|
||||||
for field in &self.fields {
|
for field in &self.fields {
|
||||||
let comment = field.get_comment();
|
let comment = field.get_comment();
|
||||||
|
|
||||||
@@ -349,28 +369,7 @@ impl ClassProcessedData {
|
|||||||
}
|
}
|
||||||
cg.addln(");");
|
cg.addln(");");
|
||||||
|
|
||||||
if self.inherits.is_some() && !self.override_v_table.is_empty() {
|
cg.add_indentedln("this._vptr = &Self::__V_TABLE;");
|
||||||
for (idx, (override_tier, v)) in self.override_v_table.iter().enumerate() {
|
|
||||||
match &override_tier.0 {
|
|
||||||
// Direct base class layout updates
|
|
||||||
None => {
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"this._super._m_oop.0 = Self::__SUPER_V_TABLES[{}];",
|
|
||||||
idx
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// Deep ancestor trait table updates
|
|
||||||
Some(path) => {
|
|
||||||
cg.add_indentedln(&v.get_comment());
|
|
||||||
cg.add_indentedln(&format!(
|
|
||||||
"(|v: &mut {}| {{v._m_oop.0 = Self::__SUPER_V_TABLES[{}];}})(&mut this);",
|
|
||||||
path.get_rust(),
|
|
||||||
idx
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cg.add_indentedln(&constructor_comment);
|
cg.add_indentedln(&constructor_comment);
|
||||||
|
|
||||||
@@ -378,7 +377,6 @@ impl ClassProcessedData {
|
|||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.add_indentedln("}\n");
|
cg.add_indentedln("}\n");
|
||||||
|
|
||||||
// Generate matching inner initialization body block
|
|
||||||
let mut constructor_params = vec![VarDecl {
|
let mut constructor_params = vec![VarDecl {
|
||||||
name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])),
|
name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])),
|
||||||
type_: Some(TypeExpr::Ref {
|
type_: Some(TypeExpr::Ref {
|
||||||
@@ -413,6 +411,7 @@ impl ClassProcessedData {
|
|||||||
for method in &self.methods {
|
for method in &self.methods {
|
||||||
match method.item.visibility {
|
match method.item.visibility {
|
||||||
Visibility::Public => {
|
Visibility::Public => {
|
||||||
|
if method.item.is_using_self() {
|
||||||
if method.item.is_override.is_none() {
|
if method.item.is_override.is_none() {
|
||||||
gen_method_point(&method.item, ctx, cg);
|
gen_method_point(&method.item, ctx, cg);
|
||||||
}
|
}
|
||||||
@@ -420,6 +419,9 @@ impl ClassProcessedData {
|
|||||||
let mut prefixed = method.clone();
|
let mut prefixed = method.clone();
|
||||||
prefixed.item.name.0.insert_str(0, "__m_");
|
prefixed.item.name.0.insert_str(0, "__m_");
|
||||||
prefixed.gen_rust(ctx, cg);
|
prefixed.gen_rust(ctx, cg);
|
||||||
|
} else {
|
||||||
|
method.gen_rust(ctx, cg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
method.gen_rust(ctx, cg);
|
method.gen_rust(ctx, cg);
|
||||||
@@ -552,7 +554,7 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC
|
|||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
cg.add_indentedln(&format!(
|
||||||
"let func_ptr = self._m_oop.0[Self::__FN_{}];",
|
"let func_ptr = self._vptr[Self::__FN_{}];",
|
||||||
method.name.0.to_uppercase()
|
method.name.0.to_uppercase()
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -566,14 +568,14 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC
|
|||||||
.filter_map(|v| v.type_)
|
.filter_map(|v| v.type_)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !param_types.is_empty() {
|
let TypeExpr::Ref { mutable, .. } = param_types.remove(0) else {
|
||||||
param_types.remove(0);
|
panic!("")
|
||||||
}
|
};
|
||||||
|
|
||||||
param_types.insert(
|
param_types.insert(
|
||||||
0,
|
0,
|
||||||
TypeExpr::UnsafePtr {
|
TypeExpr::UnsafePtr {
|
||||||
mutable: true,
|
mutable,
|
||||||
ty: Box::new(TypeExpr::Path(
|
ty: Box::new(TypeExpr::Path(
|
||||||
Path(vec![
|
Path(vec![
|
||||||
Identifier(String::from("std")),
|
Identifier(String::from("std")),
|
||||||
@@ -588,11 +590,15 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC
|
|||||||
cg.add(&TypeExpr::StaticFn(param_types, method.return_type.clone().map(Box::new)).get_rust());
|
cg.add(&TypeExpr::StaticFn(param_types, method.return_type.clone().map(Box::new)).get_rust());
|
||||||
cg.addln(" = std::mem::transmute(func_ptr);");
|
cg.addln(" = std::mem::transmute(func_ptr);");
|
||||||
|
|
||||||
cg.add_indented("func(self._m_oop.1");
|
if mutable {
|
||||||
|
cg.add_indented("func(self as *mut Self as *const std::ffi::c_void");
|
||||||
|
} else {
|
||||||
|
cg.add_indented("func(self as *const Self as *const std::ffi::c_void");
|
||||||
|
}
|
||||||
|
|
||||||
for (i, param) in ¶ms {
|
for (i, param) in ¶ms {
|
||||||
if *i == 0 {
|
if *i == 0 {
|
||||||
continue; // self._m_oop.1 already fulfills it
|
continue; // self already fulfills it
|
||||||
}
|
}
|
||||||
cg.add(", ");
|
cg.add(", ");
|
||||||
ctx.expr_ensure_semicolon = false;
|
ctx.expr_ensure_semicolon = false;
|
||||||
|
|||||||
@@ -125,3 +125,18 @@ pub struct FieldDeclStmt {
|
|||||||
pub decl: FieldDecl,
|
pub decl: FieldDecl,
|
||||||
pub init: Option<Expression>,
|
pub init: Option<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FunctionDecl {
|
||||||
|
pub fn is_using_self(&self) -> bool {
|
||||||
|
match self.params.0.get(0) {
|
||||||
|
Some(VarDecl { name, .. }) => {
|
||||||
|
if let Pattern::Path(_, v) = name {
|
||||||
|
v.0.len() == 1 && v.0[0].0 == "self"
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,11 +15,13 @@ pub class Animal<T> {
|
|||||||
pub fn test_speak(*self) {
|
pub fn test_speak(*self) {
|
||||||
self.speak();
|
self.speak();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn static_method() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub class Mammal<T> : Animal<T> {
|
pub class Mammal<T> : Animal<T> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super -> Super::new();
|
super = Super::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn args_test(*self, x i32, y *str) {}
|
pub fn args_test(*self, x i32, y *str) {}
|
||||||
@@ -31,7 +33,7 @@ pub class Mammal<T> : Animal<T> {
|
|||||||
|
|
||||||
pub class Dog : Mammal<i32> {
|
pub class Dog : Mammal<i32> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super -> Super::new();
|
super = Super::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub override(Animal<i32>) fn speak(*self) {
|
pub override(Animal<i32>) fn speak(*self) {
|
||||||
|
|||||||
Reference in New Issue
Block a user