Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor IteratorReference #501

Merged
merged 7 commits into from
Feb 23, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Rename to IteratorReference
webmaster128 committed Feb 23, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 675ce76a2a031fc5bf3bcc755564a12e8cc41305
20 changes: 14 additions & 6 deletions internal/api/bindings.h
Original file line number Diff line number Diff line change
@@ -255,27 +255,31 @@ typedef struct U8SliceView {
uintptr_t len;
} U8SliceView;

typedef struct iterator_t {
/**
* A reference to some tables on the Go side which allow accessing
* the actual iterator instance.
*/
typedef struct IteratorReference {
/**
* An ID assigned to this contract call
*/
uint64_t call_id;
uint64_t iterator_index;
} iterator_t;
} IteratorReference;

typedef struct IteratorVtable {
int32_t (*next)(struct iterator_t iterator,
int32_t (*next)(struct IteratorReference iterator,
struct gas_meter_t *gas_meter,
uint64_t *gas_used,
struct UnmanagedVector *key_out,
struct UnmanagedVector *value_out,
struct UnmanagedVector *err_msg_out);
int32_t (*next_key)(struct iterator_t iterator,
int32_t (*next_key)(struct IteratorReference iterator,
struct gas_meter_t *gas_meter,
uint64_t *gas_used,
struct UnmanagedVector *key_out,
struct UnmanagedVector *err_msg_out);
int32_t (*next_value)(struct iterator_t iterator,
int32_t (*next_value)(struct IteratorReference iterator,
struct gas_meter_t *gas_meter,
uint64_t *gas_used,
struct UnmanagedVector *value_out,
@@ -284,7 +288,11 @@ typedef struct IteratorVtable {

typedef struct GoIter {
struct gas_meter_t *gas_meter;
struct iterator_t state;
/**
* A reference which identifies the iterator and allows finding and accessing the
* actual iterator instance in Go. Once fully initalized, this is immutable.
*/
struct IteratorReference reference;
struct IteratorVtable vtable;
} GoIter;

24 changes: 12 additions & 12 deletions internal/api/callbacks.go
Original file line number Diff line number Diff line change
@@ -19,9 +19,9 @@ GoError cSet_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceV
GoError cDelete_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView key, UnmanagedVector *errOut);
GoError cScan_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView start, U8SliceView end, int32_t order, GoIter *out, UnmanagedVector *errOut);
// iterator
GoError cNext_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
GoError cNextKey_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
GoError cNextValue_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut);
GoError cNext_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
GoError cNextKey_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
GoError cNextValue_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut);
// api
GoError cHumanizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cCanonicalizeAddress_cgo(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
@@ -138,12 +138,12 @@ const frameLenLimit = 32768

// contract: original pointer/struct referenced must live longer than C.Db struct
// since this is only used internally, we can verify the code that this is the case
func buildIterator(callID uint64, it types.Iterator) (C.iterator_t, error) {
func buildIterator(callID uint64, it types.Iterator) (C.IteratorReference, error) {
idx, err := storeIterator(callID, it, frameLenLimit)
if err != nil {
return C.iterator_t{}, err
return C.IteratorReference{}, err
}
return C.iterator_t{
return C.IteratorReference{
call_id: cu64(callID),
iterator_index: cu64(idx),
}, nil
@@ -257,7 +257,7 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV
gasAfter := gm.GasConsumed()
*usedGas = (cu64)(gasAfter - gasBefore)

cIterator, err := buildIterator(state.CallID, iter)
iteratorRef, err := buildIterator(state.CallID, iter)
if err != nil {
// store the actual error message in the return buffer
*errOut = newUnmanagedVector([]byte(err.Error()))
@@ -266,15 +266,15 @@ func cScan(ptr *C.db_t, gasMeter *C.gas_meter_t, usedGas *cu64, start C.U8SliceV

*out = C.GoIter{
gas_meter: gasMeter,
state: cIterator,
reference: iteratorRef,
vtable: iterator_vtable,
}

return C.GoError_None
}

//export cNext
func cNext(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, val *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
func cNext(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, val *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
// typical usage of iterator
// for ; itr.Valid(); itr.Next() {
// k, v := itr.Key(); itr.Value()
@@ -315,17 +315,17 @@ func cNext(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.Unma
}

//export cNextKey
func cNextKey(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
func cNextKey(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, key *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
return nextPart(ref, gasMeter, usedGas, key, errOut, func(iter types.Iterator) []byte { return iter.Key() })
}

//export cNextValue
func cNextValue(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, value *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
func cNextValue(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, value *C.UnmanagedVector, errOut *C.UnmanagedVector) (ret C.GoError) {
return nextPart(ref, gasMeter, usedGas, value, errOut, func(iter types.Iterator) []byte { return iter.Value() })
}

// nextPart is a helper function that contains the shared code for key- and value-only iteration.
func nextPart(ref C.iterator_t, gasMeter *C.gas_meter_t, usedGas *cu64, output *C.UnmanagedVector, errOut *C.UnmanagedVector, valFn func(types.Iterator) []byte) (ret C.GoError) {
func nextPart(ref C.IteratorReference, gasMeter *C.gas_meter_t, usedGas *cu64, output *C.UnmanagedVector, errOut *C.UnmanagedVector, valFn func(types.Iterator) []byte) (ret C.GoError) {
// typical usage of iterator
// for ; itr.Valid(); itr.Next() {
// k, v := itr.Key(); itr.Value()
18 changes: 9 additions & 9 deletions internal/api/callbacks_cgo.go
Original file line number Diff line number Diff line change
@@ -10,9 +10,9 @@ GoError cGet(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView
GoError cDelete(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView key, UnmanagedVector *errOut);
GoError cScan(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8SliceView start, U8SliceView end, int32_t order, GoIter *out, UnmanagedVector *errOut);
// imports (iterator)
GoError cNext(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
GoError cNextKey(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
GoError cNextValue(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *value, UnmanagedVector *errOut);
GoError cNext(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut);
GoError cNextKey(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut);
GoError cNextValue(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *value, UnmanagedVector *errOut);
// imports (api)
GoError cHumanizeAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
GoError cCanonicalizeAddress(api_t *ptr, U8SliceView src, UnmanagedVector *dest, UnmanagedVector *errOut, uint64_t *used_gas);
@@ -35,14 +35,14 @@ GoError cScan_cgo(db_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, U8Slice
}
// Gateway functions (iterator)
GoError cNext_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut) {
return cNext(ptr, gas_meter, used_gas, key, val, errOut);
GoError cNext_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *val, UnmanagedVector *errOut) {
return cNext(ref, gas_meter, used_gas, key, val, errOut);
}
GoError cNextKey_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut) {
return cNextKey(ptr, gas_meter, used_gas, key, errOut);
GoError cNextKey_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *key, UnmanagedVector *errOut) {
return cNextKey(ref, gas_meter, used_gas, key, errOut);
}
GoError cNextValue_cgo(iterator_t *ptr, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut) {
return cNextValue(ptr, gas_meter, used_gas, val, errOut);
GoError cNextValue_cgo(IteratorReference *ref, gas_meter_t *gas_meter, uint64_t *used_gas, UnmanagedVector *val, UnmanagedVector *errOut) {
return cNextValue(ref, gas_meter, used_gas, val, errOut);
}
// Gateway functions (api)
20 changes: 14 additions & 6 deletions libwasmvm/bindings.h
Original file line number Diff line number Diff line change
@@ -255,27 +255,31 @@ typedef struct U8SliceView {
uintptr_t len;
} U8SliceView;

typedef struct iterator_t {
/**
* A reference to some tables on the Go side which allow accessing
* the actual iterator instance.
*/
typedef struct IteratorReference {
/**
* An ID assigned to this contract call
*/
uint64_t call_id;
uint64_t iterator_index;
} iterator_t;
} IteratorReference;

typedef struct IteratorVtable {
int32_t (*next)(struct iterator_t iterator,
int32_t (*next)(struct IteratorReference iterator,
struct gas_meter_t *gas_meter,
uint64_t *gas_used,
struct UnmanagedVector *key_out,
struct UnmanagedVector *value_out,
struct UnmanagedVector *err_msg_out);
int32_t (*next_key)(struct iterator_t iterator,
int32_t (*next_key)(struct IteratorReference iterator,
struct gas_meter_t *gas_meter,
uint64_t *gas_used,
struct UnmanagedVector *key_out,
struct UnmanagedVector *err_msg_out);
int32_t (*next_value)(struct iterator_t iterator,
int32_t (*next_value)(struct IteratorReference iterator,
struct gas_meter_t *gas_meter,
uint64_t *gas_used,
struct UnmanagedVector *value_out,
@@ -284,7 +288,11 @@ typedef struct IteratorVtable {

typedef struct GoIter {
struct gas_meter_t *gas_meter;
struct iterator_t state;
/**
* A reference which identifies the iterator and allows finding and accessing the
* actual iterator instance in Go. Once fully initalized, this is immutable.
*/
struct IteratorReference reference;
struct IteratorVtable vtable;
} GoIter;

27 changes: 15 additions & 12 deletions libwasmvm/src/iterator.rs
Original file line number Diff line number Diff line change
@@ -6,10 +6,11 @@ use crate::gas_meter::gas_meter_t;
use crate::memory::UnmanagedVector;
use crate::vtables::Vtable;

// Iterator maintains integer references to some tables on the Go side
/// A reference to some tables on the Go side which allow accessing
/// the actual iterator instance.
#[repr(C)]
#[derive(Default, Copy, Clone)]
pub struct iterator_t {
pub struct IteratorReference {
/// An ID assigned to this contract call
pub call_id: u64,
pub iterator_index: u64,
@@ -22,7 +23,7 @@ pub struct iterator_t {
pub struct IteratorVtable {
pub next: Option<
extern "C" fn(
iterator: iterator_t,
iterator: IteratorReference,
gas_meter: *mut gas_meter_t,
gas_used: *mut u64,
key_out: *mut UnmanagedVector,
@@ -32,7 +33,7 @@ pub struct IteratorVtable {
>,
pub next_key: Option<
extern "C" fn(
iterator: iterator_t,
iterator: IteratorReference,
gas_meter: *mut gas_meter_t,
gas_used: *mut u64,
key_out: *mut UnmanagedVector,
@@ -41,7 +42,7 @@ pub struct IteratorVtable {
>,
pub next_value: Option<
extern "C" fn(
iterator: iterator_t,
iterator: IteratorReference,
gas_meter: *mut gas_meter_t,
gas_used: *mut u64,
value_out: *mut UnmanagedVector,
@@ -55,7 +56,9 @@ impl Vtable for IteratorVtable {}
#[repr(C)]
pub struct GoIter {
pub gas_meter: *mut gas_meter_t,
pub state: iterator_t,
/// A reference which identifies the iterator and allows finding and accessing the
/// actual iterator instance in Go. Once fully initalized, this is immutable.
pub reference: IteratorReference,
webmaster128 marked this conversation as resolved.
Show resolved Hide resolved
pub vtable: IteratorVtable,
}

@@ -67,8 +70,8 @@ impl GoIter {
/// which is then filled in Go (see `fn scan`).
pub fn stub() -> Self {
GoIter {
reference: IteratorReference::default(),
gas_meter: std::ptr::null_mut(),
state: iterator_t::default(),
vtable: IteratorVtable::default(),
}
}
@@ -84,7 +87,7 @@ impl GoIter {
let mut error_msg = UnmanagedVector::default();
let mut used_gas = 0_u64;
let go_result: GoError = (next)(
self.state,
self.reference,
self.gas_meter,
&mut used_gas as *mut u64,
&mut output_key as *mut UnmanagedVector,
@@ -141,7 +144,7 @@ impl GoIter {
fn next_key_or_val(
&mut self,
next: extern "C" fn(
iterator: iterator_t,
iterator: IteratorReference,
gas_meter: *mut gas_meter_t,
gas_limit: *mut u64,
key_or_value_out: *mut UnmanagedVector, // key if called from next_key; value if called from next_value
@@ -152,7 +155,7 @@ impl GoIter {
let mut error_msg = UnmanagedVector::default();
let mut used_gas = 0_u64;
let go_result: GoError = (next)(
self.state,
self.reference,
self.gas_meter,
&mut used_gas as *mut u64,
&mut output as *mut UnmanagedVector,
@@ -190,8 +193,8 @@ mod test {
// creates an all null-instance
let iter = GoIter::stub();
assert!(iter.gas_meter.is_null());
assert_eq!(iter.state.call_id, 0);
assert_eq!(iter.state.iterator_index, 0);
assert_eq!(iter.reference.call_id, 0);
assert_eq!(iter.reference.iterator_index, 0);
assert!(iter.vtable.next.is_none());
assert!(iter.vtable.next_key.is_none());
assert!(iter.vtable.next_value.is_none());
4 changes: 2 additions & 2 deletions libwasmvm/src/vtables.rs
Original file line number Diff line number Diff line change
@@ -16,12 +16,12 @@
///
/// ```
/// # use wasmvm::UnmanagedVector;
/// # struct iterator_t;
/// # struct IteratorReference;
/// # struct gas_meter_t;
/// pub struct IteratorVtable {
/// pub next: Option<
/// extern "C" fn(
/// iterator: iterator_t,
/// iterator: IteratorReference,
/// gas_meter: *mut gas_meter_t,
/// gas_used: *mut u64,
/// key_out: *mut UnmanagedVector,