diff options
author | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-02-25 19:22:25 +0000 |
commit | ad547a6b5986815fda458221149728d9d9ab1d87 (patch) | |
tree | 16296910eb3eca724371474ea9aea3994dc69614 /Build/source/texk/web2c/luatexdir/luaffi/call.c | |
parent | 947b43de3dd21d58ccc2ffadefc4441ea1c2a813 (diff) |
restore Build,TODO from r57911
git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luaffi/call.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luaffi/call.c | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luaffi/call.c b/Build/source/texk/web2c/luatexdir/luaffi/call.c new file mode 100644 index 00000000000..71bb3aea884 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luaffi/call.c @@ -0,0 +1,275 @@ +/* vim: ts=4 sw=4 sts=4 et tw=78 + * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved. + * Portions copyright (c) 2011 James R. McKaskill. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +#include "ffi.h" + +static cfunction compile(Dst_DECL, lua_State* L, cfunction func, int ref); + +static void* reserve_code(struct jit* jit, lua_State* L, size_t sz); +static void commit_code(struct jit* jit, void* p, size_t sz); + +static void push_int(lua_State* L, int val) +{ lua_pushinteger(L, val); } + +static void push_uint(lua_State* L, unsigned int val) +{ lua_pushinteger(L, val); } + +static void push_float(lua_State* L, float val) +{ lua_pushnumber(L, val); } + +#ifndef _WIN32 +static int GetLastError(void) +{ return errno; } +static void SetLastError(int err) +{ errno = err; } +#endif + +#ifdef NDEBUG +#define shred(a,b,c) +#else +#define shred(p,s,e) memset((uint8_t*)(p)+(s),0xCC,(e)-(s)) +#endif + + +#ifdef _WIN64 +#include "dynasm/dasm_x86.h" +#include "call_x64win.h" +#elif defined __amd64__ +#include "dynasm/dasm_x86.h" +#include "call_x64.h" +#elif defined __arm__ || defined __arm || defined __ARM__ || defined __ARM || defined ARM || defined _ARM_ || defined ARMV4I || defined _M_ARM +#include "dynasm/dasm_arm.h" +#include "call_arm.h" +#else +#include "dynasm/dasm_x86.h" +#include "call_x86.h" +#endif + +struct jit_head { + size_t size; + int ref; + uint8_t jump[JUMP_SIZE]; +}; + +#define LINKTABLE_MAX_SIZE (sizeof(extnames) / sizeof(extnames[0]) * (JUMP_SIZE)) + +static cfunction compile(struct jit* jit, lua_State* L, cfunction func, int ref) +{ + struct jit_head* code; + size_t codesz; + int err; + + dasm_checkstep(jit, -1); + if ((err = dasm_link(jit, &codesz)) != 0) { + char buf[32]; + sprintf(buf, "%x", err); + luaL_error(L, "dasm_link error %s", buf); + } + + codesz += sizeof(struct jit_head); + code = (struct jit_head*) reserve_code(jit, L, codesz); + code->ref = ref; + code->size = codesz; + compile_extern_jump(jit, L, func, code->jump); + + if ((err = dasm_encode(jit, code+1)) != 0) { + char buf[32]; + sprintf(buf, "%x", err); + commit_code(jit, code, 0); + luaL_error(L, "dasm_encode error %s", buf); + } + + commit_code(jit, code, codesz); + return (cfunction) (code+1); +} + +typedef uint8_t jump_t[JUMP_SIZE]; + +int get_extern(struct jit* jit, uint8_t* addr, int idx, int type) +{ + struct page* page = jit->pages[jit->pagenum-1]; + jump_t* jumps = (jump_t*) (page+1); + struct jit_head* h = (struct jit_head*) ((uint8_t*) page + page->off); + uint8_t* jmp; + ptrdiff_t off; + + if (idx == jit->function_extern) { + jmp = h->jump; + } else { + jmp = jumps[idx]; + } + + /* compensate for room taken up for the offset so that we can work rip + * relative */ + addr += BRANCH_OFF; + + /* see if we can fit the offset in the branch displacement, if not use the + * jump instruction */ + off = *(uint8_t**) jmp - addr; + + if (MIN_BRANCH <= off && off <= MAX_BRANCH) { + return (int32_t) off; + } else { + return (int32_t)(jmp + sizeof(uint8_t*) - addr); + } +} + +static void* reserve_code(struct jit* jit, lua_State* L, size_t sz) +{ + struct page* page; + size_t off = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->off : 0; + size_t size = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->size : 0; + + if (off + sz >= size) { + int i; + uint8_t* pdata; + cfunction func; + + /* need to create a new page */ + jit->pages = (struct page**) realloc(jit->pages, (++jit->pagenum) * sizeof(jit->pages[0])); + + size = ALIGN_UP(sz + LINKTABLE_MAX_SIZE + sizeof(struct page), jit->align_page_size); + + page = (struct page*) AllocPage(size); + jit->pages[jit->pagenum-1] = page; + pdata = (uint8_t*) page; + page->size = size; + page->off = sizeof(struct page); + + lua_newtable(L); + +#define ADDFUNC(DLL, NAME) \ + lua_pushliteral(L, #NAME); \ + func = DLL ? (cfunction) GetProcAddressA(DLL, #NAME) : NULL; \ + func = func ? func : (cfunction) &NAME; \ + lua_pushcfunction(L, (lua_CFunction) func); \ + lua_rawset(L, -3) + + ADDFUNC(NULL, check_double); + ADDFUNC(NULL, check_float); + ADDFUNC(NULL, check_uint64); + ADDFUNC(NULL, check_int64); + ADDFUNC(NULL, check_int32); + ADDFUNC(NULL, check_uint32); + ADDFUNC(NULL, check_uintptr); + ADDFUNC(NULL, check_enum); + ADDFUNC(NULL, check_typed_pointer); + ADDFUNC(NULL, check_typed_cfunction); + ADDFUNC(NULL, check_complex_double); + ADDFUNC(NULL, check_complex_float); + ADDFUNC(NULL, unpack_varargs_stack); + ADDFUNC(NULL, unpack_varargs_stack_skip); + ADDFUNC(NULL, unpack_varargs_reg); + ADDFUNC(NULL, unpack_varargs_float); + ADDFUNC(NULL, unpack_varargs_int); + ADDFUNC(NULL, push_cdata); + ADDFUNC(NULL, push_int); + ADDFUNC(NULL, push_uint); + ADDFUNC(NULL, lua_pushinteger); + ADDFUNC(NULL, push_float); + ADDFUNC(jit->kernel32_dll, SetLastError); + ADDFUNC(jit->kernel32_dll, GetLastError); + ADDFUNC(jit->lua_dll, luaL_error); + ADDFUNC(jit->lua_dll, lua_pushnumber); + ADDFUNC(jit->lua_dll, lua_pushboolean); + ADDFUNC(jit->lua_dll, lua_gettop); + ADDFUNC(jit->lua_dll, lua_rawgeti); + ADDFUNC(jit->lua_dll, lua_pushnil); + ADDFUNC(jit->lua_dll, lua_callk); + ADDFUNC(jit->lua_dll, lua_settop); + ADDFUNC(jit->lua_dll, lua_remove); +#undef ADDFUNC + + for (i = 0; extnames[i] != NULL; i++) { + + if (strcmp(extnames[i], "FUNCTION") == 0) { + shred(pdata + page->off, 0, JUMP_SIZE); + jit->function_extern = i; + + } else { + lua_getfield(L, -1, extnames[i]); + func = (cfunction) lua_tocfunction(L, -1); + + if (func == NULL) { + luaL_error(L, "internal error: missing link for %s", extnames[i]); + } + + compile_extern_jump(jit, L, func, pdata + page->off); + lua_pop(L, 1); + } + + page->off += JUMP_SIZE; + } + + page->freed = page->off; + lua_pop(L, 1); + + } else { + page = jit->pages[jit->pagenum-1]; + EnableWrite(page, page->size); + } + + return (uint8_t*) page + page->off; +} + +static void commit_code(struct jit* jit, void* code, size_t sz) +{ + struct page* page = jit->pages[jit->pagenum-1]; + page->off += sz; + EnableExecute(page, page->size); + { +#if 0 + FILE* out = fopen("\\Hard Disk\\out.bin", "wb"); + fwrite(page, page->off, 1, out); + fclose(out); +#endif + } +} + +/* push_func_ref pushes a copy of the upval table embedded in the compiled + * function func. + */ +void push_func_ref(lua_State* L, cfunction func) +{ + struct jit_head* h = ((struct jit_head*) func) - 1; + lua_rawgeti(L, LUA_REGISTRYINDEX, h->ref); +} + +void free_code(struct jit* jit, lua_State* L, cfunction func) +{ + size_t i; + struct jit_head* h = ((struct jit_head*) func) - 1; + for (i = 0; i < jit->pagenum; i++) { + struct page* p = jit->pages[i]; + + if ((uint8_t*) h < (uint8_t*) p || (uint8_t*) p + p->size <= (uint8_t*) h) { + continue; + } + + luaL_unref(L, LUA_REGISTRYINDEX, h->ref); + + EnableWrite(p, p->size); + p->freed += h->size; + + shred(h, 0, h->size); + + if (p->freed < p->off) { + EnableExecute(p, p->size); + return; + } + + FreePage(p, p->size); + memmove(&jit->pages[i], &jit->pages[i+1], (jit->pagenum - (i+1)) * sizeof(jit->pages[0])); + jit->pagenum--; + return; + } + + assert(!"couldn't find func in the jit pages"); +} + + |