提交 b0aa0541 编写于 作者: P poonam

Merge

...@@ -648,3 +648,5 @@ c26d09f1065cd26bd8b926efc5d3938b71e09eb5 jdk8u60-b17 ...@@ -648,3 +648,5 @@ c26d09f1065cd26bd8b926efc5d3938b71e09eb5 jdk8u60-b17
624f4cc05e7e95dd2103f343c54d7bdea6a81919 hs25.60-b18 624f4cc05e7e95dd2103f343c54d7bdea6a81919 hs25.60-b18
3fa5c654c143fe309e5ddda92adc5fb132365bcf jdk8u60-b18 3fa5c654c143fe309e5ddda92adc5fb132365bcf jdk8u60-b18
b852350a2bc6d5f43006e2be53fb74d148290708 hs25.60-b19 b852350a2bc6d5f43006e2be53fb74d148290708 hs25.60-b19
bd9221771f6e34e63b3b340ffcf9906ccf882dae jdk8u60-b19
e01a710549a962cee94728271248a7d89fb56c49 hs25.60-b20
...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015 ...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2015
HS_MAJOR_VER=25 HS_MAJOR_VER=25
HS_MINOR_VER=60 HS_MINOR_VER=60
HS_BUILD_NUMBER=20 HS_BUILD_NUMBER=21
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=8 JDK_MINOR_VER=8
......
# #
# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -229,7 +229,7 @@ checks: check_os_version check_j2se_version ...@@ -229,7 +229,7 @@ checks: check_os_version check_j2se_version
# Solaris 2.5.1, 2.6). # Solaris 2.5.1, 2.6).
# Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok. # Disable this check by setting DISABLE_HOTSPOT_OS_VERSION_CHECK=ok.
SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 3% SUPPORTED_OS_VERSION = 2.4% 2.5% 2.6% 3% 4%
OS_VERSION := $(shell uname -r) OS_VERSION := $(shell uname -r)
EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION)) EMPTY_IF_NOT_SUPPORTED = $(filter $(SUPPORTED_OS_VERSION),$(OS_VERSION))
......
...@@ -1592,6 +1592,26 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl ...@@ -1592,6 +1592,26 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl
result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK); result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
} }
static void wrap_invokedynamic_exception(TRAPS) {
if (HAS_PENDING_EXCEPTION) {
if (TraceMethodHandles) {
tty->print_cr("invokedynamic throws BSME for " INTPTR_FORMAT, p2i((void *)PENDING_EXCEPTION));
PENDING_EXCEPTION->print();
}
if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
// throw these guys, since they are already wrapped
return;
}
if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
// intercept only LinkageErrors which might have failed to wrap
return;
}
// See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
Handle nested_exception(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
}
}
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
assert(EnableInvokeDynamic, ""); assert(EnableInvokeDynamic, "");
...@@ -1607,7 +1627,8 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po ...@@ -1607,7 +1627,8 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po
ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index); ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index);
if (cpce->is_f1_null()) { if (cpce->is_f1_null()) {
int pool_index = cpce->constant_pool_index(); int pool_index = cpce->constant_pool_index();
oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, CHECK); oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, THREAD);
wrap_invokedynamic_exception(CHECK);
assert(bsm_info != NULL, ""); assert(bsm_info != NULL, "");
// FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic. // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
bootstrap_specifier = Handle(THREAD, bsm_info); bootstrap_specifier = Handle(THREAD, bsm_info);
...@@ -1616,7 +1637,8 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po ...@@ -1616,7 +1637,8 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po
methodHandle method( THREAD, cpce->f1_as_method()); methodHandle method( THREAD, cpce->f1_as_method());
Handle appendix( THREAD, cpce->appendix_if_resolved(pool)); Handle appendix( THREAD, cpce->appendix_if_resolved(pool));
Handle method_type(THREAD, cpce->method_type_if_resolved(pool)); Handle method_type(THREAD, cpce->method_type_if_resolved(pool));
result.set_handle(method, appendix, method_type, CHECK); result.set_handle(method, appendix, method_type, THREAD);
wrap_invokedynamic_exception(CHECK);
return; return;
} }
...@@ -1647,25 +1669,9 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result, ...@@ -1647,25 +1669,9 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result,
&resolved_appendix, &resolved_appendix,
&resolved_method_type, &resolved_method_type,
THREAD); THREAD);
if (HAS_PENDING_EXCEPTION) { wrap_invokedynamic_exception(CHECK);
if (TraceMethodHandles) { result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
tty->print_cr("invokedynamic throws BSME for " INTPTR_FORMAT, p2i((void *)PENDING_EXCEPTION)); wrap_invokedynamic_exception(CHECK);
PENDING_EXCEPTION->print();
}
if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
// throw these guys, since they are already wrapped
return;
}
if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
// intercept only LinkageErrors which might have failed to wrap
return;
}
// See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
Handle nested_exception(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
}
result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
} }
//------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------
......
...@@ -99,9 +99,7 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size, ...@@ -99,9 +99,7 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size,
// Reserve and initialize space for _memory. // Reserve and initialize space for _memory.
size_t page_size = os::vm_page_size(); size_t page_size = os::vm_page_size();
if (os::can_execute_large_page_memory()) { if (os::can_execute_large_page_memory()) {
const size_t min_pages = 8; page_size = os::page_size_for_region_unaligned(reserved_size, 8);
page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages),
os::page_size_for_region_aligned(reserved_size, min_pages));
} }
const size_t granularity = os::vm_allocation_granularity(); const size_t granularity = os::vm_allocation_granularity();
......
...@@ -622,7 +622,8 @@ class SpaceManager : public CHeapObj<mtClass> { ...@@ -622,7 +622,8 @@ class SpaceManager : public CHeapObj<mtClass> {
Metachunk* _chunks_in_use[NumberOfInUseLists]; Metachunk* _chunks_in_use[NumberOfInUseLists];
Metachunk* _current_chunk; Metachunk* _current_chunk;
// Maximum number of small chunks to allocate to a SpaceManager // Number of small chunks to allocate to a manager
// If class space manager, small chunks are unlimited
static uint const _small_chunk_limit; static uint const _small_chunk_limit;
// Sum of all space in allocated chunks // Sum of all space in allocated chunks
...@@ -736,8 +737,6 @@ class SpaceManager : public CHeapObj<mtClass> { ...@@ -736,8 +737,6 @@ class SpaceManager : public CHeapObj<mtClass> {
// Block allocation and deallocation. // Block allocation and deallocation.
// Allocates a block from the current chunk // Allocates a block from the current chunk
MetaWord* allocate(size_t word_size); MetaWord* allocate(size_t word_size);
// Allocates a block from a small chunk
MetaWord* get_small_chunk_and_allocate(size_t word_size);
// Helper for allocations // Helper for allocations
MetaWord* allocate_work(size_t word_size); MetaWord* allocate_work(size_t word_size);
...@@ -2032,8 +2031,9 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { ...@@ -2032,8 +2031,9 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const {
size_t SpaceManager::calc_chunk_size(size_t word_size) { size_t SpaceManager::calc_chunk_size(size_t word_size) {
// Decide between a small chunk and a medium chunk. Up to // Decide between a small chunk and a medium chunk. Up to
// _small_chunk_limit small chunks can be allocated. // _small_chunk_limit small chunks can be allocated but
// After that a medium chunk is preferred. // once a medium chunk has been allocated, no more small
// chunks will be allocated.
size_t chunk_word_size; size_t chunk_word_size;
if (chunks_in_use(MediumIndex) == NULL && if (chunks_in_use(MediumIndex) == NULL &&
sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) {
...@@ -2101,7 +2101,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) { ...@@ -2101,7 +2101,7 @@ MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
word_size, words_used, words_left); word_size, words_used, words_left);
} }
// Get another chunk // Get another chunk out of the virtual space
size_t grow_chunks_by_words = calc_chunk_size(word_size); size_t grow_chunks_by_words = calc_chunk_size(word_size);
Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words); Metachunk* next = get_new_chunk(word_size, grow_chunks_by_words);
...@@ -2432,43 +2432,6 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size, ...@@ -2432,43 +2432,6 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size,
return next; return next;
} }
/*
* The policy is to allocate up to _small_chunk_limit small chunks
* after which only medium chunks are allocated. This is done to
* reduce fragmentation. In some cases, this can result in a lot
* of small chunks being allocated to the point where it's not
* possible to expand. If this happens, there may be no medium chunks
* available and OOME would be thrown. Instead of doing that,
* if the allocation request size fits in a small chunk, an attempt
* will be made to allocate a small chunk.
*/
MetaWord* SpaceManager::get_small_chunk_and_allocate(size_t word_size) {
if (word_size + Metachunk::overhead() > small_chunk_size()) {
return NULL;
}
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
MutexLockerEx cl1(expand_lock(), Mutex::_no_safepoint_check_flag);
Metachunk* chunk = chunk_manager()->chunk_freelist_allocate(small_chunk_size());
MetaWord* mem = NULL;
if (chunk != NULL) {
// Add chunk to the in-use chunk list and do an allocation from it.
// Add to this manager's list of chunks in use.
add_chunk(chunk, false);
mem = chunk->allocate(word_size);
inc_used_metrics(word_size);
// Track metaspace memory usage statistic.
track_metaspace_memory_usage();
}
return mem;
}
MetaWord* SpaceManager::allocate(size_t word_size) { MetaWord* SpaceManager::allocate(size_t word_size) {
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
...@@ -3547,20 +3510,9 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, ...@@ -3547,20 +3510,9 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
} }
} }
if (result == NULL) {
SpaceManager* sm;
if (is_class_space_allocation(mdtype)) {
sm = loader_data->metaspace_non_null()->class_vsm();
} else {
sm = loader_data->metaspace_non_null()->vsm();
}
result = sm->get_small_chunk_and_allocate(word_size);
if (result == NULL) { if (result == NULL) {
report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL); report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL);
} }
}
// Zero initialize. // Zero initialize.
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0); Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
......
...@@ -1821,7 +1821,10 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { ...@@ -1821,7 +1821,10 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
// Find the pre-loop limit; we will expand it's iterations to // Find the pre-loop limit; we will expand it's iterations to
// not ever trip low tests. // not ever trip low tests.
Node *p_f = iffm->in(0); Node *p_f = iffm->in(0);
assert(p_f->Opcode() == Op_IfFalse, ""); // pre loop may have been optimized out
if (p_f->Opcode() != Op_IfFalse) {
return;
}
CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd();
assert(pre_end->loopnode()->is_pre_loop(), ""); assert(pre_end->loopnode()->is_pre_loop(), "");
Node *pre_opaq1 = pre_end->limit(); Node *pre_opaq1 = pre_end->limit();
......
...@@ -1180,11 +1180,11 @@ static int normalize_int_widen( jint lo, jint hi, int w ) { ...@@ -1180,11 +1180,11 @@ static int normalize_int_widen( jint lo, jint hi, int w ) {
// Certain normalizations keep us sane when comparing types. // Certain normalizations keep us sane when comparing types.
// The 'SMALLINT' covers constants and also CC and its relatives. // The 'SMALLINT' covers constants and also CC and its relatives.
if (lo <= hi) { if (lo <= hi) {
if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin; if (((juint)hi - lo) <= SMALLINT) w = Type::WidenMin;
if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT if (((juint)hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT
} else { } else {
if ((juint)(lo - hi) <= SMALLINT) w = Type::WidenMin; if (((juint)lo - hi) <= SMALLINT) w = Type::WidenMin;
if ((juint)(lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT if (((juint)lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT
} }
return w; return w;
} }
...@@ -1438,11 +1438,11 @@ static int normalize_long_widen( jlong lo, jlong hi, int w ) { ...@@ -1438,11 +1438,11 @@ static int normalize_long_widen( jlong lo, jlong hi, int w ) {
// Certain normalizations keep us sane when comparing types. // Certain normalizations keep us sane when comparing types.
// The 'SMALLINT' covers constants. // The 'SMALLINT' covers constants.
if (lo <= hi) { if (lo <= hi) {
if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin; if (((julong)hi - lo) <= SMALLINT) w = Type::WidenMin;
if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG if (((julong)hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG
} else { } else {
if ((julong)(lo - hi) <= SMALLINT) w = Type::WidenMin; if (((julong)lo - hi) <= SMALLINT) w = Type::WidenMin;
if ((julong)(lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG if (((julong)lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG
} }
return w; return w;
} }
......
...@@ -1325,13 +1325,14 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive ...@@ -1325,13 +1325,14 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
Method* m = Method::resolve_jmethod_id(method_id); Method* m = Method::resolve_jmethod_id(method_id);
number_of_parameters = m->size_of_parameters(); number_of_parameters = m->size_of_parameters();
Klass* holder = m->method_holder(); Klass* holder = m->method_holder();
if (!(holder)->is_interface()) { if (call_type != JNI_VIRTUAL) {
selected_method = m;
} else if (!m->has_itable_index()) {
// non-interface call -- for that little speed boost, don't handlize // non-interface call -- for that little speed boost, don't handlize
debug_only(No_Safepoint_Verifier nosafepoint;) debug_only(No_Safepoint_Verifier nosafepoint;)
if (call_type == JNI_VIRTUAL) {
// jni_GetMethodID makes sure class is linked and initialized // jni_GetMethodID makes sure class is linked and initialized
// so m should have a valid vtable index. // so m should have a valid vtable index.
assert(!m->has_itable_index(), ""); assert(m->valid_vtable_index(), "no valid vtable index");
int vtbl_index = m->vtable_index(); int vtbl_index = m->vtable_index();
if (vtbl_index != Method::nonvirtual_vtable_index) { if (vtbl_index != Method::nonvirtual_vtable_index) {
Klass* k = h_recv->klass(); Klass* k = h_recv->klass();
...@@ -1343,21 +1344,13 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive ...@@ -1343,21 +1344,13 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
// final method // final method
selected_method = m; selected_method = m;
} }
} else {
// JNI_NONVIRTUAL call
selected_method = m;
}
} else { } else {
// interface call // interface call
KlassHandle h_holder(THREAD, holder); KlassHandle h_holder(THREAD, holder);
if (call_type == JNI_VIRTUAL) {
int itbl_index = m->itable_index(); int itbl_index = m->itable_index();
Klass* k = h_recv->klass(); Klass* k = h_recv->klass();
selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK);
} else {
selected_method = m;
}
} }
} }
......
...@@ -185,19 +185,22 @@ void InterfaceSupport::zap_dead_locals_old() { ...@@ -185,19 +185,22 @@ void InterfaceSupport::zap_dead_locals_old() {
# endif # endif
// invocation counter for InterfaceSupport::deoptimizeAll/zombieAll functions
int deoptimizeAllCounter = 0; int deoptimizeAllCounter = 0;
int zombieAllCounter = 0; int zombieAllCounter = 0;
void InterfaceSupport::zombieAll() { void InterfaceSupport::zombieAll() {
if (is_init_completed() && zombieAllCounter > ZombieALotInterval) { // This method is called by all threads when a thread make
// transition to VM state (for example, runtime calls).
// Divide number of calls by number of threads to avoid
// dependence of ZombieAll events frequency on number of threads.
int value = zombieAllCounter / Threads::number_of_threads();
if (is_init_completed() && value > ZombieALotInterval) {
zombieAllCounter = 0; zombieAllCounter = 0;
VM_ZombieAll op; VM_ZombieAll op;
VMThread::execute(&op); VMThread::execute(&op);
} else {
zombieAllCounter++;
} }
zombieAllCounter++;
} }
void InterfaceSupport::unlinkSymbols() { void InterfaceSupport::unlinkSymbols() {
...@@ -206,12 +209,17 @@ void InterfaceSupport::unlinkSymbols() { ...@@ -206,12 +209,17 @@ void InterfaceSupport::unlinkSymbols() {
} }
void InterfaceSupport::deoptimizeAll() { void InterfaceSupport::deoptimizeAll() {
if (is_init_completed() ) { // This method is called by all threads when a thread make
if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) { // transition to VM state (for example, runtime calls).
// Divide number of calls by number of threads to avoid
// dependence of DeoptimizeAll events frequency on number of threads.
int value = deoptimizeAllCounter / Threads::number_of_threads();
if (is_init_completed()) {
if (DeoptimizeALot && value > DeoptimizeALotInterval) {
deoptimizeAllCounter = 0; deoptimizeAllCounter = 0;
VM_DeoptimizeAll op; VM_DeoptimizeAll op;
VMThread::execute(&op); VMThread::execute(&op);
} else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) { } else if (DeoptimizeRandom && (value & 0x1F) == (os::random() & 0x1F)) {
VM_DeoptimizeAll op; VM_DeoptimizeAll op;
VMThread::execute(&op); VMThread::execute(&op);
} }
......
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8051045
* @summary Test that exceptions from invokedynamic are wrapped in BootstrapMethodError
* @modules java.base/jdk.internal.org.objectweb.asm
* @run main BootstrapMethodErrorTest
*/
import java.lang.reflect.Method;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Handle;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
public class BootstrapMethodErrorTest extends ClassLoader implements Opcodes {
@Override
public Class findClass(String name) throws ClassNotFoundException {
byte[] b;
try {
b = loadClassData(name);
} catch (Throwable th) {
throw new ClassNotFoundException("Loading error", th);
}
return defineClass(name, b, 0, b.length);
}
private byte[] loadClassData(String name) throws Exception {
ClassWriter cw = new ClassWriter(0);
MethodVisitor mv;
if (name.equals("C")) {
cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
{
mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, "m", "()V", null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
} else if (name.equals("Exec")) {
cw.visit(52, ACC_SUPER | ACC_PUBLIC, "Exec", null, "java/lang/Object", null);
{
mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invokeRef", "()V", null, null);
mv.visitCode();
Handle h = new Handle(H_INVOKESTATIC, "C", "m", "()V");
mv.visitInvokeDynamicInsn("C", "()V", h);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
cw.visitEnd();
return cw.toByteArray();
}
return null;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException {
new BootstrapMethodErrorTest().test();
}
public void test() throws ClassNotFoundException, IllegalAccessException, NoSuchMethodException {
Class.forName("C", true, this);
Class<?> exec = Class.forName("Exec", true, this);
try {
exec.getMethod("invokeRef").invoke(null);
} catch (Throwable e) {
Throwable c = e.getCause();
if (c == null) {
throw new RuntimeException(
"Expected BootstrapMethodError wrapped in an InvocationTargetException but it wasn't wrapped", e);
} else if (c instanceof BootstrapMethodError) {
// Only way to pass test, all else should throw
return;
} else {
throw new RuntimeException(
"Expected BootstrapMethodError but got another Error: "
+ c.getClass().getName(),
c);
}
}
throw new RuntimeException("Expected BootstrapMethodError but no Error at all was thrown");
}
}
...@@ -191,6 +191,11 @@ if [ $? = 0 ] ...@@ -191,6 +191,11 @@ if [ $? = 0 ]
then then
VM_CPU="ia64" VM_CPU="ia64"
fi fi
grep "aarch64" vm_version.out > ${NULL}
if [ $? = 0 ]
then
VM_CPU="aarch64"
fi
export VM_TYPE VM_BITS VM_OS VM_CPU export VM_TYPE VM_BITS VM_OS VM_CPU
echo "VM_TYPE=${VM_TYPE}" echo "VM_TYPE=${VM_TYPE}"
echo "VM_BITS=${VM_BITS}" echo "VM_BITS=${VM_BITS}"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册