Skip to content

Commit

Permalink
v: optimize the compiler performance (#22709)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Oct 31, 2024
1 parent 2ad5d0c commit ee4f29f
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 67 deletions.
6 changes: 0 additions & 6 deletions vlib/builtin/string.v
Original file line number Diff line number Diff line change
Expand Up @@ -746,12 +746,6 @@ fn (s string) == (a string) bool {
if s.len != a.len {
return false
}
if s.len > 0 {
last_idx := s.len - 1
if s[last_idx] != a[last_idx] {
return false
}
}
unsafe {
return vmemcmp(s.str, a.str, a.len) == 0
}
Expand Down
2 changes: 2 additions & 0 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ pub:
is_global bool
is_volatile bool
is_deprecated bool
is_embed bool
pub mut:
is_recursive bool
is_part_of_union bool
Expand Down Expand Up @@ -485,6 +486,7 @@ pub:
next_comments []Comment
has_prev_newline bool
has_break_line bool
is_embed bool
pub mut:
expr Expr // `val1`
name string // 'field1'
Expand Down
1 change: 1 addition & 0 deletions vlib/v/ast/scope.v
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub fn new_scope(parent &Scope, start_pos int) &Scope {
}
*/

@[inline]
fn (s &Scope) dont_lookup_parent() bool {
return s.parent == unsafe { nil } || s.detached_from_parent
}
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/ast/table.v
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,7 @@ pub fn (mut t Table) unwrap_generic_type_ex(typ Type, generic_names []string, co
}
}
// Update type in `info.embeds`, if it's embed
if fields[i].name.len > 1 && fields[i].name[0].is_capital() {
if fields[i].is_embed {
mut parent_sym := t.sym(typ)
mut parent_info := parent_sym.info
if mut parent_info is Struct {
Expand Down Expand Up @@ -2186,7 +2186,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
fields[i].typ = t_typ
}
// Update type in `info.embeds`, if it's embed
if fields[i].name.len > 1 && fields[i].name[0].is_capital() {
if fields[i].is_embed {
for mut embed in parent_info.embeds {
if embed == orig_type {
embed = fields[i].typ
Expand Down
14 changes: 7 additions & 7 deletions vlib/v/ast/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1701,7 +1701,7 @@ pub fn (t &TypeSymbol) embed_name() string {

pub fn (t &TypeSymbol) has_method(name string) bool {
for mut method in unsafe { t.methods } {
if method.name == name {
if method.name.len == name.len && method.name == name {
return true
}
}
Expand All @@ -1715,7 +1715,7 @@ pub fn (t &TypeSymbol) has_method_with_generic_parent(name string) bool {

pub fn (t &TypeSymbol) find_method(name string) ?Fn {
for mut method in unsafe { t.methods } {
if method.name == name {
if method.name.len == name.len && method.name == name {
return method
}
}
Expand Down Expand Up @@ -1830,7 +1830,7 @@ pub fn (t &TypeSymbol) has_field(name string) bool {

fn (a &Aggregate) find_field(name string) ?StructField {
for mut field in unsafe { a.fields } {
if field.name == name {
if field.name.len == name.len && field.name == name {
return field
}
}
Expand All @@ -1839,7 +1839,7 @@ fn (a &Aggregate) find_field(name string) ?StructField {

pub fn (i &Interface) find_field(name string) ?StructField {
for mut field in unsafe { i.fields } {
if field.name == name {
if field.name.len == name.len && field.name == name {
return field
}
}
Expand All @@ -1848,7 +1848,7 @@ pub fn (i &Interface) find_field(name string) ?StructField {

pub fn (i &Interface) find_method(name string) ?Fn {
for mut method in unsafe { i.methods } {
if method.name == name {
if method.name.len == name.len && method.name == name {
return method
}
}
Expand All @@ -1857,7 +1857,7 @@ pub fn (i &Interface) find_method(name string) ?Fn {

pub fn (i &Interface) has_method(name string) bool {
for mut method in unsafe { i.methods } {
if method.name == name {
if method.name.len == name.len && method.name == name {
return true
}
}
Expand All @@ -1866,7 +1866,7 @@ pub fn (i &Interface) has_method(name string) bool {

pub fn (s Struct) find_field(name string) ?StructField {
for mut field in unsafe { s.fields } {
if field.name == name {
if name.len == field.name.len && field.name == name {
return field
}
}
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -5360,10 +5360,10 @@ fn (c &Checker) check_import_sym_conflict(ident string) bool {
for import_sym in c.file.imports {
// Check if alias exists or not
if !import_sym.alias.is_blank() {
if import_sym.alias == ident {
if import_sym.alias.len == ident.len && import_sym.alias == ident {
return true
}
} else if import_sym.mod == ident {
} else if import_sym.mod.len == ident.len && import_sym.mod == ident {
return true
}
}
Expand Down
18 changes: 9 additions & 9 deletions vlib/v/checker/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -806,8 +806,7 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',

// all the fields of initialized embedded struct are ignored, they are considered initialized
sym := c.table.sym(init_field.typ)
if init_field.name != '' && init_field.name[0].is_capital() && sym.kind == .struct
&& sym.language == .v {
if init_field.is_embed && sym.kind == .struct && sym.language == .v {
struct_fields := c.table.struct_fields(sym)
for struct_field in struct_fields {
inited_fields << struct_field.name
Expand Down Expand Up @@ -928,7 +927,7 @@ fn (mut c Checker) check_uninitialized_struct_fields_and_embeds(node ast.StructI
continue
}
sym := c.table.sym(field.typ)
if field.name != '' && field.name[0].is_capital() && sym.info is ast.Struct {
if field.is_embed && sym.info is ast.Struct {
// struct embeds
continue
}
Expand Down Expand Up @@ -957,13 +956,14 @@ fn (mut c Checker) check_uninitialized_struct_fields_and_embeds(node ast.StructI
}
continue
}
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !field.typ.has_flag(.option)
field_is_option := field.typ.has_flag(.option)
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !field_is_option
&& !node.has_update_expr && !c.pref.translated && !c.file.is_translated {
c.error('reference field `${type_sym.name}.${field.name}` must be initialized',
node.pos)
continue
}
if !field.typ.has_flag(.option) {
if !field_is_option {
if sym.kind == .struct {
c.check_ref_fields_initialized(sym, mut checked_types, '${type_sym.name}.${field.name}',
node.pos)
Expand All @@ -976,7 +976,7 @@ fn (mut c Checker) check_uninitialized_struct_fields_and_embeds(node ast.StructI
}
}
// Do not allow empty uninitialized interfaces
if sym.kind == .interface && !node.has_update_expr && !field.typ.has_flag(.option)
if sym.kind == .interface && !node.has_update_expr && !field_is_option
&& sym.language != .js && !field.attrs.contains('noinit') {
// TODO: should be an error instead, but first `ui` needs updating.
c.note('interface field `${type_sym.name}.${field.name}` must be initialized',
Expand All @@ -996,7 +996,7 @@ fn (mut c Checker) check_uninitialized_struct_fields_and_embeds(node ast.StructI
c.error('field `${type_sym.name}.${field.name}` must be initialized', node.pos)
}
if !node.has_update_expr && !field.has_default_expr && !field.typ.is_ptr()
&& !field.typ.has_flag(.option) {
&& !field_is_option {
field_final_sym := c.table.final_sym(field.typ)
if field_final_sym.kind == .struct {
mut zero_struct_init := ast.StructInit{
Expand Down Expand Up @@ -1063,7 +1063,7 @@ fn (mut c Checker) check_ref_fields_initialized(struct_sym &ast.TypeSymbol, mut
if sym.language == .c {
continue
}
if field.name != '' && field.name[0].is_capital() && sym.language == .v {
if field.is_embed && sym.language == .v {
// an embedded struct field
continue
}
Expand Down Expand Up @@ -1106,7 +1106,7 @@ fn (mut c Checker) check_ref_fields_initialized_note(struct_sym &ast.TypeSymbol,
if sym.language == .c {
continue
}
if field.name != '' && field.name[0].is_capital() && sym.language == .v {
if field.is_embed && sym.language == .v {
// an embedded struct field
continue
}
Expand Down
4 changes: 3 additions & 1 deletion vlib/v/depgraph/depgraph.v
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@ pub fn (o &OrderedDepMap) get(name string) []string {
return res
}

@[direct_array_access]
pub fn (mut o OrderedDepMap) delete(name string) {
if name !in o.data {
panic('delete: no such key: ${name}')
}
for i, _ in o.keys {
if o.keys[i] == name {
item := o.keys[i]
if item.len == name.len && item == name {
o.keys.delete(i)
break
}
Expand Down
16 changes: 12 additions & 4 deletions vlib/v/gen/c/array.v
Original file line number Diff line number Diff line change
Expand Up @@ -1086,8 +1086,12 @@ fn (mut g Gen) gen_array_contains_methods() {
ptr_typ := g.equality_fn(elem_type)
fn_builder.writeln('\t\tif (${ptr_typ}_sumtype_eq(((${elem_type_str}*)a.data)[i], v)) {')
} else if elem_kind == .alias && elem_is_not_ptr {
ptr_typ := g.equality_fn(elem_type)
fn_builder.writeln('\t\tif (${ptr_typ}_alias_eq(((${elem_type_str}*)a.data)[i], v)) {')
if g.no_eq_method_types[elem_type] {
fn_builder.writeln('\t\tif (((${elem_type_str}*)a.data)[i] == v) {')
} else {
ptr_typ := g.equality_fn(elem_type)
fn_builder.writeln('\t\tif (${ptr_typ}_alias_eq(((${elem_type_str}*)a.data)[i], v)) {')
}
} else {
fn_builder.writeln('\t\tif (((${elem_type_str}*)a.data)[i] == v) {')
}
Expand Down Expand Up @@ -1124,8 +1128,12 @@ fn (mut g Gen) gen_array_contains_methods() {
ptr_typ := g.equality_fn(elem_type)
fn_builder.writeln('\t\tif (${ptr_typ}_sumtype_eq(a[i], v)) {')
} else if elem_kind == .alias && elem_is_not_ptr {
ptr_typ := g.equality_fn(elem_type)
fn_builder.writeln('\t\tif (${ptr_typ}_alias_eq(a[i], v)) {')
if g.no_eq_method_types[elem_type] {
fn_builder.writeln('\t\tif (a[i] == v) {')
} else {
ptr_typ := g.equality_fn(elem_type)
fn_builder.writeln('\t\tif (${ptr_typ}_alias_eq(a[i], v)) {')
}
} else {
fn_builder.writeln('\t\tif (a[i] == v) {')
}
Expand Down
24 changes: 18 additions & 6 deletions vlib/v/gen/c/auto_eq_methods.v
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,12 @@ fn (mut g Gen) gen_sumtype_equality_fn(left_type ast.Type) string {
eq_fn := g.gen_map_equality_fn(typ)
fn_builder.writeln('\t\treturn ${eq_fn}_map_eq(*${left_arg}, *${right_arg});')
} else if variant.sym.kind == .alias && !typ.is_ptr() {
eq_fn := g.gen_alias_equality_fn(typ)
fn_builder.writeln('\t\treturn ${eq_fn}_alias_eq(*${left_arg}, *${right_arg});')
if g.no_eq_method_types[typ] {
fn_builder.writeln('\t\treturn *${left_arg} == *${right_arg};')
} else {
eq_fn := g.gen_alias_equality_fn(typ)
fn_builder.writeln('\t\treturn ${eq_fn}_alias_eq(*${left_arg}, *${right_arg});')
}
} else if variant.sym.kind == .function {
fn_builder.writeln('\t\treturn *((voidptr*)(*${left_arg})) == *((voidptr*)(*${right_arg}));')
} else {
Expand Down Expand Up @@ -242,8 +246,12 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
eq_fn := g.gen_map_equality_fn(field.typ)
fn_builder.write_string('${eq_fn}_map_eq(${left_arg}, ${right_arg})')
} else if field_type.sym.kind == .alias && !field.typ.is_ptr() {
eq_fn := g.gen_alias_equality_fn(field.typ)
fn_builder.write_string('${eq_fn}_alias_eq(${left_arg}, ${right_arg})')
if g.no_eq_method_types[field.typ] {
fn_builder.write_string('${left_arg} == ${right_arg}')
} else {
eq_fn := g.gen_alias_equality_fn(field.typ)
fn_builder.write_string('${eq_fn}_alias_eq(${left_arg}, ${right_arg})')
}
} else if field_type.sym.kind == .function && !field.typ.has_flag(.option) {
fn_builder.write_string('*((voidptr*)(${left_arg})) == *((voidptr*)(${right_arg}))')
} else if field_type.sym.kind == .interface
Expand Down Expand Up @@ -385,8 +393,12 @@ fn (mut g Gen) gen_array_equality_fn(left_type ast.Type) string {
eq_fn := g.gen_map_equality_fn(elem.typ)
fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(((${ptr_elem_styp}*)${left_data})[i], ((${ptr_elem_styp}*)${right_data})[i])) {')
} else if elem.sym.kind == .alias && !elem.typ.is_ptr() {
eq_fn := g.gen_alias_equality_fn(elem.typ)
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(((${ptr_elem_styp}*)${left_data})[i], ((${ptr_elem_styp}*)${right_data})[i])) {')
if g.no_eq_method_types[elem.typ] {
fn_builder.writeln('\t\tif (((${ptr_elem_styp}*)${left_data})[i] != ((${ptr_elem_styp}*)${right_data})[i]) {')
} else {
eq_fn := g.gen_alias_equality_fn(elem.typ)
fn_builder.writeln('\t\tif (!${eq_fn}_alias_eq(((${ptr_elem_styp}*)${left_data})[i], ((${ptr_elem_styp}*)${right_data})[i])) {')
}
} else if elem.sym.kind == .function {
fn_builder.writeln('\t\tif (*((voidptr*)((byte*)${left_data}+(i*${left_elem}))) != *((voidptr*)((byte*)${right_data}+(i*${right_elem})))) {')
} else {
Expand Down
16 changes: 10 additions & 6 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ mut:
file &ast.File = unsafe { nil }
table &ast.Table = unsafe { nil }
styp_cache map[ast.Type]string
unique_file_path_hash u64 // a hash of file.path, used for making auxiliary fn generation unique (like `compare_xyz`)
no_eq_method_types map[ast.Type]bool // types that does not need to call its auto eq methods for optimization
unique_file_path_hash u64 // a hash of file.path, used for making auxiliary fn generation unique (like `compare_xyz`)
fn_decl &ast.FnDecl = unsafe { nil } // pointer to the FnDecl we are currently inside otherwise 0
last_fn_c_name string
tmp_count int // counter for unique tmp vars (_tmp1, _tmp2 etc); resets at the start of each fn.
Expand Down Expand Up @@ -466,6 +467,9 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) (str
for k, v in g.autofree_methods {
global_g.autofree_methods[k] = v
}
for k, v in g.no_eq_method_types {
global_g.no_eq_method_types[k] = v
}
}
} else {
util.timing_start('cgen serial processing')
Expand Down Expand Up @@ -1062,13 +1066,13 @@ pub fn (mut g Gen) write_typeof_functions() {
// V type to C typecc
@[inline]
fn (mut g Gen) styp(t ast.Type) string {
if t.has_flag(.option) {
if !t.has_option_or_result() {
return g.base_type(t)
} else if t.has_flag(.option) {
// Register an optional if it's not registered yet
return g.register_option(t)
} else if t.has_flag(.result) {
return g.register_result(t)
} else {
return g.base_type(t)
return g.register_result(t)
}
}

Expand Down Expand Up @@ -1098,7 +1102,7 @@ fn (mut g Gen) base_type(_t ast.Type) string {
if t.has_flag(.shared_f) {
styp = g.find_or_register_shared(t, styp)
}
nr_muls := g.unwrap_generic(t).nr_muls()
nr_muls := t.nr_muls()
if nr_muls > 0 {
styp += strings.repeat(`*`, nr_muls)
}
Expand Down
Loading

0 comments on commit ee4f29f

Please sign in to comment.