Code review fixes:

* Renamed jsonValue obj field to val
* Renamed jsonValue children field to owned + added an explicit comment about this field
* Got rid of unnecessary vm handle checks
* Renamed arg to param, identifiers to paramNames
* Raised maxID value to 100 000
* Removed freedIDs entry check
This commit is contained in:
Alexander Petrov 2019-10-02 11:47:07 +01:00 committed by Stanisław Barzowski
parent 3504d5001e
commit 4abec72f46
2 changed files with 24 additions and 42 deletions

View File

@ -20,8 +20,9 @@ type vm struct {
} }
type jsonValue struct { type jsonValue struct {
obj interface{} val interface{}
children []*C.struct_JsonnetJsonValue // these objects are exclusively owned by this jsonValue
owned []*C.struct_JsonnetJsonValue
} }
var handles = handlesTable{} var handles = handlesTable{}
@ -166,21 +167,21 @@ func jsonnet_native_callback(vmRef *C.struct_JsonnetVm, name *C.char, cb *C.Json
p := unsafe.Pointer(params) p := unsafe.Pointer(params)
sz := unsafe.Sizeof(*params) sz := unsafe.Sizeof(*params)
var identifiers ast.Identifiers var paramNames ast.Identifiers
for i := 0; ; i++ { for i := 0; ; i++ {
arg := (**C.char)(unsafe.Pointer(uintptr(p) + uintptr(i)*sz)) param := (**C.char)(unsafe.Pointer(uintptr(p) + uintptr(i)*sz))
if *arg == nil { if *param == nil {
break break
} }
identifiers = append(identifiers, ast.Identifier(C.GoString(*arg))) paramNames = append(paramNames, ast.Identifier(C.GoString(*param)))
} }
f := &jsonnet.NativeFunction{ f := &jsonnet.NativeFunction{
Name: C.GoString(name), Name: C.GoString(name),
Params: identifiers, Params: paramNames,
Func: func(x []interface{}) (interface{}, error) { Func: func(x []interface{}) (interface{}, error) {
var ( var (
arr []*C.struct_JsonnetJsonValue arr []*C.struct_JsonnetJsonValue
@ -211,7 +212,7 @@ func jsonnet_native_callback(vmRef *C.struct_JsonnetVm, name *C.char, cb *C.Json
return nil, fmt.Errorf("failed to execute native callback, code: %d", success) return nil, fmt.Errorf("failed to execute native callback, code: %d", success)
} }
return v.obj, nil return v.val, nil
}, },
} }
@ -220,9 +221,8 @@ func jsonnet_native_callback(vmRef *C.struct_JsonnetVm, name *C.char, cb *C.Json
//export jsonnet_json_extract_string //export jsonnet_json_extract_string
func jsonnet_json_extract_string(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue) *C.char { func jsonnet_json_extract_string(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue) *C.char {
_ = getVM(vmRef) // Here we check it, is it ok?
v := getJSONValue(json) v := getJSONValue(json)
str, ok := v.obj.(string) str, ok := v.val.(string)
if !ok { if !ok {
return nil return nil
@ -233,10 +233,9 @@ func jsonnet_json_extract_string(vmRef *C.struct_JsonnetVm, json *C.struct_Jsonn
//export jsonnet_json_extract_number //export jsonnet_json_extract_number
func jsonnet_json_extract_number(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue, out *C.double) C.int { func jsonnet_json_extract_number(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue, out *C.double) C.int {
_ = getVM(vmRef) // Here we check it, is it ok?
v := getJSONValue(json) v := getJSONValue(json)
switch f := v.obj.(type) { switch f := v.val.(type) {
case float64: case float64:
*out = C.double(f) *out = C.double(f)
return 1 return 1
@ -250,9 +249,8 @@ func jsonnet_json_extract_number(vmRef *C.struct_JsonnetVm, json *C.struct_Jsonn
//export jsonnet_json_extract_bool //export jsonnet_json_extract_bool
func jsonnet_json_extract_bool(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue) C.int { func jsonnet_json_extract_bool(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue) C.int {
_ = getVM(vmRef) // Here we check it, is it ok?
v := getJSONValue(json) v := getJSONValue(json)
b, ok := v.obj.(bool) b, ok := v.val.(bool)
if !ok { if !ok {
return 2 return 2
@ -267,10 +265,9 @@ func jsonnet_json_extract_bool(vmRef *C.struct_JsonnetVm, json *C.struct_Jsonnet
//export jsonnet_json_extract_null //export jsonnet_json_extract_null
func jsonnet_json_extract_null(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue) C.int { func jsonnet_json_extract_null(vmRef *C.struct_JsonnetVm, json *C.struct_JsonnetJsonValue) C.int {
_ = getVM(vmRef) // Here we check it, is it ok?
v := getJSONValue(json) v := getJSONValue(json)
if v.obj == nil { if v.val == nil {
return 1 return 1
} }
@ -306,16 +303,15 @@ func jsonnet_json_make_array(vmRef *C.struct_JsonnetVm) *C.struct_JsonnetJsonVal
func jsonnet_json_array_append(vmRef *C.struct_JsonnetVm, arr *C.struct_JsonnetJsonValue, v *C.struct_JsonnetJsonValue) { func jsonnet_json_array_append(vmRef *C.struct_JsonnetVm, arr *C.struct_JsonnetJsonValue, v *C.struct_JsonnetJsonValue) {
_ = getVM(vmRef) // Here we check it, is it ok? _ = getVM(vmRef) // Here we check it, is it ok?
json := getJSONValue(arr) json := getJSONValue(arr)
slice, ok := json.obj.([]interface{}) slice, ok := json.val.([]interface{})
if !ok { if !ok {
fmt.Fprintf(os.Stderr, "array should be provided") fmt.Fprintf(os.Stderr, "array should be provided")
os.Exit(1) os.Exit(1)
} }
val := getJSONValue(v) json.val = append(slice, getJSONValue(v).val)
json.obj = append(slice, val.obj) json.owned = append(json.owned, v)
json.children = append(json.children, v)
} }
//export jsonnet_json_make_object //export jsonnet_json_make_object
@ -332,24 +328,20 @@ func jsonnet_json_object_append(
) { ) {
_ = getVM(vmRef) // Here we check it, is it ok? _ = getVM(vmRef) // Here we check it, is it ok?
d := getJSONValue(obj) d := getJSONValue(obj)
table, ok := d.obj.(map[string]interface{}) table, ok := d.val.(map[string]interface{})
if !ok { if !ok {
fmt.Fprintf(os.Stderr, "object should be provided") fmt.Fprintf(os.Stderr, "object should be provided")
os.Exit(1) os.Exit(1)
} }
val := getJSONValue(v) table[C.GoString(f)] = getJSONValue(v).val
table[C.GoString(f)] = val.obj d.owned = append(d.owned, v)
d.children = append(d.children, v)
} }
//export jsonnet_json_destroy //export jsonnet_json_destroy
func jsonnet_json_destroy(vmRef *C.struct_JsonnetVm, v *C.struct_JsonnetJsonValue) { func jsonnet_json_destroy(vmRef *C.struct_JsonnetVm, v *C.struct_JsonnetJsonValue) {
_ = getVM(vmRef) // Here we check it, is it ok? for _, child := range getJSONValue(v).owned {
for _, child := range getJSONValue(v).children {
// TODO what if a child is already freed?
jsonnet_json_destroy(vmRef, child) jsonnet_json_destroy(vmRef, child)
} }
@ -361,9 +353,8 @@ func jsonnet_json_destroy(vmRef *C.struct_JsonnetVm, v *C.struct_JsonnetJsonValu
C.jsonnet_internal_free_json(v) C.jsonnet_internal_free_json(v)
} }
func createJSONValue(vmRef *C.struct_JsonnetVm, obj interface{}) *C.struct_JsonnetJsonValue { func createJSONValue(vmRef *C.struct_JsonnetVm, val interface{}) *C.struct_JsonnetJsonValue {
_ = getVM(vmRef) // Here we check it, is it ok? id, err := handles.make(&jsonValue{val: val})
id, err := handles.make(&jsonValue{obj: obj})
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, err.Error()) fmt.Fprintf(os.Stderr, err.Error())

View File

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
) )
const maxID = 1000 const maxID = 100000
// Because of Go GC, there are restrictions on keeping Go pointers in C. // Because of Go GC, there are restrictions on keeping Go pointers in C.
// We cannot just pass *jsonnet.VM/JsonValue to C. So instead we use "handle" structs in C // We cannot just pass *jsonnet.VM/JsonValue to C. So instead we use "handle" structs in C
@ -15,7 +15,7 @@ const maxID = 1000
// become a problem. // become a problem.
// The Handle IDs start with 1, so 0 is never a valid ID and the Handle's index in the array is (ID - 1). // The Handle IDs start with 1, so 0 is never a valid ID and the Handle's index in the array is (ID - 1).
// handlesTable is the set of active, valid Jsonnet virtual machine handles allocated by jsonnet_make*. // handlesTable is the set of active, valid Jsonnet allocated handles
type handlesTable struct { type handlesTable struct {
objects []interface{} objects []interface{}
freedIDs []uint32 freedIDs []uint32
@ -74,14 +74,5 @@ func (h *handlesTable) ensureValidID(id uint32) error {
return errInvalidHandle return errInvalidHandle
} }
// we should check freed ids too:
// * we should inform a client if there is an attempt to free already freed id
// O(len(freedIDs)) maybe need to use map?
for _, freed := range h.freedIDs {
if freed == id {
return errInvalidHandle
}
}
return nil return nil
} }