Mon, 03 Jun 2013 14:28:37 -0700
8014052: JSR292: assert(end_offset == next_offset) failed: matched ending
Summary: A call to the finalize_operands_merge() must be unconditional
Reviewed-by: kvn, twisti
Contributed-by: serguei.spitsyn@oracle.com
1 /*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
27 #include "memory/universe.hpp"
28 #include "oops/oop.inline.hpp"
30 #include "classfile/symbolTable.hpp"
31 #include "classfile/classLoaderData.hpp"
33 #include "prims/whitebox.hpp"
34 #include "prims/wbtestmethods/parserTests.hpp"
36 #include "runtime/interfaceSupport.hpp"
37 #include "runtime/os.hpp"
38 #include "utilities/debug.hpp"
39 #include "utilities/macros.hpp"
40 #include "utilities/exceptions.hpp"
42 #if INCLUDE_ALL_GCS
43 #include "gc_implementation/g1/concurrentMark.hpp"
44 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
45 #include "gc_implementation/g1/heapRegionRemSet.hpp"
46 #endif // INCLUDE_ALL_GCS
48 #ifdef INCLUDE_NMT
49 #include "services/memTracker.hpp"
50 #endif // INCLUDE_NMT
52 #include "compiler/compileBroker.hpp"
53 #include "runtime/compilationPolicy.hpp"
55 bool WhiteBox::_used = false;
57 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
58 return (jlong)(void*)JNIHandles::resolve(obj);
59 WB_END
61 WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
62 return heapOopSize;
63 WB_END
66 class WBIsKlassAliveClosure : public KlassClosure {
67 Symbol* _name;
68 bool _found;
69 public:
70 WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
72 void do_klass(Klass* k) {
73 if (_found) return;
74 Symbol* ksym = k->name();
75 if (ksym->fast_compare(_name) == 0) {
76 _found = true;
77 }
78 }
80 bool found() const {
81 return _found;
82 }
83 };
85 WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
86 Handle h_name = JNIHandles::resolve(name);
87 if (h_name.is_null()) return false;
88 Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
89 TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
91 WBIsKlassAliveClosure closure(sym);
92 ClassLoaderDataGraph::classes_do(&closure);
94 return closure.found();
95 WB_END
97 WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
98 CollectorPolicy * p = Universe::heap()->collector_policy();
99 gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
100 SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Min alignment "SIZE_FORMAT" Max alignment "SIZE_FORMAT,
101 p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
102 p->min_alignment(), p->max_alignment());
103 }
104 WB_END
106 #if INCLUDE_ALL_GCS
107 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
108 G1CollectedHeap* g1 = G1CollectedHeap::heap();
109 oop result = JNIHandles::resolve(obj);
110 const HeapRegion* hr = g1->heap_region_containing(result);
111 return hr->isHumongous();
112 WB_END
114 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
115 G1CollectedHeap* g1 = G1CollectedHeap::heap();
116 size_t nr = g1->free_regions();
117 return (jlong)nr;
118 WB_END
120 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
121 G1CollectedHeap* g1 = G1CollectedHeap::heap();
122 ConcurrentMark* cm = g1->concurrent_mark();
123 return cm->concurrent_marking_in_progress();
124 WB_END
126 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
127 return (jint)HeapRegion::GrainBytes;
128 WB_END
129 #endif // INCLUDE_ALL_GCS
131 #ifdef INCLUDE_NMT
132 // Alloc memory using the test memory type so that we can use that to see if
133 // NMT picks it up correctly
134 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
135 jlong addr = 0;
137 if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
138 addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
139 }
141 return addr;
142 WB_END
144 // Free the memory allocated by NMTAllocTest
145 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
146 os::free((void*)(uintptr_t)mem, mtTest);
147 WB_END
149 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
150 jlong addr = 0;
152 if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
153 addr = (jlong)(uintptr_t)os::reserve_memory(size);
154 MemTracker::record_virtual_memory_type((address)addr, mtTest);
155 }
157 return addr;
158 WB_END
161 WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
162 os::commit_memory((char *)(uintptr_t)addr, size);
163 MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
164 WB_END
166 WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
167 os::uncommit_memory((char *)(uintptr_t)addr, size);
168 WB_END
170 WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
171 os::release_memory((char *)(uintptr_t)addr, size);
172 WB_END
174 // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
175 WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env))
177 if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
178 return false;
179 }
181 return MemTracker::wbtest_wait_for_data_merge();
182 WB_END
184 #endif // INCLUDE_NMT
186 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
187 assert(method != NULL, "method should not be null");
188 ThreadToNativeFromVM ttn(thread);
189 return env->FromReflectedMethod(method);
190 }
192 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
193 MutexLockerEx mu(Compile_lock);
194 CodeCache::mark_all_nmethods_for_deoptimization();
195 VM_Deoptimize op;
196 VMThread::execute(&op);
197 WB_END
199 WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method))
200 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
201 MutexLockerEx mu(Compile_lock);
202 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
203 int result = 0;
204 nmethod* code = mh->code();
205 if (code != NULL) {
206 code->mark_for_deoptimization();
207 ++result;
208 }
209 result += CodeCache::mark_for_deoptimization(mh());
210 if (result > 0) {
211 VM_Deoptimize op;
212 VMThread::execute(&op);
213 }
214 return result;
215 WB_END
217 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method))
218 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
219 MutexLockerEx mu(Compile_lock);
220 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
221 nmethod* code = mh->code();
222 if (code == NULL) {
223 return JNI_FALSE;
224 }
225 return (code->is_alive() && !code->is_marked_for_deoptimization());
226 WB_END
228 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
229 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
230 MutexLockerEx mu(Compile_lock);
231 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
232 return CompilationPolicy::can_be_compiled(mh, comp_level);
233 WB_END
235 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
236 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
237 MutexLockerEx mu(Compile_lock);
238 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
239 return mh->queued_for_compilation();
240 WB_END
242 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method))
243 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
244 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
245 nmethod* code = mh->code();
246 return (code != NULL ? code->comp_level() : CompLevel_none);
247 WB_END
250 WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
251 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
252 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
253 mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
254 WB_END
256 WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
257 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
258 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
259 bool result = mh->dont_inline();
260 mh->set_dont_inline(value == JNI_TRUE);
261 return result;
262 WB_END
264 WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o))
265 return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
266 CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
267 WB_END
270 WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
271 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
272 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
273 bool result = mh->force_inline();
274 mh->set_force_inline(value == JNI_TRUE);
275 return result;
276 WB_END
278 WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level))
279 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
280 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
281 nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
282 MutexLockerEx mu(Compile_lock);
283 return (mh->queued_for_compilation() || nm != NULL);
284 WB_END
286 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
287 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
288 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
289 MutexLockerEx mu(Compile_lock);
290 MethodData* mdo = mh->method_data();
291 MethodCounters* mcs = mh->method_counters();
293 if (mdo != NULL) {
294 mdo->init();
295 ResourceMark rm;
296 int arg_count = mdo->method()->size_of_parameters();
297 for (int i = 0; i < arg_count; i++) {
298 mdo->set_arg_modified(i, 0);
299 }
300 }
302 mh->clear_not_c1_compilable();
303 mh->clear_not_c2_compilable();
304 mh->clear_not_c2_osr_compilable();
305 NOT_PRODUCT(mh->set_compiled_invocation_count(0));
306 if (mcs != NULL) {
307 mcs->backedge_counter()->init();
308 mcs->invocation_counter()->init();
309 mcs->set_interpreter_invocation_count(0);
310 mcs->set_interpreter_throwout_count(0);
312 #ifdef TIERED
313 mcs->set_rate(0.0F);
314 mh->set_prev_event_count(0, THREAD);
315 mh->set_prev_time(0, THREAD);
316 #endif
317 }
318 WB_END
320 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
321 ResourceMark rm(THREAD);
322 int len;
323 jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
324 return (StringTable::lookup(name, len) != NULL);
325 WB_END
328 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
329 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
330 Universe::heap()->collect(GCCause::_last_ditch_collection);
331 WB_END
334 WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
335 // static+volatile in order to force the read to happen
336 // (not be eliminated by the compiler)
337 static char c;
338 static volatile char* p;
340 p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
341 if (p == NULL) {
342 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
343 }
345 c = *p;
346 WB_END
348 //Some convenience methods to deal with objects from java
349 int WhiteBox::offset_for_field(const char* field_name, oop object,
350 Symbol* signature_symbol) {
351 assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
352 Thread* THREAD = Thread::current();
354 //Get the class of our object
355 Klass* arg_klass = object->klass();
356 //Turn it into an instance-klass
357 InstanceKlass* ik = InstanceKlass::cast(arg_klass);
359 //Create symbols to look for in the class
360 TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
361 THREAD);
363 //To be filled in with an offset of the field we're looking for
364 fieldDescriptor fd;
366 Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
367 if (res == NULL) {
368 tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
369 name_symbol->as_C_string());
370 fatal("Invalid layout of preloaded class");
371 }
373 //fetch the field at the offset we've found
374 int dest_offset = fd.offset();
376 return dest_offset;
377 }
380 const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
381 int offset = offset_for_field(field_name, object,
382 vmSymbols::string_signature());
383 oop string = object->obj_field(offset);
384 if (string == NULL) {
385 return NULL;
386 }
387 const char* ret = java_lang_String::as_utf8_string(string);
388 return ret;
389 }
391 bool WhiteBox::lookup_bool(const char* field_name, oop object) {
392 int offset =
393 offset_for_field(field_name, object, vmSymbols::bool_signature());
394 bool ret = (object->bool_field(offset) == JNI_TRUE);
395 return ret;
396 }
399 #define CC (char*)
401 static JNINativeMethod methods[] = {
402 {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
403 {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
404 {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
405 {CC"parseCommandLine",
406 CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
407 (void*) &WB_ParseCommandLine
408 },
409 {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
410 #if INCLUDE_ALL_GCS
411 {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
412 {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
413 {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions },
414 {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize },
415 #endif // INCLUDE_ALL_GCS
416 #ifdef INCLUDE_NMT
417 {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
418 {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree },
419 {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory },
420 {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
421 {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
422 {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
423 {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge},
424 #endif // INCLUDE_NMT
425 {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
426 {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;)I",
427 (void*)&WB_DeoptimizeMethod },
428 {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;)Z",
429 (void*)&WB_IsMethodCompiled },
430 {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;I)Z",
431 (void*)&WB_IsMethodCompilable},
432 {CC"isMethodQueuedForCompilation",
433 CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
434 {CC"makeMethodNotCompilable",
435 CC"(Ljava/lang/reflect/Executable;I)V", (void*)&WB_MakeMethodNotCompilable},
436 {CC"testSetDontInlineMethod",
437 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
438 {CC"getMethodCompilationLevel",
439 CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodCompilationLevel},
440 {CC"getCompileQueuesSize",
441 CC"()I", (void*)&WB_GetCompileQueuesSize},
442 {CC"testSetForceInlineMethod",
443 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod},
444 {CC"enqueueMethodForCompilation",
445 CC"(Ljava/lang/reflect/Executable;I)Z", (void*)&WB_EnqueueMethodForCompilation},
446 {CC"clearMethodState",
447 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
448 {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
449 {CC"fullGC", CC"()V", (void*)&WB_FullGC },
451 {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory },
452 };
454 #undef CC
456 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
457 {
458 if (WhiteBoxAPI) {
459 // Make sure that wbclass is loaded by the null classloader
460 instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
461 Handle loader(ikh->class_loader());
462 if (loader.is_null()) {
463 ResourceMark rm;
464 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
465 bool result = true;
466 // one by one registration natives for exception catching
467 jclass exceptionKlass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
468 for (int i = 0, n = sizeof(methods) / sizeof(methods[0]); i < n; ++i) {
469 if (env->RegisterNatives(wbclass, methods + i, 1) != 0) {
470 result = false;
471 if (env->ExceptionCheck() && env->IsInstanceOf(env->ExceptionOccurred(), exceptionKlass)) {
472 // j.l.NoSuchMethodError is thrown when a method can't be found or a method is not native
473 // ignoring the exception
474 tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s", methods[i].name, methods[i].signature);
475 env->ExceptionClear();
476 } else {
477 // register is failed w/o exception or w/ unexpected exception
478 tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered", methods[i].name, methods[i].signature);
479 env->UnregisterNatives(wbclass);
480 break;
481 }
482 }
483 }
485 if (result) {
486 WhiteBox::set_used();
487 }
488 }
489 }
490 }
491 JVM_END