Skip to content

llgo: fix ptrto for llgo reflect - #104

Merged
visualfc merged 1 commit into
goplus:mainfrom
visualfc:llgo_reflect_ptrto
Sep 14, 2026
Merged

visualfc merged 1 commit into
goplus:mainfrom
visualfc:llgo_reflect_ptrto

Conversation

@visualfc

Copy link
Copy Markdown
Member

No description provided.

@fennoai fennoai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: llgo_reflect_ptrto (PR #104)

This PR changes the llgo build variant (rtype_llgo.go) in two ways:

  1. setMethodSet now reads the cached PtrToThis_ instead of calling PtrTo(typ).
  2. SetUnderlying's Func case replaces an O(n) sync.Map.Range scan (LLGo's sync.Map shim does linear searches) with O(1) deletes over a new bidirectional namedFuncTypes struct linked to reflect.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.

Comment thread rtype_llgo.go Outdated
}
ptyp := PtrTo(typ)
//ptyp := PtrTo(typ)
ptyp := toType(totype(typ).PtrToThis_)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment thread rtype_llgo.go
// 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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment thread rtype_llgo.go Outdated
}
}
ptyp := PtrTo(typ)
//ptyp := PtrTo(typ)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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).

Comment thread rtype_llgo.go
}
return true
})
namedFuncTypes.Lock()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

@visualfc
visualfc merged commit 6a7707d into goplus:main Sep 14, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant