Skip to content

Commit

Permalink
Properly implement destructors
Browse files Browse the repository at this point in the history
  • Loading branch information
jerbob92 committed Sep 23, 2023
1 parent 872f6c2 commit 363b671
Show file tree
Hide file tree
Showing 15 changed files with 109 additions and 91 deletions.
20 changes: 9 additions & 11 deletions internal/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,22 @@ func (at *arrayType) ToWireType(ctx context.Context, mod api.Module, destructors
return 0, err
}

ptr := res[0]
ptr := api.DecodeU32(res[0])

for i := 0; i < at.elementsLength; i++ {
err = at.reg.elements[i].write(ctx, mod, api.DecodeI32(ptr), arr[i])
err = at.reg.elements[i].write(ctx, mod, int32(ptr), arr[i])
if err != nil {
return 0, err
}
}

if destructors != nil {
destructorsRef := *destructors
destructorsRef = append(destructorsRef, &destructorFunc{
apiFunction: at.reg.rawDestructor,
args: []uint64{ptr},
})
destructorsRef = append(destructorsRef, at.DestructorFunction(ctx, mod, ptr))
*destructors = destructorsRef
}
return ptr, nil

return api.EncodeU32(ptr), nil
}

func (at *arrayType) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) {
Expand All @@ -73,15 +71,15 @@ func (at *arrayType) ReadValueFromPointer(ctx context.Context, mod api.Module, p
return at.FromWireType(ctx, mod, api.EncodeU32(ptr))
}

func (at *arrayType) HasDestructorFunction() bool {
return true
func (at *arrayType) DestructorFunctionUndefined() bool {
return false
}

func (at *arrayType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) {
func (at *arrayType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc {
return &destructorFunc{
apiFunction: at.reg.rawDestructor,
args: []uint64{api.EncodeU32(pointer)},
}, nil
}
}

func (at *arrayType) GoType() string {
Expand Down
4 changes: 4 additions & 0 deletions internal/bigint.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ func (bt *bigintType) GoType() string {
return "int64"
}

func (bt *bigintType) DestructorFunctionUndefined() bool {
return false
}

func (bt *bigintType) FromF64(o float64) uint64 {
if !bt.signed {
return uint64(o)
Expand Down
4 changes: 4 additions & 0 deletions internal/bool.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ func (bt *boolType) GoType() string {
return "bool"
}

func (bt *boolType) DestructorFunctionUndefined() bool {
return false
}

var RegisterBool = func(hasSize bool) api.GoModuleFunc {
return api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) {
engine := MustGetEngineFromContext(ctx, mod).(*engine)
Expand Down
10 changes: 8 additions & 2 deletions internal/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -1328,9 +1328,14 @@ var RegisterSmartPtr = api.GoModuleFunc(func(ctx context.Context, mod api.Module
}

rawShareFunc, err := engine.newInvokeFunc(shareSignature, rawShare, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32})
specialShare := false
if err != nil {
// @todo: figure out why this fails for some types. Why would some have a different signature?
//panic(fmt.Errorf("could not read rawShare: %w", err))
// Some classes have a different share signature for some reason.
rawShareFunc, err = engine.newInvokeFunc(shareSignature, rawShare, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{})
if err != nil {
panic(fmt.Errorf("could not read rawShare: %w", err))
}
specialShare = true
}

rawDestructorFunc, err := engine.newInvokeFunc(destructorSignature, rawDestructor, []api.ValueType{api.ValueTypeI32}, []api.ValueType{})
Expand All @@ -1356,6 +1361,7 @@ var RegisterSmartPtr = api.GoModuleFunc(func(ctx context.Context, mod api.Module
rawConstructor: rawConstructorFunc,
rawShare: rawShareFunc,
rawDestructor: rawDestructorFunc,
specialShare: specialShare,
}

return []registeredType{smartPointerType}, nil
Expand Down
4 changes: 4 additions & 0 deletions internal/emval.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ func (et *emvalType) ReadValueFromPointer(ctx context.Context, mod api.Module, p
return et.FromWireType(ctx, mod, api.EncodeU32(value))
}

func (et *emvalType) DestructorFunctionUndefined() bool {
return false
}

func (et *emvalType) GoType() string {
return "any"
}
Expand Down
35 changes: 19 additions & 16 deletions internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ func (e *engine) craftInvokerFunction(humanName string, argTypes []registeredTyp
// TODO: Remove this completely once all function invokers are being dynamically generated.
needsDestructorStack := false
for i := 1; i < len(argTypes); i++ { // Skip return value at index 0 - it's not deleted here.
if argTypes[i] != nil && argTypes[i].HasDestructorFunction() { // The type does not define a destructor function - must use dynamic stack
if argTypes[i] != nil && argTypes[i].DestructorFunctionUndefined() { // The type does not define a destructor function - must use dynamic stack
needsDestructorStack = true
break
}
Expand Down Expand Up @@ -491,6 +491,14 @@ func (e *engine) craftInvokerFunction(humanName string, argTypes []registeredTyp
return nil, err
}

var returnVal any
if returns {
returnVal, err = retType.FromWireType(ctx, e.mod, res[0])
if err != nil {
return nil, fmt.Errorf("could not get wire type of return value (%s) on %T: %w", retType.Name(), retType, err)
}
}

if needsDestructorStack {
err = e.runDestructors(ctx, *destructors)
if err != nil {
Expand All @@ -502,29 +510,24 @@ func (e *engine) craftInvokerFunction(humanName string, argTypes []registeredTyp
if isClassMethodFunc {
startArg = 1
}

for i := startArg; i < len(argTypes); i++ {
if argTypes[i].HasDestructorFunction() {
destructorsRef := *destructors
destructor, err := argTypes[i].DestructorFunction(ctx, e.mod, api.DecodeU32(callArgs[i]))
ptrIndex := i
if !isClassMethodFunc {
ptrIndex -= 1
}

argDestructorFunc := argTypes[i].DestructorFunction(ctx, e.mod, api.DecodeU32(callArgs[ptrIndex]))
if argDestructorFunc != nil {
err = argDestructorFunc.run(ctx, e.mod)
if err != nil {
return nil, err
}
destructorsRef = append(destructorsRef, destructor)
*destructors = destructorsRef
}
}
}

if returns {
returnVal, err := retType.FromWireType(ctx, e.mod, res[0])
if err != nil {
return nil, fmt.Errorf("could not get wire type of return value (%s) on %T: %w", retType.Name(), retType, err)
}

return returnVal, nil
}

return nil, nil
return returnVal, nil
}
}

Expand Down
4 changes: 4 additions & 0 deletions internal/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ func (et *enumType) mapToGoEnum(value any) (any, error) {
return val.goValue, nil
}

func (et *enumType) DestructorFunctionUndefined() bool {
return false
}

func (et *enumType) GoType() string {
return et.name
}
Expand Down
4 changes: 4 additions & 0 deletions internal/float.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ func (ft *floatType) GoType() string {
return "float64"
}

func (ft *floatType) DestructorFunctionUndefined() bool {
return false
}

func (ft *floatType) FromF64(o float64) uint64 {
if ft.size == 4 {
return api.EncodeF32(float32(o))
Expand Down
4 changes: 4 additions & 0 deletions internal/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ func (it *intType) GoType() string {
return "int32"
}

func (it *intType) DestructorFunctionUndefined() bool {
return false
}

func (it *intType) FromF64(o float64) uint64 {
if it.size == 1 {
if !it.signed {
Expand Down
20 changes: 9 additions & 11 deletions internal/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,22 @@ func (ot *objectType) ToWireType(ctx context.Context, mod api.Module, destructor
return 0, err
}

ptr := res[0]
ptr := api.DecodeU32(res[0])

for i := range ot.reg.fields {
err = ot.reg.fields[i].write(ctx, mod, api.DecodeI32(ptr), obj[ot.reg.fields[i].fieldName])
err = ot.reg.fields[i].write(ctx, mod, int32(ptr), obj[ot.reg.fields[i].fieldName])
if err != nil {
return 0, err
}
}

if destructors != nil {
destructorsRef := *destructors
destructorsRef = append(destructorsRef, &destructorFunc{
apiFunction: ot.reg.rawDestructor,
args: []uint64{ptr},
})
destructorsRef = append(destructorsRef, ot.DestructorFunction(ctx, mod, ptr))
*destructors = destructorsRef
}
return ptr, nil

return api.EncodeU32(ptr), nil
}

func (ot *objectType) ReadValueFromPointer(ctx context.Context, mod api.Module, pointer uint32) (any, error) {
Expand All @@ -77,15 +75,15 @@ func (ot *objectType) ReadValueFromPointer(ctx context.Context, mod api.Module,
return ot.FromWireType(ctx, mod, api.EncodeU32(ptr))
}

func (ot *objectType) HasDestructorFunction() bool {
return true
func (ot *objectType) DestructorFunctionUndefined() bool {
return false
}

func (ot *objectType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) {
func (ot *objectType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc {
return &destructorFunc{
apiFunction: ot.reg.rawDestructor,
args: []uint64{api.EncodeU32(pointer)},
}, nil
}
}

func (ot *objectType) GoType() string {
Expand Down
46 changes: 22 additions & 24 deletions internal/registered_pointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type registeredPointerType struct {
rawConstructor api.Function
rawShare api.Function
rawDestructor api.Function

specialShare bool // Whether the rawShare is special for this class (no return param)
}

type registeredPointerTypeRecordCount struct {
Expand Down Expand Up @@ -85,16 +87,10 @@ func (rpt *registeredPointerType) FromWireType(ctx context.Context, mod api.Modu
}

if rawPointer == 0 {
destrFun, err := rpt.DestructorFunction(ctx, mod, ptr)
err = rpt.Destructor(ctx, ptr)
if err != nil {
return nil, err
}
if destrFun != nil {
err = destrFun.run(ctx, mod)
if err != nil {
return nil, err
}
}

return nil, nil
}
Expand All @@ -116,11 +112,8 @@ func (rpt *registeredPointerType) FromWireType(ctx context.Context, mod api.Modu
if err != nil {
return nil, err
}
destructor, err := rpt.DestructorFunction(ctx, mod, ptr)
if err != nil {
return nil, err
}
err = destructor.run(ctx, mod)

err = rpt.Destructor(ctx, ptr)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -318,16 +311,17 @@ func (rpt *registeredPointerType) genericPointerToWireType(ctx context.Context,
return 0, err
}

ptr = api.DecodeU32(res[0])
if destructors != nil {
destructorsRef := *destructors
destructorsRef = append(destructorsRef, &destructorFunc{
apiFunction: rpt.rawDestructor,
args: []uint64{res[0]},
args: []uint64{api.EncodeU32(ptr)},
})
*destructors = destructorsRef
}

return res[0], nil
return api.EncodeU32(ptr), nil
} else {
return 0, nil
}
Expand Down Expand Up @@ -410,6 +404,7 @@ func (rpt *registeredPointerType) genericPointerToWireType(ctx context.Context,
_ = clonedHandle.getClassType().delete(ctx, clonedHandle)
})

// @todo: what to do with rpt.specialShare?
res, err := rpt.rawShare.Call(ctx, api.EncodeU32(ptr), api.EncodeI32(deleteCallbackHandle))
if err != nil {
return 0, err
Expand Down Expand Up @@ -441,28 +436,31 @@ func (rpt *registeredPointerType) ReadValueFromPointer(ctx context.Context, mod
return rpt.FromWireType(ctx, mod, api.EncodeU32(value))
}

func (rpt *registeredPointerType) HasDestructorFunction() bool {
func (rpt *registeredPointerType) DestructorFunctionUndefined() bool {
if !rpt.isSmartPointer && rpt.registeredClass.baseClass == nil {
return false
}
return true
}

func (rpt *registeredPointerType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) {
if rpt.rawDestructor != nil {
return &destructorFunc{
apiFunction: rpt.rawDestructor,
args: []uint64{api.EncodeU32(pointer)},
}, nil
}

return nil, nil
func (rpt *registeredPointerType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc {
return nil
}

func (rpt *registeredPointerType) HasDeleteObject() bool {
return true
}

func (rpt *registeredPointerType) Destructor(ctx context.Context, pointer uint32) error {
if rpt.rawDestructor != nil {
_, err := rpt.rawDestructor.Call(ctx, api.EncodeU32(pointer))
if err != nil {
return err
}
}
return nil
}

func (rpt *registeredPointerType) DeleteObject(ctx context.Context, mod api.Module, handle any) error {
if handle != nil {
casted := handle.(IClassBase)
Expand Down
15 changes: 5 additions & 10 deletions internal/std_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,7 @@ func (sst *stdStringType) ToWireType(ctx context.Context, mod api.Module, destru

if destructors != nil {
destructorsRef := *destructors
destructorsRef = append(destructorsRef, &destructorFunc{
function: "free",
args: []uint64{
api.EncodeU32(base),
},
})
destructorsRef = append(destructorsRef, sst.DestructorFunction(ctx, mod, base))
*destructors = destructorsRef
}

Expand All @@ -93,15 +88,15 @@ func (sst *stdStringType) ReadValueFromPointer(ctx context.Context, mod api.Modu
return sst.FromWireType(ctx, mod, api.EncodeU32(ptr))
}

func (sst *stdStringType) HasDestructorFunction() bool {
return true
func (sst *stdStringType) DestructorFunctionUndefined() bool {
return false
}

func (sst *stdStringType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) (*destructorFunc, error) {
func (sst *stdStringType) DestructorFunction(ctx context.Context, mod api.Module, pointer uint32) *destructorFunc {
return &destructorFunc{
apiFunction: mod.ExportedFunction("free"),
args: []uint64{api.EncodeU32(pointer)},
}, nil
}
}

func (sst *stdStringType) GoType() string {
Expand Down
Loading

0 comments on commit 363b671

Please sign in to comment.