builtin: optimize `array.repeat()` (#10396)

pull/10400/head
Uwe Krüger 2021-06-09 11:52:30 +02:00 committed by GitHub
parent 115edff7e9
commit 811a3e1d38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 29 deletions

View File

@ -108,6 +108,9 @@ fn (mut a array) ensure_cap(required int) {
// repeat returns a new array with the given array elements repeated given times. // repeat returns a new array with the given array elements repeated given times.
// `cgen` will replace this with an apropriate call to `repeat_to_depth()` // `cgen` will replace this with an apropriate call to `repeat_to_depth()`
// This is a dummy placeholder that will be overridden by `cgen` with an appropriate
// call to `repeat_to_depth()`. However the `checker` needs it here.
pub fn (a array) repeat(count int) array { pub fn (a array) repeat(count int) array {
return unsafe { a.repeat_to_depth(count, 0) } return unsafe { a.repeat_to_depth(count, 0) }
} }
@ -129,14 +132,16 @@ pub fn (a array) repeat_to_depth(count int, depth int) array {
len: count * a.len len: count * a.len
cap: count * a.len cap: count * a.len
} }
if a.len > 0 {
for i in 0 .. count { for i in 0 .. count {
if a.len > 0 && depth > 0 { if depth > 0 {
ary_clone := unsafe { a.clone_to_depth(depth - 1) } ary_clone := unsafe { a.clone_to_depth(depth) }
unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(ary_clone.data), a.len * a.element_size) } unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(ary_clone.data), a.len * a.element_size) }
} else { } else {
unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(a.data), a.len * a.element_size) } unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(a.data), a.len * a.element_size) }
} }
} }
}
return arr return arr
} }
@ -334,18 +339,16 @@ fn (a array) slice2(start int, _end int, end_max bool) array {
return a.slice(start, end) return a.slice(start, end)
} }
// clone_static returns an independent copy of a given array // `clone_static_to_depth()` returns an independent copy of a given array.
// It should be used only in -autofree generated code. // Unlike `clone_to_depth()` it has a value receiver and is used internally
fn (a array) clone_static() array { // for slice-clone expressions like `a[2..4].clone()` and in -autofree generated code.
return a.clone()
}
fn (a array) clone_static_to_depth(depth int) array { fn (a array) clone_static_to_depth(depth int) array {
return unsafe { a.clone_to_depth(depth) } return unsafe { a.clone_to_depth(depth) }
} }
// clone returns an independent copy of a given array. // clone returns an independent copy of a given array.
// this will be overwritten by `cgen` with an apropriate call to `.clone_to_depth()` // this will be overwritten by `cgen` with an apropriate call to `.clone_to_depth()`
// However the `checker` needs it here.
pub fn (a &array) clone() array { pub fn (a &array) clone() array {
return unsafe { a.clone_to_depth(0) } return unsafe { a.clone_to_depth(0) }
} }
@ -703,9 +706,6 @@ fn new_array_from_c_array_noscan(len int, cap int, elm_size int, c_array voidptr
// repeat returns a new array with the given array elements repeated given times. // repeat returns a new array with the given array elements repeated given times.
// `cgen` will replace this with an apropriate call to `repeat_to_depth()` // `cgen` will replace this with an apropriate call to `repeat_to_depth()`
pub fn (a array) repeat_noscan(count int) array {
return unsafe { a.repeat_to_depth_noscan(count, 0) }
}
// version of `repeat()` that handles multi dimensional arrays // version of `repeat()` that handles multi dimensional arrays
// `unsafe` to call directly because `depth` is not checked // `unsafe` to call directly because `depth` is not checked
@ -724,17 +724,16 @@ fn (a array) repeat_to_depth_noscan(count int, depth int) array {
len: count * a.len len: count * a.len
cap: count * a.len cap: count * a.len
} }
size_of_array := int(sizeof(array)) if a.len > 0 {
for i in 0 .. count { for i in 0 .. count {
if a.len > 0 && depth > 0 { if depth > 0 {
ary := array{} ary_clone := unsafe { a.clone_to_depth_noscan(depth) }
unsafe { C.memcpy(&ary, a.data, size_of_array) } unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(ary_clone.data), a.len * a.element_size) }
ary_clone := unsafe { ary.clone_to_depth_noscan(depth - 1) }
unsafe { C.memcpy(arr.get_unsafe(i * a.len), &ary_clone, a.len * a.element_size) }
} else { } else {
unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(a.data), a.len * a.element_size) } unsafe { C.memcpy(arr.get_unsafe(i * a.len), &byte(a.data), a.len * a.element_size) }
} }
} }
}
return arr return arr
} }

View File

@ -654,9 +654,6 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
if node.name in ['clone', 'repeat'] { if node.name in ['clone', 'repeat'] {
elem_type := (left_sym.info as ast.Array).elem_type elem_type := (left_sym.info as ast.Array).elem_type
array_depth = g.get_array_depth(elem_type) array_depth = g.get_array_depth(elem_type)
if node.name == 'repeat' {
array_depth++
}
} }
} else if left_sym.kind == .chan { } else if left_sym.kind == .chan {
if node.name in ['close', 'try_pop', 'try_push'] { if node.name in ['close', 'try_pop', 'try_push'] {

View File

@ -82,14 +82,12 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.F
'21.get_unsafe', '21.get_unsafe',
'21.set_unsafe', '21.set_unsafe',
'21.get_with_check' /* used for `x := a[i] or {}` */, '21.get_with_check' /* used for `x := a[i] or {}` */,
'21.clone_static',
'21.clone_static_to_depth', '21.clone_static_to_depth',
'21.clone_to_depth', '21.clone_to_depth',
'21.first', '21.first',
'21.last', '21.last',
'21.pointers' /* TODO: handle generic methods calling array primitives more precisely in pool_test.v */, '21.pointers' /* TODO: handle generic methods calling array primitives more precisely in pool_test.v */,
'21.reverse', '21.reverse',
'21.repeat',
'21.repeat_to_depth', '21.repeat_to_depth',
'21.slice', '21.slice',
'21.slice2', '21.slice2',