Mercurial > hg > graal-compiler
annotate src/share/vm/utilities/exceptions.cpp @ 1091:6aa7255741f3
6906727: UseCompressedOops: some card-marking fixes related to object arrays
Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17).
Reviewed-by: kvn, coleenp, jmasa
author | ysr |
---|---|
date | Thu, 03 Dec 2009 15:01:57 -0800 |
parents | fcb148c6b605 |
children | 4ce7240d622c |
rev | line source |
---|---|
0 | 1 /* |
2 * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_exceptions.cpp.incl" | |
27 | |
28 | |
29 // Implementation of ThreadShadow | |
30 void check_ThreadShadow() { | |
31 const ByteSize offset1 = byte_offset_of(ThreadShadow, _pending_exception); | |
32 const ByteSize offset2 = Thread::pending_exception_offset(); | |
33 if (offset1 != offset2) fatal("ThreadShadow::_pending_exception is not positioned correctly"); | |
34 } | |
35 | |
36 | |
37 void ThreadShadow::set_pending_exception(oop exception, const char* file, int line) { | |
38 assert(exception != NULL && exception->is_oop(), "invalid exception oop"); | |
39 _pending_exception = exception; | |
40 _exception_file = file; | |
41 _exception_line = line; | |
42 } | |
43 | |
44 void ThreadShadow::clear_pending_exception() { | |
45 if (TraceClearedExceptions) { | |
46 if (_pending_exception != NULL) { | |
47 tty->print_cr("Thread::clear_pending_exception: cleared exception:"); | |
48 _pending_exception->print(); | |
49 } | |
50 } | |
51 _pending_exception = NULL; | |
52 _exception_file = NULL; | |
53 _exception_line = 0; | |
54 } | |
55 // Implementation of Exceptions | |
56 | |
57 bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) { | |
58 // bootstrapping check | |
59 if (!Universe::is_fully_initialized()) { | |
60 vm_exit_during_initialization(h_exception); | |
61 ShouldNotReachHere(); | |
62 } | |
63 | |
64 if (thread->is_VM_thread() | |
65 || thread->is_Compiler_thread() ) { | |
66 // We do not care what kind of exception we get for the vm-thread or a thread which | |
67 // is compiling. We just install a dummy exception object | |
68 thread->set_pending_exception(Universe::vm_exception(), file, line); | |
69 return true; | |
70 } | |
71 | |
72 return false; | |
73 } | |
74 | |
75 bool Exceptions::special_exception(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message) { | |
76 // bootstrapping check | |
77 if (!Universe::is_fully_initialized()) { | |
78 if (h_name.is_null()) { | |
79 // atleast an informative message. | |
80 vm_exit_during_initialization("Exception", message); | |
81 } else { | |
82 vm_exit_during_initialization(h_name, message); | |
83 } | |
84 ShouldNotReachHere(); | |
85 } | |
86 | |
87 if (thread->is_VM_thread() | |
88 || thread->is_Compiler_thread() ) { | |
89 // We do not care what kind of exception we get for the vm-thread or a thread which | |
90 // is compiling. We just install a dummy exception object | |
91 thread->set_pending_exception(Universe::vm_exception(), file, line); | |
92 return true; | |
93 } | |
94 | |
95 return false; | |
96 } | |
97 | |
98 // This method should only be called from generated code, | |
99 // therefore the exception oop should be in the oopmap. | |
100 void Exceptions::_throw_oop(Thread* thread, const char* file, int line, oop exception) { | |
101 assert(exception != NULL, "exception should not be NULL"); | |
102 Handle h_exception = Handle(thread, exception); | |
103 _throw(thread, file, line, h_exception); | |
104 } | |
105 | |
1011
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
106 void Exceptions::_throw(Thread* thread, const char* file, int line, Handle h_exception, const char* message) { |
0 | 107 assert(h_exception() != NULL, "exception should not be NULL"); |
108 | |
109 // tracing (do this up front - so it works during boot strapping) | |
110 if (TraceExceptions) { | |
111 ttyLocker ttyl; | |
112 ResourceMark rm; | |
1011
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
113 tty->print_cr("Exception <%s>%s%s (" INTPTR_FORMAT " ) \n" |
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
114 "thrown [%s, line %d]\nfor thread " INTPTR_FORMAT, |
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
115 h_exception->print_value_string(), |
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
116 message ? ": " : "", message ? message : "", |
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
117 (address)h_exception(), file, line, thread); |
0 | 118 } |
119 // for AbortVMOnException flag | |
120 NOT_PRODUCT(Exceptions::debug_check_abort(h_exception)); | |
121 | |
122 // Check for special boot-strapping/vm-thread handling | |
123 if (special_exception(thread, file, line, h_exception)) return; | |
124 | |
125 assert(h_exception->is_a(SystemDictionary::throwable_klass()), "exception is not a subclass of java/lang/Throwable"); | |
126 | |
127 // set the pending exception | |
128 thread->set_pending_exception(h_exception(), file, line); | |
129 | |
130 // vm log | |
131 Events::log("throw_exception " INTPTR_FORMAT, (address)h_exception()); | |
132 } | |
133 | |
134 | |
135 void Exceptions::_throw_msg(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_loader, Handle h_protection_domain) { | |
136 // Check for special boot-strapping/vm-thread handling | |
137 if (special_exception(thread, file, line, h_name, message)) return; | |
138 // Create and throw exception | |
139 Handle h_cause(thread, NULL); | |
140 Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain); | |
1011
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
141 _throw(thread, file, line, h_exception, message); |
0 | 142 } |
143 | |
144 // Throw an exception with a message and a cause | |
145 void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, symbolHandle h_name, const char* message, Handle h_cause, Handle h_loader, Handle h_protection_domain) { | |
146 // Check for special boot-strapping/vm-thread handling | |
147 if (special_exception(thread, file, line, h_name, message)) return; | |
148 // Create and throw exception and init cause | |
149 Handle h_exception = new_exception(thread, h_name, message, h_cause, h_loader, h_protection_domain); | |
1011
fcb148c6b605
6889302: TraceExceptions output should include detail message
never
parents:
0
diff
changeset
|
150 _throw(thread, file, line, h_exception, message); |
0 | 151 } |
152 | |
153 // This version creates handles and calls the other version | |
154 void Exceptions::_throw_msg(Thread* thread, const char* file, int line, | |
155 symbolOop name, const char* message) { | |
156 symbolHandle h_name(thread, name); | |
157 Handle h_loader(thread, NULL); | |
158 Handle h_protection_domain(thread, NULL); | |
159 Exceptions::_throw_msg(thread, file, line, h_name, message, h_loader, h_protection_domain); | |
160 } | |
161 | |
162 // This version already has a handle for name | |
163 void Exceptions::_throw_msg(Thread* thread, const char* file, int line, | |
164 symbolHandle name, const char* message) { | |
165 Handle h_loader(thread, NULL); | |
166 Handle h_protection_domain(thread, NULL); | |
167 Exceptions::_throw_msg(thread, file, line, name, message, h_loader, h_protection_domain); | |
168 } | |
169 | |
170 // This version already has a handle for name | |
171 void Exceptions::_throw_msg_cause(Thread* thread, const char* file, int line, | |
172 symbolHandle name, const char* message, Handle cause) { | |
173 Handle h_loader(thread, NULL); | |
174 Handle h_protection_domain(thread, NULL); | |
175 Exceptions::_throw_msg_cause(thread, file, line, name, message, cause, h_loader, h_protection_domain); | |
176 } | |
177 | |
178 void Exceptions::_throw_args(Thread* thread, const char* file, int line, symbolHandle h_name, symbolHandle h_signature, JavaCallArguments *args) { | |
179 // Check for special boot-strapping/vm-thread handling | |
180 if (special_exception(thread, file, line, h_name, NULL)) return; | |
181 // Create and throw exception | |
182 Handle h_loader(thread, NULL); | |
183 Handle h_prot(thread, NULL); | |
184 Handle h_cause(thread, NULL); | |
185 Handle exception = new_exception(thread, h_name, h_signature, args, h_cause, h_loader, h_prot); | |
186 _throw(thread, file, line, exception); | |
187 } | |
188 | |
189 | |
190 void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file, int line) { | |
191 Handle exception; | |
192 if (!THREAD->has_pending_exception()) { | |
193 klassOop k = SystemDictionary::StackOverflowError_klass(); | |
194 oop e = instanceKlass::cast(k)->allocate_instance(CHECK); | |
195 exception = Handle(THREAD, e); // fill_in_stack trace does gc | |
196 if (StackTraceInThrowable) { | |
197 java_lang_Throwable::fill_in_stack_trace(exception); | |
198 } | |
199 } else { | |
200 // if prior exception, throw that one instead | |
201 exception = Handle(THREAD, THREAD->pending_exception()); | |
202 } | |
203 _throw_oop(THREAD, file, line, exception()); | |
204 } | |
205 | |
206 void Exceptions::fthrow(Thread* thread, const char* file, int line, symbolHandle h_name, const char* format, ...) { | |
207 const int max_msg_size = 1024; | |
208 va_list ap; | |
209 va_start(ap, format); | |
210 char msg[max_msg_size]; | |
211 vsnprintf(msg, max_msg_size, format, ap); | |
212 msg[max_msg_size-1] = '\0'; | |
213 va_end(ap); | |
214 _throw_msg(thread, file, line, h_name, msg); | |
215 } | |
216 | |
217 // Creates an exception oop, calls the <init> method with the given signature. | |
218 // and returns a Handle | |
219 // Initializes the cause if cause non-null | |
220 Handle Exceptions::new_exception(Thread *thread, symbolHandle h_name, | |
221 symbolHandle signature, | |
222 JavaCallArguments *args, | |
223 Handle h_cause, Handle h_loader, | |
224 Handle h_protection_domain) { | |
225 assert(Universe::is_fully_initialized(), | |
226 "cannot be called during initialization"); | |
227 assert(thread->is_Java_thread(), "can only be called by a Java thread"); | |
228 assert(!thread->has_pending_exception(), "already has exception"); | |
229 | |
230 Handle h_exception; | |
231 | |
232 // Resolve exception klass | |
233 klassOop ik = SystemDictionary::resolve_or_fail(h_name, h_loader, h_protection_domain, true, thread); | |
234 instanceKlassHandle klass (thread, ik); | |
235 | |
236 if (!thread->has_pending_exception()) { | |
237 assert(klass.not_null(), "klass must exist"); | |
238 // We are about to create an instance - so make sure that klass is initialized | |
239 klass->initialize(thread); | |
240 if (!thread->has_pending_exception()) { | |
241 // Allocate new exception | |
242 h_exception = klass->allocate_instance_handle(thread); | |
243 if (!thread->has_pending_exception()) { | |
244 JavaValue result(T_VOID); | |
245 args->set_receiver(h_exception); | |
246 // Call constructor | |
247 JavaCalls::call_special(&result, klass, | |
248 vmSymbolHandles::object_initializer_name(), | |
249 signature, | |
250 args, | |
251 thread); | |
252 | |
253 } | |
254 } | |
255 | |
256 // Future: object initializer should take a cause argument | |
257 if (h_cause() != NULL) { | |
258 assert(h_cause->is_a(SystemDictionary::throwable_klass()), | |
259 "exception cause is not a subclass of java/lang/Throwable"); | |
260 JavaValue result1(T_OBJECT); | |
261 JavaCallArguments args1; | |
262 args1.set_receiver(h_exception); | |
263 args1.push_oop(h_cause); | |
264 JavaCalls::call_virtual(&result1, klass, | |
265 vmSymbolHandles::initCause_name(), | |
266 vmSymbolHandles::throwable_throwable_signature(), | |
267 &args1, | |
268 thread); | |
269 } | |
270 } | |
271 | |
272 // Check if another exception was thrown in the process, if so rethrow that one | |
273 if (thread->has_pending_exception()) { | |
274 h_exception = Handle(thread, thread->pending_exception()); | |
275 thread->clear_pending_exception(); | |
276 } | |
277 return h_exception; | |
278 } | |
279 | |
280 // Convenience method. Calls either the <init>() or <init>(String) method when | |
281 // creating a new exception | |
282 Handle Exceptions::new_exception(Thread* thread, symbolHandle h_name, | |
283 const char* message, Handle h_cause, | |
284 Handle h_loader, | |
285 Handle h_protection_domain, | |
286 ExceptionMsgToUtf8Mode to_utf8_safe) { | |
287 JavaCallArguments args; | |
288 symbolHandle signature; | |
289 if (message == NULL) { | |
290 signature = vmSymbolHandles::void_method_signature(); | |
291 } else { | |
292 // We want to allocate storage, but we can't do that if there's | |
293 // a pending exception, so we preserve any pending exception | |
294 // around the allocation. | |
295 // If we get an exception from the allocation, prefer that to | |
296 // the exception we are trying to build, or the pending exception. | |
297 // This is sort of like what PRESERVE_EXCEPTION_MARK does, except | |
298 // for the preferencing and the early returns. | |
299 Handle incoming_exception (thread, NULL); | |
300 if (thread->has_pending_exception()) { | |
301 incoming_exception = Handle(thread, thread->pending_exception()); | |
302 thread->clear_pending_exception(); | |
303 } | |
304 Handle msg; | |
305 if (to_utf8_safe == safe_to_utf8) { | |
306 // Make a java UTF8 string. | |
307 msg = java_lang_String::create_from_str(message, thread); | |
308 } else { | |
309 // Make a java string keeping the encoding scheme of the original string. | |
310 msg = java_lang_String::create_from_platform_dependent_str(message, thread); | |
311 } | |
312 if (thread->has_pending_exception()) { | |
313 Handle exception(thread, thread->pending_exception()); | |
314 thread->clear_pending_exception(); | |
315 return exception; | |
316 } | |
317 if (incoming_exception.not_null()) { | |
318 return incoming_exception; | |
319 } | |
320 args.push_oop(msg); | |
321 signature = vmSymbolHandles::string_void_signature(); | |
322 } | |
323 return new_exception(thread, h_name, signature, &args, h_cause, h_loader, h_protection_domain); | |
324 } | |
325 | |
326 // Another convenience method that creates handles for null class loaders and | |
327 // protection domains and null causes. | |
328 // If the last parameter 'to_utf8_mode' is safe_to_utf8, | |
329 // it means we can safely ignore the encoding scheme of the message string and | |
330 // convert it directly to a java UTF8 string. Otherwise, we need to take the | |
331 // encoding scheme of the string into account. One thing we should do at some | |
332 // point is to push this flag down to class java_lang_String since other | |
333 // classes may need similar functionalities. | |
334 Handle Exceptions::new_exception(Thread* thread, | |
335 symbolOop name, | |
336 const char* message, | |
337 ExceptionMsgToUtf8Mode to_utf8_safe) { | |
338 | |
339 symbolHandle h_name(thread, name); | |
340 Handle h_loader(thread, NULL); | |
341 Handle h_prot(thread, NULL); | |
342 Handle h_cause(thread, NULL); | |
343 return Exceptions::new_exception(thread, h_name, message, h_cause, h_loader, | |
344 h_prot, to_utf8_safe); | |
345 } | |
346 | |
347 // Implementation of ExceptionMark | |
348 | |
349 ExceptionMark::ExceptionMark(Thread*& thread) { | |
350 thread = Thread::current(); | |
351 _thread = thread; | |
352 if (_thread->has_pending_exception()) { | |
353 oop exception = _thread->pending_exception(); | |
354 _thread->clear_pending_exception(); // Needed to avoid infinite recursion | |
355 exception->print(); | |
356 fatal("ExceptionMark constructor expects no pending exceptions"); | |
357 } | |
358 } | |
359 | |
360 | |
361 ExceptionMark::~ExceptionMark() { | |
362 if (_thread->has_pending_exception()) { | |
363 Handle exception(_thread, _thread->pending_exception()); | |
364 _thread->clear_pending_exception(); // Needed to avoid infinite recursion | |
365 if (is_init_completed()) { | |
366 exception->print(); | |
367 fatal("ExceptionMark destructor expects no pending exceptions"); | |
368 } else { | |
369 vm_exit_during_initialization(exception); | |
370 } | |
371 } | |
372 } | |
373 | |
374 // ---------------------------------------------------------------------------------------- | |
375 | |
376 #ifndef PRODUCT | |
377 // caller frees value_string if necessary | |
378 void Exceptions::debug_check_abort(const char *value_string) { | |
379 if (AbortVMOnException != NULL && value_string != NULL && | |
380 strstr(value_string, AbortVMOnException)) { | |
381 fatal1("Saw %s, aborting", value_string); | |
382 } | |
383 } | |
384 | |
385 void Exceptions::debug_check_abort(Handle exception) { | |
386 if (AbortVMOnException != NULL) { | |
387 ResourceMark rm; | |
388 debug_check_abort(instanceKlass::cast(exception()->klass())->external_name()); | |
389 } | |
390 } | |
391 #endif |