Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ast,cgen: reduce memory usage for compiling larger v programs with long fns #18876

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
15 changes: 15 additions & 0 deletions cmd/tools/gen_1long_fn.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import strings
import os

n := os.args[1] or { '1_000_000' }.int()
stmt := os.args[2] or { 'a = b + c * d' }

mut s := strings.new_builder(1000)
s.writeln('fn main() {')
s.writeln(' mut a,b,c,d := 0,1,2,3')
for _ in 0 .. n {
s.writeln(' ${stmt}')
}
s.writeln(' println("a: \${a}")')
s.writeln('}')
os.write_file('${n}.v', s.str())!
74 changes: 74 additions & 0 deletions vlib/builtin/array_notd_gcboehm_opt.v
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,92 @@
module builtin

// this is needed in `string.v`
[inline]
fn __new_array_noscan(mylen int, cap int, elm_size int) array {
return __new_array(mylen, cap, elm_size)
}

[inline]
fn __new_array_with_default_noscan(mylen int, cap int, elm_size int, val voidptr) array {
return __new_array_with_default(mylen, cap, elm_size, val)
}

[inline]
fn __new_array_with_multi_default_noscan(mylen int, cap int, elm_size int, val voidptr) array {
return __new_array_with_multi_default(mylen, cap, elm_size, val)
}

[inline]
fn __new_array_with_array_default_noscan(mylen int, cap int, elm_size int, val array, depth int) array {
return __new_array_with_array_default(mylen, cap, elm_size, val, depth)
}

[inline]
fn new_array_from_c_array_noscan(len int, cap int, elm_size int, c_array voidptr) array {
return new_array_from_c_array(len, cap, elm_size, c_array)
}

[inline]
fn (a array) repeat_to_depth_noscan(count int, depth int) array {
return unsafe { a.repeat_to_depth(count, depth) }
}

[inline]
fn (mut a array) insert_noscan(i int, val voidptr) {
a.insert(i, val)
}

[inline]
fn (mut a array) insert_many_noscan(i int, val voidptr, size int) {
unsafe { a.insert_many(i, val, size) }
}

[inline]
fn (mut a array) prepend_noscan(val voidptr) {
a.prepend_noscan(val)
}

[inline]
fn (mut a array) prepend_many_noscan(val voidptr, size int) {
unsafe { a.prepend_many_noscan(val, size) }
}

[inline]
fn (mut a array) pop_noscan() voidptr {
return a.pop()
}

[inline]
fn (a array) clone_static_to_depth_noscan(depth int) array {
return unsafe { a.clone_static_to_depth(depth) }
}

[inline]
fn (a &array) clone_to_depth_noscan(depth int) array {
return unsafe { a.clone_to_depth(depth) }
}

[inline]
fn (mut a array) push_noscan(val voidptr) {
a.push(val)
}

[inline]
fn (mut a array) push_many_noscan(val voidptr, size int) {
unsafe { a.push_many(val, size) }
}

[inline]
fn (a array) reverse_noscan() array {
return a.reverse()
}

[inline]
fn (mut a array) grow_cap_noscan(amount int) {
a.grow_cap(amount)
}

[inline]
fn (mut a array) grow_len_noscan(amount int) {
unsafe { a.grow_len(amount) }
}
43 changes: 43 additions & 0 deletions vlib/builtin/map_notd_gcboehm_opt.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module builtin

// Dummy placeholder for functions from map_d_gcboehm_opt.v
// These functions will be called by cgen, for maps that have keys and values
// of primitive types, that do not require GC scanning, like ints, bools etc.

[inline]
fn new_dense_array_noscan(key_bytes int, key_noscan bool, value_bytes int, value_noscan bool) DenseArray {
return new_dense_array(key_bytes, value_bytes)
}

[inline]
fn new_map_noscan_key(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map {
return new_map(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, free_fn)
}

[inline]
fn new_map_noscan_value(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map {
return new_map(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, free_fn)
}

[inline]
fn new_map_noscan_key_value(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map {
return new_map(key_bytes, value_bytes, hash_fn, key_eq_fn, clone_fn, free_fn)
}

[inline]
fn new_map_init_noscan_key(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map {
return new_map_init(hash_fn, key_eq_fn, clone_fn, free_fn, n, key_bytes, value_bytes,
keys, values)
}

[inline]
fn new_map_init_noscan_value(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map {
return new_map_init(hash_fn, key_eq_fn, clone_fn, free_fn, n, key_bytes, value_bytes,
keys, values)
}

[inline]
fn new_map_init_noscan_key_value(hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn, n int, key_bytes int, value_bytes int, keys voidptr, values voidptr) map {
return new_map_init(hash_fn, key_eq_fn, clone_fn, free_fn, n, key_bytes, value_bytes,
keys, values)
}
6 changes: 3 additions & 3 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ pub mut:
end_comments []Comment // comments that after const field
// the comptime_expr_value field is filled by the checker, when it has enough
// info to evaluate the constant at compile time
comptime_expr_value ComptTimeConstValue = empty_comptime_const_expr()
comptime_expr_value ComptTimeConstValue = empty_comptime_const_expr
}

// const declaration
Expand Down Expand Up @@ -1006,9 +1006,9 @@ pub mut:
or_block OrExpr

ct_left_value_evaled bool
ct_left_value ComptTimeConstValue = empty_comptime_const_expr()
ct_left_value ComptTimeConstValue = empty_comptime_const_expr
ct_right_value_evaled bool
ct_right_value ComptTimeConstValue = empty_comptime_const_expr()
ct_right_value ComptTimeConstValue = empty_comptime_const_expr

before_op_comments []Comment
after_op_comments []Comment
Expand Down
4 changes: 1 addition & 3 deletions vlib/v/ast/comptime_const_values.v
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ pub type ComptTimeConstValue = EmptyExpr
| u8
| voidptr

pub fn empty_comptime_const_expr() ComptTimeConstValue {
return EmptyExpr(0)
}
pub const empty_comptime_const_expr = ComptTimeConstValue(EmptyExpr(0))

pub fn (val ComptTimeConstValue) i8() ?i8 {
x := val.i64()?
Expand Down
14 changes: 11 additions & 3 deletions vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,9 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
concrete_types := (left_sym.info as ast.Struct).concrete_types
mut method_name := left_sym.cname + '_' + util.replace_op(extracted_op)
method_name = g.generic_fn_name(concrete_types, method_name)
g.write(' = ${method_name}(')
g.write(' = ')
g.write(method_name)
g.write('(')
g.expr(left)
g.write(', ')
g.expr(val)
Expand All @@ -504,7 +506,9 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
&& !left_sym.has_method(extracted_op) {
g.write(' = ')
g.expr(left)
g.write(' ${extracted_op} ')
g.write(' ')
g.write(extracted_op)
g.write(' ')
g.expr(val)
g.write(';')
return
Expand Down Expand Up @@ -631,7 +635,11 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
g.writeln(';')
}
} else if !g.is_arraymap_set && !str_add && !op_overloaded {
g.write(' ${op} ')
// ordinary `=` in `x = 2 * y;`
// Note, that this branch *deliberately does not use interpolation*
g.write(' ')
g.write(op.str())
g.write(' ')
} else if str_add || op_overloaded {
g.write(', ')
}
Expand Down
13 changes: 5 additions & 8 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -6219,11 +6219,10 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty

[inline]
fn c_name(name_ string) string {
name := util.no_dots(name_)
if c.c_reserved_chk.matches(name) {
return '_v_${name}'
if c.c_reserved_chk.matches(name_) {
return '_v_${name_}'
}
return name
return util.no_dots(name_)
}

fn (mut g Gen) type_default(typ_ ast.Type) string {
Expand Down Expand Up @@ -6973,10 +6972,8 @@ pub fn (mut g Gen) contains_ptr(el_typ ast.Type) bool {
}

fn (mut g Gen) check_noscan(elem_typ ast.Type) string {
if g.pref.gc_mode in [.boehm_full_opt, .boehm_incr_opt] {
if !g.contains_ptr(elem_typ) {
return '_noscan'
}
if !g.contains_ptr(elem_typ) {
return '_noscan'
}
return ''
}
8 changes: 6 additions & 2 deletions vlib/v/gen/c/infix.v
Original file line number Diff line number Diff line change
Expand Up @@ -1016,7 +1016,9 @@ fn (mut g Gen) gen_is_none_check(node ast.InfixExpr) {
g.write(' ')
g.write('${left_var}.state')
}
g.write(' ${node.op.str()} ')
g.write(' ')
g.write(node.op.str())
g.write(' ')
g.write('2') // none state
}

Expand All @@ -1030,7 +1032,9 @@ fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) {
g.write('*')
}
g.expr(node.left)
g.write(' ${node.op.str()} ')
g.write(' ')
g.write(node.op.str())
g.write(' ')
if node.right_type.is_ptr() && node.right.is_auto_deref_var() {
g.write('*')
g.expr(node.right)
Expand Down
Loading