* Removed all Id tags.
[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 *xptr;
133
134         /* maybe the class is not already linked */
135
136         if (!(c->state & CLASS_LINKED))
137                 if (!link_class(c))
138                         return false;
139
140 #if defined(ENABLE_STATISTICS)
141         if (opt_stat)
142                 count_class_inits++;
143 #endif
144
145         /* initialize super class */
146
147         if (c->super.cls) {
148                 if (!(c->super.cls->state & CLASS_INITIALIZED)) {
149 #if !defined(NDEBUG)
150                         if (initverbose)
151                                 log_message_class_message_class("Initialize super class ",
152                                                                                                 c->super.cls,
153                                                                                                 " from ",
154                                                                                                 c);
155 #endif
156
157                         if (!initialize_class(c->super.cls))
158                                 return false;
159                 }
160         }
161
162         /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
163
164         m = class_findmethod(c, utf_clinit, utf_void__void);
165
166         if (!m) {
167 #if !defined(NDEBUG)
168                 if (initverbose)
169                         log_message_class("Class has no static class initializer: ", c);
170 #endif
171
172                 return true;
173         }
174
175         /* Sun's and IBM's JVM don't care about the static flag */
176 /*      if (!(m->flags & ACC_STATIC)) { */
177 /*              log_text("Class initializer is not static!"); */
178
179 #if !defined(NDEBUG)
180         if (initverbose)
181                 log_message_class("Starting static class initializer for class: ", c);
182 #endif
183
184         /* now call the initializer */
185
186         (void) vm_call_method(m, NULL);
187
188         /* we have an exception or error */
189
190         xptr = exceptions_get_exception();
191
192         if (xptr != NULL) {
193                 /* class is NOT initialized and is marked with error */
194
195                 c->state |= CLASS_ERROR;
196
197                 /* is this an exception, than wrap it */
198
199                 if (builtin_instanceof(xptr, class_java_lang_Exception)) {
200                         /* clear exception, because we are calling jit code again */
201
202                         exceptions_clear_exception();
203
204                         /* wrap the exception */
205
206                         exceptions_throw_exceptionininitializererror(xptr);
207                 }
208
209                 return false;
210         }
211
212 #if !defined(NDEBUG)
213         if (initverbose)
214                 log_message_class("Finished static class initializer for class: ", c);
215 #endif
216
217         return true;
218 }
219
220
221 /*
222  * These are local overrides for various environment variables in Emacs.
223  * Please do not remove this and leave it at the end of the file, where
224  * Emacs will automagically detect them.
225  * ---------------------------------------------------------------------
226  * Local variables:
227  * mode: c
228  * indent-tabs-mode: t
229  * c-basic-offset: 4
230  * tab-width: 4
231  * End:
232  */