llgo: fix ptrto for llgo reflect - #104
Conversation
There was a problem hiding this comment.
Review: llgo_reflect_ptrto (PR #104)
This PR changes the llgo build variant (rtype_llgo.go) in two ways:
setMethodSetnow reads the cachedPtrToThis_instead of callingPtrTo(typ).SetUnderlying'sFunccase replaces an O(n)sync.Map.Rangescan (LLGo'ssync.Mapshim does linear searches) with O(1) deletes over a new bidirectionalnamedFuncTypesstruct linked toreflect.namedFuncTypes.
The direction is good — both are genuine simplifications/perf wins on type-construction paths, and the type keys line up (funcType = abi.FuncType, structType = abi.StructType). Two correctness items are worth confirming before merge, plus minor cleanups. Findings are inline.
Note on the linkname: goplus/llgo main currently still declares var namedFuncMap sync.Map and has no namedFuncTypes symbol. This PR therefore depends on a paired LLGo runtime change that renames the symbol and switches to this exact struct layout. Since //go:linkname is unchecked, a layout/name mismatch is silent memory corruption, not a build error — please confirm the runtime revision this builds against matches.
| } | ||
| ptyp := PtrTo(typ) | ||
| //ptyp := PtrTo(typ) | ||
| ptyp := toType(totype(typ).PtrToThis_) |
There was a problem hiding this comment.
[P1] PtrToThis_ may be nil for types not built via newMethodSet
The old ptyp := PtrTo(typ) always returned a valid pointer type. The new toType(totype(typ).PtrToThis_) reads a field documented as "may be nil" (internal/abi/type_llgo.go:61). PtrToThis_ is only populated by newMethodSet (rtype_llgo.go:312), but setMethodSet is also reachable from the public SetRawMethods/SetMethodSet (method.go:256,276), which pass the caller's styp straight through. If such a type has a nil PtrToThis_, ptyp becomes a nil reflect.Type and the next line resizeMethod(ptyp, ...) calls totype(ptyp).Uncommon() on a nil *rtype — nil-pointer dereference.
Suggest guarding, e.g.:
ptyp := PtrTo(typ)
if p := totype(typ).PtrToThis_; p != nil {
ptyp = toType(p)
}or explicitly documenting/enforcing that PtrToThis_ is always set before setMethodSet is reached.
| // Use typed maps: LLGo's sync.Map compatibility implementation performs linear | ||
| // searches. Both directions must identify the same canonical descriptor pair. | ||
| // | ||
| //go:linkname namedFuncTypes reflect.namedFuncTypes |
There was a problem hiding this comment.
[P1] linkname struct must byte-for-byte match reflect.namedFuncTypes
This //go:linkname aliases the runtime symbol without any type checking, so the struct layout here (embedded sync.Mutex first, then funcs map[*abi.StructType]*abi.FuncType, then closures map[*abi.FuncType]*abi.StructType, in this order) must be byte-for-byte identical to the LLGo runtime's reflect.namedFuncTypes. A mismatch in field order, types, or the symbol name is silent memory corruption, not a compile error.
For reference, goplus/llgo main today still defines var namedFuncMap sync.Map and has no namedFuncTypes symbol, so this requires a matching runtime-side change. Please confirm the paired runtime revision defines this exact layout and that both maps are initialized on the runtime side (reads on a nil map are safe but would make the cleanup a silent no-op). Consider extending the comment to state the layout-match requirement and the funcs[s]==f iff closures[f]==s invariant.
| } | ||
| } | ||
| ptyp := PtrTo(typ) | ||
| //ptyp := PtrTo(typ) |
There was a problem hiding this comment.
[P3] Remove leftover commented-out //ptyp := PtrTo(typ)
Dead commented-out code directly above the live line adds noise. Remove it (a real nil-fallback, per the other finding, would be the better expression of the intent).
| } | ||
| return true | ||
| }) | ||
| namedFuncTypes.Lock() |
There was a problem hiding this comment.
[P3] Stale comment still references removed namedFuncMap
The comment just above (// delete named closure entry from namedFuncMap by matching its runtime func type) is now inaccurate: namedFuncMap was renamed to namedFuncTypes, and the code no longer "matches"/scans — it does a direct O(1) map lookup and removes both directions. Update it, e.g. // remove the named closure's entries from both namedFuncTypes maps.
8c353b0 to
b041e00
Compare
No description provided.