One Scala wrapper per engine object, cached on the object itself through Godot's instance bindings (the godot-cpp mechanism).
The first time an object is wrapped, Godot calls createCallback: it returns the object's bound user instance if it has one, else a fresh wrapper of the object's most-derived generated class (gdext.classes.ClassFactory). Later wraps are a single object_get_instance_binding call: no allocation, and the same wrapper every time. When the engine frees the object, Godot calls freeCallback, which clears the wrapper's handle, so calling a method on it throws instead of touching freed memory.
The binding is a gdext.internal.SlotTable token, never a raw Scala address, so the GC always sees the wrapper through the table.