1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
31 $Id: patcher.c 8096 2007-06-17 13:45:58Z pm $
33 GENERATED PATCHER BRANCH AFTER PATCH
37 foo bras %r14, OFFSET foo
41 Short patcher call with nops:
44 nop bras %r14, OFFSET nop --+
45 nop ===> nop ===> nop |
50 PATCHER_LONGBRANCHES_NOPS_SKIP <-+
52 br exit: ild itmp3, disp(pv) br exit -+
53 nop aadd pv, itmp3 aadd pv, itmp3 |
54 nop ===> nop ===> nop |
56 nop basr itmp3, itmp3 basr itmp3, itmp3 -+
65 #include "vm/jit/s390/codegen.h"
66 #include "vm/jit/s390/md-abi.h"
68 #include "mm/memory.h"
69 #include "native/native.h"
70 #include "vm/builtin.h"
71 #include "vmcore/class.h"
72 #include "vm/exceptions.h"
73 #include "vmcore/field.h"
74 #include "vm/initialize.h"
75 #include "vmcore/options.h"
76 #include "vmcore/references.h"
77 #include "vm/resolve.h"
78 #include "vm/jit/patcher.h"
79 #include "vm/jit/stacktrace.h"
82 #define OOPS() assert(0);
85 /* A normal patcher branch done using BRAS */
86 #define PATCHER_IS_SHORTBRANCH(brcode) ((brcode & 0xFF0F0000) == 0xA7050000)
88 /* patcher_wrapper *************************************************************
90 Wrapper for all patchers. It also creates the stackframe info
93 If the return value of the patcher function is false, it gets the
94 exception object, clears the exception pointer and returns the
97 *******************************************************************************/
99 java_objectheader *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
103 java_objectheader *o;
106 java_objectheader *e;
108 /* define the patcher function */
110 bool (*patcher_function)(u1 *);
112 /* get stuff from the stack */
114 xpc = (u1 *) *((ptrint *) (sp + 5 * 4));
115 o = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
116 f = (functionptr) *((ptrint *) (sp + 0 * 4));
118 /* For a normal branch, the patch position is SZ_BRAS bytes before the RA.
119 * For long branches it is PATCHER_LONGBRANCHES_NOPS_SKIP before the RA.
122 if (PATCHER_IS_SHORTBRANCH(*(u4 *)(xpc - SZ_BRAS))) {
125 xpc = xpc - PATCHER_LONGBRANCHES_NOPS_SKIP;
128 *((ptrint *) (sp + 5 * 4)) = (ptrint) xpc;
130 /* store PV into the patcher function position */
132 *((ptrint *) (sp + 0 * 4)) = (ptrint) pv;
134 /* cast the passed function to a patcher function */
136 patcher_function = (bool (*)(u1 *)) (ptrint) f;
138 /* enter a monitor on the patching position */
140 PATCHER_MONITORENTER;
142 /* create the stackframeinfo */
144 /* RA is passed as NULL, but the XPC is correct and can be used in
145 stacktrace_create_extern_stackframeinfo for
146 md_codegen_get_pv_from_pc. */
148 stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + (6 * 4), ra, xpc);
150 /* call the proper patcher function */
152 result = (patcher_function)(sp);
154 /* remove the stackframeinfo */
156 stacktrace_remove_stackframeinfo(&sfi);
158 /* check for return value and exit accordingly */
160 if (result == false) {
161 e = exceptions_get_and_clear_exception();
168 PATCHER_MARK_PATCHED_MONITOREXIT;
174 /* patcher_get_putstatic *******************************************************
178 *******************************************************************************/
180 bool patcher_get_putstatic(u1 *sp)
184 unresolved_field *uf;
189 /* get stuff from the stack */
191 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
192 mcode = *((u4 *) (sp + 3 * 4));
193 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
194 disp = *((s4 *) (sp + 1 * 4));
195 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
197 /* get the fieldinfo */
199 if (!(fi = resolve_field_eager(uf)))
202 /* check if the field's class is initialized */
204 if (!(fi->class->state & CLASS_INITIALIZED))
205 if (!initialize_class(fi->class))
208 *((ptrint *) (pv + disp)) = (ptrint) &(fi->value);
210 /* patch back original code */
212 *((u4 *) ra) = mcode;
218 /* patcher_get_putfield ********************************************************
222 *******************************************************************************/
224 bool patcher_get_putfield(u1 *sp)
228 unresolved_field *uf;
233 /* get stuff from the stack */
235 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
236 mcode = *((u4 *) (sp + 3 * 4));
237 uf = (unresolved_field *) *((ptrint *) (sp + 2 * 4));
238 disp = *((s4 *) (sp + 1 * 4));
240 /* get the fieldinfo */
242 if (!(fi = resolve_field_eager(uf)))
245 /* patch back original code */
247 brcode = *((u4 *) ra);
248 *((u4 *) ra) = mcode;
250 /* If NOPs are generated, skip them */
252 if (! PATCHER_IS_SHORTBRANCH(brcode))
253 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
254 else if (opt_shownops)
255 ra += PATCHER_NOPS_SKIP;
257 /* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
261 /* patch correct offset */
263 if (fi->type == TYPE_LNG) {
264 assert(N_VALID_DISP(fi->offset + 4));
265 /* 2 RX operations, for 2 words; each already contains a 0 or 4 offset. */
266 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
268 *((u4 *) ra ) |= (fi->offset + (*((u4 *) ra) & 0xF));
270 assert(N_VALID_DISP(fi->offset));
272 *((u4 *) ra) |= fi->offset;
278 /* patcher_invokestatic_special ************************************************
282 *******************************************************************************/
284 __PORTED__ bool patcher_invokestatic_special(u1 *sp)
288 unresolved_method *um;
293 /* get stuff from the stack */
295 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
296 mcode = *((u4 *) (sp + 3 * 4));
297 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
298 disp = *((s4 *) (sp + 1 * 4));
299 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
301 /* get the fieldinfo */
303 if (!(m = resolve_method_eager(um)))
306 *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
308 /* patch back original code */
310 *((u4 *) ra) = mcode;
312 /* patch stubroutine */
318 /* patcher_invokevirtual *******************************************************
322 *******************************************************************************/
324 bool patcher_invokevirtual(u1 *sp)
328 unresolved_method *um;
332 /* get stuff from the stack */
334 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
335 mcode = *((u4 *) (sp + 3 * 4));
336 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
338 /* get the fieldinfo */
340 if (!(m = resolve_method_eager(um)))
343 /* patch back original code */
345 brcode = *((u4 *) ra);
346 *((u4 *) ra) = mcode;
348 /* If NOPs are generated, skip them */
350 if (! PATCHER_IS_SHORTBRANCH(brcode))
351 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
352 else if (opt_shownops)
353 ra += PATCHER_NOPS_SKIP;
355 /* patch vftbl index */
358 off = (s4) (OFFSET(vftbl_t, table[0]) +
359 sizeof(methodptr) * m->vftblindex);
361 assert(N_VALID_DISP(off));
363 *((s4 *)(ra + 4)) |= off;
369 /* patcher_invokeinterface *****************************************************
373 *******************************************************************************/
375 bool patcher_invokeinterface(u1 *sp)
379 unresolved_method *um;
383 /* get stuff from the stack */
385 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
386 mcode = *((u4 *) (sp + 3 * 4));
387 um = (unresolved_method *) *((ptrint *) (sp + 2 * 4));
389 /* get the fieldinfo */
391 if (!(m = resolve_method_eager(um)))
394 /* patch back original code */
396 brcode = *((u4 *) ra);
397 *((u4 *) ra) = mcode;
399 /* If NOPs are generated, skip them */
401 if (! PATCHER_IS_SHORTBRANCH(brcode))
402 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
403 else if (opt_shownops)
404 ra += PATCHER_NOPS_SKIP;
406 /* get interfacetable index */
408 idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
409 sizeof(methodptr) * m->class->index) +
412 ASSERT_VALID_DISP(idx);
414 /* get method offset */
417 (s4) (sizeof(methodptr) * (m - m->class->methods));
418 ASSERT_VALID_DISP(off);
422 *((s4 *)(ra + 4)) |= idx;
423 *((s4 *)(ra + 4 + 4)) |= off;
429 /* patcher_resolve_classref_to_flags *******************************************
431 CHECKCAST/INSTANCEOF:
433 <patched call position>
435 *******************************************************************************/
437 __PORTED__ bool patcher_resolve_classref_to_flags(u1 *sp)
439 constant_classref *cr;
446 /* get stuff from the stack */
448 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
449 mcode = *((u4 *) (sp + 3 * 4));
450 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
451 disp = *((s4 *) (sp + 1 * 4));
452 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
454 /* get the fieldinfo */
456 if (!(c = resolve_classref_eager(cr)))
459 /* patch class flags */
461 *((s4 *) (pv + disp)) = (s4) c->flags;
463 /* patch back original code */
465 *((u4 *) ra) = mcode;
470 /* patcher_resolve_classref_to_classinfo ***************************************
476 *******************************************************************************/
478 __PORTED__ bool patcher_resolve_classref_to_classinfo(u1 *sp)
480 constant_classref *cr;
487 /* get stuff from the stack */
489 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
490 mcode = *((u4 *) (sp + 3 * 4));
491 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
492 disp = *((s4 *) (sp + 1 * 4));
493 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
495 /* get the classinfo */
497 if (!(c = resolve_classref_eager(cr)))
500 /* patch the classinfo pointer */
502 *((ptrint *) (pv + disp)) = (ptrint) c;
504 /* patch back original code */
506 *((u4 *) ra) = mcode;
511 /* patcher_resolve_classref_to_vftbl *******************************************
516 *******************************************************************************/
518 bool patcher_resolve_classref_to_vftbl(u1 *sp)
520 constant_classref *cr;
527 /* get stuff from the stack */
529 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
530 mcode = *((u4 *) (sp + 3 * 4));
531 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
532 disp = *((s4 *) (sp + 1 * 4));
533 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
535 /* get the fieldinfo */
537 if (!(c = resolve_classref_eager(cr)))
540 /* patch super class' vftbl */
542 *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
544 /* patch back original code */
546 *((u4 *) ra) = mcode;
551 /* patcher_checkcast_instanceof_interface **************************************
555 *******************************************************************************/
557 bool patcher_checkcast_instanceof_interface(u1 *sp)
561 constant_classref *cr;
564 /* get stuff from the stack */
566 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
567 mcode = *((u4 *) (sp + 3 * 4));
568 cr = (constant_classref *) *((ptrint *) (sp + 2 * 4));
570 /* get the fieldinfo */
572 if (!(c = resolve_classref_eager(cr)))
575 /* patch back original code */
577 brcode = *((u4 *) ra);
578 *((u4 *) ra) = mcode;
580 /* If NOPs are generated, skip them */
582 if (! PATCHER_IS_SHORTBRANCH(brcode))
583 ra += PATCHER_LONGBRANCHES_NOPS_SKIP;
584 else if (opt_shownops)
585 ra += PATCHER_NOPS_SKIP;
587 /* patch super class index */
589 /* From here, split your editor and open codegen.c */
591 switch (*(ra + 1) >> 4) {
593 /* First M_ALD is into ITMP1 */
594 /* INSTANCEOF code */
596 *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
597 *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC) |=
598 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
599 c->index * sizeof(methodptr*));
604 /* First M_ALD is into ITMP2 */
607 *(u4 *)(ra + SZ_L + SZ_L) |= (u2)(s2)(- c->index);
608 *(u4 *)(ra + SZ_L + SZ_L + SZ_AHI + SZ_BRC + SZ_ILL) |=
609 (u2)(s2)(OFFSET(vftbl_t, interfacetable[0]) -
610 c->index * sizeof(methodptr*));
622 /* patcher_clinit **************************************************************
624 May be used for GET/PUTSTATIC and in native stub.
628 *******************************************************************************/
630 __PORTED__ bool patcher_clinit(u1 *sp)
636 /* get stuff from the stack */
638 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
639 mcode = *((u4 *) (sp + 3 * 4));
640 c = (classinfo *) *((ptrint *) (sp + 2 * 4));
642 /* check if the class is initialized */
644 if (!(c->state & CLASS_INITIALIZED))
645 if (!initialize_class(c))
648 /* patch back original code */
650 *((u4 *) ra) = mcode;
656 /* patcher_athrow_areturn ******************************************************
660 <patched call position>
662 *******************************************************************************/
664 #ifdef ENABLE_VERIFIER
665 __PORTED__ bool patcher_athrow_areturn(u1 *sp)
669 unresolved_class *uc;
671 /* get stuff from the stack */
673 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
674 mcode = *((u4 *) (sp + 3 * 4));
675 uc = (unresolved_class *) *((ptrint *) (sp + 2 * 4));
677 /* resolve the class and check subtype constraints */
679 if (!resolve_class_eager_no_access_check(uc))
682 /* patch back original code */
684 *((u4 *) ra) = mcode;
688 #endif /* ENABLE_VERIFIER */
691 /* patcher_resolve_native ******************************************************
693 *******************************************************************************/
695 #if !defined(WITH_STATIC_CLASSPATH)
696 __PORTED__ bool patcher_resolve_native(u1 *sp)
705 /* get stuff from the stack */
707 ra = (u1 *) *((ptrint *) (sp + 5 * 4));
708 mcode = *((u4 *) (sp + 3 * 4));
709 disp = *((s4 *) (sp + 1 * 4));
710 m = (methodinfo *) *((ptrint *) (sp + 2 * 4));
711 pv = (u1 *) *((ptrint *) (sp + 0 * 4));
713 /* resolve native function */
715 if (!(f = native_resolve_function(m)))
718 /* patch native function pointer */
720 *((ptrint *) (pv + disp)) = (ptrint) f;
722 /* patch back original code */
724 *((u4 *) ra) = mcode;
728 #endif /* !defined(WITH_STATIC_CLASSPATH) */
732 * These are local overrides for various environment variables in Emacs.
733 * Please do not remove this and leave it at the end of the file, where
734 * Emacs will automagically detect them.
735 * ---------------------------------------------------------------------
738 * indent-tabs-mode: t
742 * vim:noexpandtab:sw=4:ts=4: