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)
29 #include "threads/thread.hpp"
31 #include "toolbox/list.hpp"
33 #include "vm/field.hpp"
35 #include "vm/jit/builtin.hpp"
36 #include "vm/jit/code.hpp"
37 #include "vm/jit/codegen-common.hpp"
38 #include "vm/jit/jit.hpp"
39 #include "vm/jit/jitcache.hpp"
40 #include "vm/jit/linenumbertable.hpp"
41 #include "vm/jit/patcher-common.hpp"
44 #include "vm/string.hpp"
56 #include "toolbox/logging.h"
58 #include "mm/memory.h"
59 #include "mm/codememory.h"
61 #include "vm/method.h"
62 #include "vm/options.h"
63 #include "vm/resolve.h"
66 #include "vm/jit/asmpart.h"
67 #include "vm/jit/exceptiontable.h"
68 #include "vm/jit/methodtree.h"
70 #include "vm/references.h"
76 /* TODO: Wrap this in vm/system.h" */
79 #define CACHEROOT "/tmp/cacao-jitcache/"
81 /* small grained helper functions */
82 char *get_dest_dir(methodinfo *);
83 char *get_dest_file(methodinfo *);
85 int mkdir_hier(char *, mode_t);
86 int open_to_read(char *);
87 int open_to_write(char *);
89 void *to_abs(void *, void *);
90 void *to_offset(void *, void *);
92 void store_utf(int, utf *);
93 void store_classinfo(int, classinfo *);
94 void store_builtin(int, builtintable_entry *);
95 void store_string(int, java_object_t *);
96 void store_methodinfo(int, methodinfo *);
97 void store_fieldinfo(int, fieldinfo *);
98 void store_cachedref(int, cachedref_t *);
100 void load_utf(utf **, int);
101 void load_classinfo(classinfo **, int, methodinfo *);
102 void load_builtin(builtintable_entry **, int);
103 void load_string(java_object_t **, int);
104 void load_methodinfo(methodinfo **, int, methodinfo *);
105 void load_fieldinfo(fieldinfo **, int, methodinfo *);
106 void load_cachedref(cachedref_t **, int, codeinfo *);
108 /* medium grained helper functions */
109 void load_from_file_patchers(codeinfo *, int);
110 void load_from_file_cachedrefs(codeinfo *, int);
111 void load_from_file_exceptiontable(codeinfo *, int);
112 void load_from_file_linenumbertable(codeinfo *, int);
114 void store_to_file_patchers(int, codeinfo *);
115 void store_to_file_cachedrefs(int, codeinfo *);
116 void store_to_file_linenumbertable(int, codeinfo *);
117 void store_to_file_exceptiontable(int, codeinfo *);
119 /* file handling functions */
120 void update_method_table(methodinfo *, int);
121 int seek_method_table(methodinfo *, int);
122 int get_cache_file_readable(methodinfo *);
123 int get_cache_file_writable(methodinfo *);
125 /* serializer forward declarations */
126 void s_dummy(int, patchref_t *, methodinfo *);
127 void s_unresolved_class(int, patchref_t *, methodinfo *);
128 void s_unresolved_field(int, patchref_t *, methodinfo *);
129 void s_unresolved_method(int, patchref_t *, methodinfo *);
130 void s_constant_classref(int, patchref_t *, methodinfo *);
131 void s_classinfo(int, patchref_t *, methodinfo *);
132 void s_methodinfo(int, patchref_t *, methodinfo *);
133 void s_fieldinfo(int, patchref_t *, methodinfo *);
134 void s_string(int, patchref_t *, methodinfo *);
136 /* deserializer forward declarations */
137 void d_dummy(patchref_t *, int, methodinfo *);
138 void d_unresolved_class(patchref_t *, int, methodinfo *);
139 void d_unresolved_field(patchref_t *, int, methodinfo *);
140 void d_unresolved_method(patchref_t *, int, methodinfo *);
141 void d_constant_classref(patchref_t *, int, methodinfo *);
142 void d_classinfo(patchref_t *, int, methodinfo *);
143 void d_methodinfo(patchref_t *, int, methodinfo *);
144 void d_fieldinfo(patchref_t *, int, methodinfo *);
145 void d_string(patchref_t *, int, methodinfo *);
147 /* The order of entries follows the order of
148 * declarations in patcher-common.h
151 static jitcache_patcher_function_list_t patcher_functions[] = {
152 { PATCHER_resolve_class, s_unresolved_class, d_unresolved_class },
153 { PATCHER_initialize_class, s_classinfo, d_classinfo },
154 { PATCHER_resolve_classref_to_classinfo, s_constant_classref, d_constant_classref },
155 { PATCHER_resolve_classref_to_vftbl, s_constant_classref, d_constant_classref },
156 { PATCHER_resolve_classref_to_index, s_constant_classref, d_constant_classref },
157 { PATCHER_resolve_classref_to_flags, s_constant_classref, d_constant_classref },
158 { PATCHER_resolve_native_function, s_methodinfo, d_methodinfo },
160 /* old patcher functions */
161 { PATCHER_get_putstatic, s_unresolved_field, d_unresolved_field },
163 #if defined(__I386__)
164 { PATCHER_getfield, s_unresolved_field, d_unresolved_field },
165 { PATCHER_putfield, s_unresolved_field, d_unresolved_field },
167 { PATCHER_get_putfield, s_unresolved_field, d_unresolved_field },
170 #if defined(__I386__) || defined(__X86_64__)
171 { PATCHER_putfieldconst, s_unresolved_field, d_unresolved_field }, /* 10 */
174 { PATCHER_invokestatic_special, s_unresolved_method, d_unresolved_method },
175 { PATCHER_invokevirtual, s_unresolved_method, d_unresolved_method },
176 { PATCHER_invokeinterface, s_unresolved_method, d_unresolved_method },
178 #if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
179 { PATCHER_checkcast_interface, s_constant_classref, d_constant_classref },
180 { PATCHER_instanceof_interface, s_constant_classref, d_constant_classref },
183 #if defined(__S390__)
184 { PATCHER_checkcast_instanceof_interface, s_dummy, d_dummy },
187 #if defined(__I386__)
188 { PATCHER_aconst, s_constant_classref, d_constant_classref }, /* 16 */
189 { PATCHER_builtin_multianewarray, s_constant_classref, d_constant_classref },
190 { PATCHER_builtin_arraycheckcast, s_constant_classref, d_constant_classref },
191 { PATCHER_checkcast_instanceof_flags, s_constant_classref, d_constant_classref },
192 { PATCHER_checkcast_class, s_constant_classref, d_constant_classref },
193 { PATCHER_instanceof_class, s_constant_classref, d_constant_classref },
196 { NULL, s_dummy, d_dummy }
199 #define JC_MRU_SIZE 100
200 static classinfo *jc_mru_list[JC_MRU_SIZE];
201 int mru_last_free = 0;
204 /* jitcache_mru_add ************************************************************
206 Adds a classinfo to the most recently used (MRU) list. The MRU uses a simple
207 strategy: it will store entries until it is full, further candidates replace
210 *******************************************************************************/
212 void jitcache_mru_add(classinfo *c, int fd)
215 assert(!c->cache_file_fd);
217 c->cache_file_fd = fd;
219 if (mru_last_free < JC_MRU_SIZE) {
220 jc_mru_list[mru_last_free] = c;
229 mru_start = JC_MRU_SIZE - 1;
231 old_c = jc_mru_list[mru_start];
234 assert (old_c->cache_file_fd);
235 os::close(old_c->cache_file_fd);
236 old_c->cache_file_fd = 0;
238 jc_mru_list[mru_start] = c;
243 void jitcache_mru_remove(classinfo *c)
247 for (i = 0; i < JC_MRU_SIZE; i++)
248 if (jc_mru_list[i] == c) {
249 jc_mru_list[j] = NULL;
251 for (j = i; i < mru_last_free - 1; j++)
252 jc_mru_list[j] = jc_mru_list[j+1];
260 /* jitcache_list_create ********************************************************
262 Creates an empty cached reference list for the given codeinfo.
264 *******************************************************************************/
266 void jitcache_list_create(codeinfo *code)
268 code->cachedrefs = new List<cachedref_t>();
272 /* jitcache_list_reset **********************************************************
274 Resets the cached reference list inside a codeinfo.
276 *******************************************************************************/
278 void jitcache_list_reset(codeinfo *code)
280 code->cachedrefs->clear();
284 /* jitcache_list_free ***********************************************************
286 Frees the cached reference list and all its entries for the given codeinfo.
288 *******************************************************************************/
290 void jitcache_list_free(codeinfo *code)
292 /* free all elements of the list */
294 jitcache_list_reset(code);
296 /* free the list itself */
298 delete code->cachedrefs;
299 code->cachedrefs = 0;
303 /* jitcache_list_find ***********************************************************
305 Find an entry inside the cached reference list for the given codeinfo
306 by specifying the displacement in the code/data segment.
308 NOTE: Caller should hold the patcher list lock or maintain
309 exclusive access otherwise.
311 *******************************************************************************/
313 static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
315 /* walk through all cached references for the given codeinfo */
317 for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
318 it != code->cachedrefs->end(); it++)
321 if (it->disp == disp)
329 /* jitcache_new_cachedref ******************************************************
331 Creates and initializes a new cachedref
333 *******************************************************************************/
335 cachedref_t jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
339 /* set reference information */
342 cr.md_patch= md_patch;
348 /* jitcache_add_cachedref_intern ***********************************************
350 Creates a new cached ref appends it to the list in the codeinfo structure.
352 *******************************************************************************/
354 void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t cachedref)
356 List<cachedref_t>::iterator it = code->cachedrefs->begin();
358 while (it != code->cachedrefs->end())
360 if (it->disp == cachedref.disp)
362 assert(it->type == cachedref.type);
363 assert(it->ref == cachedref.ref);
365 /* Cachedref for already existing object found. No need to store
374 code->cachedrefs->push_front(cachedref);
377 /* jitcache_add_cachedref_jd ***************************************************
379 Creates a new cached ref appends it to the list in the codeinfo structure
380 *or* attaches it to the *last* patchref_t if it overlaps with the address
381 of the cached reference.
383 *******************************************************************************/
385 void jitcache_add_cached_ref_jd(jitdata *jd, cachedreftype type, void* ref)
387 jitcache_add_cached_ref_md_jd(jd, type, 0, ref);
391 /* jitcache_add_cachedref_md_jd ************************************************
393 Creates a new cached ref appends it to the list in the codeinfo structure
394 *or* attaches it to the *last* patchref_t if it overlaps with the address
395 of the cached reference.
397 *******************************************************************************/
399 void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, void* ref)
404 cachedref_t cachedref;
406 if (type >= CRT_OBJECT_HEADER && !ref)
411 disp = (ptrint) (cd->mcodeptr - cd->mcodebase) - SIZEOF_VOID_P;
412 cachedref = jitcache_new_cached_ref(type, md_patch, ref, disp);
414 patchref = jd->code->patchers->front();
416 if ((patchref.mpc) <= disp
417 && (patchref.mpc + sizeof(patchref.mcode)) >= disp)
419 /* patchers and cachedref overlap: cached ref must
420 * be handled after the patcher.
423 if (opt_DebugJitCache)
425 log_message_method("cached ref overlaps with patchref: ", jd->m);
428 /* There can be only one cached ref per patcher currently.
429 * If the need arises to handle more cached refs a list can
432 assert(!patchref.attached_ref);
434 patchref.attached_ref = &cachedref;
437 jitcache_add_cached_ref_intern(jd->code, cachedref);
441 /* jitcache_add_cachedref ******************************************************
443 Creates a new cached references and appends it to the list.
445 *******************************************************************************/
447 void jitcache_add_cached_ref(codeinfo *code, cachedreftype type, void* ref, s4 disp)
451 /* allocate cachedref on heap (at least freed together with codeinfo) */
452 cr = jitcache_new_cached_ref(type, 0, ref,disp);
454 jitcache_add_cached_ref_intern(code, cr);
459 /* jitcache_handle_cached_ref **************************************************
461 Creates a new cached references and appends it to the list.
463 *******************************************************************************/
465 void jitcache_handle_cached_ref(cachedref_t *cr, codeinfo *code)
469 location = (u1 **) (code->entrypoint + cr->disp);
471 /* Write the restored reference into the code. */
472 #if defined (__ARM__)
474 patch_md(cr->md_patch, (ptrint) location, cr->ref);
477 *location = (u1 *) cr->ref;
479 md_cacheflush(location, SIZEOF_VOID_P);
481 FREE(cr, cachedref_t);
487 bool filter(utf *classname)
489 static bool printed = false;
492 int max_index = 30000;
493 const char *classes[] = {
498 "java/lang/ThreadGroup",
501 "java/util/Vector$1",
502 "java/util/AbstractList",
503 "java/util/AbstractCollection",
506 "java/lang/ClassLoader",
507 "java/lang/VMClassLoader",
510 "java/util/AbstractSet",
511 "gnu/classpath/SystemProperties",
512 "java/util/Properties",
513 "java/util/Hashtable",
514 "java/util/Dictionary",
515 "java/util/Hashtable$HashEntry",
516 "java/util/AbstractMap$SimpleEntry",
517 "java/lang/StringBuilder",
518 "java/lang/AbstractStringBuffer",
519 "java/util/Collections$SynchronizedSet",
520 "java/util/Collections$SynchronizedCollection",
521 "java/util/Hashtable$3",
522 "java/util/Hashtable$EntryIterator",
523 "java/util/Collections$SynchronizedIterator",
525 "java/util/Collections",
526 "java/util/Collections$EmptySet",
527 "java/util/Collections$EmptyList",
528 "java/util/Collections$EmptyMap",
529 "java/util/Collections$ReverseComparator",
530 "java/util/Collections$UnmodifiableMap",
532 "java/util/StringTokenizer",
533 "java/util/ArrayList",
536 "java/lang/VMSystem",
537 "java/io/FileDescriptor",
538 "gnu/java/io/FileChannelImpl",
540 "gnu/classpath/VMStackWalker",
541 "gnu/java/io/VMChannel",
542 "gnu/java/io/VMChannel$State",
543 "gnu/java/io/VMChannel$Kind",
544 "java/nio/channels/FileChannelImpl",
545 "java/nio/channels/spi/AbstractInterruptibleChannel",
547 "java/io/FileInputStream",
548 "java/io/InputStream",
549 "java/io/BufferedInputStream",
550 "java/io/FilterInputStream",
551 "java/io/PrintStream",
552 "java/io/OutputStream",
553 "java/io/BufferedOutputStream",
554 "java/io/FilterOutputStream",
558 "gnu/java/lang/CharData",
559 "java/lang/Character",
561 "java/security/VMAccessController",
562 "java/lang/ThreadLocal",
563 "java/security/CodeSource",
565 "java/security/PermissionCollection",
567 "java/security/ProtectionDomain",
568 "java/security/AccessControlContext",
569 "gnu/java/util/WeakIdentityHashMap",
570 "gnu/java/util/WeakIdentityHashMap$WeakEntrySet",
571 "java/lang/ref/ReferenceQueue",
572 "java/util/LinkedList",
573 "java/util/AbstractSequentialList",
574 "gnu/java/util/WeakIdentityHashMap$WeakBucket$WeakEntry",
575 "java/util/LinkedList$Entry",
577 "java/lang/reflect/VMConstructor",
578 "java/lang/reflect/Constructor",
579 "java/lang/reflect/Modifier",
580 "gnu/java/net/protocol/file/Handler",
581 "java/net/URLStreamHandler",
582 "java/util/ArrayList",
583 "java/security/SecureClassLoader",
584 "java/lang/Exception",
585 "java/lang/Throwable",
586 "java/lang/VMThrowable",
587 "gnu/java/net/loader/FileURLLoader",
588 "gnu/java/net/loader/URLLoader",
589 "java/security/Policy",
590 "gnu/java/security/provider/DefaultPolicy",
591 "gnu/java/net/loader/Resource",
592 "gnu/java/net/loader/FileResource",
593 "java/io/FileInputStream",
594 "gnu/java/nio/FileChannelImpl",
595 "java/nio/ByteBuffer",
597 "java/nio/ByteOrder",
598 "java/security/Permissions$PermissionsHash",
599 "java/nio/charset/Charset",
600 "gnu/java/nio/charset/Provider",
601 "gnu/java/nio/charset/Provider$1",
602 "gnu/java/nio/charset/US_ASCII",
603 "java/util/Collections$UnmodifiableSet/",
604 "java/util/Collections$UnmodifiableCollection",
605 "java/util/Collections$UnmodifiableIterator",
606 "gnu/java/nio/charset/ISO_8859_1",
607 "gnu/java/nio/charset/UTF_8",
608 "gnu/java/nio/charset/UTF_16BE",
609 "gnu/java/nio/charset/UTF_16LE",
610 "gnu/java/nio/charset/UTF_16",
611 "gnu/java/nio/charset/UnicodeLittle",
612 "gnu/java/nio/charset/Windows1250",
613 "gnu/java/nio/charset/Windows1250",
614 "gnu/java/nio/charset/ByteCharset",
615 "gnu/java/nio/charset/Windows1251",
616 "gnu/java/nio/charset/Windows1252",
617 "gnu/java/nio/charset/Windows1253",
618 "gnu/java/nio/charset/Windows1254",
619 "gnu/java/nio/charset/Windows1257",
620 "gnu/java/nio/charset/ISO_8859_2",
621 "gnu/java/nio/charset/ISO_8859_4",
622 "gnu/java/nio/charset/ISO_8859_5",
623 "gnu/java/nio/charset/ISO_8859_7",
624 "gnu/java/nio/charset/ISO_8859_9",
625 "gnu/java/nio/charset/ISO_8859_13",
626 "gnu/java/nio/charset/ISO_8859_15",
627 "gnu/java/nio/charset/KOI_8",
628 "gnu/java/nio/charset/ISO_8859_1$Encoder",
629 "java/nio/charset/CharsetEncoder",
630 "gnu/java/nio/charset/ByteEncodeLoopHelper",
631 "java/nio/charset/CodingErrorAction",
632 "java/nio/CharBuffer",
633 "java/nio/CharBufferImpl",
634 "gnu/java/nio/charset/ByteEncodeLoopHelper",
635 "java/nio/charset/CoderResult",
636 "java/nio/charset/CoderResult$1",
637 "java/nio/charset/CoderResult$2",
638 "java/nio/charset/CoderResult$Cache",
640 "gnu/java/awt/peer/gtk/GtkToolkit",
641 "gnu/java/awt/peer/gtk/GtkGenericPeer",
642 "java/util/WeakHashMap",
643 "java/util/WeakHashMap$1",
644 "java/util/WeakHashMap$WeakEntrySet",
645 "gnu/java/awt/peer/gtk/GtkWindowPeer",
646 "gnu/java/awt/peer/gtk/GtkCheckboxPeer",
647 "gnu/java/awt/peer/gtk/GtkFileDialogPeer",
648 "gnu/java/awt/peer/gtk/GtkMainThread",
649 "java/security/AccessController",
650 "java/security/Permission",
651 "java/lang/ClassLoader$StaticData",
652 "java/lang/VMString",
653 "gnu/java/lang/CPStringBuilder",
654 "gnu/java/lang/VMCPStringBuilder",
655 "java/io/FileOutputStream",
656 "gnu/java/nio/VMChannel",
657 "gnu/java/nio/VMChannel$State",
658 "gnu/java/nio/VMChannel$Kind",
659 "java/nio/channels/FileChannel",
660 "gnu/classpath/VMSystemProperties",
661 "java/lang/StringBuffer",
662 "java/lang/VMRuntime",
663 "java/lang/VMObject",
664 "java/lang/VMThread",
666 "java/lang/InheritableThreadLocal",
667 "java/lang/ClassNotFoundException",
668 "java/net/URLClassLoader",
669 "java/lang/ClassLoader$1",
670 "java/nio/ByteBufferImpl",
671 "java/io/FilePermission",
672 "gnu/java/nio/charset/ISO_8859_1$Encoder$1",
673 "java/nio/charset/spi/CharsetProvider",
674 "gnu/java/net/loader/URLStreamHandlerCache",
675 "java/util/HashMap$HashIterator",
676 "java/util/HashMap$HashEntry",
677 "java/util/AbstractMap",
678 "java/util/AbstractMap$1",
679 "java/lang/RuntimeException",
680 "java/util/Collections$UnmodifiableSet",
681 "java/lang/ref/Reference",
682 "java/lang/ref/WeakReference",
683 "gnu/java/util/WeakIdentityHashMap$WeakBucket",
684 "gnu/java/util/WeakIdentityHashMap$WeakEntrySet$1",
685 "java/lang/String$CaseInsensitiveComparator",
686 "java/lang/Throwable$StaticData",
687 "java/lang/StackTraceElement",
690 "java/lang/VMDouble",
694 "java/security/Permissions", /* 200 */
695 "java/security/AllPermission",
696 "java/security/AllPermission$AllPermissionCollection",
697 "java/util/AbstractMap$1$1", /* 203 */
702 if (getenv("FILTER_VERBOSE") && !printed)
707 log_println("[%d] - %s", i, classes[i]);
714 buf = getenv("INDEX");
716 sscanf(buf, "%d", &max_index);
719 while (classes[i] && i <= max_index)
722 if (!strcmp(classes[i], classname->text))
728 if ((buf = getenv("FILTER_VERBOSE")))
730 log_println("filtered: %s", classname->text);
742 * Causes filter_match() on which one can set a breakpoint in the debugger
743 * in the following conditions:
745 * If the environment variable NO_FILTER is set, then filter_match() is not
746 * called at all. This disables filter capabilities.
748 * If environment variable TEST_CLASS is set and the method belong to this
749 * class and there is no variable TEST_METHOD then filter_match() is called.
751 * If TEST_CLASS and TEST_METHOD match the methodinfo and TEST_DESCRIPTOR is
754 * If TEST_CLASS, TEST_METHOD and TEST_DESCRIPTOR match the methodinfo's values.
756 void filter_single(methodinfo *m)
760 buf = getenv("NO_FILTER");
764 buf = getenv("TEST_CLASS");
765 if (!buf || strcmp(m->clazz->name->text, buf))
768 buf = getenv("TEST_METHOD");
774 else if (strcmp(m->name->text, buf))
777 buf = getenv("TEST_DESCRIPTOR");
783 else if (strcmp(m->descriptor->text, buf))
789 Mutex *jitcache_lock;
791 /* jitcache_store **************************************************************
793 Saves the generated machine code to disk.
795 *******************************************************************************/
796 void jitcache_store (methodinfo *m)
798 static int init_lock = true;
804 jitcache_lock = new Mutex();
811 if (!filter(m->clazz->name))
815 /* Never try to store native method stubs because those include a reference
816 * a dynamically resolved function.
818 * TODO: Handle those, too.
820 if (m->flags & ACC_NATIVE)
823 fd = get_cache_file_writable(m);
826 if (opt_DebugJitCache)
827 log_message_method("[jitcache] store: got no file descriptor for ", m);
832 /* Write (and some read) file operations beyond this point.
833 * Acquire lock first because another thread may try to load a different
834 * method from this class.
836 /* Mutex_lock(&m->clazz->cache_file_lock);*/
837 jitcache_lock->lock();
839 if (opt_DebugJitCache)
840 log_message_method("[jitcache] store: ", m);
842 update_method_table(m, fd);
844 /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
846 system_write(fd, (const void *) &m->code->flags, sizeof(m->code->flags));
848 system_write(fd, (const void *) &m->code->optlevel, sizeof(m->code->optlevel));
849 system_write(fd, (const void *) &m->code->basicblockcount, sizeof(m->code->basicblockcount));
851 system_write(fd, (const void *) &m->code->synchronizedoffset, sizeof(m->code->synchronizedoffset));
853 system_write(fd, (const void *) &m->code->stackframesize, sizeof(m->code->stackframesize));
855 temp = to_offset(m->code->mcode, m->code->entrypoint);
856 system_write(fd, (const void *) &temp, sizeof(temp));
858 system_write(fd, (const void *) &m->code->mcodelength, sizeof(m->code->mcodelength));
860 system_write(fd, (const void *) m->code->mcode, m->code->mcodelength);
862 store_to_file_exceptiontable(fd, m->code);
864 store_to_file_linenumbertable(fd, m->code);
866 store_to_file_patchers(fd, m->code);
868 store_to_file_cachedrefs(fd, m->code);
870 /* Mutex_unlock(&m->clazz->cache_file_lock);*/
871 jitcache_lock->unlock();
875 /* jitcache_load ***************************************************************
877 Try to load previously generated machine code from disk.
879 Returns non-zero if successfull.
881 *******************************************************************************/
883 u1 jitcache_load (methodinfo *m)
890 if (!filter(m->clazz->name))
894 /* Never try to store native method stubs because those include a reference
895 * a dynamically resolved function.
897 if (m->flags & ACC_NATIVE)
900 fd = get_cache_file_readable(m);
903 if (opt_DebugJitCache)
904 log_message_method("[jitcache] load: got no file descriptor for ", m);
909 if(!seek_method_table(m, fd))
916 if (opt_DebugJitCache)
917 log_message_method("[jitcache] load: ", m);
919 code = code_codeinfo_new(m);
922 /* flags, optlevel, basicblockcount, synchronizedoffset, stackframesize, entrypoint, mcodelength, mcode
924 system_read(fd, (void *) &code->flags, sizeof(code->flags));
926 system_read(fd, (void *) &code->optlevel, sizeof(code->optlevel));
927 system_read(fd, (void *) &code->basicblockcount, sizeof(code->basicblockcount));
929 system_read(fd, (void *) &code->synchronizedoffset, sizeof(code->synchronizedoffset));
931 system_read(fd, (void *) &code->stackframesize, sizeof(code->stackframesize));
933 system_read(fd, (void *) &code->entrypoint, sizeof(code->entrypoint));
935 system_read(fd, (void *) &code->mcodelength, sizeof(code->mcodelength));
937 code->mcode = CNEW(u1, code->mcodelength);
938 system_read(fd, (void *) code->mcode, code->mcodelength);
939 code->entrypoint = (u1 *) to_abs(code->mcode, code->entrypoint);
941 load_from_file_exceptiontable(code, fd);
943 load_from_file_linenumbertable(code, fd);
945 load_from_file_patchers(code, fd);
947 load_from_file_cachedrefs(code, fd);
951 endpc = (u1 *) ((ptrint) code->mcode) + code->mcodelength;
953 /* Insert method into methodtree to find the entrypoint. */
955 methodtree_insert(code->entrypoint, endpc);
957 /* flush the instruction and data caches */
959 md_cacheflush(code->mcode, code->mcodelength);
961 if (opt_DebugJitCache)
963 log_println("[jitcache] load - registered method: %x -> %x", code->entrypoint, endpc);
973 for (i = 0; i < mru_last_free; i++)
975 os::close(jc_mru_list[i]->cache_file_fd);
976 jc_mru_list[i]->cache_file_fd = 0;
982 /* Closes all open file descriptors. */
985 void jitcache_freeclass(classinfo *c)
987 if (c->cache_file_fd)
988 jitcache_mru_remove(c);
991 /* Helper functions */
992 void update_method_table(methodinfo *m, int fd)
994 int state = 0, i, temp, offset = 0;
996 system_lseek(fd, 0, SEEK_SET);
998 system_read(fd, (void *) &state, sizeof(state));
1000 /* table does not exist yet and needs to be created first */
1003 system_lseek(fd, 0, SEEK_SET);
1005 system_write(fd, &state, sizeof(state));
1008 for (i = 0; i < m->clazz->methodscount; i++)
1009 system_write(fd, &temp, sizeof(temp));
1012 /* get last offset in file */
1013 offset = system_lseek(fd, 0, SEEK_END);
1015 /* find out the index in the methods array */
1017 for (i = 0; i < m->clazz->methodscount; i++)
1018 if (&m->clazz->methods[i] == m)
1025 /* seek to the method's entry in the table */
1026 system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
1028 /* enter the location */
1029 system_write(fd, &offset, sizeof(offset));
1031 system_lseek(fd, offset, SEEK_SET);
1034 int seek_method_table(methodinfo *m, int fd)
1036 int state = 0, i, temp, offset;
1038 system_lseek(fd, 0, SEEK_SET);
1040 system_read(fd, (void *) &state, sizeof(state));
1042 /* if table does not exist, we cannot load any machine code from this file */
1046 /* find out the index in the methods array */
1048 for (i = 0; i < m->clazz->methodscount; i++)
1049 if (&m->clazz->methods[i] == m)
1056 /* seek to the method's entry in the table */
1057 system_lseek(fd, temp * sizeof(int) + sizeof(int), SEEK_SET);
1059 /* get the location */
1060 system_read(fd, &offset, sizeof(offset));
1064 system_lseek(fd, offset, SEEK_SET);
1071 int get_cache_file_readable(methodinfo *m)
1076 if (m->clazz->cache_file_fd)
1077 return dup(m->clazz->cache_file_fd);
1080 /* load from filesystem */
1081 dest_file = get_dest_file(m);
1083 if (os::access(dest_file, F_OK) != 0)
1085 if (opt_DebugJitCache)
1086 log_message_method("[jitcache] no cache file found for ", m);
1088 perror("get_cache_file_writable: ");
1090 os::free(dest_file);
1099 fd = open_to_read(dest_file);
1101 os::free(dest_file);
1105 jitcache_mru_add(m->clazz, fd);
1110 int get_cache_file_writable(methodinfo *m)
1112 char *dest_file, *dest_dir;
1115 if (m->clazz->cache_file_fd)
1116 return m->clazz->cache_file_fd;
1118 /* try to get the file first */
1119 dest_file = get_dest_file(m);
1120 fd = open_to_write(dest_file);
1122 /* file does not exist. We need to create it and possibly
1123 * the directory hierarchy as well.
1126 dest_dir = get_dest_dir(m);
1128 if (os::access(dest_dir, F_OK) != 0)
1130 if (mkdir_hier(dest_dir, S_IRWXU | S_IRWXG) != 0)
1132 perror("get_cache_file_writable: ");
1134 if (opt_DebugJitCache)
1135 log_println("[jitcache] unable to create cache directory: %s", dest_dir);
1138 os::free(dest_file);
1146 /* try to open the file again. */
1147 fd = open_to_write(dest_file);
1148 os::free(dest_file);
1152 perror("get_cache_file_writable2: ");
1157 os::free(dest_file);
1159 jitcache_mru_add(m->clazz, fd);
1164 /* mkdir_hier ******************************************************************
1166 Creates a directory hierarchy on the filesystem.
1168 *******************************************************************************/
1169 int mkdir_hier(char *path, mode_t mode)
1172 int length = os::strlen(path);
1174 for (index = 0; index < length; index++)
1176 if (path[index] == '/')
1185 if (!mkdir(path, mode) || errno == EEXIST)
1189 /* get_dest_file ****************************************************************
1191 Returns a string denoting the file in which the method's machine code
1192 (along with the other data) is stored.
1194 *******************************************************************************/
1196 char *get_dest_file(methodinfo *m)
1198 int len_cacheroot = os::strlen(CACHEROOT);
1199 int len_classname = utf_bytes(m->clazz->name);
1201 char *dest_file = (char *) os::calloc(sizeof(u1),
1206 strcat(dest_file, CACHEROOT);
1207 utf_cat(dest_file, m->clazz->name);
1212 /* get_dest_dir ****************************************************************
1214 Returns a string denoting the directory in which the method's machine code
1215 (along with the other data) is stored.
1217 *******************************************************************************/
1219 char *get_dest_dir(methodinfo *m)
1221 int len_cacheroot = os::strlen(CACHEROOT);
1222 int len_packagename = utf_bytes(m->clazz->packagename);
1224 char *dest_dir = (char *) os::calloc(sizeof(u1),
1226 + len_packagename + 2);
1228 strcat(dest_dir, CACHEROOT);
1229 utf_cat(dest_dir, m->clazz->packagename);
1231 /* Make trailing slash from package name to 0 */
1232 dest_dir[len_cacheroot + len_packagename + 2 - 1] = 0;
1237 /* to_abs **********************************************************************
1239 Generates an absolute pointer from an offset. You need this after loading
1240 a value from the disk which is absolute at runtime.
1242 *******************************************************************************/
1244 void *to_abs(void *base, void *offset)
1246 return (void *) ((ptrint) base + (ptrint) offset);
1249 /* to_offset *******************************************************************
1251 Generates an offset from an absolute pointer. This has to be done to each
1252 absolute pointer before storing it to disk.
1254 *******************************************************************************/
1256 void *to_offset(void *base, void *abs)
1258 return (void *) ((ptrint) abs - (ptrint) base);
1261 /* open_to_read ****************************************************************
1263 Open a file for reading.
1265 *******************************************************************************/
1267 int open_to_read(char *dest_file)
1271 fd = system_open(dest_file, O_RDONLY, 0);
1273 fd = system_open(dest_file,
1275 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1280 /* open_to_write ***************************************************************
1282 Open a file for writing.
1284 *******************************************************************************/
1286 int open_to_write(char *dest_file)
1290 /* fd = system_open(filename,
1292 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1294 fd = system_open(dest_file,
1296 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1301 /* store_utf *******************************************************************
1303 Writes a utf object to disk (via filedescriptor).
1305 *******************************************************************************/
1306 void store_utf(int fd, utf *s)
1313 system_write(fd, (const void *) &len, sizeof(len));
1318 system_write(fd, (const void *) &len, sizeof(len));
1319 system_write(fd, s->text, len);
1323 /* load_utf ********************************************************************
1325 Loads a UTF8 constant from the given filedescriptor and initializes
1326 the given pointer with it.
1327 In case the stored constant's length is -1 the returned string is NULL.
1329 *******************************************************************************/
1330 void load_utf(utf **s, int fd)
1335 system_read(fd, (void *) &len, sizeof(len));
1341 tmp = (char *) os::calloc(sizeof(char), len);
1343 system_read(fd, tmp, len);
1345 *s = utf_new(tmp, len);
1352 /* store_to_file_patchers ******************************************************
1354 Writes the patchers structure of a codeinfo to disk.
1356 *******************************************************************************/
1357 void store_to_file_patchers(int fd, codeinfo *code)
1363 int size = code->patchers->size();
1365 /* serialize patchers list */
1366 system_write(fd, (const void *) &size, sizeof(size));
1367 if (opt_DebugJitCache)
1368 log_println("store_to_file_patchers - patchers size %d", size);
1370 for (List<patchref_t>::iterator it = code->patchers->begin();
1371 it != code->patchers->end(); it++)
1373 temp_ptr = to_offset(code->mcode, (u1 *) it->mpc);
1374 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1376 temp_ptr = to_offset(code->mcode, (u1 *) it->datap);
1377 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1379 system_write(fd, (const void *) &it->disp, sizeof(it->disp));
1383 while (patcher_functions[j].patcher)
1385 if (patcher_functions[j].patcher == it->patcher)
1388 system_write(fd, (const void *) &j, sizeof(j));
1390 (*patcher_functions[j].serializer)(fd, &(*it), code->m);
1392 if (patcher_functions[j].serializer == s_dummy)
1393 log_println("store_to_file_patchers: unhandled patcher function for %d", j);
1401 log_println("warning! unknown patcher function stored!");
1402 system_write(fd, (const void *) &temp, sizeof(temp));
1405 if (it->attached_ref)
1408 system_write(fd, (const void *) &temp, sizeof(temp));
1410 if (it->attached_ref)
1412 store_cachedref(fd, it->attached_ref);
1414 /* Release the cached reference now because it should not be used
1415 * in the current Cacao process.
1417 FREE(it->attached_ref, cachedref_t);
1418 it->attached_ref = NULL;
1421 system_write(fd, (const void *) &it->mcode, sizeof(it->mcode));
1426 /* store_to_file_cachedrefs *****************************************************
1428 Writes the cachedrefs structure of a codeinfo to disk.
1430 *******************************************************************************/
1431 void store_to_file_cachedrefs(int fd, codeinfo *code)
1433 int size = code->cachedrefs->size();
1434 if (opt_DebugJitCache)
1435 log_println("store_to_file_cachedrefs - cachedrefs size %d", size);
1437 /* serialize cachedrefs list */
1438 system_write(fd, (const void *) &size, sizeof(size));
1440 for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
1441 it != code->cachedrefs->end(); it++)
1442 store_cachedref(fd, &(*it));
1445 /* store_cachedref *************************************************************
1447 Stores a single cachedref_t instance to disk.
1449 *******************************************************************************/
1451 void store_cachedref(int fd, cachedref_t *cr)
1453 system_write(fd, (const void *) &cr->type, sizeof(cr->type));
1454 system_write(fd, (const void *) &cr->md_patch, sizeof(cr->md_patch));
1455 system_write(fd, (const void *) &cr->disp, sizeof(cr->disp));
1459 case CRT_ENTRYPOINT:
1460 case CRT_CODEGEN_FINISH_NATIVE_CALL:
1461 case CRT_ASM_HANDLE_EXCEPTION:
1462 case CRT_ASM_HANDLE_NAT_EXCEPTION:
1463 /* Nothing to store. */
1466 system_write(fd, (const void *) &cr->ref, sizeof(s4));
1468 case CRT_OBJECT_HEADER:
1470 case CRT_CLASSINFO_INDEX:
1471 case CRT_CLASSINFO_INTERFACETABLE:
1472 case CRT_CLASSINFO_VFTBL:
1473 /* Store classinfo */
1474 store_classinfo(fd, (classinfo *) cr->ref);
1477 case CRT_BUILTIN_FP:
1478 store_builtin(fd, (builtintable_entry *) cr->ref);
1481 store_string(fd, (java_object_t *) cr->ref);
1483 case CRT_METHODINFO_STUBROUTINE:
1484 case CRT_METHODINFO_TABLE:
1485 case CRT_METHODINFO_INTERFACETABLE:
1486 case CRT_METHODINFO_METHODOFFSET:
1487 store_methodinfo(fd, (methodinfo *) cr->ref);
1489 case CRT_FIELDINFO_VALUE:
1490 case CRT_FIELDINFO_OFFSET:
1491 case CRT_FIELDINFO_OFFSET_HIGH:
1492 store_fieldinfo(fd, (fieldinfo *) cr->ref);
1494 case CRT_JUMPREFERENCE:
1495 system_write(fd, (const void *) &cr->ref, sizeof(cr->ref));
1499 log_println("store_cachedref: Invalid cachedref type: %d", cr->type);
1505 /* store_to_file_exceptiontable ************************************************
1507 Writes the exceptiontable structure of a codeinfo to disk.
1509 *******************************************************************************/
1510 void store_to_file_exceptiontable(int fd, codeinfo *code)
1517 /* serialize exceptiontable */
1519 /* temp will contain the amount of exceptiontable entries or zero
1522 if (code->exceptiontable)
1523 count = code->exceptiontable->length;
1525 system_write(fd, (const void *) &count, sizeof(count));
1526 if (opt_DebugJitCache)
1527 log_println("store_exceptiontable - exceptiontable size %d", count);
1529 for (i = 0; i < count; i++)
1531 exceptiontable_entry_t *entry = &code->exceptiontable->entries[i];
1533 temp_ptr = to_offset(code->mcode, entry->endpc);
1534 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1536 temp_ptr = to_offset(code->mcode, entry->startpc);
1537 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1539 temp_ptr = to_offset(code->mcode, entry->handlerpc);
1540 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1542 /* store class name of entry->catchtype */
1543 if (entry->catchtype.any)
1545 name = CLASSREF_OR_CLASSINFO_NAME(entry->catchtype);
1546 store_utf(fd, name);
1549 store_utf(fd, NULL);
1556 /* store_to_file_linenumbertable ***********************************************
1558 Writes the linenumbertable structure of a codeinfo to disk.
1560 *******************************************************************************/
1561 void store_to_file_linenumbertable(int fd, codeinfo *code)
1566 if (code->linenumbertable)
1567 count = code->linenumbertable->_linenumbers.size();
1569 /* serialize patchers list */
1570 system_write(fd, (const void *) &count, sizeof(count));
1572 if (opt_DebugJitCache)
1573 log_println("store_to_file_linenumbertable - linenumbertable size %d", count);
1577 for (std::vector<Linenumber>::iterator it = code->linenumbertable->_linenumbers.begin();
1578 it != code->linenumbertable->_linenumbers.end(); it++)
1580 int temp = it->get_linenumber();
1581 system_write(fd, (const void *) &temp, sizeof(temp));
1583 temp_ptr = to_offset(code->entrypoint, it->get_pc());
1584 system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
1591 /* load_from_file_patchers *****************************************************
1593 Loads the patchers structure of codeinfo from a file.
1595 *******************************************************************************/
1596 void load_from_file_patchers(codeinfo *code, int fd)
1603 /* serialize patchers list */
1604 system_read(fd, (void *) &count, sizeof(count));
1606 if (opt_DebugJitCache /* Insert method into methodtree to find the entrypoint. */
1608 log_println("load_from_file_patchers - patcher size %d", count);
1610 patcher_list_create(code);
1612 for (i = 0;i < count; i++)
1616 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1617 pr.mpc = (ptrint) to_abs(code->mcode, temp_ptr);
1619 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1620 pr.datap = (ptrint) to_abs(code->mcode, temp_ptr);
1622 system_read(fd, (void *) &pr.disp, sizeof(pr.disp));
1624 system_read(fd, (void *) &temp, sizeof(temp));
1627 vm_abort("Invalid patcher function index loaded!");
1630 pr.patcher = patcher_functions[temp].patcher;
1632 (*patcher_functions[temp].deserializer)(&pr, fd, code->m);
1634 /* Load the pointer value to decide whether a cached reference must
1635 * be loaded or not. */
1636 system_read(fd, (void *) &temp, sizeof(temp));
1640 pr.attached_ref = 0;
1641 load_cachedref(&pr.attached_ref, fd, code);
1644 system_read(fd, (void *) &pr.mcode, sizeof(pr.mcode));
1648 code->patchers->push_front(pr);
1652 /* load_from_file_cachedrefs ***************************************************
1654 Loads the cachedrefs structure of codeinfo from a file.
1656 Note: code->entrypoint *must* be valid at this point!
1659 int - number of cachedref_t instances in the file
1660 cachedref_t - see load_cachedref
1662 *******************************************************************************/
1663 void load_from_file_cachedrefs(codeinfo *code, int fd)
1669 /* serialize cachedrefs list */
1670 system_read(fd, (void *) &count, sizeof(count));
1672 if (opt_DebugJitCache)
1673 log_println("load_from_file_cachedrefs - cachedrefs size %d", count);
1675 jitcache_list_reset(code);
1677 cr = NEW(cachedref_t);
1679 for (i = 0;i < count; i++)
1681 load_cachedref(&cr, fd, code);
1683 /* Write the restored reference into the code. */
1684 #if defined (__ARM__)
1686 patch_md(cr->md_patch, ((ptrint) code->entrypoint) + cr->disp, cr->ref);
1690 *((u1 **) (code->entrypoint + cr->disp)) = (u1 *) cr->ref;
1695 FREE(cr, cachedref_t);
1699 /* load_cachedref **************************************************************
1701 Loads a cached reference from disk and
1705 cachedreftype - type value
1706 * - cached ref specific (depends on type)
1708 *******************************************************************************/
1710 void load_cachedref(cachedref_t **result_cr, int fd, codeinfo *code)
1716 builtintable_entry *bte;
1722 *result_cr = cr = NEW(cachedref_t);
1724 system_read(fd, (void *) &cr->type, sizeof(cr->type));
1725 system_read(fd, (void *) &cr->md_patch, sizeof(cr->md_patch));
1726 system_read(fd, (void *) &cr->disp, sizeof(cr->disp));
1730 /* Just set the current codeinfo. */
1731 cr->ref = (void*) code;
1734 system_read(fd, (void *) &cr->ref, sizeof(s4));
1736 case CRT_ENTRYPOINT:
1737 /* Just set the current entrypoint. */
1738 cr->ref = (void*) code->entrypoint;
1740 case CRT_CODEGEN_FINISH_NATIVE_CALL:
1741 /* Just set the pointer to codegen_finish_native_call. */
1742 cr->ref = (void*) (ptrint) codegen_finish_native_call;
1744 case CRT_ASM_HANDLE_EXCEPTION:
1745 /* Just set the pointer to asm_handle_exception. */
1746 cr->ref = (void*) (ptrint) asm_handle_exception;
1748 case CRT_ASM_HANDLE_NAT_EXCEPTION:
1749 /* Just put the pointer to asm_handle_nat_exception. */
1750 cr->ref = (void*) (ptrint) asm_handle_nat_exception;
1752 case CRT_OBJECT_HEADER:
1753 /* Load classinfo */
1754 load_classinfo(&ci, fd, code->m);
1755 cr->ref = &ci->object.header;
1758 load_builtin(&bte, fd);
1759 /* TODO: For the time being prefer the stub if it exists, otherwise
1760 * use the function pointer directlty.
1761 * This should go away with a moving garbage collector.
1763 cr->ref = (void*) (bte->stub == NULL ? (ptrint) bte->fp : (ptrint) bte->stub);
1766 case CRT_BUILTIN_FP:
1767 load_builtin(&bte, fd);
1768 cr->ref = (void*) (ptrint) bte->fp;
1772 load_string(&h, fd);
1773 cr->ref = (void*) h;
1776 /* Load classinfo */
1777 load_classinfo(&ci, fd, code->m);
1778 cr->ref = (void*) ci;
1781 case CRT_CLASSINFO_INDEX:
1782 /* Load classinfo */
1783 load_classinfo(&ci, fd, code->m);
1784 cr->ref = (void*) ci->index;
1786 case CRT_CLASSINFO_INTERFACETABLE:
1787 /* Load classinfo */
1788 load_classinfo(&ci, fd, code->m);
1789 cr->ref = (void*) (OFFSET(vftbl_t, interfacetable[0]) -
1790 ci->index * sizeof(methodptr*));
1792 case CRT_CLASSINFO_VFTBL:
1793 /* Load classinfo */
1794 load_classinfo(&ci, fd, code->m);
1795 cr->ref = (void*) ci->vftbl;
1797 case CRT_METHODINFO_STUBROUTINE:
1798 load_methodinfo(&mi, fd, code->m);
1799 cr->ref = (void*) mi->stubroutine;
1801 case CRT_METHODINFO_TABLE:
1802 load_methodinfo(&mi, fd, code->m);
1803 cr->ref = (void*) ((OFFSET(vftbl_t, table[0]) +
1804 sizeof(methodptr) * mi->vftblindex));
1806 case CRT_METHODINFO_INTERFACETABLE:
1807 load_methodinfo(&mi, fd, code->m);
1808 cr->ref = (void*) (OFFSET(vftbl_t, interfacetable[0]) -
1809 sizeof(methodptr) * mi->clazz->index);
1811 case CRT_METHODINFO_METHODOFFSET:
1812 load_methodinfo(&mi, fd, code->m);
1813 cr->ref = (void*) ((sizeof(methodptr) * (mi - mi->clazz->methods)));
1815 case CRT_FIELDINFO_VALUE:
1816 load_fieldinfo(&fi, fd, code->m);
1818 cr->ref = (void*) fi->value;
1820 case CRT_FIELDINFO_OFFSET:
1821 load_fieldinfo(&fi, fd, code->m);
1823 cr->ref = (void*) fi->offset;
1825 case CRT_FIELDINFO_OFFSET_HIGH:
1826 /* Should be used on 32 bit archs only. */
1827 load_fieldinfo(&fi, fd, code->m);
1829 cr->ref = (void*) (fi->offset + 4);
1831 case CRT_JUMPREFERENCE:
1832 system_read(fd, (void *) &cr->ref, sizeof(cr->ref));
1834 cr->ref = (void*) ((ptrint) cr->ref + (ptrint) code->entrypoint);
1837 log_println("Invalid (or unhandled) cachedreference type: %d", cr->type);
1843 if (opt_DebugJitCache)
1846 log_println("[%X, %d]: replace (md) %X with %X", code->entrypoint + cr->disp, cr->type, 0xFFF & (u4) (*(u1 **) (code->entrypoint + cr->disp)), cr->ref);
1849 log_println("[%X, %d]: replace %X with %X", code->entrypoint + cr->disp, cr->type, *((u1 **) (code->entrypoint + cr->disp)), cr->ref);
1850 if ((cr->type == CRT_BUILTIN || cr->type == CRT_BUILTIN_FP) && (void*) (*((u1 **) (code->entrypoint + cr->disp))) != cr->ref)
1851 log_println("[!!!] differing builtin function pointer: %s", bte->cname);
1858 /* load_from_file_exceptiontable ***********************************************
1860 Loads the exceptiontable structure of codeinfo from a file.
1862 *******************************************************************************/
1863 void load_from_file_exceptiontable(codeinfo *code, int fd)
1868 constant_classref *classref;
1869 exceptiontable_entry_t *ete;
1871 code->exceptiontable = NEW(exceptiontable_t);
1873 system_read(fd, (void *) &code->exceptiontable->length, sizeof(code->exceptiontable->length));
1875 if (opt_DebugJitCache)
1876 log_println("load_exceptiontable - exceptiontable size %d", code->exceptiontable->length);
1879 ete = MNEW(exceptiontable_entry_t, code->exceptiontable->length);
1880 code->exceptiontable->entries = ete;
1882 for (i = 0; i < code->exceptiontable->length; i++)
1884 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1885 ete->endpc = to_abs(code->mcode, temp_ptr);
1887 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1888 ete->startpc = to_abs(code->mcode, temp_ptr);
1890 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1891 ete->handlerpc = to_abs(code->mcode, temp_ptr);
1893 /* load class name of entry->catchtype */
1894 load_utf(&classname, fd);
1898 classref = NEW(constant_classref);
1899 CLASSREF_INIT(*classref, code->m->clazz, classname);
1901 ete->catchtype = CLASSREF_OR_CLASSINFO(classref);
1904 ete->catchtype.any = NULL;
1912 /* load_from_file_linenumbertable **********************************************
1914 Loads the linenumbertable structure of codeinfo from a file.
1916 *******************************************************************************/
1917 void load_from_file_linenumbertable(codeinfo *code, int fd)
1922 code->linenumbertable = new LinenumberTable();
1925 system_read(fd, (void *) &size, sizeof(size));
1927 if (opt_DebugJitCache)
1928 log_println("load_linenumbertable - linenumbertable size %d", size);
1930 for (i = 0;i < size; i++)
1933 system_read(fd, (void *) &linenumber, sizeof(linenumber));
1935 system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
1937 code->linenumbertable->_linenumbers.push_back(
1938 Linenumber(linenumber, to_abs(code->entrypoint, temp_ptr)));
1943 /* s_dummy *********************************************************************
1945 Patcher serialization function which does nothing and can therefore be used
1946 as a placeholder for not yet written serializers.
1948 *******************************************************************************/
1949 void s_dummy(int fd, patchref_t *pr, methodinfo *m)
1951 /* Intentionally does nothing. */
1954 /* s_unresolved_class **********************************************************
1956 Serializes a unresolved_class reference.
1959 - utf string - classname
1961 *******************************************************************************/
1962 void s_unresolved_class(int fd, patchref_t *pr, methodinfo *m)
1964 unresolved_class *uc;
1966 uc = (unresolved_class *) pr->ref;
1968 /* Store the class name ... */
1969 store_utf(fd, uc->classref->name);
1972 log_println("s_unresolved_class:");
1973 log_message_utf("class:", uc->classref->name);
1977 /* s_unresolved_field **********************************************************
1979 Serializes a unresolved_field reference.
1982 s4 - unresolved_field.flags
1983 int - index into class' cpinfo that denotes the unresolved_field's
1986 *******************************************************************************/
1987 void s_unresolved_field(int fd, patchref_t *pr, methodinfo *m)
1991 unresolved_field *ref = (unresolved_field *) pr->ref;
1994 log_println("s_unresolved_field:");
1995 log_message_utf("field name: ", ref->fieldref->name);
1996 log_message_utf("field desc: ", ref->fieldref->descriptor);
1997 log_message_utf("field's class: ", FIELDREF_CLASSNAME(ref->fieldref));
1999 system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
2001 for (i = 0; i < m->clazz->cpcount; i++)
2003 if (m->clazz->cpinfos[i] == (void*) ref->fieldref)
2005 system_write(fd, (const void *) &i, sizeof(i));
2010 /* We should be out at this point. */
2012 vm_abort("fieldref not found");
2015 /* s_unresolved_method **********************************************************
2017 Serializes a unresolved_method reference.
2022 *******************************************************************************/
2023 void s_unresolved_method(int fd, patchref_t *pr, methodinfo *m)
2027 unresolved_method *ref = (unresolved_method *) pr->ref;
2029 system_write(fd, (const void *) &ref->flags, sizeof(ref->flags));
2031 for (i = 0; i < m->clazz->cpcount; i++)
2033 if (m->clazz->cpinfos[i] == (void*) ref->methodref)
2035 system_write(fd, (const void *) &i, sizeof(i));
2040 /* We should be out at this point. */
2042 vm_abort("methodref not found");
2045 /* s_classinfo *****************************************************************
2047 Serializes a classinfo reference.
2049 *******************************************************************************/
2050 void s_classinfo(int fd, patchref_t *pr, methodinfo *m)
2054 ci = (classinfo *) pr->ref;
2056 store_classinfo(fd, ci);
2059 /* s_methodinfo ****************************************************************
2061 Serializes a methodinfo reference.
2063 *******************************************************************************/
2064 void s_methodinfo(int fd, patchref_t *pr, methodinfo *m)
2068 mi = (methodinfo *) pr->ref;
2070 store_methodinfo(fd, mi);
2073 /* store_methodinfo ************************************************************
2075 Serializes a methodinfo reference.
2079 utf - method descriptor
2080 utf - class to which method belongs
2082 *******************************************************************************/
2083 void store_methodinfo(int fd, methodinfo *mi)
2085 store_utf(fd, mi->name);
2086 store_utf(fd, mi->descriptor);
2087 store_utf(fd, mi->clazz->name);
2090 /* s_fieldinfo ****************************************************************
2092 Serializes a fieldinfo reference.
2096 utf - field descriptor
2097 utf - class to which field belongs
2099 *******************************************************************************/
2100 void s_fieldinfo(int fd, patchref_t *pr, methodinfo *m)
2104 fi = (fieldinfo *) pr->ref;
2106 store_fieldinfo(fd, fi);
2109 void store_fieldinfo(int fd, fieldinfo *fi)
2111 store_utf(fd, fi->name);
2112 store_utf(fd, fi->descriptor);
2113 store_utf(fd, fi->clazz->name);
2116 /* s_constant_classref *********************************************************
2118 Serializes a constant_classref reference.
2121 - utf string - constant_classref's classname
2123 *******************************************************************************/
2124 void s_constant_classref(int fd, patchref_t *pr, methodinfo *m)
2126 constant_classref *cr = (constant_classref *) pr->ref;
2128 store_utf(fd, cr->name);
2132 /* store_builtin *******************************************************************
2134 Serializes a constant_classref reference.
2137 - s4 - key from builtintable_get_key()
2139 *******************************************************************************/
2140 void store_builtin(int fd, builtintable_entry *bte)
2144 key = builtintable_get_key(bte);
2146 system_write(fd, (const void *) &key, sizeof(key));
2149 /* store_string ****************************************************************
2151 Serializes a java_object_t reference which denotes a string.
2154 - utf - utf bytes of the string instance
2156 *******************************************************************************/
2157 void store_string(int fd, java_object_t *h)
2161 string = javastring_toutf((java_handle_t *) h, false);
2163 store_utf(fd, string);
2167 /* d_dummy *********************************************************************
2169 Patcher deserialization function which does nothing and can therefore be used
2170 as a placeholder for not yet written deserializers.
2172 *******************************************************************************/
2173 void d_dummy(patchref_t *pr, int fd, methodinfo *m)
2175 /* Intentionally do nothing. */
2179 * Loads UTF8 classname and creates an unresolved_class for it
2180 * using the class to which the patchref_t belongs as the referer.
2182 void d_unresolved_class(patchref_t *pr, int fd, methodinfo *m)
2185 constant_classref *classref;
2186 unresolved_class *uc;
2188 classref = NEW(constant_classref);
2190 load_utf(&classname, fd);
2192 CLASSREF_INIT(*classref, m->clazz, classname);
2194 uc = create_unresolved_class(m, classref, NULL);
2196 pr->ref = (void*) uc;
2198 /* FREE(classref, constant_classref);*/
2200 /* os::free(classname); */
2203 void d_unresolved_field(patchref_t *pr, int fd, methodinfo *m)
2207 unresolved_field *ref = NEW(unresolved_field);
2209 system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
2211 system_read(fd, (void *) &i, sizeof(i));
2212 ref->fieldref = (constant_FMIref *) m->clazz->cpinfos[i];
2214 ref->referermethod = m;
2216 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
2218 pr->ref = (void*) ref;
2221 void d_unresolved_method(patchref_t *pr, int fd, methodinfo *m)
2225 unresolved_method *ref = NEW(unresolved_method);
2227 system_read(fd, (void *) &ref->flags, sizeof(ref->flags));
2229 system_read(fd, (void *) &i, sizeof(i));
2230 ref->methodref = (constant_FMIref *) m->clazz->cpinfos[i];
2232 ref->referermethod = m;
2233 ref->paramconstraints = NULL;
2234 UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
2236 pr->ref = (void*) ref;
2239 void d_classinfo(patchref_t *pr, int fd, methodinfo *m)
2243 load_classinfo(&ci, fd, m);
2245 pr->ref = (void*) ci;
2248 void d_methodinfo(patchref_t *pr, int fd, methodinfo *m)
2252 load_methodinfo(&lm, fd, m);
2254 pr->ref = (void*) lm;
2257 void load_methodinfo(methodinfo **lm, int fd, methodinfo *m)
2263 constant_classref ref;
2265 load_utf(&m_name, fd);
2266 load_utf(&m_desc, fd);
2267 load_utf(&classname, fd);
2269 CLASSREF_INIT(ref, m->clazz, classname);
2271 clazz = resolve_classref_eager(&ref);
2273 *lm = class_findmethod(clazz, m_name, m_desc);
2276 void d_fieldinfo(patchref_t *pr, int fd, methodinfo *m)
2280 load_fieldinfo(&fi, fd, m);
2282 pr->ref = (void*) fi;
2285 void load_fieldinfo(fieldinfo **fi, int fd, methodinfo *m)
2291 constant_classref ref;
2293 load_utf(&f_name, fd);
2294 load_utf(&f_desc, fd);
2295 load_utf(&classname, fd);
2297 CLASSREF_INIT(ref, m->clazz, classname);
2299 clazz = resolve_classref_eager(&ref);
2301 if (!(clazz->state & CLASS_INITIALIZED))
2302 if (!initialize_class(clazz))
2304 *fi = class_findfield(clazz, f_name, f_desc);
2308 * Loads UTF8 classname and initializes a constant_classref for it
2309 * using the class to which the patchref_t belongs as the referer.
2311 void d_constant_classref(patchref_t *pr, int fd, methodinfo *m)
2314 constant_classref *cr = NEW(constant_classref);
2316 load_utf(&classname, fd);
2318 CLASSREF_INIT(*cr, m->clazz, classname);
2320 pr->ref = (void*) cr;
2322 /* os::free(classname);*/
2325 void load_builtin(builtintable_entry **bte, int fd)
2329 system_read(fd, (void *) &key, sizeof(key));
2331 *bte = builtintable_get_by_key(key);
2334 void load_string(java_object_t **h, int fd)
2338 load_utf(&string, fd);
2340 /* *h = javastring_new(string);*/
2341 *h = literalstring_new(string);
2344 /* store_classinfo *************************************************************
2346 Serializes a classinfo reference.
2349 - utf string - classinfo's classname
2351 *******************************************************************************/
2352 void store_classinfo(int fd, classinfo *ci)
2354 /* Store the class name ... */
2355 store_utf(fd, ci->name);
2358 /* load_classinfo *************************************************************
2360 Deserializes a classinfo reference.
2362 Binary format: see store_classinfo
2364 *******************************************************************************/
2365 void load_classinfo(classinfo **ci, int fd, methodinfo *m)
2368 constant_classref *classref;
2370 classref = NEW(constant_classref);
2372 load_utf(&classname, fd);
2374 CLASSREF_INIT(*classref, m->clazz, classname);
2376 *ci = resolve_classref_eager(classref);
2382 * These are local overrides for various environment variables in Emacs.
2383 * Please do not remove this and leave it at the end of the file, where
2384 * Emacs will automagically detect them.
2385 * ---------------------------------------------------------------------
2388 * indent-tabs-mode: t
2392 * vim:noexpandtab:sw=4:ts=4: