w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

call.c
Go to the documentation of this file.
1 /* vim: ts=4 sw=4 sts=4 et tw=78
2  * Portions copyright (c) 2015-present, Facebook, Inc. All rights reserved.
3  * Portions copyright (c) 2011 James R. McKaskill.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  */
9 #include "ffi.h"
10 
12 
13 static void* reserve_code(struct jit* jit, lua_State* L, size_t sz);
14 static void commit_code(struct jit* jit, void* p, size_t sz);
15 
16 static void push_int(lua_State* L, int val)
17 { lua_pushinteger(L, val); }
18 
19 static void push_uint(lua_State* L, unsigned int val)
20 { lua_pushinteger(L, val); }
21 
22 static void push_float(lua_State* L, float val)
23 { lua_pushnumber(L, val); }
24 
25 #ifndef _WIN32
26 static int GetLastError(void)
27 { return errno; }
28 static void SetLastError(int err)
29 { errno = err; }
30 #endif
31 
32 #ifdef NDEBUG
33 #define shred(a,b,c)
34 #else
35 #define shred(p,s,e) memset((uint8_t*)(p)+(s),0xCC,(e)-(s))
36 #endif
37 
38 
39 #ifdef _WIN64
40 #include "dynasm/dasm_x86.h"
41 #include "call_x64win.h"
42 #elif defined __amd64__
43 #include "dynasm/dasm_x86.h"
44 #include "call_x64.h"
45 #elif defined __arm__ || defined __arm || defined __ARM__ || defined __ARM || defined ARM || defined _ARM_ || defined ARMV4I || defined _M_ARM
46 #include "dynasm/dasm_arm.h"
47 #include "call_arm.h"
48 #else
49 #include "dynasm/dasm_x86.h"
50 #include "call_x86.h"
51 #endif
52 
53 struct jit_head {
54  size_t size;
55  int ref;
57 };
58 
59 #define LINKTABLE_MAX_SIZE (sizeof(extnames) / sizeof(extnames[0]) * (JUMP_SIZE))
60 
61 static cfunction compile(struct jit* jit, lua_State* L, cfunction func, int ref)
62 {
63  struct jit_head* code;
64  size_t codesz;
65  int err;
66 
67  dasm_checkstep(jit, -1);
68  if ((err = dasm_link(jit, &codesz)) != 0) {
69  char buf[32];
70  sprintf(buf, "%x", err);
71  luaL_error(L, "dasm_link error %s", buf);
72  }
73 
74  codesz += sizeof(struct jit_head);
75  code = (struct jit_head*) reserve_code(jit, L, codesz);
76  code->ref = ref;
77  code->size = codesz;
78  compile_extern_jump(jit, L, func, code->jump);
79 
80  if ((err = dasm_encode(jit, code+1)) != 0) {
81  char buf[32];
82  sprintf(buf, "%x", err);
83  commit_code(jit, code, 0);
84  luaL_error(L, "dasm_encode error %s", buf);
85  }
86 
87  commit_code(jit, code, codesz);
88  return (cfunction) (code+1);
89 }
90 
92 
93 int get_extern(struct jit* jit, uint8_t* addr, int idx, int type)
94 {
95  struct page* page = jit->pages[jit->pagenum-1];
96  jump_t* jumps = (jump_t*) (page+1);
97  struct jit_head* h = (struct jit_head*) ((uint8_t*) page + page->off);
98  uint8_t* jmp;
99  ptrdiff_t off;
100 
101  if (idx == jit->function_extern) {
102  jmp = h->jump;
103  } else {
104  jmp = jumps[idx];
105  }
106 
107  /* compensate for room taken up for the offset so that we can work rip
108  * relative */
109  addr += BRANCH_OFF;
110 
111  /* see if we can fit the offset in the branch displacement, if not use the
112  * jump instruction */
113  off = *(uint8_t**) jmp - addr;
114 
115  if (MIN_BRANCH <= off && off <= MAX_BRANCH) {
116  return (int32_t) off;
117  } else {
118  return (int32_t)(jmp + sizeof(uint8_t*) - addr);
119  }
120 }
121 
122 static void* reserve_code(struct jit* jit, lua_State* L, size_t sz)
123 {
124  struct page* page;
125  size_t off = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->off : 0;
126  size_t size = (jit->pagenum > 0) ? jit->pages[jit->pagenum-1]->size : 0;
127 
128  if (off + sz >= size) {
129  int i;
130  uint8_t* pdata;
131  cfunction func;
132 
133  /* need to create a new page */
134  jit->pages = (struct page**) realloc(jit->pages, (++jit->pagenum) * sizeof(jit->pages[0]));
135 
136  size = ALIGN_UP(sz + LINKTABLE_MAX_SIZE + sizeof(struct page), jit->align_page_size);
137 
138  page = (struct page*) AllocPage(size);
139  jit->pages[jit->pagenum-1] = page;
140  pdata = (uint8_t*) page;
141  page->size = size;
142  page->off = sizeof(struct page);
143 
144  lua_newtable(L);
145 
146 #define ADDFUNC(DLL, NAME) \
147  lua_pushliteral(L, #NAME); \
148  func = DLL ? (cfunction) GetProcAddressA(DLL, #NAME) : NULL; \
149  func = func ? func : (cfunction) &NAME; \
150  lua_pushcfunction(L, (lua_CFunction) func); \
151  lua_rawset(L, -3)
152 
186 #undef ADDFUNC
187 
188  for (i = 0; extnames[i] != NULL; i++) {
189 
190  if (strcmp(extnames[i], "FUNCTION") == 0) {
191  shred(pdata + page->off, 0, JUMP_SIZE);
192  jit->function_extern = i;
193 
194  } else {
195  lua_getfield(L, -1, extnames[i]);
196  func = (cfunction) lua_tocfunction(L, -1);
197 
198  if (func == NULL) {
199  luaL_error(L, "internal error: missing link for %s", extnames[i]);
200  }
201 
202  compile_extern_jump(jit, L, func, pdata + page->off);
203  lua_pop(L, 1);
204  }
205 
206  page->off += JUMP_SIZE;
207  }
208 
209  page->freed = page->off;
210  lua_pop(L, 1);
211 
212  } else {
213  page = jit->pages[jit->pagenum-1];
215  }
216 
217  return (uint8_t*) page + page->off;
218 }
219 
220 static void commit_code(struct jit* jit, void* code, size_t sz)
221 {
222  struct page* page = jit->pages[jit->pagenum-1];
223  page->off += sz;
225  {
226 #if 0
227  FILE* out = fopen("\\Hard Disk\\out.bin", "wb");
228  fwrite(page, page->off, 1, out);
229  fclose(out);
230 #endif
231  }
232 }
233 
234 /* push_func_ref pushes a copy of the upval table embedded in the compiled
235  * function func.
236  */
238 {
239  struct jit_head* h = ((struct jit_head*) func) - 1;
241 }
242 
244 {
245  size_t i;
246  struct jit_head* h = ((struct jit_head*) func) - 1;
247  for (i = 0; i < jit->pagenum; i++) {
248  struct page* p = jit->pages[i];
249 
250  if ((uint8_t*) h < (uint8_t*) p || (uint8_t*) p + p->size <= (uint8_t*) h) {
251  continue;
252  }
253 
255 
256  EnableWrite(p, p->size);
257  p->freed += h->size;
258 
259  shred(h, 0, h->size);
260 
261  if (p->freed < p->off) {
262  EnableExecute(p, p->size);
263  return;
264  }
265 
266  FreePage(p, p->size);
267  memmove(&jit->pages[i], &jit->pages[i+1], (jit->pagenum - (i+1)) * sizeof(jit->pages[0]));
268  jit->pagenum--;
269  return;
270  }
271 
272  assert(!"couldn't find func in the jit pages");
273 }
274 
275 
int ptrdiff_t
Definition: CPAL.d:3845
int code
Definition: aftopl.c:52
#define type(a)
Definition: aptex-macros.h:171
static void commit_code(struct jit *jit, void *p, size_t sz)
Definition: call.c:220
#define ADDFUNC(DLL, NAME)
static cfunction compile(struct jit *Dst, lua_State *L, cfunction func, int ref)
Definition: call.c:61
static void push_int(lua_State *L, int val)
Definition: call.c:16
void push_func_ref(lua_State *L, cfunction func)
Definition: call.c:237
#define shred(p, s, e)
Definition: call.c:35
#define LINKTABLE_MAX_SIZE
Definition: call.c:59
static void SetLastError(int err)
Definition: call.c:28
static void push_float(lua_State *L, float val)
Definition: call.c:22
void free_code(struct jit *jit, lua_State *L, cfunction func)
Definition: call.c:243
static void push_uint(lua_State *L, unsigned int val)
Definition: call.c:19
uint8_t jump_t[4]
Definition: call.c:91
int get_extern(struct jit *jit, uint8_t *addr, int idx, int type)
Definition: call.c:93
static void * reserve_code(struct jit *jit, lua_State *L, size_t sz)
Definition: call.c:122
static int GetLastError(void)
Definition: call.c:26
#define BRANCH_OFF
Definition: call_arm.h:606
#define JUMP_SIZE
Definition: call_arm.h:603
#define MIN_BRANCH
Definition: call_arm.h:604
static void compile_extern_jump(struct jit *jit, lua_State *L, cfunction func, uint8_t *code)
Definition: call_arm.h:608
#define MAX_BRANCH
Definition: call_arm.h:605
static const char *const extnames[]
Definition: call_arm.h:572
static struct sed_label * jumps
Definition: compile.c:116
void * push_cdata(lua_State *L, int ct_usr, const struct ctype *ct)
Definition: ctype.c:136
int h
Definition: dviconv.c:9
#define fopen
Definition: xxstdio.h:21
int strcmp()
Definition: coll.cpp:143
int32_t check_int32(lua_State *L, int idx)
Definition: ffi.c:274
uint32_t check_uint32(lua_State *L, int idx)
Definition: ffi.c:277
int32_t check_enum(lua_State *L, int idx, int to_usr, const struct ctype *to_ct)
Definition: ffi.c:477
float check_float(lua_State *L, int idx)
Definition: ffi.c:289
void unpack_varargs_stack_skip(lua_State *L, int first, int last, int ints_to_skip, int floats_to_skip, char *to)
Definition: ffi.c:419
double check_double(lua_State *L, int idx)
Definition: ffi.c:286
void unpack_varargs_stack(lua_State *L, int first, int last, char *to)
Definition: ffi.c:410
complex_float check_complex_float(lua_State *L, int idx)
Definition: ffi.c:343
cfunction check_typed_cfunction(lua_State *L, int idx, int to_usr, const struct ctype *tt)
Definition: ffi.c:800
void unpack_varargs_int(lua_State *L, int first, int last, int max, char *to)
Definition: ffi.c:449
void unpack_varargs_reg(lua_State *L, int first, int last, char *to)
Definition: ffi.c:462
void * check_typed_pointer(lua_State *L, int idx, int to_usr, const struct ctype *tt)
Definition: ffi.c:611
int64_t check_int64(lua_State *L, int idx)
Definition: ffi.c:280
uintptr_t check_uintptr(lua_State *L, int idx)
Definition: ffi.c:292
complex_double check_complex_double(lua_State *L, int idx)
Definition: ffi.c:295
void unpack_varargs_float(lua_State *L, int first, int last, int max, char *to)
Definition: ffi.c:436
uint64_t check_uint64(lua_State *L, int idx)
Definition: ffi.c:283
#define ALIGN_UP(PTR, MASK)
Definition: ffi.h:236
#define EnableExecute(data, size)
Definition: ffi.h:198
void(* cfunction)(void)
Definition: ffi.h:379
#define FreePage(data, size)
Definition: ffi.h:197
#define AllocPage(size)
Definition: ffi.h:196
#define EnableWrite(data, size)
Definition: ffi.h:199
#define memmove(d, s, n)
Definition: gsftopk.c:65
FILE * out
Definition: hbf2gf.c:286
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
signed int int32_t
Definition: stdint.h:77
unsigned char uint8_t
Definition: stdint.h:78
int errno
#define buf
#define fclose
Definition: debug.h:100
Code related to b fwrite(a, sizeof(char), b, stdout) @d C_printf(c
#define sprintf
Definition: snprintf.c:44
static luaL_Reg func[]
Definition: except.c:32
#define realloc
Definition: glob.c:206
@ err
Definition: mtxline.h:24
dictionary off
Definition: fc-lang.py:226
def ref(x)
Definition: pdf-org.py:104
static int sz
Definition: pdftocairo.cc:114
static int size
Definition: ppmlabel.c:24
int dasm_encode(Dst_DECL, void *buffer)
Definition: dasm_arm.h:344
int dasm_link(Dst_DECL, size_t *szp)
Definition: dasm_arm.h:278
#define dasm_checkstep(a, b)
Definition: dasm_proto.h:79
#define Dst_DECL
Definition: dasm_proto.h:17
int lua_gettop(lua_State *L)
Definition: lapi.c:167
void lua_pushinteger(lua_State *L, lua_Integer n)
Definition: lapi.c:466
void lua_pushnumber(lua_State *L, lua_Number n)
Definition: lapi.c:458
void lua_callk(lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k)
Definition: lapi.c:909
void lua_pushnil(lua_State *L)
Definition: lapi.c:450
void lua_settop(lua_State *L, int idx)
Definition: lapi.c:172
lua_CFunction lua_tocfunction(lua_State *L, int idx)
Definition: lapi.c:404
int lua_rawgeti(lua_State *L, int idx, lua_Integer n)
Definition: lapi.c:658
int lua_getfield(lua_State *L, int idx, const char *k)
Definition: lapi.c:622
void lua_pushboolean(lua_State *L, int b)
Definition: lapi.c:557
int luaL_error(lua_State *L, const char *fmt,...)
Definition: lauxlib.c:223
void luaL_unref(lua_State *L, int t, int ref)
Definition: lauxlib.c:616
#define LUA_REGISTRYINDEX
Definition: lua.h:41
#define lua_remove(L, idx)
Definition: lua.h:370
#define lua_newtable(L)
Definition: lua.h:345
#define lua_pop(L, n)
Definition: lua.h:343
Definition: sed.h:84
Definition: inftrees.h:24
Definition: call.c:53
size_t size
Definition: call.c:54
int ref
Definition: call.c:55
uint8_t jump[4]
Definition: call.c:56
Definition: ffi.h:221
int function_extern
Definition: ffi.h:229
size_t pagenum
Definition: ffi.h:225
struct page ** pages
Definition: ffi.h:226
size_t align_page_size
Definition: ffi.h:227
void * lua_dll
Definition: ffi.h:230
void * kernel32_dll
Definition: ffi.h:231
Definition: mendex.h:14
size_t size
Definition: ffi.h:216
size_t off
Definition: ffi.h:217
size_t freed
Definition: ffi.h:218
Definition: strexpr.c:21
#define FILE
Definition: t1stdio.h:34
page
Definition: tex4ht.c:3916
@ L
Definition: ubidiimp.h:45