diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/LuaJIT-1.1.7/src/lcoco.c | 693 |
1 files changed, 0 insertions, 693 deletions
diff --git a/libraries/LuaJIT-1.1.7/src/lcoco.c b/libraries/LuaJIT-1.1.7/src/lcoco.c deleted file mode 100644 index c3acc68..0000000 --- a/libraries/LuaJIT-1.1.7/src/lcoco.c +++ /dev/null | |||
@@ -1,693 +0,0 @@ | |||
1 | /* | ||
2 | ** Copyright (C) 2004-2011 Mike Pall. All rights reserved. | ||
3 | ** | ||
4 | ** Permission is hereby granted, free of charge, to any person obtaining | ||
5 | ** a copy of this software and associated documentation files (the | ||
6 | ** "Software"), to deal in the Software without restriction, including | ||
7 | ** without limitation the rights to use, copy, modify, merge, publish, | ||
8 | ** distribute, sublicense, and/or sell copies of the Software, and to | ||
9 | ** permit persons to whom the Software is furnished to do so, subject to | ||
10 | ** the following conditions: | ||
11 | ** | ||
12 | ** The above copyright notice and this permission notice shall be | ||
13 | ** included in all copies or substantial portions of the Software. | ||
14 | ** | ||
15 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
16 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
17 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
18 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
19 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
20 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
21 | ** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
22 | ** | ||
23 | ** [ MIT license: http://www.opensource.org/licenses/mit-license.php ] | ||
24 | */ | ||
25 | |||
26 | /* Coco -- True C coroutines for Lua. http://luajit.org/coco.html */ | ||
27 | #ifndef COCO_DISABLE | ||
28 | |||
29 | #define lcoco_c | ||
30 | #define LUA_CORE | ||
31 | |||
32 | #include "lua.h" | ||
33 | |||
34 | #include "lobject.h" | ||
35 | #include "lstate.h" | ||
36 | #include "ldo.h" | ||
37 | #include "lvm.h" | ||
38 | #include "lgc.h" | ||
39 | |||
40 | |||
41 | /* | ||
42 | ** Define this if you want to run Coco with valgrind. You will get random | ||
43 | ** errors about accessing memory from newly allocated C stacks if you don't. | ||
44 | ** You need at least valgrind 3.0 for this to work. | ||
45 | ** | ||
46 | ** This macro evaluates to a no-op if not run with valgrind. I.e. you can | ||
47 | ** use the same binary for regular runs, too (without a performance loss). | ||
48 | */ | ||
49 | #ifdef USE_VALGRIND | ||
50 | #include <valgrind/valgrind.h> | ||
51 | #define STACK_REG(coco, p, sz) (coco)->vgid = VALGRIND_STACK_REGISTER(p, p+sz); | ||
52 | #define STACK_DEREG(coco) VALGRIND_STACK_DEREGISTER((coco)->vgid); | ||
53 | #define STACK_VGID unsigned int vgid; | ||
54 | #else | ||
55 | #define STACK_REG(coco, p, sz) | ||
56 | #define STACK_DEREG(id) | ||
57 | #define STACK_VGID | ||
58 | #endif | ||
59 | |||
60 | /* ------------------------------------------------------------------------ */ | ||
61 | |||
62 | /* Use Windows Fibers. */ | ||
63 | #if defined(COCO_USE_FIBERS) | ||
64 | |||
65 | #define _WIN32_WINNT 0x0400 | ||
66 | #include <windows.h> | ||
67 | |||
68 | #define COCO_MAIN_DECL CALLBACK | ||
69 | |||
70 | typedef LPFIBER_START_ROUTINE coco_MainFunc; | ||
71 | |||
72 | #define COCO_NEW(OL, NL, cstacksize, mainfunc) \ | ||
73 | if ((L2COCO(NL)->fib = CreateFiber(cstacksize, mainfunc, NL)) == NULL) \ | ||
74 | luaD_throw(OL, LUA_ERRMEM); | ||
75 | |||
76 | #define COCO_FREE(L) \ | ||
77 | DeleteFiber(L2COCO(L)->fib); \ | ||
78 | L2COCO(L)->fib = NULL; | ||
79 | |||
80 | /* See: http://blogs.msdn.com/oldnewthing/archive/2004/12/31/344799.aspx */ | ||
81 | #define COCO_JUMPIN(coco) \ | ||
82 | { void *cur = GetCurrentFiber(); \ | ||
83 | coco->back = (cur == NULL || cur == (void *)0x1e00) ? \ | ||
84 | ConvertThreadToFiber(NULL) : cur; } \ | ||
85 | SwitchToFiber(coco->fib); | ||
86 | |||
87 | #define COCO_JUMPOUT(coco) \ | ||
88 | SwitchToFiber(coco->back); | ||
89 | |||
90 | /* CreateFiber() defaults to STACKSIZE from the Windows module .def file. */ | ||
91 | #define COCO_DEFAULT_CSTACKSIZE 0 | ||
92 | |||
93 | /* ------------------------------------------------------------------------ */ | ||
94 | |||
95 | #else /* !COCO_USE_FIBERS */ | ||
96 | |||
97 | #ifndef COCO_USE_UCONTEXT | ||
98 | |||
99 | /* Try inline asm first. */ | ||
100 | #if __GNUC__ >= 3 && !defined(COCO_USE_SETJMP) | ||
101 | |||
102 | #if defined(__i386) || defined(__i386__) | ||
103 | |||
104 | #ifdef __PIC__ | ||
105 | typedef void *coco_ctx[4]; /* eip, esp, ebp, ebx */ | ||
106 | static inline void coco_switch(coco_ctx from, coco_ctx to) | ||
107 | { | ||
108 | __asm__ __volatile__ ( | ||
109 | "call 1f\n" "1:\tpopl %%eax\n\t" "addl $(2f-1b),%%eax\n\t" | ||
110 | "movl %%eax, (%0)\n\t" "movl %%esp, 4(%0)\n\t" | ||
111 | "movl %%ebp, 8(%0)\n\t" "movl %%ebx, 12(%0)\n\t" | ||
112 | "movl 12(%1), %%ebx\n\t" "movl 8(%1), %%ebp\n\t" | ||
113 | "movl 4(%1), %%esp\n\t" "jmp *(%1)\n" "2:\n" | ||
114 | : "+S" (from), "+D" (to) : : "eax", "ecx", "edx", "memory", "cc"); | ||
115 | } | ||
116 | #else | ||
117 | typedef void *coco_ctx[3]; /* eip, esp, ebp */ | ||
118 | static inline void coco_switch(coco_ctx from, coco_ctx to) | ||
119 | { | ||
120 | __asm__ __volatile__ ( | ||
121 | "movl $1f, (%0)\n\t" "movl %%esp, 4(%0)\n\t" "movl %%ebp, 8(%0)\n\t" | ||
122 | "movl 8(%1), %%ebp\n\t" "movl 4(%1), %%esp\n\t" "jmp *(%1)\n" "1:\n" | ||
123 | : "+S" (from), "+D" (to) : : "eax", "ebx", "ecx", "edx", "memory", "cc"); | ||
124 | } | ||
125 | #endif | ||
126 | |||
127 | #define COCO_CTX coco_ctx | ||
128 | #define COCO_SWITCH(from, to) coco_switch(from, to); | ||
129 | #define COCO_MAKECTX(coco, buf, func, stack, a0) \ | ||
130 | buf[0] = (void *)(func); \ | ||
131 | buf[1] = (void *)(stack); \ | ||
132 | buf[2] = (void *)0; \ | ||
133 | stack[0] = 0xdeadc0c0; /* Dummy return address. */ \ | ||
134 | coco->arg0 = (size_t)(a0); | ||
135 | #define COCO_STATE_HEAD size_t arg0; | ||
136 | |||
137 | #elif defined(__x86_64__) | ||
138 | |||
139 | static void coco_wrap_main(void) | ||
140 | { | ||
141 | __asm__ __volatile__ ("\tmovq %r13, %rdi\n\tjmpq *%r12\n"); | ||
142 | } | ||
143 | |||
144 | typedef void *coco_ctx[8]; /* rip, rsp, rbp, rbx, r12, r13, r14, r15 */ | ||
145 | static inline void coco_switch(coco_ctx from, coco_ctx to) | ||
146 | { | ||
147 | __asm__ __volatile__ ( | ||
148 | "leaq 1f(%%rip), %%rax\n\t" | ||
149 | "movq %%rax, (%0)\n\t" "movq %%rsp, 8(%0)\n\t" "movq %%rbp, 16(%0)\n\t" | ||
150 | "movq %%rbx, 24(%0)\n\t" "movq %%r12, 32(%0)\n\t" "movq %%r13, 40(%0)\n\t" | ||
151 | "movq %%r14, 48(%0)\n\t" "movq %%r15, 56(%0)\n\t" | ||
152 | "movq 56(%1), %%r15\n\t" "movq 48(%1), %%r14\n\t" "movq 40(%1), %%r13\n\t" | ||
153 | "movq 32(%1), %%r12\n\t" "movq 24(%1), %%rbx\n\t" "movq 16(%1), %%rbp\n\t" | ||
154 | "movq 8(%1), %%rsp\n\t" "jmpq *(%1)\n" "1:\n" | ||
155 | : "+S" (from), "+D" (to) : | ||
156 | : "rax", "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc"); | ||
157 | } | ||
158 | |||
159 | #define COCO_CTX coco_ctx | ||
160 | #define COCO_SWITCH(from, to) coco_switch(from, to); | ||
161 | #define COCO_MAKECTX(coco, buf, func, stack, a0) \ | ||
162 | buf[0] = (void *)(coco_wrap_main); \ | ||
163 | buf[1] = (void *)(stack); \ | ||
164 | buf[2] = (void *)0; \ | ||
165 | buf[3] = (void *)0; \ | ||
166 | buf[4] = (void *)(func); \ | ||
167 | buf[5] = (void *)(a0); \ | ||
168 | buf[6] = (void *)0; \ | ||
169 | buf[7] = (void *)0; \ | ||
170 | stack[0] = 0xdeadc0c0deadc0c0; /* Dummy return address. */ \ | ||
171 | |||
172 | #elif __mips && _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi) | ||
173 | |||
174 | /* No way to avoid the function prologue with inline assembler. So use this: */ | ||
175 | static const unsigned int coco_switch[] = { | ||
176 | #ifdef __mips_soft_float | ||
177 | #define COCO_STACKSAVE -10 | ||
178 | 0x27bdffd8, /* addiu sp, sp, -(10*4) */ | ||
179 | #else | ||
180 | #define COCO_STACKSAVE -22 | ||
181 | 0x27bdffa8, /* addiu sp, sp, -(10*4+6*8) */ | ||
182 | /* sdc1 {$f20-$f30}, offset(sp) */ | ||
183 | 0xf7be0050, 0xf7bc0048, 0xf7ba0040, 0xf7b80038, 0xf7b60030, 0xf7b40028, | ||
184 | #endif | ||
185 | /* sw {gp,s0-s8}, offset(sp) */ | ||
186 | 0xafbe0024, 0xafb70020, 0xafb6001c, 0xafb50018, 0xafb40014, 0xafb30010, | ||
187 | 0xafb2000c, 0xafb10008, 0xafb00004, 0xafbc0000, | ||
188 | /* sw sp, 4(a0); sw ra, 0(a0); lw ra, 0(a1); lw sp, 4(a1); move t9, ra */ | ||
189 | 0xac9d0004, 0xac9f0000, 0x8cbf0000, 0x8cbd0004, 0x03e0c821, | ||
190 | /* lw caller-saved-reg, offset(sp) */ | ||
191 | 0x8fbe0024, 0x8fb70020, 0x8fb6001c, 0x8fb50018, 0x8fb40014, 0x8fb30010, | ||
192 | 0x8fb2000c, 0x8fb10008, 0x8fb00004, 0x8fbc0000, | ||
193 | #ifdef __mips_soft_float | ||
194 | 0x03e00008, 0x27bd0028 /* jr ra; addiu sp, sp, 10*4 */ | ||
195 | #else | ||
196 | /* ldc1 {$f20-$f30}, offset(sp) */ | ||
197 | 0xd7be0050, 0xd7bc0048, 0xd7ba0040, 0xd7b80038, 0xd7b60030, 0xd7b40028, | ||
198 | 0x03e00008, 0x27bd0058 /* jr ra; addiu sp, sp, 10*4+6*8 */ | ||
199 | #endif | ||
200 | }; | ||
201 | |||
202 | typedef void *coco_ctx[2]; /* ra, sp */ | ||
203 | #define COCO_CTX coco_ctx | ||
204 | #define COCO_SWITCH(from, to) \ | ||
205 | ((void (*)(coco_ctx, coco_ctx))coco_switch)(from, to); | ||
206 | #define COCO_MAKECTX(coco, buf, func, stack, a0) \ | ||
207 | buf[0] = (void *)(func); \ | ||
208 | buf[1] = (void *)&stack[COCO_STACKSAVE]; \ | ||
209 | stack[4] = (size_t)(a0); /* Assumes o32 ABI. */ | ||
210 | #define COCO_STACKADJUST 8 | ||
211 | #define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L | ||
212 | |||
213 | #elif defined(__sparc__) | ||
214 | |||
215 | typedef void *coco_ctx[4]; | ||
216 | #define COCO_CTX coco_ctx | ||
217 | #define COCO_SWITCH(from, to) coco_switch(from, to); | ||
218 | #define COCO_STACKADJUST 24 | ||
219 | |||
220 | #if defined(__LP64__) | ||
221 | #define COCO_STACKBIAS (2047UL) | ||
222 | #define COCO_PTR2SP(stack) (((unsigned long)stack)-COCO_STACKBIAS) | ||
223 | static inline void coco_switch(coco_ctx from, coco_ctx to) | ||
224 | { | ||
225 | void *__stack[16] __attribute__((aligned (16))); | ||
226 | unsigned long __tmp_sp = COCO_PTR2SP(__stack); | ||
227 | __asm__ __volatile__ | ||
228 | (/* Flush register window(s) to stack and save the previous stack | ||
229 | pointer to capture the current registers, %l0-%l7 and %i0-%i7. */ | ||
230 | "ta 3\n\t" | ||
231 | "stx %%sp,[%0+8]\n\t" | ||
232 | /* Move to a temporary stack. If the register window is flushed | ||
233 | for some reason (e.g. context switch), not the next stack | ||
234 | but the temporary stack should be used so as not to break | ||
235 | neither the previous nor next stack */ | ||
236 | "mov %2,%%sp\n\t" | ||
237 | "sethi %%hh(1f),%%g1\n\t" /* i.e. setx 1f,%%g1 */ | ||
238 | "or %%g1,%%hm(1f),%%g1\n\t" | ||
239 | "sethi %%lm(1f),%%g2\n\t" | ||
240 | "or %%g2,%%lo(1f),%%g2\n\t" | ||
241 | "sllx %%g1,32,%%g1\n\t" | ||
242 | "or %%g1,%%g2,%%g1\n\t" | ||
243 | "stx %%g1,[%0]\n\t" | ||
244 | /* Restore registers from stack. DO NOT load the next stack | ||
245 | pointer directly to %sp. The register window can be possibly | ||
246 | flushed and restored asynchronous (e.g. context switch). */ | ||
247 | "mov %1,%%o1\n\t" | ||
248 | "ldx [%%o1+8],%%o2\n\t" | ||
249 | "ldx [%%o2+%3],%%l0\n\t" | ||
250 | "ldx [%%o2+%3+8],%%l1\n\t" | ||
251 | "ldx [%%o2+%3+0x10],%%l2\n\t" | ||
252 | "ldx [%%o2+%3+0x18],%%l3\n\t" | ||
253 | "ldx [%%o2+%3+0x20],%%l4\n\t" | ||
254 | "ldx [%%o2+%3+0x28],%%l5\n\t" | ||
255 | "ldx [%%o2+%3+0x30],%%l6\n\t" | ||
256 | "ldx [%%o2+%3+0x38],%%l7\n\t" | ||
257 | "ldx [%%o2+%3+0x40],%%i0\n\t" | ||
258 | "ldx [%%o2+%3+0x48],%%i1\n\t" | ||
259 | "ldx [%%o2+%3+0x50],%%i2\n\t" | ||
260 | "ldx [%%o2+%3+0x58],%%i3\n\t" | ||
261 | "ldx [%%o2+%3+0x60],%%i4\n\t" | ||
262 | "ldx [%%o2+%3+0x68],%%i5\n\t" | ||
263 | "ldx [%%o2+%3+0x70],%%i6\n\t" | ||
264 | "ldx [%%o2+%3+0x78],%%i7\n\t" | ||
265 | /* Move to the next stack with the consistent registers atomically */ | ||
266 | "mov %%o2,%%sp\n\t" | ||
267 | "ldx [%%o1],%%o2\n\t" | ||
268 | /* Since %o0-%o7 are marked as clobbered, values are safely overwritten | ||
269 | across the inline assembly. %o0-%o7 will have meaningless values | ||
270 | after leaving the inline assembly. The only exception is %o0, which | ||
271 | serves as an argument to coco_main */ | ||
272 | "ldx [%%o1+16],%%o0\n\t" | ||
273 | "jmpl %%o2,%%g0\n\t" | ||
274 | "nop\n\t" | ||
275 | "1:\n" | ||
276 | /* An assumption is made here; no input operand is assigned to %g1 | ||
277 | nor %g2. It's the case for the currently avilable gcc's */ | ||
278 | : : "r"(from),"r"(to),"r"(__tmp_sp),"i"(COCO_STACKBIAS) | ||
279 | : "g1","g2","o0","o1","o2","o3","o4","o5","o7","memory","cc"); | ||
280 | } | ||
281 | |||
282 | #define COCO_MAKECTX(coco, buf, func, stack, a0) \ | ||
283 | buf[0] = (void *)(func); \ | ||
284 | buf[1] = (void *)COCO_PTR2SP(&(stack)[0]); \ | ||
285 | buf[2] = (void *)(a0); \ | ||
286 | stack[0] = 0; \ | ||
287 | stack[1] = 0; \ | ||
288 | stack[2] = 0; \ | ||
289 | stack[3] = 0; \ | ||
290 | stack[4] = 0; \ | ||
291 | stack[5] = 0; \ | ||
292 | stack[6] = 0; \ | ||
293 | stack[7] = 0; \ | ||
294 | stack[8] = 0; \ | ||
295 | stack[9] = 0; \ | ||
296 | stack[10] = 0; \ | ||
297 | stack[11] = 0; \ | ||
298 | stack[12] = 0; \ | ||
299 | stack[13] = 0; \ | ||
300 | stack[14] = COCO_PTR2SP(&(stack)[COCO_STACKADJUST]); \ | ||
301 | stack[15] = 0xdeadc0c0deadc0c0; /* Dummy return address. */ \ | ||
302 | |||
303 | #else | ||
304 | static inline void coco_switch(coco_ctx from, coco_ctx to) | ||
305 | { | ||
306 | void *__tmp_stack[16] __attribute__((aligned (16))); | ||
307 | __asm__ __volatile__ | ||
308 | ("ta 3\n\t" | ||
309 | "st %%sp,[%0+4]\n\t" | ||
310 | "mov %2,%%sp\n\t" | ||
311 | "set 1f,%%g1\n\t" | ||
312 | "st %%g1,[%0]\n\t" | ||
313 | "mov %1,%%o1\n\t" | ||
314 | "ld [%%o1+4],%%o2\n\t" | ||
315 | "ldd [%%o2],%%l0\n\t" | ||
316 | "ldd [%%o2+8],%%l2\n\t" | ||
317 | "ldd [%%o2+0x10],%%l4\n\t" | ||
318 | "ldd [%%o2+0x18],%%l6\n\t" | ||
319 | "ldd [%%o2+0x20],%%i0\n\t" | ||
320 | "ldd [%%o2+0x28],%%i2\n\t" | ||
321 | "ldd [%%o2+0x30],%%i4\n\t" | ||
322 | "ldd [%%o2+0x38],%%i6\n\t" | ||
323 | "mov %%o2,%%sp\n\t" | ||
324 | "ld [%%o1],%%o2\n\t" | ||
325 | "ld [%%o1+8],%%o0\n\t" | ||
326 | "jmpl %%o2,%%g0\n\t" | ||
327 | "nop\n\t" | ||
328 | "1:\n" | ||
329 | : : "r"(from),"r"(to),"r"(__tmp_stack) | ||
330 | : "g1","o0","o1","o2","o3","o4","o5","o7","memory","cc"); | ||
331 | } | ||
332 | |||
333 | #define COCO_MAKECTX(coco, buf, func, stack, a0) \ | ||
334 | buf[0] = (void *)(func); \ | ||
335 | buf[1] = (void *)(stack); \ | ||
336 | buf[2] = (void *)(a0); \ | ||
337 | stack[0] = 0; \ | ||
338 | stack[1] = 0; \ | ||
339 | stack[2] = 0; \ | ||
340 | stack[3] = 0; \ | ||
341 | stack[4] = 0; \ | ||
342 | stack[5] = 0; \ | ||
343 | stack[6] = 0; \ | ||
344 | stack[7] = 0; \ | ||
345 | stack[8] = 0; \ | ||
346 | stack[9] = 0; \ | ||
347 | stack[10] = 0; \ | ||
348 | stack[11] = 0; \ | ||
349 | stack[12] = 0; \ | ||
350 | stack[13] = 0; \ | ||
351 | stack[14] = (size_t)&stack[COCO_STACKADJUST]; \ | ||
352 | stack[15] = 0xdeadc0c0; /* Dummy return address. */ \ | ||
353 | |||
354 | #endif /* !define(__LP64__) */ | ||
355 | |||
356 | #endif /* arch check */ | ||
357 | |||
358 | #endif /* !(__GNUC__ >= 3 && !defined(COCO_USE_SETJMP)) */ | ||
359 | |||
360 | /* Try _setjmp/_longjmp with a patched jump buffer. */ | ||
361 | #ifndef COCO_MAKECTX | ||
362 | #include <setjmp.h> | ||
363 | |||
364 | /* Check for supported CPU+OS combinations. */ | ||
365 | #if defined(__i386) || defined(__i386__) | ||
366 | |||
367 | #define COCO_STATE_HEAD size_t arg0; | ||
368 | #define COCO_SETJMP_X86(coco, stack, a0) \ | ||
369 | stack[COCO_STACKADJUST-1] = 0xdeadc0c0; /* Dummy return address. */ \ | ||
370 | coco->arg0 = (size_t)(a0); | ||
371 | |||
372 | #if __GLIBC__ == 2 && defined(JB_SP) /* x86-linux-glibc2 */ | ||
373 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
374 | buf->__jmpbuf[JB_PC] = (int)(func); \ | ||
375 | buf->__jmpbuf[JB_SP] = (int)(stack); \ | ||
376 | buf->__jmpbuf[JB_BP] = 0; \ | ||
377 | COCO_SETJMP_X86(coco, stack, a0) | ||
378 | #elif defined(__linux__) && defined(_I386_JMP_BUF_H) /* x86-linux-libc5 */ | ||
379 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
380 | buf->__pc = (func); \ | ||
381 | buf->__sp = (stack); \ | ||
382 | buf->__bp = NULL; \ | ||
383 | COCO_SETJMP_X86(coco, stack, a0) | ||
384 | #elif defined(__FreeBSD__) /* x86-FreeBSD */ | ||
385 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
386 | buf->_jb[0] = (long)(func); \ | ||
387 | buf->_jb[2] = (long)(stack); \ | ||
388 | buf->_jb[3] = 0; /* ebp */ \ | ||
389 | COCO_SETJMP_X86(coco, stack, a0) | ||
390 | #define COCO_STACKADJUST 2 | ||
391 | #elif defined(__NetBSD__) || defined(__OpenBSD__) /* x86-NetBSD, x86-OpenBSD */ | ||
392 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
393 | buf[0] = (long)(func); \ | ||
394 | buf[2] = (long)(stack); \ | ||
395 | buf[3] = 0; /* ebp */ \ | ||
396 | COCO_SETJMP_X86(coco, stack, a0) | ||
397 | #define COCO_STACKADJUST 2 | ||
398 | #elif defined(__solaris__) && _JBLEN == 10 /* x86-solaris */ | ||
399 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
400 | buf[5] = (int)(func); \ | ||
401 | buf[4] = (int)(stack); \ | ||
402 | buf[3] = 0; \ | ||
403 | COCO_SETJMP_X86(coco, stack, a0) | ||
404 | #elif defined(__MACH__) && defined(_BSD_I386_SETJMP_H) /* x86-macosx */ | ||
405 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
406 | buf[12] = (int)(func); \ | ||
407 | buf[9] = (int)(stack); \ | ||
408 | buf[8] = 0; /* ebp */ \ | ||
409 | COCO_SETJMP_X86(coco, stack, a0) | ||
410 | #endif | ||
411 | |||
412 | #elif defined(__x86_64__) || defined(__x86_64) | ||
413 | |||
414 | #define COCO_STATE_HEAD size_t arg0; | ||
415 | |||
416 | #define COCO_MAIN_PARAM \ | ||
417 | int _a, int _b, int _c, int _d, int _e, int _f, lua_State *L | ||
418 | |||
419 | #if defined(__solaris__) && _JBLEN == 8 /* x64-solaris */ | ||
420 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
421 | buf[7] = (long)(func); \ | ||
422 | buf[6] = (long)(stack); \ | ||
423 | buf[5] = 0; \ | ||
424 | stack[0] = 0xdeadc0c0; /* Dummy return address. */ \ | ||
425 | coco->arg0 = (size_t)(a0); | ||
426 | #endif | ||
427 | |||
428 | #elif defined(PPC) || defined(__ppc__) || defined(__PPC__) || \ | ||
429 | defined(__powerpc__) || defined(__POWERPC__) || defined(_ARCH_PPC) | ||
430 | |||
431 | #define COCO_STACKADJUST 16 | ||
432 | #define COCO_MAIN_PARAM \ | ||
433 | int _a, int _b, int _c, int _d, int _e, int _f, int _g, int _h, lua_State *L | ||
434 | |||
435 | #if defined(__MACH__) && defined(_BSD_PPC_SETJMP_H_) /* ppc32-macosx */ | ||
436 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
437 | buf[21] = (int)(func); \ | ||
438 | buf[0] = (int)(stack); \ | ||
439 | stack[6+8] = (size_t)(a0); | ||
440 | #endif | ||
441 | |||
442 | #elif (defined(MIPS) || defined(MIPSEL) || defined(__mips)) && \ | ||
443 | _MIPS_SIM == _MIPS_SIM_ABI32 && !defined(__mips_eabi) | ||
444 | |||
445 | /* Stack layout for o32 ABI. */ | ||
446 | #define COCO_STACKADJUST 8 | ||
447 | #define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L | ||
448 | |||
449 | #if __GLIBC__ == 2 || defined(__UCLIBC__) /* mips32-linux-glibc2 */ | ||
450 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
451 | buf->__jmpbuf->__pc = (func); /* = t9 in _longjmp. Reqd. for -mabicalls. */ \ | ||
452 | buf->__jmpbuf->__sp = (stack); \ | ||
453 | buf->__jmpbuf->__fp = (void *)0; \ | ||
454 | stack[4] = (size_t)(a0); | ||
455 | #endif | ||
456 | |||
457 | #elif defined(__arm__) || defined(__ARM__) | ||
458 | |||
459 | #if __GLIBC__ == 2 || defined(__UCLIBC__) /* arm-linux-glibc2 */ | ||
460 | #ifndef __JMP_BUF_SP | ||
461 | #define __JMP_BUF_SP ((sizeof(__jmp_buf)/sizeof(int))-2) | ||
462 | #endif | ||
463 | #define COCO_PATCHCTX(coco, buf, func, stack, a0) \ | ||
464 | buf->__jmpbuf[__JMP_BUF_SP+1] = (int)(func); /* pc */ \ | ||
465 | buf->__jmpbuf[__JMP_BUF_SP] = (int)(stack); /* sp */ \ | ||
466 | buf->__jmpbuf[__JMP_BUF_SP-1] = 0; /* fp */ \ | ||
467 | stack[0] = (size_t)(a0); | ||
468 | #define COCO_STACKADJUST 2 | ||
469 | #define COCO_MAIN_PARAM int _a, int _b, int _c, int _d, lua_State *L | ||
470 | #endif | ||
471 | |||
472 | #endif /* arch check */ | ||
473 | |||
474 | #ifdef COCO_PATCHCTX | ||
475 | #define COCO_CTX jmp_buf | ||
476 | #define COCO_MAKECTX(coco, buf, func, stack, a0) \ | ||
477 | _setjmp(buf); COCO_PATCHCTX(coco, buf, func, stack, a0) | ||
478 | #define COCO_SWITCH(from, to) if (!_setjmp(from)) _longjmp(to, 1); | ||
479 | #endif | ||
480 | |||
481 | #endif /* !defined(COCO_MAKECTX) */ | ||
482 | |||
483 | #endif /* !defined(COCO_USE_UCONTEXT) */ | ||
484 | |||
485 | /* ------------------------------------------------------------------------ */ | ||
486 | |||
487 | /* Use inline asm or _setjmp/_longjmp if available. */ | ||
488 | #ifdef COCO_MAKECTX | ||
489 | |||
490 | #ifndef COCO_STACKADJUST | ||
491 | #define COCO_STACKADJUST 1 | ||
492 | #endif | ||
493 | |||
494 | #define COCO_FILL(coco, NL, mainfunc) \ | ||
495 | { /* Include the return address to get proper stack alignment. */ \ | ||
496 | size_t *stackptr = &((size_t *)coco)[-COCO_STACKADJUST]; \ | ||
497 | COCO_MAKECTX(coco, coco->ctx, mainfunc, stackptr, NL) \ | ||
498 | } | ||
499 | |||
500 | /* ------------------------------------------------------------------------ */ | ||
501 | |||
502 | /* Else fallback to ucontext. Slower, because it saves/restores signals. */ | ||
503 | #else /* !defined(COCO_MAKECTX) */ | ||
504 | |||
505 | #include <ucontext.h> | ||
506 | |||
507 | #define COCO_CTX ucontext_t | ||
508 | |||
509 | /* Ugly workaround for makecontext() deficiencies on 64 bit CPUs. */ | ||
510 | /* Note that WIN64 (which is LLP64) never comes here. See above. */ | ||
511 | #if defined(__LP64__) || defined(_LP64) || INT_MAX != LONG_MAX | ||
512 | /* 64 bit CPU: split the pointer into two 32 bit ints. */ | ||
513 | #define COCO_MAIN_PARAM unsigned int lo, unsigned int hi | ||
514 | #define COCO_MAIN_GETL \ | ||
515 | lua_State *L = (lua_State *)((((unsigned long)hi)<<32)+(unsigned long)lo); | ||
516 | #define COCO_MAKECTX(coco, NL, mainfunc) \ | ||
517 | makecontext(&coco->ctx, mainfunc, 2, \ | ||
518 | (int)(ptrdiff_t)NL, (int)((ptrdiff_t)NL>>32)); | ||
519 | #else | ||
520 | /* 32 bit CPU: a pointer fits into an int. */ | ||
521 | #define COCO_MAKECTX(coco, NL, mainfunc) \ | ||
522 | makecontext(&coco->ctx, mainfunc, 1, (int)NL); | ||
523 | #endif | ||
524 | |||
525 | #define COCO_FILL(coco, NL, mainfunc) \ | ||
526 | getcontext(&coco->ctx); \ | ||
527 | coco->ctx.uc_link = NULL; /* We never exit from coco_main. */ \ | ||
528 | coco->ctx.uc_stack.ss_sp = coco->allocptr; \ | ||
529 | coco->ctx.uc_stack.ss_size = (char *)coco - (char *)(coco->allocptr); \ | ||
530 | COCO_MAKECTX(coco, NL, mainfunc) | ||
531 | |||
532 | #define COCO_SWITCH(from, to) swapcontext(&(from), &(to)); | ||
533 | |||
534 | #endif /* !defined(COCO_MAKECTX) */ | ||
535 | |||
536 | |||
537 | /* Common code for inline asm/setjmp/ucontext to allocate/free the stack. */ | ||
538 | |||
539 | struct coco_State { | ||
540 | #ifdef COCO_STATE_HEAD | ||
541 | COCO_STATE_HEAD | ||
542 | #endif | ||
543 | COCO_CTX ctx; /* Own context. */ | ||
544 | COCO_CTX back; /* Context to switch back to. */ | ||
545 | void *allocptr; /* Pointer to allocated memory. */ | ||
546 | int allocsize; /* Size of allocated memory. */ | ||
547 | int nargs; /* Number of arguments to pass. */ | ||
548 | STACK_VGID /* Optional valgrind stack id. See above. */ | ||
549 | }; | ||
550 | |||
551 | typedef void (*coco_MainFunc)(void); | ||
552 | |||
553 | /* Put the Coco state at the end and align it downwards. */ | ||
554 | #define ALIGNED_END(p, s, t) \ | ||
555 | ((t *)(((char *)0) + ((((char *)(p)-(char *)0)+(s)-sizeof(t)) & -16))) | ||
556 | |||
557 | /* TODO: use mmap. */ | ||
558 | #define COCO_NEW(OL, NL, cstacksize, mainfunc) \ | ||
559 | { \ | ||
560 | void *ptr = luaM_malloc(OL, cstacksize); \ | ||
561 | coco_State *coco = ALIGNED_END(ptr, cstacksize, coco_State); \ | ||
562 | STACK_REG(coco, ptr, cstacksize) \ | ||
563 | coco->allocptr = ptr; \ | ||
564 | coco->allocsize = cstacksize; \ | ||
565 | COCO_FILL(coco, NL, mainfunc) \ | ||
566 | L2COCO(NL) = coco; \ | ||
567 | } | ||
568 | |||
569 | #define COCO_FREE(L) \ | ||
570 | STACK_DEREG(L2COCO(L)) \ | ||
571 | luaM_freemem(L, L2COCO(L)->allocptr, L2COCO(L)->allocsize); \ | ||
572 | L2COCO(L) = NULL; | ||
573 | |||
574 | #define COCO_JUMPIN(coco) COCO_SWITCH(coco->back, coco->ctx) | ||
575 | #define COCO_JUMPOUT(coco) COCO_SWITCH(coco->ctx, coco->back) | ||
576 | |||
577 | #endif /* !COCO_USE_FIBERS */ | ||
578 | |||
579 | /* ------------------------------------------------------------------------ */ | ||
580 | |||
581 | #ifndef COCO_MIN_CSTACKSIZE | ||
582 | #define COCO_MIN_CSTACKSIZE (32768+4096) | ||
583 | #endif | ||
584 | |||
585 | /* Don't use multiples of 64K to avoid D-cache aliasing conflicts. */ | ||
586 | #ifndef COCO_DEFAULT_CSTACKSIZE | ||
587 | #define COCO_DEFAULT_CSTACKSIZE (65536-4096) | ||
588 | #endif | ||
589 | |||
590 | static int defaultcstacksize = COCO_DEFAULT_CSTACKSIZE; | ||
591 | |||
592 | /* Start the Lua or C function. */ | ||
593 | static void coco_start(lua_State *L, void *ud) | ||
594 | { | ||
595 | if (luaD_precall(L, (StkId)ud, LUA_MULTRET) == PCRLUA) | ||
596 | luaV_execute(L, L->ci - L->base_ci); | ||
597 | } | ||
598 | |||
599 | #ifndef COCO_MAIN_PARAM | ||
600 | #define COCO_MAIN_PARAM lua_State *L | ||
601 | #endif | ||
602 | |||
603 | #ifndef COCO_MAIN_DECL | ||
604 | #define COCO_MAIN_DECL | ||
605 | #endif | ||
606 | |||
607 | /* Toplevel function for the new coroutine stack. Never exits. */ | ||
608 | static void COCO_MAIN_DECL coco_main(COCO_MAIN_PARAM) | ||
609 | { | ||
610 | #ifdef COCO_MAIN_GETL | ||
611 | COCO_MAIN_GETL | ||
612 | #endif | ||
613 | coco_State *coco = L2COCO(L); | ||
614 | for (;;) { | ||
615 | L->status = luaD_rawrunprotected(L, coco_start, L->top - (coco->nargs+1)); | ||
616 | if (L->status != 0) luaD_seterrorobj(L, L->status, L->top); | ||
617 | COCO_JUMPOUT(coco) | ||
618 | } | ||
619 | } | ||
620 | |||
621 | /* Add a C stack to a coroutine. */ | ||
622 | lua_State *lua_newcthread(lua_State *OL, int cstacksize) | ||
623 | { | ||
624 | lua_State *NL = lua_newthread(OL); | ||
625 | |||
626 | if (cstacksize < 0) | ||
627 | return NL; | ||
628 | if (cstacksize == 0) | ||
629 | cstacksize = defaultcstacksize; | ||
630 | else if (cstacksize < COCO_MIN_CSTACKSIZE) | ||
631 | cstacksize = COCO_MIN_CSTACKSIZE; | ||
632 | cstacksize &= -16; | ||
633 | |||
634 | COCO_NEW(OL, NL, cstacksize, ((coco_MainFunc)(coco_main))) | ||
635 | |||
636 | return NL; | ||
637 | } | ||
638 | |||
639 | /* Free the C stack of a coroutine. Called from lstate.c. */ | ||
640 | void luaCOCO_free(lua_State *L) | ||
641 | { | ||
642 | COCO_FREE(L) | ||
643 | } | ||
644 | |||
645 | /* Resume a coroutine with a C stack. Called from ldo.c. */ | ||
646 | int luaCOCO_resume(lua_State *L, int nargs) | ||
647 | { | ||
648 | coco_State *coco = L2COCO(L); | ||
649 | coco->nargs = nargs; | ||
650 | COCO_JUMPIN(coco) | ||
651 | #ifndef COCO_DISABLE_EARLY_FREE | ||
652 | if (L->status != LUA_YIELD) { | ||
653 | COCO_FREE(L) | ||
654 | } | ||
655 | #endif | ||
656 | return L->status; | ||
657 | } | ||
658 | |||
659 | /* Yield from a coroutine with a C stack. Called from ldo.c. */ | ||
660 | int luaCOCO_yield(lua_State *L) | ||
661 | { | ||
662 | coco_State *coco = L2COCO(L); | ||
663 | L->status = LUA_YIELD; | ||
664 | COCO_JUMPOUT(coco) | ||
665 | L->status = 0; | ||
666 | { | ||
667 | StkId base = L->top - coco->nargs; | ||
668 | StkId rbase = L->base; | ||
669 | if (rbase < base) { /* Need to move args down? */ | ||
670 | while (base < L->top) | ||
671 | setobjs2s(L, rbase++, base++); | ||
672 | L->top = rbase; | ||
673 | } | ||
674 | } | ||
675 | L->base = L->ci->base; /* Restore invariant. */ | ||
676 | return coco->nargs; | ||
677 | } | ||
678 | |||
679 | /* Get/set the default C stack size. */ | ||
680 | int luaCOCO_cstacksize(int cstacksize) | ||
681 | { | ||
682 | int oldsz = defaultcstacksize; | ||
683 | if (cstacksize >= 0) { | ||
684 | if (cstacksize == 0) | ||
685 | cstacksize = COCO_DEFAULT_CSTACKSIZE; | ||
686 | else if (cstacksize < COCO_MIN_CSTACKSIZE) | ||
687 | cstacksize = COCO_MIN_CSTACKSIZE; | ||
688 | defaultcstacksize = cstacksize; | ||
689 | } | ||
690 | return oldsz; | ||
691 | } | ||
692 | |||
693 | #endif | ||