all: implement reference receiver optimization for big structs (#9268)
parent
92e95f127a
commit
945769a4f6
|
@ -33,6 +33,9 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string, m2a map[string]s
|
||||||
styp = styp[1..] // remove &
|
styp = styp[1..] // remove &
|
||||||
}
|
}
|
||||||
styp = util.no_cur_mod(styp, cur_mod)
|
styp = util.no_cur_mod(styp, cur_mod)
|
||||||
|
if node.params[0].is_auto_rec {
|
||||||
|
styp = styp.trim('&')
|
||||||
|
}
|
||||||
receiver = '($m$node.receiver.name $styp) '
|
receiver = '($m$node.receiver.name $styp) '
|
||||||
/*
|
/*
|
||||||
sym := t.get_type_symbol(node.receiver.typ)
|
sym := t.get_type_symbol(node.receiver.typ)
|
||||||
|
|
|
@ -2444,6 +2444,9 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
got_typ_sym := c.table.get_type_symbol(got_typ)
|
got_typ_sym := c.table.get_type_symbol(got_typ)
|
||||||
mut exp_typ_sym := c.table.get_type_symbol(exp_type)
|
mut exp_typ_sym := c.table.get_type_symbol(exp_type)
|
||||||
pos := return_stmt.exprs[i].position()
|
pos := return_stmt.exprs[i].position()
|
||||||
|
if return_stmt.exprs[i].is_auto_deref_var() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if exp_typ_sym.kind == .interface_ {
|
if exp_typ_sym.kind == .interface_ {
|
||||||
c.type_implements(got_typ, exp_type, return_stmt.pos)
|
c.type_implements(got_typ, exp_type, return_stmt.pos)
|
||||||
continue
|
continue
|
||||||
|
@ -2454,12 +2457,18 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
||||||
if (got_typ.is_ptr() || got_typ.is_pointer())
|
if (got_typ.is_ptr() || got_typ.is_pointer())
|
||||||
&& (!exp_type.is_ptr() && !exp_type.is_pointer()) {
|
&& (!exp_type.is_ptr() && !exp_type.is_pointer()) {
|
||||||
pos := return_stmt.exprs[i].position()
|
pos := return_stmt.exprs[i].position()
|
||||||
|
if return_stmt.exprs[i].is_auto_deref_var() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
c.error('fn `$c.cur_fn.name` expects you to return a non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
c.error('fn `$c.cur_fn.name` expects you to return a non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
if (exp_type.is_ptr() || exp_type.is_pointer())
|
if (exp_type.is_ptr() || exp_type.is_pointer())
|
||||||
&& (!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != table.int_literal_type {
|
&& (!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != table.int_literal_type {
|
||||||
pos := return_stmt.exprs[i].position()
|
pos := return_stmt.exprs[i].position()
|
||||||
|
if return_stmt.exprs[i].is_auto_deref_var() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
c.error('fn `$c.cur_fn.name` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
c.error('fn `$c.cur_fn.name` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
|
@ -4713,7 +4722,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym table.TypeS
|
||||||
}
|
}
|
||||||
|
|
||||||
// smartcast takes the expression with the current type which should be smartcasted to the target type in the given scope
|
// smartcast takes the expression with the current type which should be smartcasted to the target type in the given scope
|
||||||
fn (c Checker) smartcast_sumtype(expr ast.Expr, cur_type table.Type, to_type table.Type, mut scope ast.Scope) {
|
fn (c &Checker) smartcast_sumtype(expr ast.Expr, cur_type table.Type, to_type table.Type, mut scope ast.Scope) {
|
||||||
match mut expr {
|
match mut expr {
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
|
@ -5684,7 +5693,7 @@ pub fn (mut c Checker) error(message string, pos token.Position) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check `to` has all fields of `from`
|
// check `to` has all fields of `from`
|
||||||
fn (c Checker) check_struct_signature(from table.Struct, to table.Struct) bool {
|
fn (c &Checker) check_struct_signature(from table.Struct, to table.Struct) bool {
|
||||||
// Note: `to` can have extra fields
|
// Note: `to` can have extra fields
|
||||||
if from.fields.len == 0 {
|
if from.fields.len == 0 {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -4496,7 +4496,18 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
} else {
|
} else {
|
||||||
g.write('return ')
|
g.write('return ')
|
||||||
}
|
}
|
||||||
|
if expr0.is_auto_deref_var() {
|
||||||
|
if g.fn_decl.return_type.is_ptr() {
|
||||||
|
g.write('&(*')
|
||||||
|
g.expr(expr0)
|
||||||
|
g.write(')')
|
||||||
|
} else {
|
||||||
|
g.write('*')
|
||||||
|
g.expr(expr0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
|
}
|
||||||
if free {
|
if free {
|
||||||
expr := node.exprs[0]
|
expr := node.exprs[0]
|
||||||
if expr is ast.Ident {
|
if expr is ast.Ident {
|
||||||
|
|
|
@ -279,7 +279,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
name: param.name
|
name: param.name
|
||||||
typ: param.typ
|
typ: param.typ
|
||||||
is_mut: param.is_mut
|
is_mut: param.is_mut
|
||||||
is_auto_deref: param.is_mut
|
is_auto_deref: param.is_mut || param.is_auto_rec
|
||||||
pos: param.pos
|
pos: param.pos
|
||||||
is_used: true
|
is_used: true
|
||||||
is_arg: true
|
is_arg: true
|
||||||
|
@ -478,10 +478,22 @@ fn (mut p Parser) fn_receiver(mut params []table.Param, mut rec ReceiverParsingI
|
||||||
if is_atomic {
|
if is_atomic {
|
||||||
rec.typ = rec.typ.set_flag(.atomic_f)
|
rec.typ = rec.typ.set_flag(.atomic_f)
|
||||||
}
|
}
|
||||||
|
// optimize method `automatic use fn (a &big_foo) instead of fn (a big_foo)`
|
||||||
|
type_sym := p.table.get_type_symbol(rec.typ)
|
||||||
|
mut is_auto_rec := false
|
||||||
|
if type_sym.kind == .struct_ {
|
||||||
|
info := type_sym.info as table.Struct
|
||||||
|
if !rec.is_mut && !rec.typ.is_ptr() && info.fields.len > 8 {
|
||||||
|
rec.typ = rec.typ.to_ptr()
|
||||||
|
is_auto_rec = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params << table.Param{
|
params << table.Param{
|
||||||
pos: rec_start_pos
|
pos: rec_start_pos
|
||||||
name: rec.name
|
name: rec.name
|
||||||
is_mut: rec.is_mut
|
is_mut: rec.is_mut
|
||||||
|
is_auto_rec: is_auto_rec
|
||||||
typ: rec.typ
|
typ: rec.typ
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
|
|
|
@ -60,6 +60,7 @@ pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
name string
|
name string
|
||||||
is_mut bool
|
is_mut bool
|
||||||
|
is_auto_rec bool
|
||||||
typ Type
|
typ Type
|
||||||
type_pos token.Position
|
type_pos token.Position
|
||||||
is_hidden bool // interface first arg
|
is_hidden bool // interface first arg
|
||||||
|
|
Loading…
Reference in New Issue