aboutsummaryrefslogtreecommitdiff
path: root/src/parse.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-09-01 13:04:26 +0200
committerlemon <lsof@mailbox.org>2022-09-01 14:07:46 +0200
commit6ea6819e5a8b6e2b2c818249642e7923db9f81c8 (patch)
tree01aeb453d0b18e2cad018970daedb216095ad028 /src/parse.cff
parent2e0160015d756702a799be95db237b7a91bae400 (diff)
on big aggregates big, use a hash map to lookup fields
Diffstat (limited to 'src/parse.cff')
-rw-r--r--src/parse.cff45
1 files changed, 26 insertions, 19 deletions
diff --git a/src/parse.cff b/src/parse.cff
index 7afec96..1b5fba3 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -730,23 +730,13 @@ fn isdecltokt(t TokT) bool {
struct BloomFilt {
bits [4]u32,
- fn _hash(x u32) u32 {
- // https://nullprogram.com/blog/2018/07/31/
- x ^= x >> 16;
- x *= 0x7feb352dU;
- x ^= x >> 15;
- x *= 0x846ca68bU;
- x ^= x >> 16;
- return x;
- }
-
def NHASH = 4;
def NBITS = 8 * sizeof BloomFilt;
fn add(this *BloomFilt, s *const u8) void {
let h u32 = as(uptrint)s;
for let i = 0; i < NHASH; ++i {
- h = _hash(h);
+ h = cwhash32(h);
let idx = h % NBITS;
this.bits[idx/32] |= 1u32 << (idx%32);
}
@@ -755,7 +745,7 @@ struct BloomFilt {
fn matches(this *const BloomFilt, s *const u8) bool {
let h u32 = as(uptrint)s;
for let i = 0; i < NHASH; ++i {
- h = _hash(h);
+ h = cwhash32(h);
let idx = h % NBITS;
if this.bits[idx/32] & (1u64 << (idx%32)) == 0 {
return #f;
@@ -840,6 +830,11 @@ fn parseagg(P *Parser, loc Loc, kind AggKind, name *const u8, retdecl **Decl) *c
ty.size = size;
ty.align = align;
agg.flds = flds.dat[0::flds.len];
+ if agg.flds.#len >= IDXMAP_MIN_WORTHIT {
+ agg.idxmap->init(agg.flds.#len, agg.flds.#ptr, sizeof AggField);
+ } else {
+ agg.idxmap = {};
+ }
*constty = *ty;
constty.konst = #t;
if kind == :EUnion {
@@ -890,7 +885,10 @@ fn parseagg(P *Parser, loc Loc, kind AggKind, name *const u8, retdecl **Decl) *c
}
fn findaggfield(ty *const Type, name *const u8) *AggField {
- foreach_ptr(fld, i, ty.u.Agg.flds) {
+ if ty.u.Agg.idxmap.idxs {
+ return ty.u.Agg.idxmap->find(name, ty.u.Agg.flds.#ptr, sizeof AggField);
+ }
+ foreach_ptr(fld, _, ty.u.Agg.flds) {
if fld.name == name {
return fld;
}
@@ -899,7 +897,10 @@ fn findaggfield(ty *const Type, name *const u8) *AggField {
}
fn findbitffield(ty *const Type, name *const u8) *BitFField {
- foreach_ptr(fld, i, ty.u.BitF.flds) {
+ if ty.u.BitF.idxmap.idxs {
+ return ty.u.BitF.idxmap->find(name, ty.u.BitF.flds.#ptr, sizeof BitFField);
+ }
+ foreach_ptr(fld, _, ty.u.BitF.flds) {
if fld.name == name {
return fld;
}
@@ -987,6 +988,11 @@ fn parsebitfield(P *Parser, name *const u8) *const Type {
}
bitf.flds = flds->move(P.alloc);
+ if bitf.flds.#len >= IDXMAP_MIN_WORTHIT {
+ bitf.idxmap->init(bitf.flds.#len, bitf.flds.#ptr, sizeof BitFField);
+ } else {
+ bitf.idxmap = {};
+ }
return interntype(&ty);
}
@@ -2303,11 +2309,12 @@ fn pexassign(P *Parser) Expr {
switch {
case !islvalue(&ex);
err(P, ex.loc, "left operand to assignment is not lvalue");
- case (typeof2(ex.ty, rhs.ty) == #null)
- and !((ex.ty->is(:Ptr) and rhs.ty->is(:Int)
- and (tok.t == '+=' or tok.t == '-=')));
+ case ex.ty->is(:Ptr) and rhs.ty->is(:Int) and (tok.t == '+=' or tok.t == '-=');
+ // pass
+ case typeof2(ex.ty, rhs.ty) == #null;
err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT",
ex.ty, rhs.ty, &tok);
+
case okind == :IntFlo and (!isnumtype(ex.ty) or !isnumtype(rhs.ty));
err(P, tok.loc, "invalid operands %t and %t for assignment operator %qT",
ex.ty, rhs.ty, &tok);
@@ -2957,7 +2964,7 @@ fn doimport(P *Parser, loc Loc, path *const u8) [#]*Decl {
return d0.decls;
}
rpath = strcpy(malloc(strlen(rpath) + 1), rpath);
- let e = seen->put(rpath, { {}, #t });
+ seen->put(rpath, { {}, #t });
let P2 Parser #?;
parser_init(&P2, rpath);
P2.is_header = #t;
@@ -2965,7 +2972,7 @@ fn doimport(P *Parser, loc Loc, path *const u8) [#]*Decl {
P2.alloc = P.alloc;
let decls = parse4import(&P2);
- *e = { decls, #f };
+ seen->put(rpath, { decls, #f });
return decls;
}