gc: extend optimized mode to strings (#10409)
parent
d0100faf26
commit
3f654a69e3
|
@ -256,6 +256,59 @@ pub fn malloc(n int) &byte {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[unsafe]
|
||||||
|
pub fn malloc_noscan(n int) &byte {
|
||||||
|
if n <= 0 {
|
||||||
|
panic('> V malloc(<=0)')
|
||||||
|
}
|
||||||
|
$if vplayground ? {
|
||||||
|
if n > 10000 {
|
||||||
|
panic('allocating more than 10 KB at once is not allowed in the V playground')
|
||||||
|
}
|
||||||
|
if total_m > 50 * 1024 * 1024 {
|
||||||
|
panic('allocating more than 50 MB is not allowed in the V playground')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$if trace_malloc ? {
|
||||||
|
total_m += n
|
||||||
|
C.fprintf(C.stderr, c'v_malloc %6d total %10d\n', n, total_m)
|
||||||
|
// print_backtrace()
|
||||||
|
}
|
||||||
|
mut res := &byte(0)
|
||||||
|
$if prealloc {
|
||||||
|
return unsafe { prealloc_malloc(n) }
|
||||||
|
} $else $if gcboehm ? {
|
||||||
|
$if gcboehm_opt ? {
|
||||||
|
unsafe {
|
||||||
|
res = C.GC_MALLOC_ATOMIC(n)
|
||||||
|
}
|
||||||
|
} $else {
|
||||||
|
unsafe {
|
||||||
|
res = C.GC_MALLOC(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} $else $if freestanding {
|
||||||
|
mut e := Errno{}
|
||||||
|
res, e = mm_alloc(u64(n))
|
||||||
|
if e != .enoerror {
|
||||||
|
eprint('malloc() failed: ')
|
||||||
|
eprintln(e.str())
|
||||||
|
panic('malloc() failed')
|
||||||
|
}
|
||||||
|
} $else {
|
||||||
|
res = unsafe { C.malloc(n) }
|
||||||
|
}
|
||||||
|
if res == 0 {
|
||||||
|
panic('malloc($n) failed')
|
||||||
|
}
|
||||||
|
$if debug_malloc ? {
|
||||||
|
// Fill in the memory with something != 0, so it is easier to spot
|
||||||
|
// when the calling code wrongly relies on it being zeroed.
|
||||||
|
unsafe { C.memset(res, 0x88, n) }
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// v_realloc resizes the memory block `b` with `n` bytes.
|
// v_realloc resizes the memory block `b` with `n` bytes.
|
||||||
// The `b byteptr` must be a pointer to an existing memory block
|
// The `b byteptr` must be a pointer to an existing memory block
|
||||||
// previously allocated with `malloc`, `v_calloc` or `vcalloc`.
|
// previously allocated with `malloc`, `v_calloc` or `vcalloc`.
|
||||||
|
@ -369,7 +422,11 @@ pub fn vcalloc_noscan(n int) &byte {
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
panic('calloc(<0)')
|
panic('calloc(<0)')
|
||||||
}
|
}
|
||||||
return unsafe { &byte(C.memset(C.GC_MALLOC_ATOMIC(n), 0, n)) }
|
return $if gcboehm_opt ? {
|
||||||
|
unsafe { &byte(C.memset(C.GC_MALLOC_ATOMIC(n), 0, n)) }
|
||||||
|
} $else {
|
||||||
|
unsafe { &byte(C.GC_MALLOC(n)) }
|
||||||
|
}
|
||||||
} $else {
|
} $else {
|
||||||
return unsafe { vcalloc(n) }
|
return unsafe { vcalloc(n) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,7 +248,7 @@ pub fn (a string) clone() string {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
mut b := string{
|
mut b := string{
|
||||||
str: unsafe { malloc(a.len + 1) }
|
str: unsafe { malloc_noscan(a.len + 1) }
|
||||||
len: a.len
|
len: a.len
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -303,7 +303,7 @@ pub fn (s string) replace(rep string, with string) string {
|
||||||
}
|
}
|
||||||
// Now we know the number of replacements we need to do and we can calc the len of the new string
|
// Now we know the number of replacements we need to do and we can calc the len of the new string
|
||||||
new_len := s.len + idxs.len * (with.len - rep.len)
|
new_len := s.len + idxs.len * (with.len - rep.len)
|
||||||
mut b := unsafe { malloc(new_len + 1) } // add space for the null byte at the end
|
mut b := unsafe { malloc_noscan(new_len + 1) } // add space for the null byte at the end
|
||||||
// Fill the new string
|
// Fill the new string
|
||||||
mut b_i := 0
|
mut b_i := 0
|
||||||
mut s_idx := 0
|
mut s_idx := 0
|
||||||
|
@ -406,7 +406,7 @@ pub fn (s string) replace_each(vals []string) string {
|
||||||
return s.clone()
|
return s.clone()
|
||||||
}
|
}
|
||||||
idxs.sort2()
|
idxs.sort2()
|
||||||
mut b := unsafe { malloc(new_len + 1) } // add space for 0 terminator
|
mut b := unsafe { malloc_noscan(new_len + 1) } // add space for 0 terminator
|
||||||
// Fill the new string
|
// Fill the new string
|
||||||
mut idx_pos := 0
|
mut idx_pos := 0
|
||||||
mut cur_idx := idxs[idx_pos]
|
mut cur_idx := idxs[idx_pos]
|
||||||
|
@ -532,7 +532,7 @@ fn (s string) < (a string) bool {
|
||||||
fn (s string) + (a string) string {
|
fn (s string) + (a string) string {
|
||||||
new_len := a.len + s.len
|
new_len := a.len + s.len
|
||||||
mut res := string{
|
mut res := string{
|
||||||
str: unsafe { malloc(new_len + 1) }
|
str: unsafe { malloc_noscan(new_len + 1) }
|
||||||
len: new_len
|
len: new_len
|
||||||
}
|
}
|
||||||
for j in 0 .. s.len {
|
for j in 0 .. s.len {
|
||||||
|
@ -676,7 +676,7 @@ pub fn (s string) substr(start int, end int) string {
|
||||||
return s.clone()
|
return s.clone()
|
||||||
}
|
}
|
||||||
mut res := string{
|
mut res := string{
|
||||||
str: unsafe { malloc(len + 1) }
|
str: unsafe { malloc_noscan(len + 1) }
|
||||||
len: len
|
len: len
|
||||||
}
|
}
|
||||||
for i in 0 .. len {
|
for i in 0 .. len {
|
||||||
|
@ -948,7 +948,7 @@ pub fn (s string) ends_with(p string) bool {
|
||||||
// TODO only works with ASCII
|
// TODO only works with ASCII
|
||||||
pub fn (s string) to_lower() string {
|
pub fn (s string) to_lower() string {
|
||||||
unsafe {
|
unsafe {
|
||||||
mut b := malloc(s.len + 1)
|
mut b := malloc_noscan(s.len + 1)
|
||||||
for i in 0 .. s.len {
|
for i in 0 .. s.len {
|
||||||
if s.str[i] >= `A` && s.str[i] <= `Z` {
|
if s.str[i] >= `A` && s.str[i] <= `Z` {
|
||||||
b[i] = s.str[i] + 32
|
b[i] = s.str[i] + 32
|
||||||
|
@ -977,7 +977,7 @@ pub fn (s string) is_lower() bool {
|
||||||
// Example: assert 'Hello V'.to_upper() == 'HELLO V'
|
// Example: assert 'Hello V'.to_upper() == 'HELLO V'
|
||||||
pub fn (s string) to_upper() string {
|
pub fn (s string) to_upper() string {
|
||||||
unsafe {
|
unsafe {
|
||||||
mut b := malloc(s.len + 1)
|
mut b := malloc_noscan(s.len + 1)
|
||||||
for i in 0 .. s.len {
|
for i in 0 .. s.len {
|
||||||
if s.str[i] >= `a` && s.str[i] <= `z` {
|
if s.str[i] >= `a` && s.str[i] <= `z` {
|
||||||
b[i] = s.str[i] - 32
|
b[i] = s.str[i] - 32
|
||||||
|
@ -1262,7 +1262,11 @@ pub fn (s string) ustring() ustring {
|
||||||
mut res := ustring{
|
mut res := ustring{
|
||||||
s: s // runes will have at least s.len elements, save reallocations
|
s: s // runes will have at least s.len elements, save reallocations
|
||||||
// TODO use VLA for small strings?
|
// TODO use VLA for small strings?
|
||||||
runes: __new_array(0, s.len, int(sizeof(int)))
|
}
|
||||||
|
$if gcboehm_opt ? {
|
||||||
|
res.runes = __new_array_noscan(0, s.len, int(sizeof(int)))
|
||||||
|
} $else {
|
||||||
|
res.runes = __new_array(0, s.len, int(sizeof(int)))
|
||||||
}
|
}
|
||||||
for i := 0; i < s.len; i++ {
|
for i := 0; i < s.len; i++ {
|
||||||
char_len := utf8_char_len(unsafe { s.str[i] })
|
char_len := utf8_char_len(unsafe { s.str[i] })
|
||||||
|
@ -1282,8 +1286,12 @@ __global (
|
||||||
|
|
||||||
pub fn (s string) ustring_tmp() ustring {
|
pub fn (s string) ustring_tmp() ustring {
|
||||||
if g_ustring_runes.len == 0 {
|
if g_ustring_runes.len == 0 {
|
||||||
|
$if gcboehm_opt ? {
|
||||||
|
g_ustring_runes = __new_array_noscan(0, 128, int(sizeof(int)))
|
||||||
|
} $else {
|
||||||
g_ustring_runes = __new_array(0, 128, int(sizeof(int)))
|
g_ustring_runes = __new_array(0, 128, int(sizeof(int)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mut res := ustring{
|
mut res := ustring{
|
||||||
s: s
|
s: s
|
||||||
}
|
}
|
||||||
|
@ -1311,7 +1319,11 @@ fn (u ustring) < (a ustring) bool {
|
||||||
fn (u ustring) + (a ustring) ustring {
|
fn (u ustring) + (a ustring) ustring {
|
||||||
mut res := ustring{
|
mut res := ustring{
|
||||||
s: u.s + a.s
|
s: u.s + a.s
|
||||||
runes: __new_array(0, u.s.len + a.s.len, int(sizeof(int)))
|
}
|
||||||
|
$if gcboehm_opt ? {
|
||||||
|
res.runes = __new_array_noscan(0, u.s.len + a.s.len, int(sizeof(int)))
|
||||||
|
} $else {
|
||||||
|
res.runes = __new_array(0, u.s.len + a.s.len, int(sizeof(int)))
|
||||||
}
|
}
|
||||||
mut j := 0
|
mut j := 0
|
||||||
for i := 0; i < u.s.len; i++ {
|
for i := 0; i < u.s.len; i++ {
|
||||||
|
@ -1586,7 +1598,7 @@ pub fn (a []string) join(sep string) string {
|
||||||
len -= sep.len
|
len -= sep.len
|
||||||
// Allocate enough memory
|
// Allocate enough memory
|
||||||
mut res := string{
|
mut res := string{
|
||||||
str: unsafe { malloc(len + 1) }
|
str: unsafe { malloc_noscan(len + 1) }
|
||||||
len: len
|
len: len
|
||||||
}
|
}
|
||||||
mut idx := 0
|
mut idx := 0
|
||||||
|
@ -1621,7 +1633,7 @@ pub fn (s string) reverse() string {
|
||||||
return s.clone()
|
return s.clone()
|
||||||
}
|
}
|
||||||
mut res := string{
|
mut res := string{
|
||||||
str: unsafe { malloc(s.len + 1) }
|
str: unsafe { malloc_noscan(s.len + 1) }
|
||||||
len: s.len
|
len: s.len
|
||||||
}
|
}
|
||||||
for i := s.len - 1; i >= 0; i-- {
|
for i := s.len - 1; i >= 0; i-- {
|
||||||
|
@ -1676,7 +1688,7 @@ pub fn (s string) repeat(count int) string {
|
||||||
} else if count == 1 {
|
} else if count == 1 {
|
||||||
return s.clone()
|
return s.clone()
|
||||||
}
|
}
|
||||||
mut ret := unsafe { malloc(s.len * count + 1) }
|
mut ret := unsafe { malloc_noscan(s.len * count + 1) }
|
||||||
for i in 0 .. count {
|
for i in 0 .. count {
|
||||||
for j in 0 .. s.len {
|
for j in 0 .. s.len {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1753,7 +1765,7 @@ pub fn (s string) strip_margin_custom(del byte) string {
|
||||||
}
|
}
|
||||||
// don't know how much space the resulting string will be, but the max it
|
// don't know how much space the resulting string will be, but the max it
|
||||||
// can be is this big
|
// can be is this big
|
||||||
mut ret := unsafe { malloc(s.len + 1) }
|
mut ret := unsafe { malloc_noscan(s.len + 1) }
|
||||||
mut count := 0
|
mut count := 0
|
||||||
for i := 0; i < s.len; i++ {
|
for i := 0; i < s.len; i++ {
|
||||||
if s[i] in [10, 13] {
|
if s[i] in [10, 13] {
|
||||||
|
|
Loading…
Reference in New Issue