Line data Source code
1 : /* src/vm/initialize.cpp - static class initializer functions
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 <string.h>
29 :
30 : #include "vm/types.hpp"
31 :
32 : #include "threads/thread.hpp"
33 : #include "threads/atomic.hpp" // for write_memory_barrier
34 : #include "threads/lock.hpp"
35 :
36 : #include "toolbox/logging.hpp"
37 :
38 : #include "vm/jit/builtin.hpp"
39 : #include "vm/class.hpp"
40 : #include "vm/exceptions.hpp"
41 : #include "vm/global.hpp"
42 : #include "vm/globals.hpp"
43 : #include "vm/initialize.hpp"
44 : #include "vm/loader.hpp"
45 : #include "vm/options.hpp"
46 : #include "vm/vm.hpp"
47 : #include "vm/statistics.hpp"
48 :
49 :
50 : STAT_REGISTER_VAR(int,count_class_inits,0,"class inits","Number of class inits")
51 :
52 : /* private functions **********************************************************/
53 :
54 : static bool initialize_class_intern(classinfo *c);
55 :
56 :
57 : /* initialize_init *************************************************************
58 :
59 : Initialize important system classes.
60 :
61 : *******************************************************************************/
62 :
63 163 : void initialize_init(void)
64 : {
65 163 : TRACESUBSYSTEMINITIALIZATION("initialize_init");
66 :
67 : #if defined(ENABLE_JAVASE)
68 : # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
69 :
70 : /* Nothing. */
71 :
72 : # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
73 :
74 : if (!initialize_class(class_java_lang_String))
75 : vm_abort("initialize_init: Initialization failed: java.lang.String");
76 :
77 : if (!initialize_class(class_java_lang_System))
78 : vm_abort("initialize_init: Initialization failed: java.lang.System");
79 :
80 : if (!initialize_class(class_java_lang_ThreadGroup))
81 : vm_abort("initialize_init: Initialization failed: java.lang.ThreadGroup");
82 :
83 : if (!initialize_class(class_java_lang_Thread))
84 : vm_abort("initialize_init: Initialization failed: java.lang.Thread");
85 :
86 : if (!initialize_class(class_java_lang_Class))
87 : vm_abort("initialize_init: Initialization failed: java.lang.Class");
88 :
89 : # else
90 : # error unknown classpath configuration
91 : # endif
92 :
93 : #elif defined(ENABLE_JAVAME_CLDC1_1)
94 :
95 : /* Nothing. */
96 :
97 : #else
98 : # error unknown Java configuration
99 : #endif
100 163 : }
101 :
102 : /* initialize_class ************************************************************
103 :
104 : In Java, every class can have a static initialization
105 : function. This function has to be called BEFORE calling other
106 : methods or accessing static variables.
107 :
108 : *******************************************************************************/
109 :
110 105528 : bool initialize_class(classinfo *c)
111 : {
112 : bool r;
113 :
114 105528 : if (!makeinitializations)
115 0 : return true;
116 :
117 105528 : LOCK_MONITOR_ENTER(c);
118 :
119 : /* maybe the class is already initalized or the current thread, which can
120 : pass the monitor, is currently initalizing this class */
121 :
122 105528 : if (class_is_or_almost_initialized(c)) {
123 79510 : LOCK_MONITOR_EXIT(c);
124 :
125 79510 : return true;
126 : }
127 :
128 : /* if <clinit> throw an Error before, the class was marked with an
129 : error and we have to throw a NoClassDefFoundError */
130 :
131 26018 : if (c->state & CLASS_ERROR) {
132 0 : exceptions_throw_noclassdeffounderror(c->name);
133 :
134 0 : LOCK_MONITOR_EXIT(c);
135 :
136 : /* ...but return true, this is ok (mauve test) */
137 :
138 0 : return true;
139 : }
140 :
141 : /* this initalizing run begins NOW */
142 :
143 26018 : c->initializing_thread = thread_get_current();
144 26018 : c->state |= CLASS_INITIALIZING;
145 :
146 : /* call the internal function */
147 :
148 26018 : r = initialize_class_intern(c);
149 :
150 : /* if return value is not NULL everything was ok and the class is
151 : initialized */
152 :
153 26018 : if (r) {
154 : // Let's make sure that everything is flushed out to memory before
155 : // marking the class as initialized.
156 26015 : Atomic::write_memory_barrier();
157 :
158 26015 : c->state |= CLASS_INITIALIZED;
159 : }
160 :
161 : /* this initalizing run is done */
162 :
163 26018 : c->state &= ~CLASS_INITIALIZING;
164 :
165 26018 : LOCK_MONITOR_EXIT(c);
166 :
167 26018 : return r;
168 : }
169 :
170 :
171 : /* initialize_class_intern *****************************************************
172 :
173 : This function MUST NOT be called directly, because of thread
174 : <clinit> race conditions.
175 :
176 : *******************************************************************************/
177 :
178 26018 : static bool initialize_class_intern(classinfo *c)
179 : {
180 : methodinfo *m;
181 : java_handle_t *cause;
182 : classinfo *clazz;
183 :
184 : /* maybe the class is not already linked */
185 :
186 26018 : if (!(c->state & CLASS_LINKED))
187 26 : if (!link_class(c))
188 0 : return false;
189 :
190 : STATISTICS(count_class_inits++);
191 :
192 : /* Initialize super class. */
193 :
194 26018 : if (c->super != NULL) {
195 25855 : if (!(c->super->state & CLASS_INITIALIZED)) {
196 : #if !defined(NDEBUG)
197 5772 : if (initverbose)
198 : log_message_class_message_class("Initialize super class ",
199 : c->super,
200 : " from ",
201 0 : c);
202 : #endif
203 :
204 5772 : if (!initialize_class(c->super))
205 0 : return false;
206 : }
207 : }
208 :
209 : /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
210 :
211 26018 : m = class_findmethod(c, utf8::clinit, utf8::void__void);
212 :
213 26018 : if (m == NULL) {
214 : #if !defined(NDEBUG)
215 18589 : if (initverbose)
216 0 : log_message_class("Class has no static class initializer: ", c);
217 : #endif
218 :
219 18589 : return true;
220 : }
221 :
222 : /* Sun's and IBM's JVM don't care about the static flag */
223 : /* if (!(m->flags & ACC_STATIC)) { */
224 : /* log_text("Class initializer is not static!"); */
225 :
226 : #if !defined(NDEBUG)
227 7429 : if (initverbose)
228 0 : log_message_class("Starting static class initializer for class: ", c);
229 : #endif
230 :
231 : /* now call the initializer */
232 :
233 7429 : (void) vm_call_method(m, NULL);
234 :
235 : /* we have an exception or error */
236 :
237 7429 : cause = exceptions_get_exception();
238 :
239 7429 : if (cause != NULL) {
240 : /* class is NOT initialized and is marked with error */
241 :
242 3 : c->state |= CLASS_ERROR;
243 :
244 : /* Load java/lang/Exception for the instanceof check. */
245 :
246 3 : clazz = load_class_bootstrap(utf8::java_lang_Exception);
247 :
248 3 : if (clazz == NULL)
249 0 : return false;
250 :
251 : /* Is this an exception? Yes, than wrap it. */
252 :
253 3 : if (builtin_instanceof(cause, clazz)) {
254 : /* clear exception, because we are calling jit code again */
255 :
256 3 : exceptions_clear_exception();
257 :
258 : /* wrap the exception */
259 :
260 3 : exceptions_throw_exceptionininitializererror(cause);
261 : }
262 :
263 3 : return false;
264 : }
265 :
266 : #if !defined(NDEBUG)
267 7426 : if (initverbose)
268 0 : log_message_class("Finished static class initializer for class: ", c);
269 : #endif
270 :
271 7426 : return true;
272 : }
273 :
274 :
275 : /*
276 : * These are local overrides for various environment variables in Emacs.
277 : * Please do not remove this and leave it at the end of the file, where
278 : * Emacs will automagically detect them.
279 : * ---------------------------------------------------------------------
280 : * Local variables:
281 : * mode: c++
282 : * indent-tabs-mode: t
283 : * c-basic-offset: 4
284 : * tab-width: 4
285 : * End:
286 : * vim:noexpandtab:sw=4:ts=4:
287 : */
|