Line data Source code
1 : /* src/vm/jit/stubs.cpp - JIT stubs
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 : Copyright (C) 2008 Theobroma Systems Ltd.
6 :
7 : This file is part of CACAO.
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License as
11 : published by the Free Software Foundation; either version 2, or (at
12 : your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 : 02110-1301, USA.
23 :
24 : */
25 :
26 : #include "vm/jit/stubs.hpp"
27 : #include <stdint.h> // for uint8_t
28 : #include "arch.hpp" // for JIT_COMPILER_VIA_SIGNAL
29 : #include "config.h" // for ENABLE_JIT
30 : #include "md-stubs.hpp" // for CompilerStub::get_code_size
31 : #include "md.hpp" // for md_cacheflush
32 : #include "mm/codememory.hpp"
33 : #include "mm/dumpmemory.hpp" // for DumpMemory, DumpMemoryArea
34 : #include "vm/descriptor.hpp" // for methoddesc, typedesc, etc
35 : #include "vm/jit/abi.hpp" // for md_param_alloc_native
36 : #include "vm/jit/builtin.hpp" // for builtintable_entry
37 : #include "vm/jit/code.hpp" // for code_unflag_leafmethod, etc
38 : #include "vm/jit/codegen-common.hpp" // for codegen_emit_stub_native, etc
39 : #include "vm/jit/disass.hpp"
40 : #include "vm/jit/dseg.hpp"
41 : #include "vm/jit/emit-common.hpp" // for emit_trap_compiler
42 : #include "vm/jit/jit.hpp" // for jitdata, jit_jitdata_new
43 : #include "vm/jit/reg.hpp" // for reg_setup
44 : #include "vm/jit/show.hpp"
45 : #include "vm/jit/trap.hpp"
46 : #include "vm/method.hpp" // for methodinfo
47 : #include "vm/options.hpp" // for opt_verbosecall
48 : #include "vm/statistics.hpp" // for StatVar
49 : #include "vm/types.hpp" // for ptrint, u1
50 :
51 : STAT_DECLARE_VAR(int,count_cstub_len,0)
52 : STAT_DECLARE_VAR(int,size_stub_native,0)
53 :
54 : /**
55 : * Wrapper for codegen_emit_stub_compiler.
56 : *
57 : * @param m Method object.
58 : *
59 : * @return Pointer to the compiler stub code.
60 : */
61 422722 : void* CompilerStub::generate(methodinfo *m)
62 : {
63 : jitdata *jd;
64 : codegendata *cd;
65 : ptrint *d; /* pointer to data memory */
66 : u1 *c; /* pointer to code memory */
67 :
68 : // Create new dump memory area.
69 422722 : DumpMemoryArea dma;
70 :
71 : /* allocate required data structures */
72 :
73 422722 : jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
74 :
75 422722 : jd->m = m;
76 422722 : jd->cd = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
77 422722 : jd->flags = 0;
78 :
79 : /* get required compiler data */
80 :
81 422722 : cd = jd->cd;
82 :
83 : #if !defined(JIT_COMPILER_VIA_SIGNAL)
84 : /* allocate code memory */
85 :
86 : c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
87 :
88 : /* set pointers correctly */
89 :
90 : d = (ptrint *) c;
91 :
92 : cd->mcodebase = c;
93 :
94 : c = c + 3 * SIZEOF_VOID_P;
95 : cd->mcodeptr = c;
96 :
97 : /* NOTE: The codeinfo pointer is actually a pointer to the
98 : methodinfo (this fakes a codeinfo structure). */
99 :
100 : d[0] = (ptrint) asm_call_jit_compiler;
101 : d[1] = (ptrint) m;
102 : d[2] = (ptrint) &d[1]; /* fake code->m */
103 :
104 : /* call the emit function */
105 :
106 : codegen_emit_stub_compiler(jd);
107 :
108 : STATISTICS(count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size());
109 :
110 : /* flush caches */
111 :
112 : md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
113 : #else
114 : /* Allocate code memory. */
115 :
116 422722 : c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
117 :
118 : /* Set pointers correctly. */
119 :
120 422722 : d = (ptrint *) c;
121 :
122 422722 : cd->mcodebase = c;
123 :
124 422722 : c = c + 2 * SIZEOF_VOID_P;
125 422722 : cd->mcodeptr = c;
126 :
127 : /* NOTE: The codeinfo pointer is actually a pointer to the
128 : methodinfo (this fakes a codeinfo structure). */
129 :
130 422722 : d[0] = (ptrint) m;
131 422722 : d[1] = (ptrint) &d[0]; /* fake code->m */
132 :
133 : /* Emit the trap instruction. */
134 :
135 422722 : emit_trap_compiler(cd);
136 :
137 : STATISTICS(count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size());
138 :
139 : /* Flush caches. */
140 :
141 422722 : md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
142 : #endif
143 :
144 : /* return native stub code */
145 :
146 422722 : return c;
147 : }
148 :
149 :
150 : /**
151 : * Free a compiler stub from memory.
152 : *
153 : * @param
154 : */
155 0 : void CompilerStub::remove(void* stub)
156 : {
157 : // Pass size 1 to keep the intern function happy.
158 0 : CFREE(stub, 1);
159 0 : }
160 :
161 :
162 : /* codegen_disassemble_nativestub **********************************************
163 :
164 : Disassembles the generated builtin or native stub.
165 :
166 : *******************************************************************************/
167 :
168 : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
169 : static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
170 : {
171 : printf("Stub code: ");
172 : if (m->clazz != NULL)
173 : utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
174 : else
175 : printf("NULL");
176 : printf(".");
177 : utf_fprint_printable_ascii(stdout, m->name);
178 : utf_fprint_printable_ascii(stdout, m->descriptor);
179 : printf("\nLength: %d\n\n", (s4) (end - start));
180 :
181 : DISASSEMBLE(start, end);
182 : }
183 : #endif
184 :
185 :
186 : /**
187 : * Wrapper for codegen_emit_stub_native.
188 : *
189 : * @param m Method object.
190 : * @param bte Builtin function structure.
191 : */
192 2282 : void BuiltinStub::generate(methodinfo* m, builtintable_entry* bte)
193 : {
194 : jitdata *jd;
195 : codeinfo *code;
196 : int skipparams;
197 :
198 : // Create new dump memory area.
199 2282 : DumpMemoryArea dma;
200 :
201 : /* Create JIT data structure. */
202 :
203 2282 : jd = jit_jitdata_new(m);
204 :
205 : /* Get required compiler data. */
206 :
207 2282 : code = jd->code;
208 :
209 : /* Stubs are non-leaf methods. */
210 :
211 2282 : code_unflag_leafmethod(code);
212 :
213 : /* setup code generation stuff */
214 :
215 2282 : codegen_setup(jd);
216 :
217 : /* Set the number of native arguments we need to skip. */
218 :
219 2282 : skipparams = 0;
220 :
221 : /* generate the code */
222 :
223 : #if defined(ENABLE_JIT)
224 : # if defined(ENABLE_INTRP)
225 : if (!opt_intrp) {
226 : # endif
227 2282 : assert(bte->fp != NULL);
228 2282 : codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
229 : # if defined(ENABLE_INTRP)
230 : }
231 : # endif
232 : #endif
233 :
234 : /* reallocate the memory and finish the code generation */
235 :
236 2282 : codegen_finish(jd);
237 :
238 : /* set the stub entry point in the builtin table */
239 :
240 2282 : bte->stub = code->entrypoint;
241 :
242 2282 : STATISTICS(size_stub_native += code->mcodelength);
243 :
244 : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
245 : /* disassemble native stub */
246 :
247 : if (opt_DisassembleStubs) {
248 : codegen_disassemble_stub(m,
249 : (u1 *) (ptrint) code->entrypoint,
250 : (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
251 :
252 : /* show data segment */
253 :
254 : if (opt_showddatasegment)
255 : dseg_display(jd);
256 : }
257 : #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
258 2282 : }
259 :
260 : void *AbstractMethodErrorStub::stubcode;
261 :
262 163 : void AbstractMethodErrorStub::generate()
263 : {
264 163 : codegendata *cd = NEW(codegendata);
265 : // 16 bytes should be enough for all architectures
266 163 : cd->mcodebase = cd->mcodeptr = CNEW(u1, 16);
267 :
268 163 : emit_abstractmethoderror_trap(cd);
269 163 : md_cacheflush(cd->mcodebase, 16);
270 163 : stubcode = cd->mcodebase;
271 163 : }
272 :
273 :
274 : /**
275 : * Wrapper for codegen_emit_stub_native.
276 : *
277 : * @param m Method object of the native function.
278 : * @param f Native function pointer.
279 : *
280 : * @return The codeinfo representing the stub code.
281 : */
282 10775 : codeinfo* NativeStub::generate(methodinfo* m, functionptr f)
283 : {
284 : jitdata *jd;
285 : codeinfo *code;
286 : methoddesc *md;
287 : methoddesc *nmd;
288 : int skipparams;
289 :
290 : // Create new dump memory area.
291 10775 : DumpMemoryArea dma;
292 :
293 : /* Create JIT data structure. */
294 :
295 10775 : jd = jit_jitdata_new(m);
296 :
297 : /* Get required compiler data. */
298 :
299 10775 : code = jd->code;
300 :
301 : /* Stubs are non-leaf methods. */
302 :
303 10775 : code_unflag_leafmethod(code);
304 :
305 : /* set the flags for the current JIT run */
306 :
307 : #if defined(ENABLE_PROFILING)
308 : if (opt_prof)
309 : jd->flags |= JITDATA_FLAG_INSTRUMENT;
310 : #endif
311 :
312 10775 : if (opt_verbosecall)
313 0 : jd->flags |= JITDATA_FLAG_VERBOSECALL;
314 :
315 : /* setup code generation stuff */
316 :
317 : #if defined(ENABLE_JIT)
318 : # if defined(ENABLE_INTRP)
319 : if (!opt_intrp)
320 : # endif
321 10775 : reg_setup(jd);
322 : #endif
323 :
324 10775 : codegen_setup(jd);
325 :
326 : /* create new method descriptor with additional native parameters */
327 :
328 10775 : md = m->parseddesc;
329 :
330 : /* Set the number of native arguments we need to skip. */
331 :
332 10775 : if (m->flags & ACC_STATIC)
333 5157 : skipparams = 2;
334 : else
335 5618 : skipparams = 1;
336 :
337 : nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
338 : md->paramcount * sizeof(typedesc) +
339 10775 : skipparams * sizeof(typedesc));
340 :
341 10775 : nmd->paramcount = md->paramcount + skipparams;
342 :
343 10775 : nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
344 :
345 10775 : nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
346 :
347 10775 : if (m->flags & ACC_STATIC)
348 5157 : nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
349 :
350 : MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
351 10775 : md->paramcount);
352 :
353 : #if defined(ENABLE_JIT)
354 : # if defined(ENABLE_INTRP)
355 : if (!opt_intrp)
356 : # endif
357 : /* pre-allocate the arguments for the native ABI */
358 :
359 10775 : md_param_alloc_native(nmd);
360 : #endif
361 :
362 : /* generate the code */
363 :
364 : #if defined(ENABLE_JIT)
365 : # if defined(ENABLE_INTRP)
366 : if (opt_intrp)
367 : intrp_createnativestub(f, jd, nmd);
368 : else
369 : # endif
370 10775 : codegen_emit_stub_native(jd, nmd, f, skipparams);
371 : #else
372 : intrp_createnativestub(f, jd, nmd);
373 : #endif
374 :
375 : /* reallocate the memory and finish the code generation */
376 :
377 10775 : codegen_finish(jd);
378 :
379 : /* must be done after codegen_finish() */
380 : STATISTICS(size_stub_native += code->mcodelength);
381 :
382 : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
383 : /* disassemble native stub */
384 :
385 : if (opt_DisassembleStubs) {
386 : # if defined(ENABLE_DEBUG_FILTER)
387 : if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
388 : # endif
389 : {
390 : codegen_disassemble_stub(m,
391 : (u1 *) (ptrint) code->entrypoint,
392 : (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
393 :
394 : /* show data segment */
395 :
396 : if (opt_showddatasegment)
397 : dseg_display(jd);
398 : }
399 : }
400 : #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
401 :
402 : /* return native stub code */
403 :
404 10775 : return code;
405 : }
406 :
407 :
408 : /**
409 : * Free a native stub from memory.
410 : *
411 : * @param stub Pointer to stub memory.
412 : */
413 0 : void NativeStub::remove(void* stub)
414 : {
415 : // Pass size 1 to keep the intern function happy.
416 0 : CFREE(stub, 1);
417 0 : }
418 :
419 :
420 : /*
421 : * These are local overrides for various environment variables in Emacs.
422 : * Please do not remove this and leave it at the end of the file, where
423 : * Emacs will automagically detect them.
424 : * ---------------------------------------------------------------------
425 : * Local variables:
426 : * mode: c++
427 : * indent-tabs-mode: t
428 : * c-basic-offset: 4
429 : * tab-width: 4
430 : * End:
431 : * vim:noexpandtab:sw=4:ts=4:
432 : */
|