v.markused: cleanup, extract more fields from ast.Table to ast.UsedFeatures, to reduce its size

This commit is contained in:
Delyan Angelov 2024-11-19 11:05:34 +02:00
parent b0dc186a2c
commit 09f8b56904
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
7 changed files with 101 additions and 64 deletions

View File

@ -26,6 +26,23 @@ pub mut:
arr_pop bool // arr.pop() arr_pop bool // arr.pop()
option_or_result bool // has panic call option_or_result bool // has panic call
print_types map[int]bool // print() idx types print_types map[int]bool // print() idx types
used_fns map[string]bool // filled in by markused
used_consts map[string]bool // filled in by markused
used_globals map[string]bool // filled in by markused
used_veb_types []Type // veb context types, filled in by checker
used_maps int // how many times maps were used, filled in by markused
used_arrays int // how many times arrays were used, filled in by markused
}
@[unsafe]
pub fn (mut uf UsedFeatures) free() {
unsafe {
uf.print_types.free()
uf.used_fns.free()
uf.used_consts.free()
uf.used_globals.free()
uf.used_veb_types.free()
}
} }
@[heap; minify] @[heap; minify]
@ -48,14 +65,9 @@ pub mut:
sumtypes map[int]SumTypeDecl sumtypes map[int]SumTypeDecl
cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.` cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
is_fmt bool is_fmt bool
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true; used_features &UsedFeatures = &UsedFeatures{} // filled in by the checker/markused, when pref.skip_unused = true;
used_consts map[string]bool // filled in by the checker, when pref.skip_unused = true;
used_globals map[string]bool // filled in by the checker, when pref.skip_unused = true;
used_features UsedFeatures // filled in by the checker, when pref.skip_unused = true;
used_veb_types []Type // veb context types, filled in by checker, when pref.skip_unused = true;
veb_res_idx_cache int // Cache of `veb.Result` type veb_res_idx_cache int // Cache of `veb.Result` type
veb_ctx_idx_cache int // Cache of `veb.Context` type veb_ctx_idx_cache int // Cache of `veb.Context` type
used_maps int // how many times maps were used, filled in by checker, when pref.skip_unused = true;
panic_handler FnPanicHandler = default_table_panic_handler panic_handler FnPanicHandler = default_table_panic_handler
panic_userdata voidptr = unsafe { nil } // can be used to pass arbitrary data to panic_handler; panic_userdata voidptr = unsafe { nil } // can be used to pass arbitrary data to panic_handler;
panic_npanics int panic_npanics int
@ -94,10 +106,7 @@ pub fn (mut t Table) free() {
t.redefined_fns.free() t.redefined_fns.free()
t.fn_generic_types.free() t.fn_generic_types.free()
t.cmod_prefix.free() t.cmod_prefix.free()
t.used_fns.free() t.used_features.free()
t.used_consts.free()
t.used_globals.free()
t.used_veb_types.free()
} }
} }

View File

@ -94,7 +94,7 @@ fn (mut m Mapper) visit(node &ast.Node) ! {
ast.FnDecl { ast.FnDecl {
m.is_caller_used = true m.is_caller_used = true
if m.pref.skip_unused { if m.pref.skip_unused {
m.is_caller_used = m.table.used_fns[node.fkey()] m.is_caller_used = m.table.used_features.used_fns[node.fkey()]
} }
m.fn_decl = unsafe { &node } m.fn_decl = unsafe { &node }
m.caller_name = m.fn_name(node.name, node.receiver.typ, node.is_method) m.caller_name = m.fn_name(node.name, node.receiver.typ, node.is_method)

View File

@ -624,7 +624,7 @@ fn (mut c Checker) verify_all_vweb_routes() {
if c.vweb_gen_types.len == 0 { if c.vweb_gen_types.len == 0 {
return return
} }
c.table.used_veb_types = c.vweb_gen_types c.table.used_features.used_veb_types = c.vweb_gen_types
typ_vweb_result := c.table.find_type('vweb.Result') typ_vweb_result := c.table.find_type('vweb.Result')
old_file := c.file old_file := c.file
for vgt in c.vweb_gen_types { for vgt in c.vweb_gen_types {

View File

@ -849,7 +849,7 @@ pub fn (mut g Gen) init() {
} else { } else {
g.cheaders.writeln(c_headers) g.cheaders.writeln(c_headers)
} }
if !g.pref.skip_unused || g.table.used_maps > 0 { if !g.pref.skip_unused || g.table.used_features.used_maps > 0 {
g.cheaders.writeln(c_wyhash_headers) g.cheaders.writeln(c_wyhash_headers)
} }
} }
@ -936,11 +936,11 @@ pub fn (mut g Gen) init() {
// and this is being called in the main thread, so we can mutate the table // and this is being called in the main thread, so we can mutate the table
mut muttable := unsafe { &ast.Table(g.table) } mut muttable := unsafe { &ast.Table(g.table) }
if g.use_segfault_handler { if g.use_segfault_handler {
muttable.used_fns['v_segmentation_fault_handler'] = true muttable.used_features.used_fns['v_segmentation_fault_handler'] = true
} }
muttable.used_fns['eprintln'] = true muttable.used_features.used_fns['eprintln'] = true
muttable.used_fns['print_backtrace'] = true muttable.used_features.used_fns['print_backtrace'] = true
muttable.used_fns['exit'] = true muttable.used_features.used_fns['exit'] = true
} }
pub fn (mut g Gen) finish() { pub fn (mut g Gen) finish() {
@ -6009,7 +6009,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
} }
for field in node.fields { for field in node.fields {
if g.pref.skip_unused { if g.pref.skip_unused {
if field.name !in g.table.used_consts { if field.name !in g.table.used_features.used_consts {
$if trace_skip_unused_consts ? { $if trace_skip_unused_consts ? {
eprintln('>> skipping unused const name: ${field.name}') eprintln('>> skipping unused const name: ${field.name}')
} }
@ -6413,7 +6413,7 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) {
} }
for field in node.fields { for field in node.fields {
if g.pref.skip_unused { if g.pref.skip_unused {
if field.name !in g.table.used_globals { if field.name !in g.table.used_features.used_globals {
$if trace_skip_unused_globals ? { $if trace_skip_unused_globals ? {
eprintln('>> skipping unused global name: ${field.name}') eprintln('>> skipping unused global name: ${field.name}')
} }

View File

@ -16,7 +16,7 @@ fn (mut g Gen) is_used_by_main(node ast.FnDecl) bool {
mut is_used_by_main := true mut is_used_by_main := true
if g.pref.skip_unused { if g.pref.skip_unused {
fkey := node.fkey() fkey := node.fkey()
is_used_by_main = g.table.used_fns[fkey] is_used_by_main = g.table.used_features.used_fns[fkey]
$if trace_skip_unused_fns ? { $if trace_skip_unused_fns ? {
println('> is_used_by_main: ${is_used_by_main} | node.name: ${node.name} | fkey: ${fkey} | node.is_method: ${node.is_method}') println('> is_used_by_main: ${is_used_by_main} | node.name: ${node.name} | fkey: ${fkey} | node.is_method: ${node.is_method}')
} }

View File

@ -339,14 +339,14 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
if 'C.cJSON_Parse' in all_fns { if 'C.cJSON_Parse' in all_fns {
all_fn_root_names << 'tos5' all_fn_root_names << 'tos5'
} }
mut walker := Walker{ mut walker := Walker.new(
table: table table: table
files: ast_files files: ast_files
all_fns: all_fns all_fns: all_fns
all_consts: all_consts all_consts: all_consts
all_globals: all_globals all_globals: all_globals
pref: pref_ pref: pref_
} )
// println( all_fns.keys() ) // println( all_fns.keys() )
walker.mark_markused_fns() // tagged with `@[markused]` walker.mark_markused_fns() // tagged with `@[markused]`
walker.mark_markused_consts() // tagged with `@[markused]` walker.mark_markused_consts() // tagged with `@[markused]`
@ -357,7 +357,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
if walker.n_asserts > 0 { if walker.n_asserts > 0 {
unsafe { walker.fn_decl(mut all_fns['__print_assert_failure']) } unsafe { walker.fn_decl(mut all_fns['__print_assert_failure']) }
} }
if table.used_maps > 0 { if table.used_features.used_maps > 0 {
for k, mut mfn in all_fns { for k, mut mfn in all_fns {
mut method_receiver_typename := '' mut method_receiver_typename := ''
if mfn.is_method { if mfn.is_method {
@ -405,15 +405,15 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
walker.mark_const_as_used(kcon) walker.mark_const_as_used(kcon)
} }
} }
table.used_fns = walker.used_fns.move() table.used_features.used_fns = walker.used_fns.move()
table.used_consts = walker.used_consts.move() table.used_features.used_consts = walker.used_consts.move()
table.used_globals = walker.used_globals.move() table.used_features.used_globals = walker.used_globals.move()
$if trace_skip_unused ? { $if trace_skip_unused ? {
eprintln('>> t.used_fns: ${table.used_fns.keys()}') eprintln('>> t.used_fns: ${table.used_features.used_fns.keys()}')
eprintln('>> t.used_consts: ${table.used_consts.keys()}') eprintln('>> t.used_consts: ${table.used_features.used_consts.keys()}')
eprintln('>> t.used_globals: ${table.used_globals.keys()}') eprintln('>> t.used_globals: ${table.used_features.used_globals.keys()}')
eprintln('>> walker.table.used_maps: ${walker.table.used_maps}') eprintln('>> walker.table.used_features.used_maps: ${walker.table.used_features.used_maps}')
} }
} }
@ -460,7 +460,7 @@ fn handle_vweb(mut table ast.Table, mut all_fn_root_names []string, result_name
all_fn_root_names << filter_name all_fn_root_names << filter_name
typ_vweb_context := table.find_type(context_name).set_nr_muls(1) typ_vweb_context := table.find_type(context_name).set_nr_muls(1)
all_fn_root_names << '${int(typ_vweb_context)}.html' all_fn_root_names << '${int(typ_vweb_context)}.html'
for vgt in table.used_veb_types { for vgt in table.used_features.used_veb_types {
sym_app := table.sym(vgt) sym_app := table.sym(vgt)
for m in sym_app.methods { for m in sym_app.methods {
mut skip := true mut skip := true

View File

@ -10,6 +10,7 @@ import v.pref
pub struct Walker { pub struct Walker {
pub mut: pub mut:
table &ast.Table = unsafe { nil } table &ast.Table = unsafe { nil }
features &ast.UsedFeatures = unsafe { nil }
used_fns map[string]bool // used_fns['println'] == true used_fns map[string]bool // used_fns['println'] == true
used_consts map[string]bool // used_consts['os.args'] == true used_consts map[string]bool // used_consts['os.args'] == true
used_globals map[string]bool used_globals map[string]bool
@ -23,6 +24,14 @@ mut:
all_globals map[string]ast.GlobalField all_globals map[string]ast.GlobalField
} }
pub fn Walker.new(params Walker) &Walker {
mut new_walker := &Walker{
...params
}
new_walker.features = params.table.used_features
return new_walker
}
pub fn (mut w Walker) mark_fn_as_used(fkey string) { pub fn (mut w Walker) mark_fn_as_used(fkey string) {
$if trace_skip_unused_marked ? { $if trace_skip_unused_marked ? {
eprintln(' fn > |${fkey}|') eprintln(' fn > |${fkey}|')
@ -77,7 +86,7 @@ pub fn (mut w Walker) mark_root_fns(all_fn_root_names []string) {
for fn_name in all_fn_root_names { for fn_name in all_fn_root_names {
if fn_name !in w.used_fns { if fn_name !in w.used_fns {
$if trace_skip_unused_roots ? { $if trace_skip_unused_roots ? {
println('>>>> ${fn_name} uses: ') println('>>>> walking root func: ${fn_name} ...')
} }
unsafe { w.fn_decl(mut w.all_fns[fn_name]) } unsafe { w.fn_decl(mut w.all_fns[fn_name]) }
} }
@ -87,6 +96,9 @@ pub fn (mut w Walker) mark_root_fns(all_fn_root_names []string) {
pub fn (mut w Walker) mark_exported_fns() { pub fn (mut w Walker) mark_exported_fns() {
for _, mut func in w.all_fns { for _, mut func in w.all_fns {
if func.is_exported { if func.is_exported {
$if trace_skip_unused_exported_fns ? {
println('>>>> walking exported func: ${func.name} ...')
}
w.fn_decl(mut func) w.fn_decl(mut func)
} }
} }
@ -95,6 +107,9 @@ pub fn (mut w Walker) mark_exported_fns() {
pub fn (mut w Walker) mark_markused_fns() { pub fn (mut w Walker) mark_markused_fns() {
for _, mut func in w.all_fns { for _, mut func in w.all_fns {
if func.is_markused { if func.is_markused {
$if trace_skip_unused_markused_fns ? {
println('>>>> walking markused func: ${func.name} ...')
}
w.fn_decl(mut func) w.fn_decl(mut func)
} }
} }
@ -103,6 +118,9 @@ pub fn (mut w Walker) mark_markused_fns() {
pub fn (mut w Walker) mark_markused_consts() { pub fn (mut w Walker) mark_markused_consts() {
for ckey, mut constfield in w.all_consts { for ckey, mut constfield in w.all_consts {
if constfield.is_markused { if constfield.is_markused {
$if trace_skip_unused_markused_consts ? {
println('>>>> walking markused const: ${ckey}')
}
w.mark_const_as_used(ckey) w.mark_const_as_used(ckey)
} }
} }
@ -111,6 +129,9 @@ pub fn (mut w Walker) mark_markused_consts() {
pub fn (mut w Walker) mark_markused_globals() { pub fn (mut w Walker) mark_markused_globals() {
for gkey, mut globalfield in w.all_globals { for gkey, mut globalfield in w.all_globals {
if globalfield.is_markused || globalfield.is_exported { if globalfield.is_markused || globalfield.is_exported {
$if trace_skip_unused_markused_globals ? {
println('>>>> walking markused global: ${gkey}')
}
w.mark_global_as_used(gkey) w.mark_global_as_used(gkey)
} }
} }
@ -170,9 +191,10 @@ pub fn (mut w Walker) stmt(node_ ast.Stmt) {
w.expr(node.high) w.expr(node.high)
w.stmts(node.stmts) w.stmts(node.stmts)
if node.kind == .map { if node.kind == .map {
w.table.used_maps++ w.features.used_maps++
} } else if node.kind == .array {
if node.kind == .struct { w.features.used_arrays++
} else if node.kind == .struct {
if node.cond_type == 0 { if node.cond_type == 0 {
return return
} }
@ -268,6 +290,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
w.expr(node.cap_expr) w.expr(node.cap_expr)
w.expr(node.init_expr) w.expr(node.init_expr)
w.exprs(node.exprs) w.exprs(node.exprs)
w.features.used_arrays++
} }
ast.Assoc { ast.Assoc {
w.exprs(node.exprs) w.exprs(node.exprs)
@ -325,7 +348,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
} }
sym := w.table.final_sym(node.left_type) sym := w.table.final_sym(node.left_type)
if sym.kind == .map { if sym.kind == .map {
w.table.used_maps++ w.features.used_maps++
} else if sym.kind == .array {
w.features.used_arrays++
} }
} }
ast.InfixExpr { ast.InfixExpr {
@ -347,8 +372,12 @@ fn (mut w Walker) expr(node_ ast.Expr) {
return return
} }
right_sym := w.table.sym(node.right_type) right_sym := w.table.sym(node.right_type)
if node.op in [.not_in, .key_in] && right_sym.kind == .map { if node.op in [.not_in, .key_in] {
w.table.used_maps++ if right_sym.kind == .map {
w.features.used_maps++
} else if right_sym.kind == .array {
w.features.used_arrays++
}
} }
} }
ast.IfGuardExpr { ast.IfGuardExpr {
@ -387,7 +416,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
ast.MapInit { ast.MapInit {
w.exprs(node.keys) w.exprs(node.keys)
w.exprs(node.vals) w.exprs(node.vals)
w.table.used_maps++ w.features.used_maps++
} }
ast.MatchExpr { ast.MatchExpr {
w.expr(node.cond) w.expr(node.cond)
@ -503,9 +532,10 @@ pub fn (mut w Walker) a_struct_info(sname string, info ast.Struct) {
if ifield.typ != 0 { if ifield.typ != 0 {
fsym := w.table.sym(ifield.typ) fsym := w.table.sym(ifield.typ)
if fsym.kind == .map { if fsym.kind == .map {
w.table.used_maps++ w.features.used_maps++
} } else if fsym.kind == .array {
if fsym.kind == .struct { w.features.used_arrays++
} else if fsym.kind == .struct {
w.a_struct_info(fsym.name, fsym.struct_info()) w.a_struct_info(fsym.name, fsym.struct_info())
} }
} }
@ -518,8 +548,6 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
} }
fkey := node.fkey() fkey := node.fkey()
if w.used_fns[fkey] { if w.used_fns[fkey] {
// This function is already known to be called, meaning it has been processed already.
// Save CPU time and do nothing.
return return
} }
w.mark_fn_as_used(fkey) w.mark_fn_as_used(fkey)
@ -533,7 +561,7 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
} }
if node.language == .c { if node.language == .c {
if node.name in ['C.wyhash', 'C.wyhash64'] { if node.name in ['C.wyhash', 'C.wyhash64'] {
w.table.used_maps++ w.features.used_maps++
} }
return return
} }