aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-04-25 14:52:29 +0200
committerMike Pall <mike>2010-04-25 14:52:29 +0200
commit87e4daf89c9f37e417993dedc9c5369da89ebca2 (patch)
treefd3a01473df776e90ba6be633209f0675d92e8b2 /src
parent2e24770ed3241342a6a5896e05629a382d35262b (diff)
downloadluajit-87e4daf89c9f37e417993dedc9c5369da89ebca2.tar.gz
luajit-87e4daf89c9f37e417993dedc9c5369da89ebca2.tar.bz2
luajit-87e4daf89c9f37e417993dedc9c5369da89ebca2.zip
Reorganize and fix placement of generated machine code on x64.
Diffstat (limited to 'src')
-rw-r--r--src/lj_mcode.c110
1 files changed, 57 insertions, 53 deletions
diff --git a/src/lj_mcode.c b/src/lj_mcode.c
index 75e0c696..9b1cae00 100644
--- a/src/lj_mcode.c
+++ b/src/lj_mcode.c
@@ -32,7 +32,7 @@ static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, DWORD prot)
32{ 32{
33 void *p = VirtualAlloc((void *)hint, sz, 33 void *p = VirtualAlloc((void *)hint, sz,
34 MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, prot); 34 MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, prot);
35 if (!p) 35 if (!p && !hint)
36 lj_trace_err(J, LJ_TRERR_MCODEAL); 36 lj_trace_err(J, LJ_TRERR_MCODEAL);
37 return p; 37 return p;
38} 38}
@@ -64,7 +64,7 @@ static void mcode_setprot(void *p, size_t sz, DWORD prot)
64static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot) 64static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot)
65{ 65{
66 void *p = mmap((void *)hint, sz, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 66 void *p = mmap((void *)hint, sz, prot, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
67 if (p == MAP_FAILED) 67 if (p == MAP_FAILED && !hint)
68 lj_trace_err(J, LJ_TRERR_MCODEAL); 68 lj_trace_err(J, LJ_TRERR_MCODEAL);
69 return p; 69 return p;
70} 70}
@@ -80,6 +80,10 @@ static void mcode_setprot(void *p, size_t sz, int prot)
80 mprotect(p, sz, prot); 80 mprotect(p, sz, prot);
81} 81}
82 82
83#elif LJ_64
84
85#error "Missing OS support for allocating executable memory"
86
83#else 87#else
84 88
85/* Fallback allocator. This will fail if memory is not executable by default. */ 89/* Fallback allocator. This will fail if memory is not executable by default. */
@@ -103,51 +107,7 @@ static void mcode_free(jit_State *J, void *p, size_t sz)
103 107
104#endif 108#endif
105 109
106/* -- MCode area allocation ----------------------------------------------- */ 110/* -- MCode area protection ----------------------------------------------- */
107
108#if LJ_64
109
110/* Get memory within relative jump distance of our code in 64 bit mode. */
111static void *mcode_alloc(jit_State *J, size_t sz, int prot)
112{
113 /* Target an address in the static assembler code (64K aligned).
114 ** Try addresses within a distance of target-1GB+1MB .. target+1GB-1MB.
115 */
116 uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff;
117 const uintptr_t range = (1u<<31) - (1u << 21);
118 int i;
119 /* First try a contiguous area below the last one. */
120 if (J->mcarea && (uintptr_t)J->mcarea - sz < (uintptr_t)1<<47) {
121 void *p = mcode_alloc_at(J, (uintptr_t)J->mcarea - sz, sz, prot);
122 if ((uintptr_t)p + sz - target < range || target - (uintptr_t)p < range)
123 return p;
124 mcode_free(J, p, sz); /* Free badly placed area. */
125 }
126 /* Next try probing with hinted addresses. */
127 for (i = 0; i < 32; i++) { /* 32 attempts ought to be enough ... */
128 uintptr_t hint;
129 void *p;
130 do {
131 hint = (0x78fb ^ LJ_PRNG_BITS(J, 15)) << 16; /* 64K aligned. */
132 } while (!(hint + sz < range &&
133 target + hint - (range>>1) < (uintptr_t)1<<47));
134 p = mcode_alloc_at(J, target + hint - (range>>1), sz, prot);
135 if ((uintptr_t)p + sz - target < range || target - (uintptr_t)p < range)
136 return p;
137 mcode_free(J, p, sz); /* Free badly placed area. */
138 }
139 lj_trace_err(J, LJ_TRERR_MCODEAL); /* Give up. OS probably ignores hints? */
140 return NULL;
141}
142
143#else
144
145/* All 32 bit memory addresses are reachable by relative jumps on x86. */
146#define mcode_alloc(J, sz, prot) mcode_alloc_at((J), 0, (sz), (prot))
147
148#endif
149
150/* -- MCode area management ----------------------------------------------- */
151 111
152/* Define this ONLY if the page protection twiddling becomes a bottleneck. */ 112/* Define this ONLY if the page protection twiddling becomes a bottleneck. */
153#ifdef LUAJIT_UNPROTECT_MCODE 113#ifdef LUAJIT_UNPROTECT_MCODE
@@ -165,6 +125,11 @@ static void *mcode_alloc(jit_State *J, size_t sz, int prot)
165#define MCPROT_GEN MCPROT_RWX 125#define MCPROT_GEN MCPROT_RWX
166#define MCPROT_RUN MCPROT_RWX 126#define MCPROT_RUN MCPROT_RWX
167 127
128static void mcode_protect(jit_State *J, int prot)
129{
130 UNUSED(J); UNUSED(prot);
131}
132
168#else 133#else
169 134
170/* This is the default behaviour and much safer: 135/* This is the default behaviour and much safer:
@@ -178,21 +143,60 @@ static void *mcode_alloc(jit_State *J, size_t sz, int prot)
178#define MCPROT_GEN MCPROT_RW 143#define MCPROT_GEN MCPROT_RW
179#define MCPROT_RUN MCPROT_RX 144#define MCPROT_RUN MCPROT_RX
180 145
181#endif
182
183/* Change protection of MCode area. */ 146/* Change protection of MCode area. */
184static void mcode_protect(jit_State *J, int prot) 147static void mcode_protect(jit_State *J, int prot)
185{ 148{
186#ifdef LUAJIT_UNPROTECT_MCODE
187 UNUSED(J); UNUSED(prot);
188#else
189 if (J->mcprot != prot) { 149 if (J->mcprot != prot) {
190 mcode_setprot(J->mcarea, J->szmcarea, prot); 150 mcode_setprot(J->mcarea, J->szmcarea, prot);
191 J->mcprot = prot; 151 J->mcprot = prot;
192 } 152 }
153}
154
193#endif 155#endif
156
157/* -- MCode area allocation ----------------------------------------------- */
158
159#if LJ_64
160
161/* Get memory within relative jump distance of our code in 64 bit mode. */
162static void *mcode_alloc(jit_State *J, size_t sz)
163{
164 /* Target an address in the static assembler code (64K aligned).
165 ** Try addresses within a distance of target-1GB+1MB .. target+1GB-1MB.
166 */
167 uintptr_t target = (uintptr_t)(void *)lj_vm_exit_handler & ~(uintptr_t)0xffff;
168 const uintptr_t range = (1u<<31) - (1u << 21);
169 /* First try a contiguous area below the last one. */
170 uintptr_t hint = (uintptr_t)J->mcarea - sz;
171 int i;
172 for (i = 0; i < 32; i++) { /* 32 attempts ought to be enough ... */
173 if (hint && hint < (uintptr_t)1<<47) {
174 void *p = mcode_alloc_at(J, hint, sz, MCPROT_GEN);
175 if (p && (uintptr_t)p < (uintptr_t)1<<47) {
176 if ((uintptr_t)p + sz - target < range || target - (uintptr_t)p < range)
177 return p;
178 mcode_free(J, p, sz); /* Free badly placed area. */
179 }
180 }
181 /* Next try probing pseudo-random addresses. */
182 do {
183 hint = (0x78fb ^ LJ_PRNG_BITS(J, 15)) << 16; /* 64K aligned. */
184 } while (!(hint + sz < range));
185 hint = target + hint - (range>>1);
186 }
187 lj_trace_err(J, LJ_TRERR_MCODEAL); /* Give up. OS probably ignores hints? */
188 return NULL;
194} 189}
195 190
191#else
192
193/* All 32 bit memory addresses are reachable by relative jumps on x86. */
194#define mcode_alloc(J, sz) mcode_alloc_at((J), 0, (sz), MCPROT_GEN)
195
196#endif
197
198/* -- MCode area management ----------------------------------------------- */
199
196/* Linked list of MCode areas. */ 200/* Linked list of MCode areas. */
197typedef struct MCLink { 201typedef struct MCLink {
198 MCode *next; /* Next area. */ 202 MCode *next; /* Next area. */
@@ -205,7 +209,7 @@ static void mcode_allocarea(jit_State *J)
205 MCode *oldarea = J->mcarea; 209 MCode *oldarea = J->mcarea;
206 size_t sz = (size_t)J->param[JIT_P_sizemcode] << 10; 210 size_t sz = (size_t)J->param[JIT_P_sizemcode] << 10;
207 sz = (sz + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1); 211 sz = (sz + LJ_PAGESIZE-1) & ~(size_t)(LJ_PAGESIZE - 1);
208 J->mcarea = (MCode *)mcode_alloc(J, sz, MCPROT_GEN); 212 J->mcarea = (MCode *)mcode_alloc(J, sz);
209 J->szmcarea = sz; 213 J->szmcarea = sz;
210 J->mcprot = MCPROT_GEN; 214 J->mcprot = MCPROT_GEN;
211 J->mctop = (MCode *)((char *)J->mcarea + J->szmcarea); 215 J->mctop = (MCode *)((char *)J->mcarea + J->szmcarea);