Line data Source code
1 : /* src/vm/jit/optimizing/recompiler.cpp - recompilation system
2 :
3 : Copyright (C) 1996-2013
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 :
6 : This file is part of CACAO.
7 :
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.
12 :
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.
17 :
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
21 : 02110-1301, USA.
22 :
23 : */
24 :
25 :
26 : #include "config.h"
27 :
28 : #include <assert.h>
29 :
30 : #include "threads/condition.hpp"
31 : #include "threads/mutex.hpp"
32 : #include "threads/thread.hpp"
33 :
34 : #include "vm/classcache.hpp"
35 : #include "vm/exceptions.hpp"
36 : #include "vm/options.hpp"
37 :
38 : #include "vm/jit/builtin.hpp"
39 : #include "vm/jit/code.hpp"
40 : #include "vm/jit/jit.hpp"
41 :
42 : #include "vm/jit/optimizing/recompiler.hpp"
43 :
44 :
45 : /**
46 : * Stop the worker thread.
47 : */
48 0 : Recompiler::~Recompiler()
49 : {
50 : // Set the running flag to false.
51 0 : _run = false;
52 :
53 : // Now signal the worker thread.
54 0 : _cond.signal();
55 :
56 : // TODO We should wait here until the thread exits.
57 0 : }
58 :
59 :
60 : /* recompile_replace_vftbl *****************************************************
61 :
62 : XXX
63 :
64 : *******************************************************************************/
65 :
66 0 : static void recompile_replace_vftbl(methodinfo *m)
67 : {
68 : codeinfo *code;
69 : codeinfo *pcode;
70 : u4 slot;
71 : classcache_name_entry *nmen;
72 : classcache_class_entry *clsen;
73 : classinfo *c;
74 : vftbl_t *vftbl;
75 : s4 i;
76 :
77 : /* get current and previous codeinfo structure */
78 :
79 0 : code = m->code;
80 0 : pcode = code->prev;
81 :
82 0 : assert(pcode);
83 :
84 : /* iterate over all classes */
85 :
86 0 : for (slot = 0; slot < hashtable_classcache.size; slot++) {
87 0 : nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
88 :
89 0 : for (; nmen; nmen = nmen->hashlink) {
90 : /* iterate over all class entries */
91 :
92 0 : for (clsen = nmen->classes; clsen; clsen = clsen->next) {
93 0 : c = clsen->classobj;
94 :
95 0 : if (c == NULL)
96 0 : continue;
97 :
98 : /* Search for entrypoint of the previous codeinfo in
99 : the vftbl and replace it with the current one. */
100 :
101 0 : vftbl = c->vftbl;
102 :
103 : /* Is the class linked? Means, is the vftbl finished? */
104 :
105 0 : if (!(c->state & CLASS_LINKED))
106 0 : continue;
107 :
108 : /* Does the class have a vftbl? Some internal classes
109 : (e.g. $NEW$) are linked, but do not have a
110 : vftbl. */
111 :
112 0 : if (vftbl == NULL)
113 0 : continue;
114 :
115 0 : for (i = 0; i < vftbl->vftbllength; i++) {
116 0 : if (vftbl->table[i] == pcode->entrypoint) {
117 : #if !defined(NDEBUG)
118 0 : printf("replacing vftbl in: ");
119 0 : class_println(c);
120 : #endif
121 0 : vftbl->table[i] = code->entrypoint;
122 : }
123 : }
124 : }
125 : }
126 : }
127 0 : }
128 :
129 :
130 : /**
131 : * The actual recompilation thread.
132 : */
133 163 : void Recompiler::thread()
134 : {
135 : // FIXME This just works for one recompiler.
136 163 : Recompiler& r = VM::get_current()->get_recompiler();
137 :
138 326 : while (r._run == true) {
139 : // Enter the recompile mutex, so we can call wait.
140 163 : r._mutex.lock();
141 :
142 : // Wait forever on that condition until we are signaled.
143 163 : r._cond.wait(r._mutex);
144 :
145 : // Leave the mutex.
146 0 : r._mutex.unlock();
147 :
148 : // FIXME Move this into the for loop.
149 0 : if (r._run == false)
150 0 : break;
151 :
152 : // Get the next method form the queue and recompile it.
153 0 : while (r._methods.empty() == false) {
154 0 : methodinfo* m = r._methods.front();
155 :
156 : // Recompile this method.
157 0 : if (jit_recompile(m) != NULL) {
158 : // Replace in vftbl's.
159 0 : recompile_replace_vftbl(m);
160 : }
161 : else {
162 : // XXX What is the right-thing(tm) to do here?
163 0 : exceptions_print_current_exception();
164 : }
165 :
166 : // Remove the method from the queue.
167 0 : r._methods.pop();
168 : }
169 : }
170 0 : }
171 :
172 :
173 : /**
174 : * Start the recompilation thread.
175 : *
176 : * @return true on success, false otherwise.
177 : */
178 163 : bool Recompiler::start()
179 : {
180 163 : Utf8String name = Utf8String::from_utf8("Recompiler");
181 :
182 163 : if (!threads_thread_start_internal(name, (functionptr) &Recompiler::thread))
183 0 : return false;
184 :
185 163 : return true;
186 : }
187 :
188 :
189 : /**
190 : * Add a method to the recompilation queue and signal the
191 : * recompilation thread that there is some work to do.
192 : *
193 : * @param m Method to recompile.
194 : */
195 0 : void Recompiler::queue_method(methodinfo *m)
196 : {
197 : // Add the method to the queue.
198 0 : _methods.push(m);
199 :
200 : // Enter the recompile mutex, so we can call notify.
201 0 : _mutex.lock();
202 :
203 : // Signal the recompiler thread.
204 0 : _cond.signal();
205 :
206 : // Leave the mutex.
207 0 : _mutex.unlock();
208 0 : }
209 :
210 :
211 :
212 : // Legacy C interface.
213 0 : void Recompiler_queue_method(methodinfo* m) { VM::get_current()->get_recompiler().queue_method(m); }
214 :
215 : /*
216 : * These are local overrides for various environment variables in Emacs.
217 : * Please do not remove this and leave it at the end of the file, where
218 : * Emacs will automagically detect them.
219 : * ---------------------------------------------------------------------
220 : * Local variables:
221 : * mode: c++
222 : * indent-tabs-mode: t
223 : * c-basic-offset: 4
224 : * tab-width: 4
225 : * End:
226 : * vim:noexpandtab:sw=4:ts=4:
227 : */
|