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/method.hpp" // for methodinfo
46 : #include "vm/options.hpp" // for opt_verbosecall
47 : #include "vm/statistics.hpp" // for StatVar
48 : #include "vm/types.hpp" // for ptrint, u1
49 :
50 : STAT_DECLARE_VAR(int,count_cstub_len,0)
51 : STAT_DECLARE_VAR(int,size_stub_native,0)
52 :
53 : /**
54 : * Wrapper for codegen_emit_stub_compiler.
55 : *
56 : * @param m Method object.
57 : *
58 : * @return Pointer to the compiler stub code.
59 : */
60 422722 : void* CompilerStub::generate(methodinfo *m)
61 : {
62 : jitdata *jd;
63 : codegendata *cd;
64 : ptrint *d; /* pointer to data memory */
65 : u1 *c; /* pointer to code memory */
66 :
67 : // Create new dump memory area.
68 422722 : DumpMemoryArea dma;
69 :
70 : /* allocate required data structures */
71 :
72 422722 : jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
73 :
74 422722 : jd->m = m;
75 422722 : jd->cd = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
76 422722 : jd->flags = 0;
77 :
78 : /* get required compiler data */
79 :
80 422722 : cd = jd->cd;
81 :
82 : #if !defined(JIT_COMPILER_VIA_SIGNAL)
83 : /* allocate code memory */
84 :
85 : c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
86 :
87 : /* set pointers correctly */
88 :
89 : d = (ptrint *) c;
90 :
91 : cd->mcodebase = c;
92 :
93 : c = c + 3 * SIZEOF_VOID_P;
94 : cd->mcodeptr = c;
95 :
96 : /* NOTE: The codeinfo pointer is actually a pointer to the
97 : methodinfo (this fakes a codeinfo structure). */
98 :
99 : d[0] = (ptrint) asm_call_jit_compiler;
100 : d[1] = (ptrint) m;
101 : d[2] = (ptrint) &d[1]; /* fake code->m */
102 :
103 : /* call the emit function */
104 :
105 : codegen_emit_stub_compiler(jd);
106 :
107 : STATISTICS(count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size());
108 :
109 : /* flush caches */
110 :
111 : md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
112 : #else
113 : /* Allocate code memory. */
114 :
115 422722 : c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
116 :
117 : /* Set pointers correctly. */
118 :
119 422722 : d = (ptrint *) c;
120 :
121 422722 : cd->mcodebase = c;
122 :
123 422722 : c = c + 2 * SIZEOF_VOID_P;
124 422722 : cd->mcodeptr = c;
125 :
126 : /* NOTE: The codeinfo pointer is actually a pointer to the
127 : methodinfo (this fakes a codeinfo structure). */
128 :
129 422722 : d[0] = (ptrint) m;
130 422722 : d[1] = (ptrint) &d[0]; /* fake code->m */
131 :
132 : /* Emit the trap instruction. */
133 :
134 422722 : emit_trap_compiler(cd);
135 :
136 : STATISTICS(count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size());
137 :
138 : /* Flush caches. */
139 :
140 422722 : md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
141 : #endif
142 :
143 : /* return native stub code */
144 :
145 422722 : return c;
146 : }
147 :
148 :
149 : /**
150 : * Free a compiler stub from memory.
151 : *
152 : * @param
153 : */
154 0 : void CompilerStub::remove(void* stub)
155 : {
156 : // Pass size 1 to keep the intern function happy.
157 0 : CFREE(stub, 1);
158 0 : }
159 :
160 :
161 : /* codegen_disassemble_nativestub **********************************************
162 :
163 : Disassembles the generated builtin or native stub.
164 :
165 : *******************************************************************************/
166 :
167 : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
168 : static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
169 : {
170 : printf("Stub code: ");
171 : if (m->clazz != NULL)
172 : utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
173 : else
174 : printf("NULL");
175 : printf(".");
176 : utf_fprint_printable_ascii(stdout, m->name);
177 : utf_fprint_printable_ascii(stdout, m->descriptor);
178 : printf("\nLength: %d\n\n", (s4) (end - start));
179 :
180 : DISASSEMBLE(start, end);
181 : }
182 : #endif
183 :
184 :
185 : /**
186 : * Wrapper for codegen_emit_stub_native.
187 : *
188 : * @param m Method object.
189 : * @param bte Builtin function structure.
190 : */
191 2282 : void BuiltinStub::generate(methodinfo* m, builtintable_entry* bte)
192 : {
193 : jitdata *jd;
194 : codeinfo *code;
195 : int skipparams;
196 :
197 : // Create new dump memory area.
198 2282 : DumpMemoryArea dma;
199 :
200 : /* Create JIT data structure. */
201 :
202 2282 : jd = jit_jitdata_new(m);
203 :
204 : /* Get required compiler data. */
205 :
206 2282 : code = jd->code;
207 :
208 : /* Stubs are non-leaf methods. */
209 :
210 2282 : code_unflag_leafmethod(code);
211 :
212 : /* setup code generation stuff */
213 :
214 2282 : codegen_setup(jd);
215 :
216 : /* Set the number of native arguments we need to skip. */
217 :
218 2282 : skipparams = 0;
219 :
220 : /* generate the code */
221 :
222 : #if defined(ENABLE_JIT)
223 : # if defined(ENABLE_INTRP)
224 : if (!opt_intrp) {
225 : # endif
226 2282 : assert(bte->fp != NULL);
227 2282 : codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
228 : # if defined(ENABLE_INTRP)
229 : }
230 : # endif
231 : #endif
232 :
233 : /* reallocate the memory and finish the code generation */
234 :
235 2282 : codegen_finish(jd);
236 :
237 : /* set the stub entry point in the builtin table */
238 :
239 2282 : bte->stub = code->entrypoint;
240 :
241 2282 : STATISTICS(size_stub_native += code->mcodelength);
242 :
243 : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
244 : /* disassemble native stub */
245 :
246 : if (opt_DisassembleStubs) {
247 : codegen_disassemble_stub(m,
248 : (u1 *) (ptrint) code->entrypoint,
249 : (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
250 :
251 : /* show data segment */
252 :
253 : if (opt_showddatasegment)
254 : dseg_display(jd);
255 : }
256 : #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
257 2282 : }
258 :
259 :
260 : /**
261 : * Wrapper for codegen_emit_stub_native.
262 : *
263 : * @param m Method object of the native function.
264 : * @param f Native function pointer.
265 : *
266 : * @return The codeinfo representing the stub code.
267 : */
268 10775 : codeinfo* NativeStub::generate(methodinfo* m, functionptr f)
269 : {
270 : jitdata *jd;
271 : codeinfo *code;
272 : methoddesc *md;
273 : methoddesc *nmd;
274 : int skipparams;
275 :
276 : // Create new dump memory area.
277 10775 : DumpMemoryArea dma;
278 :
279 : /* Create JIT data structure. */
280 :
281 10775 : jd = jit_jitdata_new(m);
282 :
283 : /* Get required compiler data. */
284 :
285 10775 : code = jd->code;
286 :
287 : /* Stubs are non-leaf methods. */
288 :
289 10775 : code_unflag_leafmethod(code);
290 :
291 : /* set the flags for the current JIT run */
292 :
293 : #if defined(ENABLE_PROFILING)
294 : if (opt_prof)
295 : jd->flags |= JITDATA_FLAG_INSTRUMENT;
296 : #endif
297 :
298 10775 : if (opt_verbosecall)
299 0 : jd->flags |= JITDATA_FLAG_VERBOSECALL;
300 :
301 : /* setup code generation stuff */
302 :
303 : #if defined(ENABLE_JIT)
304 : # if defined(ENABLE_INTRP)
305 : if (!opt_intrp)
306 : # endif
307 10775 : reg_setup(jd);
308 : #endif
309 :
310 10775 : codegen_setup(jd);
311 :
312 : /* create new method descriptor with additional native parameters */
313 :
314 10775 : md = m->parseddesc;
315 :
316 : /* Set the number of native arguments we need to skip. */
317 :
318 10775 : if (m->flags & ACC_STATIC)
319 5157 : skipparams = 2;
320 : else
321 5618 : skipparams = 1;
322 :
323 : nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
324 : md->paramcount * sizeof(typedesc) +
325 10775 : skipparams * sizeof(typedesc));
326 :
327 10775 : nmd->paramcount = md->paramcount + skipparams;
328 :
329 10775 : nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
330 :
331 10775 : nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
332 :
333 10775 : if (m->flags & ACC_STATIC)
334 5157 : nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
335 :
336 : MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
337 10775 : md->paramcount);
338 :
339 : #if defined(ENABLE_JIT)
340 : # if defined(ENABLE_INTRP)
341 : if (!opt_intrp)
342 : # endif
343 : /* pre-allocate the arguments for the native ABI */
344 :
345 10775 : md_param_alloc_native(nmd);
346 : #endif
347 :
348 : /* generate the code */
349 :
350 : #if defined(ENABLE_JIT)
351 : # if defined(ENABLE_INTRP)
352 : if (opt_intrp)
353 : intrp_createnativestub(f, jd, nmd);
354 : else
355 : # endif
356 10775 : codegen_emit_stub_native(jd, nmd, f, skipparams);
357 : #else
358 : intrp_createnativestub(f, jd, nmd);
359 : #endif
360 :
361 : /* reallocate the memory and finish the code generation */
362 :
363 10775 : codegen_finish(jd);
364 :
365 : /* must be done after codegen_finish() */
366 : STATISTICS(size_stub_native += code->mcodelength);
367 :
368 : #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
369 : /* disassemble native stub */
370 :
371 : if (opt_DisassembleStubs) {
372 : # if defined(ENABLE_DEBUG_FILTER)
373 : if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
374 : # endif
375 : {
376 : codegen_disassemble_stub(m,
377 : (u1 *) (ptrint) code->entrypoint,
378 : (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
379 :
380 : /* show data segment */
381 :
382 : if (opt_showddatasegment)
383 : dseg_display(jd);
384 : }
385 : }
386 : #endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
387 :
388 : /* return native stub code */
389 :
390 10775 : return code;
391 : }
392 :
393 :
394 : /**
395 : * Free a native stub from memory.
396 : *
397 : * @param stub Pointer to stub memory.
398 : */
399 0 : void NativeStub::remove(void* stub)
400 : {
401 : // Pass size 1 to keep the intern function happy.
402 0 : CFREE(stub, 1);
403 0 : }
404 :
405 :
406 : /*
407 : * These are local overrides for various environment variables in Emacs.
408 : * Please do not remove this and leave it at the end of the file, where
409 : * Emacs will automagically detect them.
410 : * ---------------------------------------------------------------------
411 : * Local variables:
412 : * mode: c++
413 : * indent-tabs-mode: t
414 : * c-basic-offset: 4
415 : * tab-width: 4
416 : * End:
417 : * vim:noexpandtab:sw=4:ts=4:
418 : */
|