1 /* src/vm/jit/jitcache.c - JIT caching stuff
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
27 #if defined(ENABLE_JITCACHE)
37 #include "toolbox/list.h"
38 #include "toolbox/logging.h"
40 #include "mm/memory.h"
41 #include "mm/codememory.h"
44 #include "vm/resolve.h"
45 #include "vm/builtin.h"
46 #include "vm/stringlocal.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/jit.h"
50 #include "vm/jit/code.h"
51 #include "vm/jit/patcher-common.h"
52 #include "vm/jit/codegen-common.h"
53 #include "vm/jit/linenumbertable.h"
54 #include "vm/jit/exceptiontable.h"
55 #include "vm/jit/methodtree.h"
57 #include "vmcore/references.h"
58 #include "vmcore/method.h"
59 #include "vmcore/system.h"
60 #include "vmcore/field.h"
61 #include "vmcore/utf8.h"
62 #include "vmcore/options.h"
64 #include "vm/jit/jitcache.h"
66 #include "threads/mutex.h"
68 /* TODO: Wrap this in vm/system.h" */
71 #define CACHEROOT "/tmp/cacao-jitcache/"
73 /* small grained helper functions */
74 char *get_dest_dir(methodinfo *);
75 char *get_dest_file(methodinfo *);
77 int mkdir_hier(char *, mode_t);
78 int open_to_read(char *);
79 int open_to_write(char *);
81 u1 *to_abs(u1 *, u1 *);
82 u1 *to_offset(u1 *, u1 *);
84 void store_utf(int, utf *);
85 void store_classinfo(int, classinfo *);
86 void store_builtin(int, builtintable_entry *);
87 void store_string(int, java_object_t *);
88 void store_methodinfo(int, methodinfo *);
89 void store_fieldinfo(int, fieldinfo *);
90 void store_cachedref(int, cachedref_t *);
92 void load_utf(utf **, int);
93 void load_classinfo(classinfo **, int, methodinfo *);
94 void load_builtin(builtintable_entry **, int);
95 void load_string(java_object_t **, int);
96 void load_methodinfo(methodinfo **, int, methodinfo *);
97 void load_fieldinfo(fieldinfo **, int, methodinfo *);
98 void load_cachedref(cachedref_t **, int, codeinfo *);
100 /* medium grained helper functions */
101 void load_from_file_patchers(codeinfo *, int);
102 void load_from_file_cachedrefs(codeinfo *, int);
103 void load_from_file_exceptiontable(codeinfo *, int);
104 void load_from_file_linenumbertable(codeinfo *, int);
106 void store_to_file_patchers(int, codeinfo *);
107 void store_to_file_cachedrefs(int, codeinfo *);
108 void store_to_file_linenumbertable(int, codeinfo *);
109 void store_to_file_exceptiontable(int, codeinfo *);
111 /* file handling functions */
112 void update_method_table(methodinfo *, int);
113 int seek_method_table(methodinfo *, int);
114 int get_cache_file_readable(methodinfo *);
115 int get_cache_file_writable(methodinfo *);
117 /* serializer forward declarations */
118 void s_dummy(int, patchref_t *, methodinfo *);
119 void s_unresolved_class(int, patchref_t *, methodinfo *);
120 void s_unresolved_field(int, patchref_t *, methodinfo *);
121 void s_unresolved_method(int, patchref_t *, methodinfo *);
122 void s_constant_classref(int, patchref_t *, methodinfo *);
123 void s_classinfo(int, patchref_t *, methodinfo *);
124 void s_methodinfo(int, patchref_t *, methodinfo *);
125 void s_fieldinfo(int, patchref_t *, methodinfo *);
126 void s_string(int, patchref_t *, methodinfo *);
128 /* deserializer forward declarations */
129 void d_dummy(patchref_t *, int, methodinfo *);
130 void d_unresolved_class(patchref_t *, int, methodinfo *);
131 void d_unresolved_field(patchref_t *, int, methodinfo *);
132 void d_unresolved_method(patchref_t *, int, methodinfo *);
133 void d_constant_classref(patchref_t *, int, methodinfo *);
134 void d_classinfo(patchref_t *, int, methodinfo *);
135 void d_methodinfo(patchref_t *, int, methodinfo *);
136 void d_fieldinfo(patchref_t *, int, methodinfo *);
137 void d_string(patchref_t *, int, methodinfo *);
139 /* The order of entries follows the order of
140 * declarations in patcher-common.h
143 static jitcache_patcher_function_list_t patcher_functions[] = {
144 { PATCHER_resolve_class, s_unresolved_class, d_unresolved_class },
145 { PATCHER_initialize_class, s_classinfo, d_classinfo },
146 { PATCHER_resolve_classref_to_classinfo, s_constant_classref, d_constant_classref },
147 { PATCHER_resolve_classref_to_vftbl, s_constant_classref, d_constant_classref },
148 { PATCHER_resolve_classref_to_index, s_constant_classref, d_constant_classref },
149 { PATCHER_resolve_classref_to_flags, s_constant_classref, d_constant_classref },
150 { PATCHER_resolve_native_function, s_methodinfo, d_methodinfo },
152 /* old patcher functions */
153 { PATCHER_get_putstatic, s_unresolved_field, d_unresolved_field },
155 #if defined(__I386__)
156 { PATCHER_getfield, s_unresolved_field, d_unresolved_field },
157 { PATCHER_putfield, s_unresolved_field, d_unresolved_field },
159 { PATCHER_get_putfield, s_unresolved_field, d_unresolved_field },
162 #if defined(__I386__) || defined(__X86_64__)
163 { PATCHER_putfieldconst, s_unresolved_field, d_unresolved_field }, /* 10 */
166 { PATCHER_invokestatic_special, s_unresolved_method, d_unresolved_method },
167 { PATCHER_invokevirtual, s_unresolved_method, d_unresolved_method },
168 { PATCHER_invokeinterface, s_unresolved_method, d_unresolved_method },
170 #if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
171 { PATCHER_checkcast_interface, s_constant_classref, d_constant_classref },
172 { PATCHER_instanceof_interface, s_constant_classref, d_constant_classref },
175 #if defined(__S390__)
176 { PATCHER_checkcast_instanceof_interface, s_dummy, d_dummy },
179 #if defined(__I386__)
180 { PATCHER_aconst, s_constant_classref, d_constant_classref }, /* 16 */
181 { PATCHER_builtin_multianewarray, s_constant_classref, d_constant_classref },
182 { PATCHER_builtin_arraycheckcast, s_constant_classref, d_constant_classref },
183 { PATCHER_checkcast_instanceof_flags, s_constant_classref, d_constant_classref },
184 { PATCHER_checkcast_class, s_constant_classref, d_constant_classref },
185 { PATCHER_instanceof_class, s_constant_classref, d_constant_classref },
188 { NULL, s_dummy, d_dummy }
191 #define JC_MRU_SIZE 100
192 static classinfo *jc_mru_list[JC_MRU_SIZE];
193 int mru_last_free = 0;
196 /* jitcache_mru_add ************************************************************
198 Adds a classinfo to the most recently used (MRU) list. The MRU uses a simple
199 strategy: it will store entries until it is full, further candidates replace
202 *******************************************************************************/
204 void jitcache_mru_add(classinfo *c, int fd)
207 assert(!c->cache_file_fd);
209 c->cache_file_fd = fd;
211 if (mru_last_free < JC_MRU_SIZE) {
212 jc_mru_list[mru_last_free] = c;
221 mru_start = JC_MRU_SIZE - 1;
223 old_c = jc_mru_list[mru_start];
226 assert (old_c->cache_file_fd);
227 system_close(old_c->cache_file_fd);
228 old_c->cache_file_fd = 0;
230 jc_mru_list[mru_start] = c;
235 void jitcache_mru_remove(classinfo *c)
239 for (i = 0; i < JC_MRU_SIZE; i++)
240 if (jc_mru_list[i] == c) {
241 jc_mru_list[j] = NULL;
243 for (j = i; i < mru_last_free - 1; j++)
244 jc_mru_list[j] = jc_mru_list[j+1];
252 /* jitcache_list_create ********************************************************
254 Creates an empty cached reference list for the given codeinfo.
256 *******************************************************************************/
258 void jitcache_list_create(codeinfo *code)
260 code->cachedrefs = list_create(OFFSET(cachedref_t, linkage));
264 /* jitcache_list_reset **********************************************************
266 Resets the cached reference list inside a codeinfo.
268 *******************************************************************************/
270 void jitcache_list_reset(codeinfo *code)
274 /* free all elements of the list */
276 while((pr = list_first(code->cachedrefs)) != NULL) {
277 list_remove(code->cachedrefs, pr);
279 FREE(pr, cachedref_t);
281 #if defined(ENABLE_STATISTICS)
283 size_cachedref -= sizeof(cachedref_t);
289 /* jitcache_list_free ***********************************************************
291 Frees the cached reference list and all its entries for the given codeinfo.
293 *******************************************************************************/
295 void jitcache_list_free(codeinfo *code)
297 /* free all elements of the list */
299 jitcache_list_reset(code);
301 /* free the list itself */
303 FREE(code->cachedrefs, list_t);
307 /* jitcache_list_find ***********************************************************
309 Find an entry inside the cached reference list for the given codeinfo
310 by specifying the displacement in the code/data segment.
312 NOTE: Caller should hold the patcher list lock or maintain
313 exclusive access otherwise.
315 *******************************************************************************/
317 static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
321 /* walk through all cached references for the given codeinfo */
323 cr = list_first(code->cachedrefs);
326 if (cr->disp == disp)
329 cr = list_next(code->cachedrefs, cr);
336 /* jitcache_new_cachedref ******************************************************
338 Creates and initializes a new cachedref
340 *******************************************************************************/
342 cachedref_t *jitcache_new_cached_ref(cachedreftype type, s4 md_patch, voidptr ref, s4 disp)
346 /* allocate cachedref on heap (at least freed together with codeinfo) */
348 cr = NEW(cachedref_t);
350 #if defined(ENABLE_STATISTICS)
352 size_cachedref += sizeof(cachedref_t);
355 /* set reference information */
358 cr->md_patch= md_patch;
364 /* jitcache_add_cachedref_jd ***************************************************
366 Creates a new cached ref appends it to the list in the codeinfo structure
367 *or* attaches it to the *last* patchref_t if it overlaps with the address
368 of the cached reference.
370 *******************************************************************************/
372 void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t *cachedref)
374 cachedref_t *list_cr;
376 list_cr = (cachedref_t *) list_first(code->cachedrefs);
380 if (list_cr->disp == cachedref->disp)
382 assert(list_cr->type == cachedref->type);
383 assert(list_cr->ref == cachedref->ref);
385 /* Cachedref for already existing object found. No need to store
391 list_cr = list_next(code->cachedrefs, list_cr);
394 list_add_first(code->cachedrefs, cachedref);
397 /* jitcache_add_cachedref_jd ***************************************************
399 Creates a new cached ref appends it to the list in the codeinfo structure
400 *or* attaches it to the *last* patchref_t if it overlaps with the address
401 of the cached reference.
403 *******************************************************************************/
405 void jitcache_add_cached_ref_jd(jitdata *jd, cachedreftype type, voidptr ref)
407 jitcache_add_cached_ref_md_jd(jd, type, 0, ref);
411 /* jitcache_add_cachedref_md_jd ************************************************
413 Creates a new cached ref appends it to the list in the codeinfo structure
414 *or* attaches it to the *last* patchref_t if it overlaps with the address
415 of the cached reference.
417 *******************************************************************************/
419 void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, voidptr ref)
421 patchref_t *patchref;
424 cachedref_t *cachedref;
426 if (type >= CRT_OBJECT_HEADER && !ref)
431 disp = (s4) (cd->mcodeptr - cd->mcodebase) - SIZEOF_VOID_P;
432 cachedref = jitcache_new_cached_ref(type, md_patch, ref, disp);
434 patchref = (patchref_t *) list_first(jd->code->patchers);
437 && (patchref->mpc) <= disp
438 && (patchref->mpc + sizeof(patchref->mcode)) >= disp)
440 /* patchers and cachedref overlap: cached ref must
441 * be handled after the patcher.
444 if (opt_DebugJitCache)
446 log_message_method("cached ref overlaps with patchref: ", jd->m);
449 /* There can be only one cached ref per patcher currently.
450 * If the need arises to handle more cached refs a list can
453 assert(!patchref->attached_ref);
455 patchref->attached_ref = cachedref;
458 jitcache_add_cached_ref_intern(jd->code, cachedref);
462 /* jitcache_add_cachedref ******************************************************
464 Creates a new cached references and appends it to the list.
466 *******************************************************************************/
468 void jitcache_add_cached_ref(codeinfo *code, cachedreftype type, voidptr ref, s4 disp)
472 /* allocate cachedref on heap (at least freed together with codeinfo) */
473 cr = jitcache_new_cached_ref(type, 0, ref,disp);
475 jitcache_add_cached_ref_intern(code, cr);
480 /* jitcache_handle_cached_ref **************************************************
482 Creates a new cached references and appends it to the list.
484 *******************************************************************************/
486 void jitcache_handle_cached_ref(cachedref_t *cr, codeinfo *code)
490 location = (u1 **) (code->entrypoint + cr->disp);
492 /* Write the restored reference into the code. */
494 patch_md(cr->md_patch, (ptrint) location, cr->ref);
498 md_cacheflush(location, SIZEOF_VOID_P);
500 FREE(cr, cachedref_t);
506 bool filter(utf *classname)
508 static bool printed = false;
511 int max_index = 30000;
512 const char *classes[] = {
517 "java/lang/ThreadGroup",
520 "java/util/Vector$1",
521 "java/util/AbstractList",
522 "java/util/AbstractCollection",
525 "java/lang/ClassLoader",
526 "java/lang/VMClassLoader",
529 "java/util/AbstractSet",
530 "gnu/classpath/SystemProperties",
531 "java/util/Properties",
532 "java/util/Hashtable",
533 "java/util/Dictionary",
534 "java/util/Hashtable$HashEntry",
535 "java/util/AbstractMap$SimpleEntry",
536 "java/lang/StringBuilder",
537 "java/lang/AbstractStringBuffer",
538 "java/util/Collections$SynchronizedSet",
539 "java/util/Collections$SynchronizedCollection",
540 "java/util/Hashtable$3",
541 "java/util/Hashtable$EntryIterator",
542 "java/util/Collections$SynchronizedIterator",
544 "java/util/Collections",
545 "java/util/Collections$EmptySet",
546 "java/util/Collections$EmptyList",
547 "java/util/Collections$EmptyMap",
548 "java/util/Collections$ReverseComparator",
549 "java/util/Collections$UnmodifiableMap",
551 "java/util/StringTokenizer",
552 "java/util/ArrayList",
555 "java/lang/VMSystem",
556 "java/io/FileDescriptor",
557 "gnu/java/io/FileChannelImpl",
559 "gnu/classpath/VMStackWalker",
560 "gnu/java/io/VMChannel",
561 "gnu/java/io/VMChannel$State",
562 "gnu/java/io/VMChannel$Kind",
563 "java/nio/channels/FileChannelImpl",
564 "java/nio/channels/spi/AbstractInterruptibleChannel",
566 "java/io/FileInputStream",
567 "java/io/InputStream",
568 "java/io/BufferedInputStream",
569 "java/io/FilterInputStream",
570 "java/io/PrintStream",
571 "java/io/OutputStream",
572 "java/io/BufferedOutputStream",
573 "java/io/FilterOutputStream",
577 "gnu/java/lang/CharData",
578 "java/lang/Character",
580 "java/security/VMAccessController",
581 "java/lang/ThreadLocal",
582 "java/security/CodeSource",
584 "java/security/PermissionCollection",
586 "java/security/ProtectionDomain",
587 "java/security/AccessControlContext",
588 "gnu/java/util/WeakIdentityHashMap",
589 "gnu/java/util/WeakIdentityHashMap$WeakEntrySet",
590 "java/lang/ref/ReferenceQueue",
591 "java/util/LinkedList",
592 "java/util/AbstractSequentialList",
593 "gnu/java/util/WeakIdentityHashMap$WeakBucket$WeakEntry",
594 "java/util/LinkedList$Entry",
596 "java/lang/reflect/VMConstructor",
597 "java/lang/reflect/Constructor",
598 "java/lang/reflect/Modifier",
599 "gnu/java/net/protocol/file/Handler",
600 "java/net/URLStreamHandler",
601 "java/util/ArrayList",
602 "java/security/SecureClassLoader",
603 "java/lang/Exception",
604 "java/lang/Throwable",
605 "java/lang/VMThrowable",
606 "gnu/java/net/loader/FileURLLoader",
607 "gnu/java/net/loader/URLLoader",
608 "java/security/Policy",
609 "gnu/java/security/provider/DefaultPolicy",
610 "gnu/java/net/loader/Resource",
611 "gnu/java/net/loader/FileResource",
612 "java/io/FileInputStream",
613 "gnu/java/nio/FileChannelImpl",
614 "java/nio/ByteBuffer",
616 "java/nio/ByteOrder",
617 "java/security/Permissions$PermissionsHash",
618 "java/nio/charset/Charset",
619 "gnu/java/nio/charset/Provider",
620 "gnu/java/nio/charset/Provider$1",
621 "gnu/java/nio/charset/US_ASCII",
622 "java/util/Collections$UnmodifiableSet/",
623 "java/util/Collections$UnmodifiableCollection",
624 "java/util/Collections$UnmodifiableIterator",
625 "gnu/java/nio/charset/ISO_8859_1",
626 "gnu/java/nio/charset/UTF_8",
627 "gnu/java/nio/charset/UTF_16BE",
628 "gnu/java/nio/charset/UTF_16LE",
629 "gnu/java/nio/charset/UTF_16",
630 "gnu/java/nio/charset/UnicodeLittle",
631 "gnu/java/nio/charset/Windows1250",
632 "gnu/java/nio/charset/Windows1250",
633 "gnu/java/nio/charset/ByteCharset",
634 "gnu/java/nio/charset/Windows1251",
635 "gnu/java/nio/charset/Windows1252",
636 "gnu/java/nio/charset/Windows1253",
637 "gnu/java/nio/charset/Windows1254",
638 "gnu/java/nio/charset/Windows1257",
639 "gnu/java/nio/charset/ISO_8859_2",
640 "gnu/java/nio/charset/ISO_8859_4",
641 "gnu/java/nio/charset/ISO_8859_5",
642 "gnu/java/nio/charset/ISO_8859_7",
643 "gnu/java/nio/charset/ISO_8859_9",
644 "gnu/java/nio/charset/ISO_8859_13",
645 "gnu/java/nio/charset/ISO_8859_15",
646 "gnu/java/nio/charset/KOI_8",
647 "gnu/java/nio/charset/ISO_8859_1$Encoder",
648 "java/nio/charset/CharsetEncoder",
649 "gnu/java/nio/charset/ByteEncodeLoopHelper",
650 "java/nio/charset/CodingErrorAction",
651 "java/nio/CharBuffer",
652 "java/nio/CharBufferImpl",
653 "gnu/java/nio/charset/ByteEncodeLoopHelper",
654 "java/nio/charset/CoderResult",
655 "java/nio/charset/CoderResult$1",
656 "java/nio/charset/CoderResult$2",
657 "java/nio/charset/CoderResult$Cache",
659 "gnu/java/awt/peer/gtk/GtkToolkit",
660 "gnu/java/awt/peer/gtk/GtkGenericPeer",
661 "java/util/WeakHashMap",
662 "java/util/WeakHashMap$1",
663 "java/util/WeakHashMap$WeakEntrySet",
664 "gnu/java/awt/peer/gtk/GtkWindowPeer",
665 "gnu/java/awt/peer/gtk/GtkCheckboxPeer",
666 "gnu/java/awt/peer/gtk/GtkFileDialogPeer",
667 "gnu/java/awt/peer/gtk/GtkMainThread",
668 "java/security/AccessController",
669 "java/security/Permission",
670 "java/lang/ClassLoader$StaticData",
671 "java/lang/VMString",
672 "gnu/java/lang/CPStringBuilder",
673 "gnu/java/lang/VMCPStringBuilder",
674 "java/io/FileOutputStream",
675 "gnu/java/nio/VMChannel",
676 "gnu/java/nio/VMChannel$State",
677 "gnu/java/nio/VMChannel$Kind",
678 "java/nio/channels/FileChannel",
679 "gnu/classpath/VMSystemProperties",
680 "java/lang/StringBuffer",
681 "java/lang/VMRuntime",
682 "java/lang/VMObject",
683 "java/lang/VMThread",
685 "java/lang/InheritableThreadLocal",
686 "java/lang/ClassNotFoundException",
687 "java/net/URLClassLoader",
688 "java/lang/ClassLoader$1",
689 "java/nio/ByteBufferImpl",
690 "java/io/FilePermission",
691 "gnu/java/nio/charset/ISO_8859_1$Encoder$1",
692 "java/nio/charset/spi/CharsetProvider",
693 "gnu/java/net/loader/URLStreamHandlerCache",
694 "java/util/HashMap$HashIterator",
695 "java/util/HashMap$HashEntry",
696 "java/util/AbstractMap",
697 "java/util/AbstractMap$1",
698 "java/lang/RuntimeException",
699 "java/util/Collections$UnmodifiableSet",
700 "java/lang/ref/Reference",
701 "java/lang/ref/WeakReference",
702 "gnu/java/util/WeakIdentityHashMap$WeakBucket",
703 "gnu/java/util/WeakIdentityHashMap$WeakEntrySet$1",
704 "java/lang/String$CaseInsensitiveComparator",
705 "java/lang/Throwable$StaticData",
706 "java/lang/StackTraceElement",
709 "java/lang/VMDouble",
713 "java/security/Permissions", /* 200 */
714 "java/security/AllPermission",
715 "java/security/AllPermission$AllPermissionCollection",
716 "java/util/AbstractMap$1$1", /* 203 */
721 if (getenv("FILTER_VERBOSE") && !printed)
726 log_println("[%d] - %s", i, classes[i]);
733 buf = getenv("INDEX");
735 sscanf(buf, "%d", &max_index);
738 while (classes[i] && i <= max_index)
741 if (!strcmp(classes[i], classname->text))
747 if ((buf = getenv("FILTER_VERBOSE")))
749 log_println("filtered: %s", classname->text);
761 * Causes filter_match() on which one can set a breakpoint in the debugger
762 * in the following conditions:
764 * If the environment variable NO_FILTER is set, then filter_match() is not
765 * called at all. This disables filter capabilities.
767 * If environment variable TEST_CLASS is set and the method belong to this
768 * class and there is no variable TEST_METHOD then filter_match() is called.
770 * If TEST_CLASS and TEST_METHOD match the methodinfo and TEST_DESCRIPTOR is
773 * If TEST_CLASS, TEST_METHOD and TEST_DESCRIPTOR match the methodinfo's values.
775 void filter_single(methodinfo *m)
779 buf = getenv("NO_FILTER");
783 buf = getenv("TEST_CLASS");
784 if (!buf || strcmp(m->clazz->name->text, buf))
787 buf = getenv("TEST_METHOD");
793 else if (strcmp(m->name->text, buf))
796 buf = getenv("TEST_DESCRIPTOR");
802 else if (strcmp(m->descriptor->text, buf))
808 mutex_t jitcache_lock;
810 /* jitcache_store **************************************************************
812 Saves the generated machine code to disk.
814 *******************************************************************************/
815 void jitcache_store (methodinfo *m)
817 static int init_lock = true;
823 mutex_init(&jitcache_lock);
830 if (!filter(m->clazz->name))
834 /* Never try to store native method stubs because those include a reference
835 * a dynamically resolved function.
837 * TODO: Handle those, too.
839 if (m->flags & ACC_NATIVE)
842 fd = get_cache_file_writable(m);
845 if (opt_DebugJitCache)
846 log_message_method("[jitcache] store: got no file descriptor for ", m);
851 /* Write (and some read) file operations beyond this point.
852 * Acquire lock first because another thread may try to load a different
853 * method from this class.
855 /* mutex_lock(&m->clazz->cache_file_lock);*/
856 mutex_lock(&jitcache_lock);
858 if (opt_DebugJitCache)
859 log_message_method("[jitcache] store: ", m);
861 update_method_table(m, fd);
863 /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
865 system_write(fd, (const void *) &m->code->flags, sizeof(m->code->flags));
867 system_write(fd, (const void *) &m->code->optlevel, sizeof(m->code->optlevel));
868 system_write(fd, (const void *) &m->code->basicblockcount, sizeof(m->code->basicblockcount));
870 system_write(fd, (const void *) &m->code->synchronizedoffset, sizeof(m->code->synchronizedoffset));
872 system_write(fd, (const void *) &m->code->stackframesize, sizeof(m->code->stackframesize));
874 temp = to_offset(m->code->mcode, m->code->entrypoint);
875 system_write(fd, (const void *) &temp, sizeof(temp));
877 system_write(fd, (const void *) &m->code->mcodelength, sizeof(m->code->mcodelength));
879 system_write(fd, (const void *) m->code->mcode, m->code->mcodelength);
881 store_to_file_exceptiontable(fd, m->code);
883 store_to_file_linenumbertable(fd, m->code);
885 store_to_file_patchers(fd, m->code);
887 store_to_file_cachedrefs(fd, m->code);
889 /* mutex_unlock(&m->clazz->cache_file_lock);*/
890 mutex_unlock(&jitcache_lock);
894 /* jitcache_load ***************************************************************
896 Try to load previously generated machine code from disk.
898 Returns non-zero if successfull.
900 *******************************************************************************/
902 u1 jitcache_load (methodinfo *m)
909 if (!filter(m->clazz->name))
913 /* Never try to store native method stubs because those include a reference
914 * a dynamically resolved function.
916 if (m->flags & ACC_NATIVE)
919 fd = get_cache_file_readable(m);
922 if (opt_DebugJitCache)
923 log_message_method("[jitcache] load: got no file descriptor for ", m);
928 if(!seek_method_table(m, fd))
935 if (opt_DebugJitCache)
936 log_message_method("[jitcache] load: ", m);
938 code = code_codeinfo_new(m);
941 /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
943 system_read(fd, (void *) &code->flags, sizeof(code->flags));
945 system_read(fd, (void *) &code->optlevel, sizeof(code->optlevel));
946 system_read(fd, (void *) &code->basicblockcount, sizeof(code->basicblockcount));
948 system_read(fd, (void *) &code->synchronizedoffset, sizeof(code->synchronizedoffset));
950 system_read(fd, (void *) &code->stackframesize, sizeof(code->stackframesize));
952 system_read(fd, (void *) &code->entrypoint, sizeof(code->entrypoint));
954 system_read(fd, (void *) &code->mcodelength, sizeof(code->mcodelength));
956 code->mcode = CNEW(u1, code->mcodelength);
957 system_read(fd, (void *) code->mcode, code->mcodelength);
958 code->entrypoint = to_abs(code->mcode, code->entrypoint);
960 load_from_file_exceptiontable(code, fd);
962 load_from_file_linenumbertable(code, fd);
964 load_from_file_patchers(code, fd);
966 load_from_file_cachedrefs(code, fd);
970 endpc = (u1 *) ((ptrint) code->mcode) + code->mcodelength;
972 /* Insert method into methodtree to find the entrypoint. */
974 methodtree_insert(code->entrypoint, endpc);
976 /* flush the instruction and data caches */
978 md_cacheflush(code->mcode, code->mcodelength);
980 if (opt_DebugJitCache)
982 log_println("[jitcache] load - registered method: %x -> %x", code->entrypoint, endpc);
992 for (i = 0; i < mru_last_free; i++)
994 system_close(jc_mru_list[i]->cache_file_fd);
995 jc_mru_list[i]->cache_file_fd = 0;
1001 /* Closes all open file descriptors. */
1004 void jitcache_freeclass(classinfo *c)
1006 if (c->cache_file_fd)
1007 jitcache_mru_remove(c);
1010 /* Helper functions */
1011 void update_method_table(methodinfo *m, int fd)
1013 int state = 0, i, temp, offset = 0;
1015 system_lseek(fd, 0, SEEK_SET);
1017 system_read(fd, (void *) &state, sizeof(state));
1019 /* table does not exist yet and needs to be created first */
1022 system_lseek(fd, 0, SEEK_SET);
1024 system_write(fd, &state, sizeof(state));
1027 for (i = 0; i < m->clazz->methodscount; i++)
1028 system_write(fd, &temp, sizeof(temp));
1031 /* get last offset in file */
1032 offset = system_lseek(fd, 0, SEEK_END);
1034 /* find out the index in the methods array */
1036 for (i = 0; i < m->clazz->methodscount; i++)
1037 if (&m->clazz->methods[i] == m)
1044 /* seek to the method's entry in the table */
1045 system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
1047 /* enter the location */
1048 system_write(fd, &offset, sizeof(offset));
1050 system_lseek(fd, offset, SEEK_SET);
1053 int seek_method_table(methodinfo *m, int fd)
1055 int state = 0, i, temp, offset;
1057 system_lseek(fd, 0, SEEK_SET);
1059 system_read(fd, (void *) &state, sizeof(state));
1061 /* if table does not exist, we cannot load any machine code from this file */
1065 /* find out the index in the methods array */
1067 for (i = 0; i < m->clazz->methodscount; i++)
1068 if (&m->clazz->methods[i] == m)
1075 /* seek to the method's entry in the table */
1076 system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
1078 /* get the location */
1079 system_read(fd, &offset, sizeof(offset));
1083 system_lseek(fd, offset, SEEK_SET);
1090 int get_cache_file_readable(methodinfo *m)
1095 if (m->clazz->cache_file_fd)
1096 return dup(m->clazz->cache_file_fd);
1099 /* load from filesystem */
1100 dest_file = get_dest_file(m);
1102 if (system_access(dest_file, F_OK) != 0)
1104 if (opt_DebugJitCache)
1105 log_message_method("[jitcache] no cache file found for ", m);
1107 system_free(dest_file);
1116 fd = open_to_read(dest_file);
1118 system_free(dest_file);
1122 jitcache_mru_add(m->clazz, fd);
1127 int get_cache_file_writable(methodinfo *m)
1129 char *dest_file, *dest_dir;
1132 if (m->clazz->cache_file_fd)
1133 return m->clazz->cache_file_fd;
1135 /* try to get the file first */
1136 dest_file = get_dest_file(m);
1137 fd = open_to_write(dest_file);
1139 /* file does not exist. We need to create it and possibly
1140 * the directory hierarchy as well.
1143 dest_dir = get_dest_dir(m);
1145 if (system_access(dest_dir, F_OK) != 0)
1147 if (mkdir_hier(dest_dir, S_IRWXU | S_IRWXG) != 0)
1149 if (opt_DebugJitCache)
1150 log_println("[jitcache] unable to create cache directory: %s", dest_dir);
1152 system_free(dest_dir);
1153 system_free(dest_file);
1159 system_free(dest_dir);
1161 /* try to open the file again. */
1162 fd = open_to_write(dest_file);
1163 system_free(dest_file);
1169 system_free(dest_file);
1171 jitcache_mru_add(m->clazz, fd);
1176 /* mkdir_hier ******************************************************************
1178 Creates a directory hierarchy on the filesystem.
1180 *******************************************************************************/
1181 int mkdir_hier(char *path, mode_t mode)
1184 int length = system_strlen(path);
1186 for (index = 0; index < length; index++)
1188 if (path[index] == '/')
1197 return mkdir(path, mode);
1200 /* get_dest_file ****************************************************************
1202 Returns a string denoting the file in which the method's machine code
1203 (along with the other data) is stored.
1205 *******************************************************************************/
1207 char *get_dest_file(methodinfo *m)
1209 int len_cacheroot = system_strlen(CACHEROOT);
1210 int len_classname = utf_bytes(m->clazz->name);
1212 char *dest_file = system_calloc(sizeof(u1),
1217 strcat(dest_file, CACHEROOT);
1218 utf_cat(dest_file, m->clazz->name);
1223 /* get_dest_dir ****************************************************************
1225 Returns a string denoting the directory in which the method's machine code
1226 (along with the other data) is stored.
1228 *******************************************************************************/
1230 char *get_dest_dir(methodinfo *m)
1232 int len_cacheroot = system_strlen(CACHEROOT);
1233 int len_packagename = utf_bytes(m->clazz->packagename);
1235 char *dest_dir = system_calloc(sizeof(u1),
1237 + len_packagename + 2);
1239 strcat(dest_dir, CACHEROOT);
1240 utf_cat(dest_dir, m->clazz->packagename);
1242 /* Make trailing slash from package name to 0 */
1243 dest_dir[len_cacheroot + len_packagename + 2 - 1] = 0;
1248 /* to_abs **********************************************************************
1250 Generates an absolute pointer from an offset. You need this after loading
1251 a value from the disk which is absolute at runtime.
1253 *******************************************************************************/
1255 u1 *to_abs(u1 *base, u1 *offset)
1257 return (u1 *) ((ptrint) base + (ptrint) offset);
1260 /* to_offset *******************************************************************
1262 Generates an offset from an absolute pointer. This has to be done to each
1263 absolute pointer before storing it to disk.
1265 *******************************************************************************/
1267 u1 *to_offset(u1 *base, u1 *abs)
1269 return (u1 *) ((ptrint) abs - (ptrint) base);
1272 /* open_to_read ****************************************************************
1274 Open a file for reading.
1276 *******************************************************************************/
1278 int open_to_read(char *dest_file)
1282 fd = system_open(dest_file, O_RDONLY, 0);
1284 fd = system_open(dest_file,
1286 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1291 /* open_to_write ***************************************************************
1293 Open a file for writing.
1295 *******************************************************************************/
1297 int open_to_write(char *dest_file)
1301 /* fd = system_open(filename,
1303 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1305 fd = system_open(dest_file,
1307 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1312 /* store_utf *******************************************************************
1314 Writes a utf object to disk (via filedescriptor).
1316 *******************************************************************************/
1317 void store_utf(int fd, utf *s)
1324 system_write(fd, (const void *) &len, sizeof(len));
1329 system_write(fd, (const void *) &len, sizeof(len));
1330 system_write(fd, s->text, len);
1334 /* load_utf ********************************************************************
1336 Loads a UTF8 constant from the given filedescriptor and initializes
1337 the given pointer with it.
1338 In case the stored constant's length is -1 the returned string is NULL.
1340 *******************************************************************************/
1341 void load_utf(utf **s, int fd)
1346 system_read(fd, (void *) &len, sizeof(len));
1352 tmp = system_calloc(sizeof(char), len);
1354 system_read(fd, tmp, len);
1356 *s = utf_new(tmp, len);
1358 /* system_free(tmp);*/
1363 /* store_to_file_patchers ******************************************************
1365 Writes the patchers structure of a codeinfo to disk.
1367 *******************************************************************************/
1368 void store_to_file_patchers(int fd, codeinfo *code)
1375 list_t *patchers = code->patchers;
1377 /* serialize patchers list */
1378 system_write(fd, (const void *) &patchers->size, sizeof(patchers->size));
1379 if (opt_DebugJitCache)
1380 log_println("store_to_file_patchers - patchers size %d", patchers->size);
1382 for (pr = (patchref_t *) list_first(patchers); pr != NULL; pr = (patchref_t *) list_next(patchers, pr))
1384 temp_ptr = to_offset(code->mcode, (u1 *) pr->mpc);
1385 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1387 temp_ptr = to_offset(code->mcode, (u1 *) pr->datap);
1388 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1390 system_write(fd, (const void *) &pr->disp, sizeof(pr->disp));
1394 while (patcher_functions[j].patcher)
1396 if (patcher_functions[j].patcher == pr->patcher)
1399 system_write(fd, (const void *) &j, sizeof(j));
1401 (*patcher_functions[j].serializer)(fd, pr, code->m);
1403 if (patcher_functions[j].serializer == s_dummy)
1404 log_println("store_to_file_patchers: unhandled patcher function for %d", j);
1412 log_println("warning! unknown patcher function stored!");
1413 system_write(fd, (const void *) &temp, sizeof(temp));
1416 system_write(fd, (const void *) &pr->attached_ref, sizeof(pr->attached_ref));
1418 if (pr->attached_ref)
1420 store_cachedref(fd, pr->attached_ref);
1422 /* Release the cached reference now because it should not be used
1423 * in the current Cacao process.
1425 FREE(pr->attached_ref, cachedref_t);
1426 pr->attached_ref = NULL;
1429 system_write(fd, (const void *) &pr->mcode, sizeof(pr->mcode));
1434 /* store_to_file_cachedrefs *****************************************************
1436 Writes the cachedrefs structure of a codeinfo to disk.
1438 *******************************************************************************/
1439 void store_to_file_cachedrefs(int fd, codeinfo *code)
1443 list_t *cachedrefs = code->cachedrefs;
1444 if (opt_DebugJitCache)
1445 log_println("store_to_file_cachedrefs - cachedrefs size %d", cachedrefs->size);
1447 /* serialize cachedrefs list */
1448 system_write(fd, (const void *) &cachedrefs->size, sizeof(cachedrefs->size));
1450 for (cr = (cachedref_t *) list_first(cachedrefs);
1452 cr = (cachedref_t *) list_next(cachedrefs, cr))
1453 store_cachedref(fd, cr);
1456 /* store_cachedref *************************************************************
1458 Stores a single cachedref_t instance to disk.
1460 *******************************************************************************/
1462 void store_cachedref(int fd, cachedref_t *cr)
1464 system_write(fd, (const void *) &cr->type, sizeof(cr->type));
1465 system_write(fd, (const void *) &cr->md_patch, sizeof(cr->md_patch));
1466 system_write(fd, (const void *) &cr->disp, sizeof(cr->disp));
1470 case CRT_ENTRYPOINT:
1471 case CRT_CODEGEN_FINISH_NATIVE_CALL:
1472 case CRT_ASM_HANDLE_EXCEPTION:
1473 case CRT_ASM_HANDLE_NAT_EXCEPTION:
1474 /* Nothing to store. */
1477 system_write(fd, (const void *) &cr->ref, sizeof(s4));
1479 case CRT_OBJECT_HEADER:
1481 case CRT_CLASSINFO_INDEX:
1482 case CRT_CLASSINFO_INTERFACETABLE:
1483 case CRT_CLASSINFO_VFTBL:
1484 /* Store classinfo */
1485 store_classinfo(fd, (classinfo *) cr->ref);
1488 case CRT_BUILTIN_FP:
1489 store_builtin(fd, (builtintable_entry *) cr->ref);
1492 store_string(fd, (java_object_t *) cr->ref);
1494 case CRT_METHODINFO_STUBROUTINE:
1495 case CRT_METHODINFO_TABLE:
1496 case CRT_METHODINFO_INTERFACETABLE:
1497 case CRT_METHODINFO_METHODOFFSET:
1498 store_methodinfo(fd, (methodinfo *) cr->ref);
1500 case CRT_FIELDINFO_VALUE:
1501 case CRT_FIELDINFO_OFFSET:
1502 case CRT_FIELDINFO_OFFSET_HIGH:
1503 store_fieldinfo(fd, (fieldinfo *) cr->ref);
1505 case CRT_JUMPREFERENCE:
1506 system_write(fd, (const void *) &cr->ref, sizeof(cr->ref));
1510 log_println("store_cachedref: Invalid cachedref type: %d", cr->type);
1516 /* store_to_file_exceptiontable ************************************************
1518 Writes the exceptiontable structure of a codeinfo to disk.
1520 *******************************************************************************/
1521 void store_to_file_exceptiontable(int fd, codeinfo *code)
1528 /* serialize exceptiontable */
1530 /* temp will contain the amount of exceptiontable entries or zero
1533 if (code->exceptiontable)
1534 count = code->exceptiontable->length;
1536 system_write(fd, (const void *) &count, sizeof(count));
1537 if (opt_DebugJitCache)
1538 log_println("store_exceptiontable - exceptiontable size %d", count);
1540 for (i = 0; i < count; i++)
1542 exceptiontable_entry_t *entry = &code->exceptiontable->entries[i];
1544 temp_ptr = to_offset(code->mcode, entry->endpc);
1545 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1547 temp_ptr = to_offset(code->mcode, entry->startpc);
1548 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1550 temp_ptr = to_offset(code->mcode, entry->handlerpc);
1551 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1553 /* store class name of entry->catchtype */
1554 if (entry->catchtype.any)
1556 name = CLASSREF_OR_CLASSINFO_NAME(entry->catchtype);
1557 store_utf(fd, name);
1560 store_utf(fd, NULL);
1567 /* store_to_file_linenumbertable ***********************************************
1569 Writes the linenumbertable structure of a codeinfo to disk.
1571 *******************************************************************************/
1572 void store_to_file_linenumbertable(int fd, codeinfo *code)
1575 linenumbertable_entry_t *lte;
1578 linenumbertable_t *linenumbertable;
1580 linenumbertable = code->linenumbertable;
1582 if (code->linenumbertable)
1583 count = code->linenumbertable->length;
1585 /* serialize patchers list */
1586 system_write(fd, (const void *) &count, sizeof(count));
1588 if (opt_DebugJitCache)
1589 log_println("store_to_file_linenumbertable - linenumbertable size %d", count);
1593 lte = linenumbertable->entries;
1594 for (i = 0; i < count; i++)
1596 system_write(fd, (const void *) <e->linenumber, sizeof(lte->linenumber));
1598 temp_ptr = to_offset(code->entrypoint, lte->pc);
1599 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1608 /* load_from_file_patchers *****************************************************
1610 Loads the patchers structure of codeinfo from a file.
1612 *******************************************************************************/
1613 void load_from_file_patchers(codeinfo *code, int fd)
1620 /* serialize patchers list */
1621 system_read(fd, (void *) &count, sizeof(count));
1623 if (opt_DebugJitCache /* Insert method into methodtree to find the entrypoint. */
1625 log_println("load_from_file_patchers - patcher size %d", count);
1627 patcher_list_create(code);
1629 for (i = 0;i < count; i++)
1631 patchref_t *pr = NEW(patchref_t);
1633 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1634 pr->mpc = (ptrint) to_abs(code->mcode, temp_ptr);
1636 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1637 pr->datap = (ptrint) to_abs(code->mcode, temp_ptr);
1639 system_read(fd, (void *) &pr->disp, sizeof(pr->disp));
1641 system_read(fd, (void *) &temp, sizeof(temp));
1644 vm_abort("Invalid patcher function index loaded!");
1647 pr->patcher = patcher_functions[temp].patcher;
1649 (*patcher_functions[temp].deserializer)(pr, fd, code->m);
1651 /* Load the pointer value to decide whether a cached reference must
1652 * be loaded or not. */
1653 system_read(fd, (void *) &pr->attached_ref, sizeof(pr->attached_ref));
1655 if (pr->attached_ref)
1657 pr->attached_ref = NULL;
1658 load_cachedref(&pr->attached_ref, fd, code);
1661 system_read(fd, (void *) &pr->mcode, sizeof(pr->mcode));
1665 list_add_first(code->patchers, pr);
1669 /* load_from_file_cachedrefs ***************************************************
1671 Loads the cachedrefs structure of codeinfo from a file.
1673 Note: code->entrypoint *must* be valid at this point!
1676 int - number of cachedref_t instances in the file
1677 cachedref_t - see load_cachedref
1679 *******************************************************************************/
1680 void load_from_file_cachedrefs(codeinfo *code, int fd)
1686 /* serialize cachedrefs list */
1687 system_read(fd, (void *) &count, sizeof(count));
1689 if (opt_DebugJitCache)
1690 log_println("load_from_file_cachedrefs - cachedrefs size %d", count);
1692 jitcache_list_reset(code);
1694 cr = NEW(cachedref_t);
1696 for (i = 0;i < count; i++)
1698 load_cachedref(&cr, fd, code);
1700 /* Write the restored reference into the code. */
1702 patch_md(cr->md_patch, ((ptrint) code->entrypoint) + cr->disp, cr->ref);
1705 *((u1 **) (code->entrypoint + cr->disp)) = cr->ref;
1710 FREE(cr, cachedref_t);
1714 /* load_cachedref **************************************************************
1716 Loads a cached reference from disk and
1720 cachedreftype - type value
1721 * - cached ref specific (depends on type)
1723 *******************************************************************************/
1725 void load_cachedref(cachedref_t **result_cr, int fd, codeinfo *code)
1731 builtintable_entry *bte;
1737 *result_cr = cr = NEW(cachedref_t);
1739 system_read(fd, (void *) &cr->type, sizeof(cr->type));
1740 system_read(fd, (void *) &cr->md_patch, sizeof(cr->md_patch));
1741 system_read(fd, (void *) &cr->disp, sizeof(cr->disp));
1745 /* Just set the current codeinfo. */
1746 cr->ref = (voidptr) code;
1749 system_read(fd, (void *) &cr->ref, sizeof(s4));
1751 case CRT_ENTRYPOINT:
1752 /* Just set the current entrypoint. */
1753 cr->ref = (voidptr) code->entrypoint;
1755 case CRT_CODEGEN_FINISH_NATIVE_CALL:
1756 /* Just set the pointer to codegen_finish_native_call. */
1757 cr->ref = (voidptr) (ptrint) codegen_finish_native_call;
1759 case CRT_ASM_HANDLE_EXCEPTION:
1760 /* Just set the pointer to asm_handle_exception. */
1761 cr->ref = (voidptr) (ptrint) asm_handle_exception;
1763 case CRT_ASM_HANDLE_NAT_EXCEPTION:
1764 /* Just put the pointer to asm_handle_nat_exception. */
1765 cr->ref = (voidptr) (ptrint) asm_handle_nat_exception;
1767 case CRT_OBJECT_HEADER:
1768 /* Load classinfo */
1769 load_classinfo(&ci, fd, code->m);
1770 cr->ref = &ci->object.header;
1773 load_builtin(&bte, fd);
1774 /* TODO: For the time being prefer the stub if it exists, otherwise
1775 * use the function pointer directlty.
1776 * This should go away with a moving garbage collector.
1778 cr->ref = (voidptr) (bte->stub == NULL ? (ptrint) bte->fp : (ptrint) bte->stub);
1781 case CRT_BUILTIN_FP:
1782 load_builtin(&bte, fd);
1783 cr->ref = (voidptr) (ptrint) bte->fp;
1787 load_string(&h, fd);
1788 cr->ref = (voidptr) h;
1791 /* Load classinfo */
1792 load_classinfo(&ci, fd, code->m);
1793 cr->ref = (voidptr) ci;
1796 case CRT_CLASSINFO_INDEX:
1797 /* Load classinfo */
1798 load_classinfo(&ci, fd, code->m);
1799 cr->ref = (voidptr) ci->index;
1801 case CRT_CLASSINFO_INTERFACETABLE:
1802 /* Load classinfo */
1803 load_classinfo(&ci, fd, code->m);
1804 cr->ref = (voidptr) (OFFSET(vftbl_t, interfacetable[0]) -
1805 ci->index * sizeof(methodptr*));
1807 case CRT_CLASSINFO_VFTBL:
1808 /* Load classinfo */
1809 load_classinfo(&ci, fd, code->m);
1810 cr->ref = (voidptr) ci->vftbl;
1812 case CRT_METHODINFO_STUBROUTINE:
1813 load_methodinfo(&mi, fd, code->m);
1814 cr->ref = (voidptr) mi->stubroutine;
1816 case CRT_METHODINFO_TABLE:
1817 load_methodinfo(&mi, fd, code->m);
1818 cr->ref = (voidptr) ((OFFSET(vftbl_t, table[0]) +
1819 sizeof(methodptr) * mi->vftblindex));
1821 case CRT_METHODINFO_INTERFACETABLE:
1822 load_methodinfo(&mi, fd, code->m);
1823 cr->ref = (voidptr) (OFFSET(vftbl_t, interfacetable[0]) -
1824 sizeof(methodptr) * mi->clazz->index);
1826 case CRT_METHODINFO_METHODOFFSET:
1827 load_methodinfo(&mi, fd, code->m);
1828 cr->ref = (voidptr) ((sizeof(methodptr) * (mi - mi->clazz->methods)));
1830 case CRT_FIELDINFO_VALUE:
1831 load_fieldinfo(&fi, fd, code->m);
1833 cr->ref = (voidptr) fi->value;
1835 case CRT_FIELDINFO_OFFSET:
1836 load_fieldinfo(&fi, fd, code->m);
1838 cr->ref = (voidptr) fi->offset;
1840 case CRT_FIELDINFO_OFFSET_HIGH:
1841 /* Should be used on 32 bit archs only. */
1842 load_fieldinfo(&fi, fd, code->m);
1844 cr->ref = (voidptr) fi->offset + 4;
1846 case CRT_JUMPREFERENCE:
1847 system_read(fd, (void *) &cr->ref, sizeof(cr->ref));
1849 cr->ref = (voidptr) ((ptrint) cr->ref + (ptrint) code->entrypoint);
1852 log_println("Invalid (or unhandled) cachedreference type: %d", cr->type);
1858 if (opt_DebugJitCache)
1861 log_println("[%X, %d]: replace (md) %X with %X", code->entrypoint + cr->disp, cr->type, 0xFFF & (u4) (*(u1 **) (code->entrypoint + cr->disp)), cr->ref);
1864 log_println("[%X, %d]: replace %X with %X", code->entrypoint + cr->disp, cr->type, *((u1 **) (code->entrypoint + cr->disp)), cr->ref);
1865 if ((cr->type == CRT_BUILTIN || cr->type == CRT_BUILTIN_FP) && (voidptr) (*((u1 **) (code->entrypoint + cr->disp))) != cr->ref)
1866 log_println("[!!!] differing builtin function pointer: %s", bte->cname);
1873 /* load_from_file_exceptiontable ***********************************************
1875 Loads the exceptiontable structure of codeinfo from a file.
1877 *******************************************************************************/
1878 void load_from_file_exceptiontable(codeinfo *code, int fd)
1883 constant_classref *classref;
1884 exceptiontable_entry_t *ete;
1886 code->exceptiontable = NEW(exceptiontable_t);
1888 system_read(fd, (void *) &code->exceptiontable->length, sizeof(code->exceptiontable->length));
1890 if (opt_DebugJitCache)
1891 log_println("load_exceptiontable - exceptiontable size %d", code->exceptiontable->length);
1894 ete = MNEW(exceptiontable_entry_t, code->exceptiontable->length);
1895 code->exceptiontable->entries = ete;
1897 for (i = 0; i < code->exceptiontable->length; i++)
1899 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1900 ete->endpc = to_abs(code->mcode, temp_ptr);
1902 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1903 ete->startpc = to_abs(code->mcode, temp_ptr);
1905 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1906 ete->handlerpc = to_abs(code->mcode, temp_ptr);
1908 /* load class name of entry->catchtype */
1909 load_utf(&classname, fd);
1913 classref = NEW(constant_classref);
1914 CLASSREF_INIT(*classref, code->m->clazz, classname);
1916 ete->catchtype = CLASSREF_OR_CLASSINFO(classref);
1919 ete->catchtype.any = NULL;
1927 /* load_from_file_linenumbertable **********************************************
1929 Loads the linenumbertable structure of codeinfo from a file.
1931 *******************************************************************************/
1932 void load_from_file_linenumbertable(codeinfo *code, int fd)
1934 linenumbertable_entry_t *lte;
1938 code->linenumbertable = NEW(linenumbertable_t);
1940 system_read(fd, (void *) &code->linenumbertable->length, sizeof(code->linenumbertable->length));
1942 if (opt_DebugJitCache)
1943 log_println("load_linenumbertable - linenumbertable size %d", code->linenumbertable->length);
1945 lte = MNEW(linenumbertable_entry_t, code->linenumbertable->length);
1946 code->linenumbertable->entries = lte;
1948 for (i = 0;i < code->linenumbertable->length; i++)
1950 system_read(fd, (void *) <e->linenumber, sizeof(lte->linenumber));
1952 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1953 lte->pc = to_abs(code->entrypoint, temp_ptr);
1960 /* s_dummy *********************************************************************
1962 Patcher serialization function which does nothing and can therefore be used
1963 as a placeholder for not yet written serializers.
1965 *******************************************************************************/
1966 void s_dummy(int fd, patchref_t *pr, methodinfo *m)
1968 /* Intentionally does nothing. */
1971 /* s_unresolved_class **********************************************************
1973 Serializes a unresolved_class reference.
1976 - utf string - classname
1978 *******************************************************************************/
1979 void s_unresolved_class(int fd, patchref_t *pr, methodinfo *m)
1981 unresolved_class *uc;
1983 uc = (unresolved_class *) pr->ref;
1985 /* Store the class name ... */
1986 store_utf(fd, uc->classref->name);
1989 log_println("s_unresolved_class:");
1990 log_message_utf("class:", uc->classref->name);
1994 /* s_unresolved_field **********************************************************
1996 Serializes a unresolved_field reference.
1999 s4 - unresolved_field.flags
2000 int - index into class' cpinfo that denotes the unresolved_field's
2003 *******************************************************************************/
2004 void s_unresolved_field(int fd, patchref_t *pr, methodinfo *m)
2008 unresolved_field *ref = (unresolved_field *) pr->ref;
2011 log_println("s_unresolved_field:");
2012 log_message_utf("field name: ", ref->fieldref->name);
2013 log_message_utf("field desc: ", ref->fieldref->descriptor);
2014 log_message_utf("field's class: ", FIELDREF_CLASSNAME(ref->fieldref));
2016 system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
2018 for (i = 0; i < m->clazz->cpcount; i++)
2020 if (m->clazz->cpinfos[i] == (voidptr) ref->fieldref)
2022 system_write(fd, (const void *) &i, sizeof(i));
2027 /* We should be out at this point. */
2029 vm_abort("fieldref not found");
2032 /* s_unresolved_method **********************************************************
2034 Serializes a unresolved_method reference.
2039 *******************************************************************************/
2040 void s_unresolved_method(int fd, patchref_t *pr, methodinfo *m)
2044 unresolved_method *ref = (unresolved_method *) pr->ref;
2046 system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
2048 for (i = 0; i < m->clazz->cpcount; i++)
2050 if (m->clazz->cpinfos[i] == (voidptr) ref->methodref)
2052 system_write(fd, (const void *) &i, sizeof(i));
2057 /* We should be out at this point. */
2059 vm_abort("methodref not found");
2062 /* s_classinfo *****************************************************************
2064 Serializes a classinfo reference.
2066 *******************************************************************************/
2067 void s_classinfo(int fd, patchref_t *pr, methodinfo *m)
2071 ci = (classinfo *) pr->ref;
2073 store_classinfo(fd, ci);
2076 /* s_methodinfo ****************************************************************
2078 Serializes a methodinfo reference.
2080 *******************************************************************************/
2081 void s_methodinfo(int fd, patchref_t *pr, methodinfo *m)
2085 mi = (methodinfo *) pr->ref;
2087 store_methodinfo(fd, mi);
2090 /* store_methodinfo ************************************************************
2092 Serializes a methodinfo reference.
2096 utf - method descriptor
2097 utf - class to which method belongs
2099 *******************************************************************************/
2100 void store_methodinfo(int fd, methodinfo *mi)
2102 store_utf(fd, mi->name);
2103 store_utf(fd, mi->descriptor);
2104 store_utf(fd, mi->clazz->name);
2107 /* s_fieldinfo ****************************************************************
2109 Serializes a fieldinfo reference.
2113 utf - field descriptor
2114 utf - class to which field belongs
2116 *******************************************************************************/
2117 void s_fieldinfo(int fd, patchref_t *pr, methodinfo *m)
2121 fi = (fieldinfo *) pr->ref;
2123 store_fieldinfo(fd, fi);
2126 void store_fieldinfo(int fd, fieldinfo *fi)
2128 store_utf(fd, fi->name);
2129 store_utf(fd, fi->descriptor);
2130 store_utf(fd, fi->clazz->name);
2133 /* s_constant_classref *********************************************************
2135 Serializes a constant_classref reference.
2138 - utf string - constant_classref's classname
2140 *******************************************************************************/
2141 void s_constant_classref(int fd, patchref_t *pr, methodinfo *m)
2143 constant_classref *cr = (constant_classref *) pr->ref;
2145 store_utf(fd, cr->name);
2149 /* store_builtin *******************************************************************
2151 Serializes a constant_classref reference.
2154 - s4 - key from builtintable_get_key()
2156 *******************************************************************************/
2157 void store_builtin(int fd, builtintable_entry *bte)
2161 key = builtintable_get_key(bte);
2163 system_write(fd, (const void *) &key, sizeof(key));
2166 /* store_string ****************************************************************
2168 Serializes a java_object_t reference which denotes a string.
2171 - utf - utf bytes of the string instance
2173 *******************************************************************************/
2174 void store_string(int fd, java_object_t *h)
2178 string = javastring_toutf((java_handle_t *) h, false);
2180 store_utf(fd, string);
2184 /* d_dummy *********************************************************************
2186 Patcher deserialization function which does nothing and can therefore be used
2187 as a placeholder for not yet written deserializers.
2189 *******************************************************************************/
2190 void d_dummy(patchref_t *pr, int fd, methodinfo *m)
2192 /* Intentionally do nothing. */
2196 * Loads UTF8 classname and creates an unresolved_class for it
2197 * using the class to which the patchref_t belongs as the referer.
2199 void d_unresolved_class(patchref_t *pr, int fd, methodinfo *m)
2202 constant_classref *classref;
2203 unresolved_class *uc;
2205 classref = NEW(constant_classref);
2207 load_utf(&classname, fd);
2209 CLASSREF_INIT(*classref, m->clazz, classname);
2211 uc = create_unresolved_class(m, classref, NULL);
2213 pr->ref = (voidptr) uc;
2215 /* FREE(classref, constant_classref);*/
2217 /* system_free(classname); */
2220 void d_unresolved_field(patchref_t *pr, int fd, methodinfo *m)
2224 unresolved_field *ref = NEW(unresolved_field);
2226 system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
2228 system_read(fd, (void *) &i, sizeof(i));
2229 ref->fieldref = (constant_FMIref *) m->clazz->cpinfos[i];
2231 ref->referermethod = m;
2233 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2235 pr->ref = (voidptr) ref;
2238 void d_unresolved_method(patchref_t *pr, int fd, methodinfo *m)
2242 unresolved_method *ref = NEW(unresolved_method);
2244 system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
2246 system_read(fd, (void *) &i, sizeof(i));
2247 ref->methodref = (constant_FMIref *) m->clazz->cpinfos[i];
2249 ref->referermethod = m;
2250 ref->paramconstraints = NULL;
2251 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2253 pr->ref = (voidptr) ref;
2256 void d_classinfo(patchref_t *pr, int fd, methodinfo *m)
2260 load_classinfo(&ci, fd, m);
2262 pr->ref = (voidptr) ci;
2265 void d_methodinfo(patchref_t *pr, int fd, methodinfo *m)
2269 load_methodinfo(&lm, fd, m);
2271 pr->ref = (voidptr) lm;
2274 void load_methodinfo(methodinfo **lm, int fd, methodinfo *m)
2280 constant_classref ref;
2282 load_utf(&m_name, fd);
2283 load_utf(&m_desc, fd);
2284 load_utf(&classname, fd);
2286 CLASSREF_INIT(ref, m->clazz, classname);
2288 class = resolve_classref_eager(&ref);
2290 *lm = class_findmethod(class, m_name, m_desc);
2293 void d_fieldinfo(patchref_t *pr, int fd, methodinfo *m)
2297 load_fieldinfo(&fi, fd, m);
2299 pr->ref = (voidptr) fi;
2302 void load_fieldinfo(fieldinfo **fi, int fd, methodinfo *m)
2308 constant_classref ref;
2310 load_utf(&f_name, fd);
2311 load_utf(&f_desc, fd);
2312 load_utf(&classname, fd);
2314 CLASSREF_INIT(ref, m->clazz, classname);
2316 class = resolve_classref_eager(&ref);
2318 if (!(class->state & CLASS_INITIALIZED))
2319 if (!initialize_class(class))
2321 *fi = class_findfield(class, f_name, f_desc);
2325 * Loads UTF8 classname and initializes a constant_classref for it
2326 * using the class to which the patchref_t belongs as the referer.
2328 void d_constant_classref(patchref_t *pr, int fd, methodinfo *m)
2331 constant_classref *cr = NEW(constant_classref);
2333 load_utf(&classname, fd);
2335 CLASSREF_INIT(*cr, m->clazz, classname);
2337 pr->ref = (voidptr) cr;
2339 /* system_free(classname);*/
2342 void load_builtin(builtintable_entry **bte, int fd)
2346 system_read(fd, (void *) &key, sizeof(key));
2348 *bte = builtintable_get_by_key(key);
2351 void load_string(java_object_t **h, int fd)
2355 load_utf(&string, fd);
2357 /* *h = javastring_new(string);*/
2358 *h = literalstring_new(string);
2361 /* store_classinfo *************************************************************
2363 Serializes a classinfo reference.
2366 - utf string - classinfo's classname
2368 *******************************************************************************/
2369 void store_classinfo(int fd, classinfo *ci)
2371 /* Store the class name ... */
2372 store_utf(fd, ci->name);
2376 /* load_classinfo *************************************************************
2378 Deserializes a classinfo reference.
2380 Binary format: see store_classinfo
2382 *******************************************************************************/
2383 void load_classinfo(classinfo **ci, int fd, methodinfo *m)
2386 constant_classref *classref;
2388 classref = NEW(constant_classref);
2390 load_utf(&classname, fd);
2392 CLASSREF_INIT(*classref, m->clazz, classname);
2394 *ci = resolve_classref_eager(classref);
2399 * These are local overrides for various environment variables in Emacs.
2400 * Please do not remove this and leave it at the end of the file, where
2401 * Emacs will automagically detect them.
2402 * ---------------------------------------------------------------------
2405 * indent-tabs-mode: t
2409 * vim:noexpandtab:sw=4:ts=4: