all: cached modules fixes

pull/5874/head
Alexander Medvednikov 2020-07-18 11:14:03 +02:00
parent 411eaadc15
commit 38e5569503
8 changed files with 160 additions and 14 deletions

View File

@ -6,11 +6,12 @@
- thread safe arrays/maps - thread safe arrays/maps
- C2V translator - C2V translator
- doom.v - doom.v
- rune type, replace ustring with []rune - rune type, replace `ustring` with `[]rune`, fix `byte.str()`
- maps with non-string keys - maps with non-string keys
- iOS/Android support - iOS/Android support
- make `-autofree` the default - make `-autofree` the default
- parallel parser (and maybe checker/gen?) - parallel parser (and maybe checker/gen?)
- `recover()` from panics

View File

@ -4,7 +4,8 @@
module builtin module builtin
import strings import strings
import hash.wyhash //import hash.wyhash as hash
import hash
/* /*
This is a highly optimized hashmap implementation. It has several traits that This is a highly optimized hashmap implementation. It has several traits that
@ -225,7 +226,7 @@ fn new_map_init(n, value_bytes int, keys &string, values voidptr) map {
[inline] [inline]
fn (m &map) key_to_index(key string) (u32,u32) { fn (m &map) key_to_index(key string) (u32,u32) {
hash := wyhash.wyhash_c(key.str, u64(key.len), 0) hash := hash.wyhash_c(key.str, u64(key.len), 0)
index := hash & m.cap index := hash & m.cap
meta := ((hash >> m.shift) & hash_mask) | probe_inc meta := ((hash >> m.shift) & hash_mask) | probe_inc
return u32(index),u32(meta) return u32(index),u32(meta)

139
vlib/hash/wyhash.v 100644
View File

@ -0,0 +1,139 @@
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
//
// this is an implementation of wyhash v4
// from https://github.com/wangyi-fudan/wyhash
//
// TODO: use u128 once implemented
// currently the C version performs slightly better
// because it uses 128 bit int when available and
// branch prediction hints. the C version will be
// removed once the perfomance is matched.
// you can test performance by running:
// `v run cmd/tools/bench/wyhash.v`
// try running with and without the `-prod` flag
module hash
//#flag -I @VROOT/thirdparty/wyhash
//#include "wyhash.h"
fn C.wyhash(byteptr, u64, u64) u64
const (
wyp0 = u64(0xa0761d6478bd642f)
wyp1 = u64(0xe7037ed1a0b428db)
wyp2 = u64(0x8ebc6af09c88c6e3)
wyp3 = u64(0x589965cc75374cc3)
wyp4 = u64(0x1d8e4e27c47d124f)
)
[inline]
pub fn wyhash_c(key byteptr, len, seed u64) u64 {
return C.wyhash(key, len, seed)
}
[inline]
pub fn sum64_string(key string, seed u64) u64 {
return wyhash64(key.str, u64(key.len), seed)
}
[inline]
pub fn sum64(key []byte, seed u64) u64 {
return wyhash64(byteptr(key.data), u64(key.len), seed)
}
[inline]
fn wyhash64(key byteptr, len, seed_ u64) u64 {
if len == 0 {
return 0
}
mut p := key
mut seed := seed_
mut i := len & 63
unsafe {
if i < 4 {
seed = wymum(wyr3(p, i) ^ seed ^ wyp0, seed ^ wyp1)
}
else if i <= 8 {
seed = wymum(wyr4(p) ^ seed ^ wyp0, wyr4(p + i - 4) ^ seed ^ wyp1)
}
else if i <= 16 {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + i - 8) ^ seed ^ wyp1)
}
else if i <= 24 {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1) ^ wymum(wyr8(p + i - 8) ^ seed ^ wyp2, seed ^ wyp3)
}
else if i <= 32 {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1) ^ wymum(wyr8(p + 16) ^ seed ^ wyp2, wyr8(p + i - 8) ^ seed ^ wyp3)
}
else {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1) ^ wymum(wyr8(p + 16) ^ seed ^ wyp2, wyr8(p + 24) ^ seed ^ wyp3) ^ wymum(wyr8(p + i - 32) ^ seed ^ wyp1, wyr8(p + i - 24) ^ seed ^ wyp2) ^ wymum(wyr8(p + i - 16) ^ seed ^ wyp3, wyr8(p + i - 8) ^ seed ^ wyp0)
}
}
if i == len {
return wymum(seed, len ^ wyp4)
}
mut see1 := seed
mut see2 := seed
mut see3 := seed
unsafe {
p = p + i
for i = len - i; i >= 64; i -= 64 {
seed = wymum(wyr8(p) ^ seed ^ wyp0, wyr8(p + 8) ^ seed ^ wyp1)
see1 = wymum(wyr8(p + 16) ^ see1 ^ wyp2, wyr8(p + 24) ^ see1 ^ wyp3)
see2 = wymum(wyr8(p + 32) ^ see2 ^ wyp1, wyr8(p + 40) ^ see2 ^ wyp2)
see3 = wymum(wyr8(p + 48) ^ see3 ^ wyp3, wyr8(p + 56) ^ see3 ^ wyp0)
p = p + 64
}
}
return wymum(seed ^ see1 ^ see2, see3 ^ len ^ wyp4)
}
[inline]
fn wyrotr(v u64, k u32) u64 {
return (v>>k) | (v<<(64 - k))
}
[inline]
pub fn wymum(a, b u64) u64 {
/*
mut r := u128(a)
r = r*b
return (r>>64)^r
*/
mask32 := u32(4294967295)
x0 := a & mask32
x1 := a>>32
y0 := b & mask32
y1 := b>>32
w0 := x0 * y0
t := x1 * y0 + (w0>>32)
mut w1 := t & mask32
w2 := t>>32
w1 += x0 * y1
hi := x1 * y1 + w2 + (w1>>32)
lo := a * b
return hi ^ lo
}
[inline]
fn wyr3(p byteptr, k u64) u64 {
unsafe {
return (u64(p[0])<<16) | (u64(p[k>>1])<<8) | u64(p[k - 1])
}
}
[inline]
fn wyr4(p byteptr) u64 {
unsafe {
return u32(p[0]) | (u32(p[1])<<u32(8)) | (u32(p[2])<<u32(16)) | (u32(p[3])<<u32(24))
}
}
[inline]
fn wyr8(p byteptr) u64 {
unsafe {
return u64(p[0]) | (u64(p[1])<<8) | (u64(p[2])<<16) | (u64(p[3])<<24) | (u64(p[4])<<32) | (u64(p[5])<<40) | (u64(p[6])<<48) | (u64(p[7])<<56)
}
}

View File

@ -65,7 +65,7 @@ const(
// max 46 char // max 46 char
// -3.40282346638528859811704183484516925440e+38 // -3.40282346638528859811704183484516925440e+38
fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string { pub fn (d Dec32) get_string_32(neg bool, i_n_digit int, i_pad_digit int) string {
n_digit := i_n_digit + 1 n_digit := i_n_digit + 1
pad_digit := i_pad_digit + 1 pad_digit := i_pad_digit + 1
mut out := d.m mut out := d.m

View File

@ -355,7 +355,7 @@ fn (mut v Builder) cc() {
} }
if v.pref.use_cache { if v.pref.use_cache {
// vexe := pref.vexe_path() // vexe := pref.vexe_path()
cached_modules := ['builtin', 'os', 'math', 'strconv', 'strings', 'hash.wyhash', 'strconv.ftoa'] cached_modules := ['builtin', 'os', 'math', 'strconv', 'strings', 'hash'] // , 'strconv.ftoa']
for cfile in cached_modules { for cfile in cached_modules {
ofile := os.join_path(pref.default_module_path, 'cache', 'vlib', cfile.replace('.', '/') + ofile := os.join_path(pref.default_module_path, 'cache', 'vlib', cfile.replace('.', '/') +
'.o') '.o')

View File

@ -102,7 +102,7 @@ mut:
const ( const (
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t', tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
'\t\t\t\t\t\t\t\t' '\t\t\t\t\t\t\t\t',
] ]
) )
@ -721,7 +721,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
mut skip := false mut skip := false
pos := g.out.buf.len pos := g.out.buf.len
if g.pref.build_mode == .build_module { if g.pref.build_mode == .build_module {
if !node.name.starts_with(g.module_built + '.') { if !node.name.starts_with(g.module_built + '.') && node.mod != g.module_built {
// Skip functions that don't have to be generated // Skip functions that don't have to be generated
// for this module. // for this module.
skip = true skip = true
@ -743,7 +743,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
node.name == 'backtrace_symbols_fd' { node.name == 'backtrace_symbols_fd' {
g.write('\n#ifndef __cplusplus\n') g.write('\n#ifndef __cplusplus\n')
} }
g.gen_fn_decl(node) g.gen_fn_decl(node, skip)
if node.name == 'backtrace' || if node.name == 'backtrace' ||
node.name == 'backtrace_symbols' || node.name == 'backtrace_symbols' ||
node.name == 'backtrace_symbols_fd' { node.name == 'backtrace_symbols_fd' {
@ -2376,7 +2376,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
if !is_guard { if !is_guard {
is_guard = true is_guard = true
guard_idx = i guard_idx = i
guard_vars = []string{ len: node.branches.len } guard_vars = []string{len: node.branches.len}
g.writeln('{ /* if guard */ ') g.writeln('{ /* if guard */ ')
} }
var_name := g.new_tmp_var() var_name := g.new_tmp_var()
@ -2898,7 +2898,7 @@ fn (mut g Gen) go_back_out(n int) {
const ( const (
skip_struct_init = ['strconv__ftoa__Uf32', 'strconv__ftoa__Uf64', 'strconv__Float64u', 'struct stat', skip_struct_init = ['strconv__ftoa__Uf32', 'strconv__ftoa__Uf64', 'strconv__Float64u', 'struct stat',
'struct addrinfo' 'struct addrinfo',
] ]
) )

View File

@ -7,7 +7,7 @@ import v.ast
import v.table import v.table
import v.util import v.util
fn (mut g Gen) gen_fn_decl(it ast.FnDecl) { fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
if it.language == .c { if it.language == .c {
// || it.no_body { // || it.no_body {
return return
@ -15,6 +15,9 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
// if g.fileis('vweb.v') { // if g.fileis('vweb.v') {
// println('\ngen_fn_decl() $it.name $it.is_generic $g.cur_generic_type') // println('\ngen_fn_decl() $it.name $it.is_generic $g.cur_generic_type')
// } // }
if g.pref.use_cache && skip {
return
}
if it.is_generic && g.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion if it.is_generic && g.cur_generic_type == 0 { // need the cur_generic_type check to avoid inf. recursion
// loop thru each generic type and generate a function // loop thru each generic type and generate a function
for gen_type in g.table.fn_gen_types[it.name] { for gen_type in g.table.fn_gen_types[it.name] {
@ -23,7 +26,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
println('gen fn `$it.name` for type `$sym.name`') println('gen fn `$it.name` for type `$sym.name`')
} }
g.cur_generic_type = gen_type g.cur_generic_type = gen_type
g.gen_fn_decl(it) g.gen_fn_decl(it, skip)
} }
g.cur_generic_type = 0 g.cur_generic_type = 0
return return
@ -107,7 +110,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
fargs, fargtypes := g.fn_args(it.args, it.is_variadic) fargs, fargtypes := g.fn_args(it.args, it.is_variadic)
if it.no_body || (g.pref.use_cache && it.is_builtin) { if it.no_body || (g.pref.use_cache && it.is_builtin) {
// Just a function header. Builtin function bodies are defined in builtin.o // Just a function header. Builtin function bodies are defined in builtin.o
g.definitions.writeln(');') g.definitions.writeln('); // NO BODY')
g.writeln(');') g.writeln(');')
return return
} }

View File

@ -12,7 +12,9 @@ pub const (
// math.bits is needed by strconv.ftoa // math.bits is needed by strconv.ftoa
pub const ( pub const (
builtin_module_parts = ['math.bits', 'strconv', 'strconv.ftoa', 'hash.wyhash', 'strings', 'builtin'] builtin_module_parts = ['math.bits', 'strconv', 'strconv.ftoa', 'hash', 'hash.wyhash', 'strings',
'builtin',
]
) )
pub const ( pub const (