* src/vm/jit/i386/darwin/md-asm.h: Repaired --enable-cycles-stats.
[cacao.git] / src / vm / initialize.c
1 /* src/vm/initialize.c - static class initializer functions
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <string.h>
31
32 #include "vm/types.h"
33
34 #include "threads/lock-common.h"
35
36 #include "vm/global.h"
37 #include "vm/initialize.h"
38 #include "vm/builtin.h"
39 #include "vm/exceptions.h"
40 #include "vm/stringlocal.h"
41 #include "vm/vm.h"
42
43 #include "vm/jit/asmpart.h"
44
45 #include "vmcore/class.h"
46 #include "vmcore/loader.h"
47 #include "vmcore/options.h"
48
49 #if defined(ENABLE_STATISTICS)
50 # include "vmcore/statistics.h"
51 #endif
52
53
54 /* private functions **********************************************************/
55
56 static bool initialize_class_intern(classinfo *c);
57
58
59 /* initialize_class ************************************************************
60
61    In Java, every class can have a static initialization
62    function. This function has to be called BEFORE calling other
63    methods or accessing static variables.
64
65 *******************************************************************************/
66
67 bool initialize_class(classinfo *c)
68 {
69         bool r;
70
71         if (!makeinitializations)
72                 return true;
73
74         LOCK_MONITOR_ENTER(c);
75
76         /* maybe the class is already initalized or the current thread, which can
77            pass the monitor, is currently initalizing this class */
78
79         if (CLASS_IS_OR_ALMOST_INITIALIZED(c)) {
80                 LOCK_MONITOR_EXIT(c);
81
82                 return true;
83         }
84
85         /* if <clinit> throw an Error before, the class was marked with an
86        error and we have to throw a NoClassDefFoundError */
87
88         if (c->state & CLASS_ERROR) {
89                 exceptions_throw_noclassdeffounderror(c->name);
90
91                 LOCK_MONITOR_EXIT(c);
92
93                 /* ...but return true, this is ok (mauve test) */
94
95                 return true;
96         }
97
98         /* this initalizing run begins NOW */
99
100         c->state |= CLASS_INITIALIZING;
101
102         /* call the internal function */
103
104         r = initialize_class_intern(c);
105
106         /* if return value is not NULL everything was ok and the class is
107            initialized */
108
109         if (r)
110                 c->state |= CLASS_INITIALIZED;
111
112         /* this initalizing run is done */
113
114         c->state &= ~CLASS_INITIALIZING;
115
116         LOCK_MONITOR_EXIT(c);
117
118         return r;
119 }
120
121
122 /* initialize_class_intern *****************************************************
123
124    This function MUST NOT be called directly, because of thread
125    <clinit> race conditions.
126
127 *******************************************************************************/
128
129 static bool initialize_class_intern(classinfo *c)
130 {
131         methodinfo    *m;
132         java_handle_t *cause;
133         classinfo     *class;
134
135         /* maybe the class is not already linked */
136
137         if (!(c->state & CLASS_LINKED))
138                 if (!link_class(c))
139                         return false;
140
141 #if defined(ENABLE_STATISTICS)
142         if (opt_stat)
143                 count_class_inits++;
144 #endif
145
146         /* Initialize super class. */
147
148         if (c->super != NULL) {
149                 if (!(c->super->state & CLASS_INITIALIZED)) {
150 #if !defined(NDEBUG)
151                         if (initverbose)
152                                 log_message_class_message_class("Initialize super class ",
153                                                                                                 c->super,
154                                                                                                 " from ",
155                                                                                                 c);
156 #endif
157
158                         if (!initialize_class(c->super))
159                                 return false;
160                 }
161         }
162
163         /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
164
165         m = class_findmethod(c, utf_clinit, utf_void__void);
166
167         if (m == NULL) {
168 #if !defined(NDEBUG)
169                 if (initverbose)
170                         log_message_class("Class has no static class initializer: ", c);
171 #endif
172
173                 return true;
174         }
175
176         /* Sun's and IBM's JVM don't care about the static flag */
177 /*      if (!(m->flags & ACC_STATIC)) { */
178 /*              log_text("Class initializer is not static!"); */
179
180 #if !defined(NDEBUG)
181         if (initverbose)
182                 log_message_class("Starting static class initializer for class: ", c);
183 #endif
184
185         /* now call the initializer */
186
187         (void) vm_call_method(m, NULL);
188
189         /* we have an exception or error */
190
191         cause = exceptions_get_exception();
192
193         if (cause != NULL) {
194                 /* class is NOT initialized and is marked with error */
195
196                 c->state |= CLASS_ERROR;
197
198                 /* Load java/lang/Exception for the instanceof check. */
199
200                 class = load_class_bootstrap(utf_java_lang_Exception);
201
202                 if (class == NULL)
203                         return false;
204
205                 /* Is this an exception?  Yes, than wrap it. */
206
207                 if (builtin_instanceof(cause, class)) {
208                         /* clear exception, because we are calling jit code again */
209
210                         exceptions_clear_exception();
211
212                         /* wrap the exception */
213
214                         exceptions_throw_exceptionininitializererror(cause);
215                 }
216
217                 return false;
218         }
219
220 #if !defined(NDEBUG)
221         if (initverbose)
222                 log_message_class("Finished static class initializer for class: ", c);
223 #endif
224
225         return true;
226 }
227
228
229 /*
230  * These are local overrides for various environment variables in Emacs.
231  * Please do not remove this and leave it at the end of the file, where
232  * Emacs will automagically detect them.
233  * ---------------------------------------------------------------------
234  * Local variables:
235  * mode: c
236  * indent-tabs-mode: t
237  * c-basic-offset: 4
238  * tab-width: 4
239  * End:
240  */