MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

improve T_FFI usage and remove wrapper funcs

+95 -42
+4 -3
examples/ffi/basic/printf.js
··· 12 12 } 13 13 14 14 const libc = dlopen(libcName); 15 - const printf = (...args) => libc.call('printf', ...args); 16 15 17 16 libc.define('putchar', { 18 17 args: [FFIType.int], ··· 24 23 returns: FFIType.int 25 24 }); 26 25 26 + console.log(libc); 27 + 27 28 console.log('calling putchar(65):'); 28 - libc.call('putchar', 65); // 'A' 29 + libc.putchar(65); // 'A' 29 30 30 31 console.log('\ncalling printf:'); 31 - printf('Hello FFI! I see %d\n', 42); 32 + libc.printf('Hello FFI! I see %d\n', 42); 32 33 33 34 console.log('calling putchar(66):'); 34 35 libc.call('putchar', 66); // 'B'
+3
include/ant.h
··· 119 119 jsval_t js_mktypedarray(void *data); 120 120 void *js_gettypedarray(jsval_t val); 121 121 122 + jsval_t js_mkffi(unsigned int index); 123 + int js_getffi(jsval_t val); 124 + 122 125 void js_resolve_promise(struct js *js, jsval_t promise, jsval_t value); 123 126 void js_reject_promise(struct js *js, jsval_t promise, jsval_t value); 124 127
+1
include/modules/ffi.h
··· 4 4 #include "ant.h" 5 5 6 6 jsval_t ffi_library(struct js *js); 7 + jsval_t ffi_call_by_index(struct js *js, unsigned int func_index, jsval_t *args, int nargs); 7 8 8 9 #endif
+1 -1
meson.build
··· 79 79 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 80 80 81 81 version_conf = configuration_data() 82 - version_conf.set('ANT_VERSION', '0.2.2.5') 82 + version_conf.set('ANT_VERSION', '0.2.2.6') 83 83 version_conf.set('ANT_GIT_HASH', git_hash) 84 84 version_conf.set('ANT_BUILD_DATE', build_date) 85 85
+68 -14
src/ant.c
··· 26 26 #include "modules/timer.h" 27 27 #include "modules/fetch.h" 28 28 #include "modules/symbol.h" 29 + #include "modules/ffi.h" 29 30 30 31 #define MINICORO_IMPL 31 32 #include "minicoro.h" ··· 451 452 enum { 452 453 T_OBJ, T_PROP, T_STR, T_UNDEF, T_NULL, T_NUM, T_BOOL, T_FUNC, 453 454 T_CODEREF, T_CFUNC, T_ERR, T_ARR, T_PROMISE, T_TYPEDARRAY, 454 - T_BIGINT, T_PROPREF, T_SYMBOL, T_GENERATOR 455 + T_BIGINT, T_PROPREF, T_SYMBOL, T_GENERATOR, T_FFI 455 456 }; 456 457 457 458 static const char *typestr_raw(uint8_t t) { 458 459 const char *names[] = { 459 460 "object", "prop", "string", "undefined", "null", "number", 460 461 "boolean", "function", "coderef", "cfunc", "err", "array", 461 - "promise", "typedarray", "bigint", "propref", "symbol", "generator" 462 + "promise", "typedarray", "bigint", "propref", "symbol", "generator", "ffi" 462 463 }; 463 464 464 465 return (t < sizeof(names) / sizeof(names[0])) ? names[t] : "??"; ··· 548 549 void *js_gettypedarray(jsval_t val) { 549 550 if (vtype(val) != T_TYPEDARRAY) return NULL; 550 551 return (void *)vdata(val); 552 + } 553 + 554 + jsval_t js_mkffi(unsigned int index) { 555 + return mkval(T_FFI, (uint64_t)index); 556 + } 557 + 558 + int js_getffi(jsval_t val) { 559 + if (vtype(val) != T_FFI) return -1; 560 + return (int)vdata(val); 551 561 } 552 562 553 563 static jsval_t mkcoderef(jsval_t off, jsoff_t len) { ··· 2192 2202 case T_PROMISE: return strpromise(js, value, buf, len); 2193 2203 case T_FUNC: return strfunc(js, value, buf, len); 2194 2204 case T_CFUNC: return cpy(buf, len, "[Function (native)]", 19); 2205 + case T_FFI: return cpy(buf, len, "[Function (native)]", 19); 2195 2206 case T_PROP: return (size_t) snprintf(buf, len, "PROP@%lu", (unsigned long) vdata(value)); 2196 2207 default: return (size_t) snprintf(buf, len, "VTYPE%d", vtype(value)); 2197 2208 } ··· 4945 4956 } 4946 4957 } 4947 4958 4948 - static jsval_t call_c(struct js *js, 4949 - jsval_t (*fn)(struct js *, jsval_t *, int)) { 4959 + static int parse_call_args(struct js *js, jsval_t *err_out) { 4950 4960 int argc = 0; 4951 - jsval_t target_this = peek_this(); 4952 4961 4953 4962 while (js->pos < js->clen) { 4954 4963 if (next(js) == TOK_RPAREN) break; 4955 4964 bool is_spread = (next(js) == TOK_REST); 4956 4965 if (is_spread) js->consumed = 1; 4957 4966 jsval_t arg = resolveprop(js, js_expr(js)); 4958 - if (is_err(arg)) return arg; 4967 + if (is_err(arg)) { *err_out = arg; return -1; } 4959 4968 if (is_spread && vtype(arg) == T_ARR) { 4960 4969 jsoff_t len = arr_length(js, arg); 4961 4970 for (jsoff_t i = 0; i < len; i++) { 4962 4971 jsval_t elem = arr_get(js, arg, i); 4963 - if (js->brk + sizeof(elem) > js->size) return js_mkerr(js, "call oom"); 4972 + if (js->brk + sizeof(elem) > js->size) { *err_out = js_mkerr(js, "call oom"); return -1; } 4964 4973 js->size -= (jsoff_t) sizeof(elem); 4965 4974 memcpy(&js->mem[js->size], &elem, sizeof(elem)); 4966 4975 argc++; 4967 4976 } 4968 4977 } else { 4969 - if (js->brk + sizeof(arg) > js->size) return js_mkerr(js, "call oom"); 4978 + if (js->brk + sizeof(arg) > js->size) { *err_out = js_mkerr(js, "call oom"); return -1; } 4970 4979 js->size -= (jsoff_t) sizeof(arg); 4971 4980 memcpy(&js->mem[js->size], &arg, sizeof(arg)); 4972 4981 argc++; ··· 4974 4983 if (next(js) == TOK_COMMA) js->consumed = 1; 4975 4984 } 4976 4985 4977 - jsval_t saved_this = js->this_val; 4978 - js->this_val = target_this; 4979 4986 reverse((jsval_t *) &js->mem[js->size], argc); 4980 - jsval_t res = fn(js, (jsval_t *) &js->mem[js->size], argc); 4987 + return argc; 4988 + } 4989 + 4990 + static jsval_t call_c(struct js *js, jsval_t (*fn)(struct js *, jsval_t *, int)) { 4991 + jsoff_t saved_size = js->size; 4992 + jsval_t err, res; 4993 + 4994 + int argc = parse_call_args(js, &err); 4995 + if (argc < 0) { js->size = saved_size; return err; } 4996 + 4997 + jsval_t saved_this = js->this_val; 4998 + js->this_val = peek_this(); 4999 + res = fn(js, (jsval_t *) &js->mem[js->size], argc); 4981 5000 js->this_val = saved_this; 4982 5001 setlwm(js); 4983 5002 4984 - js->size += (jsoff_t) sizeof(jsval_t) * (jsoff_t) argc; 5003 + js->size = saved_size; 4985 5004 return res; 4986 5005 } 4987 5006 ··· 5705 5724 return res; 5706 5725 } 5707 5726 5727 + static jsval_t call_ffi(struct js *js, unsigned int func_index) { 5728 + jsoff_t saved_size = js->size; 5729 + jsval_t err, res; 5730 + 5731 + int argc = parse_call_args(js, &err); 5732 + if (argc < 0) { js->size = saved_size; return err; } 5733 + 5734 + res = ffi_call_by_index(js, func_index, (jsval_t *) &js->mem[js->size], argc); 5735 + setlwm(js); 5736 + 5737 + js->size = saved_size; 5738 + return res; 5739 + } 5740 + 5708 5741 static jsval_t do_call_op(struct js *js, jsval_t func, jsval_t args) { 5709 5742 if (vtype(args) != T_CODEREF) return js_mkerr(js, "bad call"); 5710 - if (vtype(func) != T_FUNC && vtype(func) != T_CFUNC) return js_mkerr(js, "calling non-function"); 5743 + if (vtype(func) != T_FUNC && vtype(func) != T_CFUNC && vtype(func) != T_FFI) return js_mkerr(js, "calling non-function"); 5744 + 5745 + if (vtype(func) == T_FFI) { 5746 + const char *code = js->code; 5747 + jsoff_t clen = js->clen, pos = js->pos; 5748 + uint8_t tok = js->tok, flags = js->flags; 5749 + jsoff_t nogc = js->nogc; 5750 + 5751 + js->code = &js->code[coderefoff(args)]; 5752 + js->clen = codereflen(args); 5753 + js->pos = skiptonext(js->code, js->clen, 0, NULL); 5754 + 5755 + jsval_t res = call_ffi(js, (unsigned int)vdata(func)); 5756 + 5757 + js->code = code; js->clen = clen; js->pos = pos; 5758 + js->flags = (flags & ~F_THROW) | (js->flags & F_THROW); 5759 + js->tok = tok; js->nogc = nogc; 5760 + js->consumed = 1; 5761 + return res; 5762 + } 5711 5763 5712 5764 jsval_t target_this = peek_this(); 5713 5765 bool is_constructor_call = (vtype(target_this) == T_OBJ && lkp_interned(js, target_this, INTERN_PROTO, 9) == 0); ··· 20834 20886 } 20835 20887 20836 20888 static jsval_t js_call_internal(struct js *js, jsval_t func, jsval_t bound_this, jsval_t *args, int nargs, bool use_bound_this) { 20837 - if (vtype(func) == T_CFUNC) { 20889 + if (vtype(func) == T_FFI) { 20890 + return ffi_call_by_index(js, (unsigned int)vdata(func), args, nargs); 20891 + } else if (vtype(func) == T_CFUNC) { 20838 20892 jsval_t (*fn)(struct js *, jsval_t *, int) = (jsval_t(*)(struct js *, jsval_t *, int)) vdata(func); 20839 20893 return fn(js, args, nargs); 20840 20894 } else if (vtype(func) == T_FUNC) {
+18 -24
src/modules/ffi.c
··· 332 332 unsigned int func_index = utarray_len(ffi_functions_array) - 1; 333 333 pthread_mutex_unlock(&ffi_functions_mutex); 334 334 335 - char index_key[256]; 336 - snprintf(index_key, sizeof(index_key), "__ffi_index_%s", func_name); 337 - js_set(js, this_obj, index_key, js_mknum((double)func_index)); 335 + js_set(js, this_obj, func_name, js_mkffi(func_index)); 338 336 339 337 return js_mkundef(); 340 338 } ··· 347 345 size_t func_name_len; 348 346 const char *func_name = js_getstr(js, args[0], &func_name_len); 349 347 350 - char index_key[256]; 351 - snprintf(index_key, sizeof(index_key), "__ffi_index_%s", func_name); 352 - jsval_t index_val = js_get(js, lib_obj, index_key); 353 - 354 - if (js_type(index_val) != JS_NUM) { 348 + jsval_t ffi_val = js_get(js, lib_obj, func_name); 349 + int func_index = js_getffi(ffi_val); 350 + if (func_index < 0) { 355 351 return js_mkerr(js, "Function '%s' not defined", func_name); 356 352 } 357 353 358 - unsigned int func_index = (unsigned int)js_getnum(index_val); 359 - 360 - pthread_mutex_lock(&ffi_functions_mutex); 361 - if (func_index >= utarray_len(ffi_functions_array)) { 362 - pthread_mutex_unlock(&ffi_functions_mutex); 363 - return js_mkerr(js, "Invalid function index"); 364 - } 365 - 366 - ffi_func_t *func = 367 - *(ffi_func_t **)utarray_eltptr(ffi_functions_array, func_index); 368 - pthread_mutex_unlock(&ffi_functions_mutex); 369 - 370 - jsval_t *call_args = args + 1; 371 - int call_nargs = nargs - 1; 372 - 373 - return ffi_call_function(js, func, call_args, call_nargs); 354 + return ffi_call_by_index(js, (unsigned int)func_index, args + 1, nargs - 1); 374 355 } 375 356 376 357 static jsval_t ffi_call_function(struct js *js, ffi_func_t *func, jsval_t *args,int nargs) { ··· 436 417 } 437 418 438 419 return ffi_to_js_value(js, &result, func->ret_type, func->ret_type_str); 420 + } 421 + 422 + jsval_t ffi_call_by_index(struct js *js, unsigned int func_index, jsval_t *args, int nargs) { 423 + pthread_mutex_lock(&ffi_functions_mutex); 424 + if (func_index >= utarray_len(ffi_functions_array)) { 425 + pthread_mutex_unlock(&ffi_functions_mutex); 426 + return js_mkerr(js, "Invalid FFI function index"); 427 + } 428 + 429 + ffi_func_t *func = *(ffi_func_t **)utarray_eltptr(ffi_functions_array, func_index); 430 + pthread_mutex_unlock(&ffi_functions_mutex); 431 + 432 + return ffi_call_function(js, func, args, nargs); 439 433 } 440 434 441 435 static jsval_t ffi_alloc_memory(struct js *js, jsval_t *args, int nargs) {