github.com/moontrade/wavm-go@v0.3.2-0.20220316110326-d229dd66ad65/worker/worker.go (about)

     1  package worker
     2  
     3  /*
     4  #include <stdio.h>
     5  #include <stdlib.h>
     6  #include <time.h>
     7  #include "worker.h"
     8  #include "wavm-c.h"
     9  */
    10  import "C"
    11  import (
    12  	"fmt"
    13  	"github.com/moontrade/wavm-go"
    14  	"unsafe"
    15  )
    16  
    17  func Now() int64 {
    18  	return runtimeNano()
    19  }
    20  
    21  type Worker struct {
    22  	id               int64
    23  	next             *Worker
    24  	prev             *Worker
    25  	engine           *wavm.Engine
    26  	compartment      *wavm.Compartment
    27  	store            *wavm.Store
    28  	memory           *wavm.Memory
    29  	start            *wavm.Func
    30  	resume           *wavm.Func
    31  	alloc            *wavm.Func
    32  	realloc          *wavm.Func
    33  	free             *wavm.Func
    34  	stub             *wavm.Func
    35  	funcCall         *C.void // wasm_func_call ptr
    36  	log              *C.char // log buffer managed by C (malloc/free)
    37  	logLen           int64
    38  	logCap           int64
    39  	begin            int64
    40  	end              int64
    41  	started          int64
    42  	resumeAt         int64
    43  	resumeAtStack    *int64 // setTimeout stack managed by C (malloc/free)
    44  	resumeAtStackLen int64
    45  	resumeAtStackCap int64
    46  	Params           []wavm.Val
    47  	Results          []wavm.Val
    48  	Funcs            []*wavm.Func
    49  	Globals          []*wavm.Global
    50  	Tables           []*wavm.Table
    51  	Memories         []*wavm.Memory
    52  	Args             args
    53  }
    54  
    55  type args struct {
    56  	worker         uintptr
    57  	thunk          uintptr
    58  	fn             uintptr
    59  	trap           uintptr
    60  	argPointer     uintptr
    61  	resultsPointer uintptr
    62  	args           [8]wavm.Val
    63  	results        [8]wavm.Val
    64  }
    65  
    66  func (w *Worker) SetArgI32(index int, value int32) {
    67  	w.Args.args[index].SetI32(value)
    68  }
    69  func (w *Worker) SetArgF32(index int, value float32) {
    70  	w.Args.args[index].SetF32(value)
    71  }
    72  func (w *Worker) SetArgI64(index int, value int64) {
    73  	w.Args.args[index].SetI64(value)
    74  }
    75  func (w *Worker) SetArgF64(index int, value float64) {
    76  	w.Args.args[index].SetF64(value)
    77  }
    78  func (w *Worker) SetArgV128(index int, value wavm.V128T) {
    79  	w.Args.args[index].SetV128(value)
    80  }
    81  func (w *Worker) ResultI32(index int) int32 {
    82  	return w.Args.results[index].I32()
    83  }
    84  func (w *Worker) ResultI64(index int) int64 {
    85  	return w.Args.results[index].I64()
    86  }
    87  func (w *Worker) ResultF32(index int) float32 {
    88  	return w.Args.results[index].F32()
    89  }
    90  func (w *Worker) ResultF64(index int) float64 {
    91  	return w.Args.results[index].F64()
    92  }
    93  func (w *Worker) ResultV128(index int) wavm.V128T {
    94  	return w.Args.results[index].V128()
    95  }
    96  
    97  func (w *Worker) init() {
    98  	const (
    99  		secondOffset         = unsafe.Sizeof(uintptr(0))
   100  		argsPointerOffset    = secondOffset + unsafe.Sizeof(uintptr(0))
   101  		argsMax              = 8
   102  		argsSize             = unsafe.Sizeof(wavm.Val{}) * argsMax
   103  		resultsPointerOffset = argsPointerOffset + unsafe.Sizeof(uintptr(0))
   104  	)
   105  
   106  	w.Args.worker = uintptr(unsafe.Pointer(w))
   107  	w.Args.argPointer = uintptr(unsafe.Pointer(&w.Args.args[0]))
   108  	w.Args.resultsPointer = uintptr(unsafe.Pointer(&w.Args.results[0]))
   109  }
   110  
   111  func (w *Worker) Close() error {
   112  	if w.log != nil {
   113  		C.free(unsafe.Pointer(w.log))
   114  		w.log = nil
   115  	}
   116  	if w.resumeAtStack != nil {
   117  		C.free(unsafe.Pointer(w.resumeAtStack))
   118  		w.resumeAtStack = nil
   119  	}
   120  
   121  	w.store.Delete()
   122  	w.compartment.Delete()
   123  	w.engine.Delete()
   124  	return nil
   125  }
   126  
   127  func (w *Worker) Start() error {
   128  	w.begin = Now()
   129  	if err := w.Call(w.start); err != nil {
   130  		w.end = Now()
   131  		return err
   132  	}
   133  	w.end = Now()
   134  	w.started = w.end
   135  	return nil
   136  }
   137  
   138  var (
   139  	funcCall             = uintptr(unsafe.Pointer(wavm.WASMFuncCall))
   140  	funcCallNoCopy       = uintptr(unsafe.Pointer(wavm.WASMFuncCallNoCopy))
   141  	funcCallNoTrap       = uintptr(unsafe.Pointer(wavm.WASMFuncCallNoTrap))
   142  	funcCallNoCopyNoTrap = uintptr(unsafe.Pointer(wavm.WASMFuncCallNoCopyNoTrap))
   143  )
   144  
   145  func (w *Worker) Call(fn *wavm.Func) error {
   146  	w.Args.fn = uintptr(unsafe.Pointer(fn))
   147  	w.Args.thunk = funcCall
   148  	w.Args.trap = 0
   149  	w.doCall()
   150  	if w.Args.trap != 0 {
   151  		trap := (*wavm.Trap)(unsafe.Pointer(w.Args.trap))
   152  		e := fmt.Errorf(trap.String())
   153  		trap.Delete()
   154  		return e
   155  	}
   156  	return nil
   157  }
   158  
   159  func (w *Worker) CallNoCopy(fn *wavm.Func) error {
   160  	w.Args.fn = uintptr(unsafe.Pointer(fn))
   161  	w.Args.thunk = funcCallNoCopy
   162  	w.Args.trap = 0
   163  	w.doCall()
   164  	if w.Args.trap != 0 {
   165  		trap := (*wavm.Trap)(unsafe.Pointer(w.Args.trap))
   166  		e := fmt.Errorf(trap.String())
   167  		trap.Delete()
   168  		return e
   169  	}
   170  	return nil
   171  }
   172  
   173  func (w *Worker) CallNoTrap(fn *wavm.Func) error {
   174  	w.Args.fn = uintptr(unsafe.Pointer(fn))
   175  	w.Args.thunk = funcCallNoTrap
   176  	w.Args.trap = 0
   177  	w.doCall()
   178  	if w.Args.trap != 0 {
   179  		trap := (*wavm.Trap)(unsafe.Pointer(w.Args.trap))
   180  		e := fmt.Errorf(trap.String())
   181  		trap.Delete()
   182  		return e
   183  	}
   184  	return nil
   185  }
   186  
   187  func (w *Worker) CallNoCopyNoTrap(fn *wavm.Func) error {
   188  	w.Args.fn = uintptr(unsafe.Pointer(fn))
   189  	w.Args.thunk = funcCallNoCopyNoTrap
   190  	w.Args.trap = 0
   191  	w.doCall()
   192  	if w.Args.trap != 0 {
   193  		trap := (*wavm.Trap)(unsafe.Pointer(w.Args.trap))
   194  		e := fmt.Errorf(trap.String())
   195  		trap.Delete()
   196  		return e
   197  	}
   198  	return nil
   199  }
   200  
   201  ////export moontradeSetTimeout
   202  //func moontradeSetTimeout(workerPtr unsafe.Pointer, nanos int64) {
   203  //	worker := (*Worker)(workerPtr)
   204  //	_ = worker
   205  //	println("setTimeout", uintptr(workerPtr), nanos)
   206  //}
   207  
   208  func moontrade_fd_write() wavm.FuncCallback {
   209  	return (wavm.FuncCallback)(C.moontrade_fd_write)
   210  }
   211  
   212  func moontrade_clock_time_get() wavm.FuncCallback {
   213  	return (wavm.FuncCallback)(C.moontrade_clock_time_get)
   214  }
   215  
   216  func moontrade_args_sizes_get() wavm.FuncCallback {
   217  	return (wavm.FuncCallback)(C.moontrade_args_sizes_get)
   218  }
   219  
   220  func moontrade_args_get() wavm.FuncCallback {
   221  	return (wavm.FuncCallback)(C.moontrade_args_get)
   222  }
   223  
   224  func moontrade_set_timeout() wavm.FuncCallback {
   225  	return (wavm.FuncCallback)(C.moontrade_set_timeout)
   226  }
   227  
   228  ////////////////////////////////////////////////////////////////////////////////////////////////////
   229  // Testing Stuff
   230  ////////////////////////////////////////////////////////////////////////////////////////////////////
   231  func stub_safe() {
   232  	C.moontrade_stub()
   233  }
   234  
   235  func stub_fast() {
   236  	callStub()
   237  }
   238  
   239  func moontrade_benchmark_stub(worker *Worker, n int) {
   240  	C.moontrade_benchmark_stub((*C.moontrade_worker_t)(unsafe.Pointer(worker)), (C.int64_t)(n))
   241  }
   242  
   243  func moontrade_benchmark_stub_no_copy(worker *Worker, n int) {
   244  	C.moontrade_benchmark_stub_fn((*C.moontrade_worker_t)(unsafe.Pointer(worker)), unsafe.Pointer((*C.void)(wavm.WASMFuncCallNoCopy)), (C.int64_t)(n))
   245  }
   246  
   247  func moontrade_benchmark_stub_no_trap(worker *Worker, n int) {
   248  	C.moontrade_benchmark_stub_fn((*C.moontrade_worker_t)(unsafe.Pointer(worker)), unsafe.Pointer((*C.void)(wavm.WASMFuncCallNoTrap)), (C.int64_t)(n))
   249  }
   250  
   251  func moontrade_benchmark_stub_no_copy_no_trap(worker *Worker, n int) {
   252  	C.moontrade_benchmark_stub_fn((*C.moontrade_worker_t)(unsafe.Pointer(worker)), unsafe.Pointer((*C.void)(wavm.WASMFuncCallNoCopyNoTrap)), (C.int64_t)(n))
   253  }