1 /* src/vm/jit/methodtree.c - AVL tree of methods
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
30 #include "mm/memory.h"
32 #include "toolbox/avl.h"
34 #include "vm/jit/asmpart.h"
35 #include "vm/jit/methodtree.h"
36 #include "vm/jit/stacktrace.hpp"
39 /* methodtree_element *********************************************************/
41 typedef struct methodtree_element_t methodtree_element_t;
43 struct methodtree_element_t {
49 /* in this tree we store all method addresses *********************************/
51 static avl_tree_t *methodtree = NULL;
54 /* static functions ***********************************************************/
56 static int methodtree_comparator(const void *treenode, const void *node);
59 /* methodtree_init *************************************************************
61 Initialize the global method tree.
63 *******************************************************************************/
65 void methodtree_init(void)
67 #if defined(ENABLE_JIT)
68 methodtree_element_t *mte;
71 methodtree = avl_create(&methodtree_comparator);
73 #if defined(ENABLE_JIT)
74 /* Insert asm_vm_call_method. */
76 mte = NEW(methodtree_element_t);
78 mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
79 mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
81 avl_insert(methodtree, mte);
86 /* methodtree_comparator *******************************************************
88 Comparator function used for the AVL tree of methods.
91 treenode ... the node from the tree
92 node ....... the node to compare to the tree-node
99 *******************************************************************************/
101 static int methodtree_comparator(const void *treenode, const void *node)
103 methodtree_element_t *mte;
104 methodtree_element_t *mtepc;
106 mte = (methodtree_element_t *) treenode;
107 mtepc = (methodtree_element_t *) node;
109 /* compare both startpc and endpc of pc, even if they have the same value,
110 otherwise the avl_probe sometimes thinks the element is already in the
114 /* On S390 addresses are 31 bit. Compare only 31 bits of value.
116 # define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
118 # define ADDR_MASK(a) (a)
121 if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
122 ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
123 ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
124 ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
127 } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
138 /* methodtree_insert ***********************************************************
140 Insert the machine code range of a method into the AVL tree of
144 startpc ... start address of the method
145 endpc ..... end address of the method
147 *******************************************************************************/
149 void methodtree_insert(void *startpc, void *endpc)
151 methodtree_element_t *mte;
153 /* Allocate new method entry. */
155 mte = NEW(methodtree_element_t);
157 mte->startpc = startpc;
160 /* This function does not return an error, but asserts for
161 duplicate entries. */
163 avl_insert(methodtree, mte);
167 /* methodtree_find *************************************************************
169 Find the PV for the given PC by searching in the AVL tree of
172 *******************************************************************************/
174 void *methodtree_find(void *pc)
178 /* Try to find a method. */
180 pv = methodtree_find_nocheck(pc);
183 /* No method was found. Let's dump a stacktrace. */
185 #if defined(ENABLE_VMLOG)
186 vmlog_cacao_signl("SIGSEGV");
189 log_println("We received a SIGSEGV and tried to handle it, but we were");
190 log_println("unable to find a Java method at:");
192 #if SIZEOF_VOID_P == 8
193 log_println("PC=0x%016lx", pc);
195 log_println("PC=0x%08x", pc);
199 log_println("Dumping the current stacktrace:");
201 stacktrace_print_current();
203 vm_abort("Exiting...");
210 /* methodtree_find_nocheck *****************************************************
212 Find the PV for the given PC by searching in the AVL tree of
213 methods. This method does not check the return value and is used
216 *******************************************************************************/
218 void *methodtree_find_nocheck(void *pc)
220 methodtree_element_t mtepc;
221 methodtree_element_t *mte;
226 mte = avl_find(methodtree, &mtepc);
236 * These are local overrides for various environment variables in Emacs.
237 * Please do not remove this and leave it at the end of the file, where
238 * Emacs will automagically detect them.
239 * ---------------------------------------------------------------------
242 * indent-tabs-mode: t
246 * vim:noexpandtab:sw=4:ts=4: