1 /* src/vm/jit/i386/patcher.c - i386 code patching functions
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "vm/jit/i386/codegen.h"
33 #include "vm/jit/i386/md.h"
35 #include "mm/memory.hpp"
37 #include "native/native.hpp"
39 #include "vm/jit/builtin.hpp"
40 #include "vm/class.hpp"
41 #include "vm/field.hpp"
42 #include "vm/initialize.hpp"
43 #include "vm/options.h"
44 #include "vm/references.h"
45 #include "vm/resolve.hpp"
47 #include "vm/jit/patcher-common.hpp"
50 #define PATCH_BACK_ORIGINAL_MCODE \
52 *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode; \
53 md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE); \
57 /* patcher_patch_code **********************************************************
59 Just patches back the original machine code.
61 *******************************************************************************/
63 void patcher_patch_code(patchref_t *pr)
65 PATCH_BACK_ORIGINAL_MCODE;
69 /* patcher_get_putstatic *******************************************************
73 <patched call position>
74 b8 00 00 00 00 mov $0x00000000,%eax
76 *******************************************************************************/
78 bool patcher_get_putstatic(patchref_t *pr)
84 /* get stuff from the stack */
87 uf = (unresolved_field *) pr->ref;
89 /* get the fieldinfo */
91 if (!(fi = resolve_field_eager(uf)))
94 /* check if the field's class is initialized */
96 if (!(fi->clazz->state & CLASS_INITIALIZED))
97 if (!initialize_class(fi->clazz))
100 PATCH_BACK_ORIGINAL_MCODE;
102 /* patch the field value's address */
104 *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
110 /* patcher_getfield ************************************************************
114 <patched call position>
115 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
117 *******************************************************************************/
119 bool patcher_getfield(patchref_t *pr)
122 unresolved_field *uf;
125 /* get stuff from the stack */
128 uf = (unresolved_field *) pr->ref;
130 /* get the fieldinfo */
132 if (!(fi = resolve_field_eager(uf)))
135 PATCH_BACK_ORIGINAL_MCODE;
137 /* patch the field's offset */
139 *((u4 *) (ra + 2)) = (u4) (fi->offset);
141 /* if the field has type long, we need to patch the second move too */
143 if (fi->type == TYPE_LNG)
144 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
150 /* patcher_putfield ************************************************************
154 <patched call position>
155 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
157 *******************************************************************************/
159 bool patcher_putfield(patchref_t *pr)
162 unresolved_field *uf;
165 /* get stuff from the stack */
168 uf = (unresolved_field *) pr->ref;
170 /* get the fieldinfo */
172 if (!(fi = resolve_field_eager(uf)))
175 PATCH_BACK_ORIGINAL_MCODE;
177 /* patch the field's offset */
179 if (fi->type != TYPE_LNG) {
180 *((u4 *) (ra + 2)) = (u4) (fi->offset);
183 /* The long code is special:
185 * 89 8d 00 00 00 00 mov %ecx,0x00000000(%ebp)
186 * 89 95 00 00 00 00 mov %edx,0x00000000(%ebp)
189 *((u4 *) (ra + 2)) = (u4) (fi->offset);
190 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
197 /* patcher_putfieldconst *******************************************************
201 <patched call position>
202 c7 85 00 00 00 00 7b 00 00 00 movl $0x7b,0x0(%ebp)
204 *******************************************************************************/
206 bool patcher_putfieldconst(patchref_t *pr)
209 unresolved_field *uf;
212 /* get stuff from the stack */
215 uf = (unresolved_field *) pr->ref;
217 /* get the fieldinfo */
219 if (!(fi = resolve_field_eager(uf)))
222 PATCH_BACK_ORIGINAL_MCODE;
224 /* patch the field's offset */
226 if (!IS_2_WORD_TYPE(fi->type)) {
227 *((u4 *) (ra + 2)) = (u4) (fi->offset);
230 /* long/double code is different:
232 * c7 80 00 00 00 00 c8 01 00 00 movl $0x1c8,0x0(%eax)
233 * c7 80 04 00 00 00 00 00 00 00 movl $0x0,0x4(%eax)
236 *((u4 *) (ra + 2)) = (u4) (fi->offset);
237 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
244 /* patcher_aconst **************************************************************
248 <patched call postition>
249 c7 04 24 00 00 00 00 movl $0x0000000,(%esp)
250 b8 00 00 00 00 mov $0x0000000,%eax
252 *******************************************************************************/
254 bool patcher_aconst(patchref_t *pr)
257 constant_classref *cr;
260 /* get stuff from the stack */
263 cr = (constant_classref *) pr->ref;
265 /* get the classinfo */
267 if (!(c = resolve_classref_eager(cr)))
270 PATCH_BACK_ORIGINAL_MCODE;
272 /* patch the classinfo pointer */
274 *((ptrint *) (ra + 1)) = (ptrint) c;
280 /* patcher_builtin_multianewarray **********************************************
284 <patched call position>
285 c7 04 24 02 00 00 00 movl $0x2,(%esp)
286 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
288 83 c0 0c add $0xc,%eax
289 89 44 24 08 mov %eax,0x8(%esp)
290 b8 00 00 00 00 mov $0x00000000,%eax
293 *******************************************************************************/
295 bool patcher_builtin_multianewarray(patchref_t *pr)
298 constant_classref *cr;
301 /* get stuff from the stack */
304 cr = (constant_classref *) pr->ref;
306 /* get the classinfo */
308 if (!(c = resolve_classref_eager(cr)))
311 PATCH_BACK_ORIGINAL_MCODE;
313 /* patch the classinfo pointer */
315 *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
321 /* patcher_builtin_arraycheckcast **********************************************
325 <patched call position>
326 c7 44 24 04 00 00 00 00 movl $0x00000000,0x4(%esp)
327 ba 00 00 00 00 mov $0x00000000,%edx
330 *******************************************************************************/
332 bool patcher_builtin_arraycheckcast(patchref_t *pr)
335 constant_classref *cr;
338 /* get stuff from the stack */
341 cr = (constant_classref *) pr->ref;
343 /* get the classinfo */
345 if (!(c = resolve_classref_eager(cr)))
348 PATCH_BACK_ORIGINAL_MCODE;
350 /* patch the classinfo pointer */
352 *((ptrint *) (ra + 4)) = (ptrint) c;
354 /* patch new function address */
356 *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
362 /* patcher_invokestatic_special ************************************************
366 <patched call position>
367 b9 00 00 00 00 mov $0x00000000,%ecx
370 *******************************************************************************/
372 bool patcher_invokestatic_special(patchref_t *pr)
375 unresolved_method *um;
378 /* get stuff from the stack */
381 um = (unresolved_method *) pr->ref;
383 /* get the fieldinfo */
385 if (!(m = resolve_method_eager(um)))
388 PATCH_BACK_ORIGINAL_MCODE;
390 /* patch stubroutine */
392 *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
398 /* patcher_invokevirtual *******************************************************
402 <patched call position>
403 8b 08 mov (%eax),%ecx
404 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
407 *******************************************************************************/
409 bool patcher_invokevirtual(patchref_t *pr)
412 unresolved_method *um;
415 /* get stuff from the stack */
418 um = (unresolved_method *) pr->ref;
420 /* get the fieldinfo */
422 if (!(m = resolve_method_eager(um)))
425 PATCH_BACK_ORIGINAL_MCODE;
427 /* patch vftbl index */
429 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
430 sizeof(methodptr) * m->vftblindex);
436 /* patcher_invokeinterface *****************************************************
440 <patched call position>
441 8b 00 mov (%eax),%eax
442 8b 88 00 00 00 00 mov 0x00000000(%eax),%ecx
443 8b 81 00 00 00 00 mov 0x00000000(%ecx),%eax
446 *******************************************************************************/
448 bool patcher_invokeinterface(patchref_t *pr)
451 unresolved_method *um;
454 /* get stuff from the stack */
457 um = (unresolved_method *) pr->ref;
459 /* get the fieldinfo */
461 if (!(m = resolve_method_eager(um)))
464 PATCH_BACK_ORIGINAL_MCODE;
466 /* patch interfacetable index */
468 *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
469 sizeof(methodptr) * m->clazz->index);
471 /* patch method offset */
473 *((s4 *) (ra + 2 + 6 + 2)) =
474 (s4) (sizeof(methodptr) * (m - m->clazz->methods));
480 /* patcher_checkcast_instanceof_flags ******************************************
484 <patched call position>
485 b9 00 00 00 00 mov $0x00000000,%ecx
487 *******************************************************************************/
489 bool patcher_checkcast_instanceof_flags(patchref_t *pr)
492 constant_classref *cr;
495 /* get stuff from the stack */
498 cr = (constant_classref *) pr->ref;
500 /* get the fieldinfo */
502 if (!(c = resolve_classref_eager(cr)))
505 PATCH_BACK_ORIGINAL_MCODE;
507 /* patch class flags */
509 *((s4 *) (ra + 1)) = (s4) c->flags;
515 /* patcher_checkcast_interface *************************************************
519 <patched call position>
520 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
521 81 ea 00 00 00 00 sub $0x00000000,%edx
523 0f 8f 06 00 00 00 jg 0x00000000
524 8b 35 03 00 00 00 mov 0x3,%esi
525 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
527 *******************************************************************************/
529 bool patcher_checkcast_interface(patchref_t *pr)
532 constant_classref *cr;
535 /* get stuff from the stack */
538 cr = (constant_classref *) pr->ref;
540 /* get the fieldinfo */
542 if (!(c = resolve_classref_eager(cr)))
545 PATCH_BACK_ORIGINAL_MCODE;
547 /* patch super class index */
549 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
551 *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
552 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
553 c->index * sizeof(methodptr*));
559 /* patcher_instanceof_interface ************************************************
563 <patched call position>
564 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
565 81 ea 00 00 00 00 sub $0x00000000,%edx
567 0f 8e 13 00 00 00 jle 0x00000000
568 8b 91 00 00 00 00 mov 0x00000000(%ecx),%edx
570 *******************************************************************************/
572 bool patcher_instanceof_interface(patchref_t *pr)
575 constant_classref *cr;
578 /* get stuff from the stack */
581 cr = (constant_classref *) pr->ref;
583 /* get the fieldinfo */
585 if (!(c = resolve_classref_eager(cr)))
588 PATCH_BACK_ORIGINAL_MCODE;
590 /* patch super class index */
592 *((s4 *) (ra + 6 + 2)) = (s4) c->index;
594 *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
595 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
596 c->index * sizeof(methodptr*));
602 /* patcher_checkcast_class *****************************************************
606 <patched call position>
607 ba 00 00 00 00 mov $0x00000000,%edx
608 8b 89 00 00 00 00 mov 0x00000000(%ecx),%ecx
609 8b 92 00 00 00 00 mov 0x00000000(%edx),%edx
611 ba 00 00 00 00 mov $0x00000000,%edx
613 *******************************************************************************/
615 bool patcher_checkcast_class(patchref_t *pr)
618 constant_classref *cr;
621 /* get stuff from the stack */
624 cr = (constant_classref *) pr->ref;
626 /* get the fieldinfo */
628 if (!(c = resolve_classref_eager(cr)))
631 PATCH_BACK_ORIGINAL_MCODE;
633 /* patch super class' vftbl */
635 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
641 /* patcher_instanceof_class ****************************************************
645 <patched call position>
646 b9 00 00 00 00 mov $0x0,%ecx
647 8b 40 14 mov 0x14(%eax),%eax
648 8b 51 18 mov 0x18(%ecx),%edx
649 8b 49 14 mov 0x14(%ecx),%ecx
651 *******************************************************************************/
653 bool patcher_instanceof_class(patchref_t *pr)
656 constant_classref *cr;
659 /* get stuff from the stack */
662 cr = (constant_classref *) pr->ref;
664 /* get the fieldinfo */
666 if (!(c = resolve_classref_eager(cr)))
669 PATCH_BACK_ORIGINAL_MCODE;
671 /* patch super class' vftbl */
673 *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
680 * These are local overrides for various environment variables in Emacs.
681 * Please do not remove this and leave it at the end of the file, where
682 * Emacs will automagically detect them.
683 * ---------------------------------------------------------------------
686 * indent-tabs-mode: t
690 * vim:noexpandtab:sw=4:ts=4: