Sun, 24 Apr 2016 20:50:03 +0100
Merge
src/share/vm/opto/parse1.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/opto/type.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/os/posix/vm/os_posix.cpp Mon Apr 18 15:28:31 2016 -0700 1.2 +++ b/src/os/posix/vm/os_posix.cpp Sun Apr 24 20:50:03 2016 +0100 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 -* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 +* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -678,6 +678,21 @@ 1.11 #if defined(IA64) && !defined(AIX) 1.12 { SIGSEGV, SEGV_PSTKOVF, "SEGV_PSTKOVF", "Paragraph stack overflow" }, 1.13 #endif 1.14 +#if defined(__sparc) && defined(SOLARIS) 1.15 +// define Solaris Sparc M7 ADI SEGV signals 1.16 +#if !defined(SEGV_ACCADI) 1.17 +#define SEGV_ACCADI 3 1.18 +#endif 1.19 + { SIGSEGV, SEGV_ACCADI, "SEGV_ACCADI", "ADI not enabled for mapped object." }, 1.20 +#if !defined(SEGV_ACCDERR) 1.21 +#define SEGV_ACCDERR 4 1.22 +#endif 1.23 + { SIGSEGV, SEGV_ACCDERR, "SEGV_ACCDERR", "ADI disrupting exception." }, 1.24 +#if !defined(SEGV_ACCPERR) 1.25 +#define SEGV_ACCPERR 5 1.26 +#endif 1.27 + { SIGSEGV, SEGV_ACCPERR, "SEGV_ACCPERR", "ADI precise exception." }, 1.28 +#endif // defined(__sparc) && defined(SOLARIS) 1.29 { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment." }, 1.30 { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Nonexistent physical address." }, 1.31 { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object-specific hardware error." },
2.1 --- a/src/os/solaris/vm/os_solaris.cpp Mon Apr 18 15:28:31 2016 -0700 2.2 +++ b/src/os/solaris/vm/os_solaris.cpp Sun Apr 24 20:50:03 2016 +0100 2.3 @@ -6248,14 +6248,7 @@ 2.4 } 2.5 2.6 size_t os::write(int fd, const void *buf, unsigned int nBytes) { 2.7 - Thread* t = ThreadLocalStorage::thread(); 2.8 - if (t->is_Java_thread()) { 2.9 - INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted); 2.10 - } else { 2.11 - size_t res; 2.12 - RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res); 2.13 - return res; 2.14 - } 2.15 + INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted); 2.16 } 2.17 2.18 int os::close(int fd) {
3.1 --- a/src/share/vm/c1/c1_Runtime1.cpp Mon Apr 18 15:28:31 2016 -0700 3.2 +++ b/src/share/vm/c1/c1_Runtime1.cpp Sun Apr 24 20:50:03 2016 +0100 3.3 @@ -312,6 +312,7 @@ 3.4 NOT_PRODUCT(_new_instance_slowcase_cnt++;) 3.5 3.6 assert(klass->is_klass(), "not a class"); 3.7 + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive 3.8 instanceKlassHandle h(thread, klass); 3.9 h->check_valid_for_instantiation(true, CHECK); 3.10 // make sure klass is initialized 3.11 @@ -347,6 +348,7 @@ 3.12 // anymore after new_objArray() and no GC can happen before. 3.13 // (This may have to change if this code changes!) 3.14 assert(array_klass->is_klass(), "not a class"); 3.15 + Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive 3.16 Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); 3.17 objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK); 3.18 thread->set_vm_result(obj); 3.19 @@ -363,6 +365,7 @@ 3.20 3.21 assert(klass->is_klass(), "not a class"); 3.22 assert(rank >= 1, "rank must be nonzero"); 3.23 + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive 3.24 oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); 3.25 thread->set_vm_result(obj); 3.26 JRT_END
4.1 --- a/src/share/vm/opto/c2compiler.cpp Mon Apr 18 15:28:31 2016 -0700 4.2 +++ b/src/share/vm/opto/c2compiler.cpp Sun Apr 24 20:50:03 2016 +0100 4.3 @@ -49,6 +49,9 @@ 4.4 const char* C2Compiler::retry_no_escape_analysis() { 4.5 return "retry without escape analysis"; 4.6 } 4.7 +const char* C2Compiler::retry_class_loading_during_parsing() { 4.8 + return "retry class loading during parsing"; 4.9 +} 4.10 bool C2Compiler::init_c2_runtime() { 4.11 4.12 // Check assumptions used while running ADLC 4.13 @@ -115,6 +118,10 @@ 4.14 4.15 // Check result and retry if appropriate. 4.16 if (C.failure_reason() != NULL) { 4.17 + if (C.failure_reason_is(retry_class_loading_during_parsing())) { 4.18 + env->record_failure(C.failure_reason()); 4.19 + continue; // retry 4.20 + } 4.21 if (C.failure_reason_is(retry_no_subsuming_loads())) { 4.22 assert(subsume_loads, "must make progress"); 4.23 subsume_loads = false;
5.1 --- a/src/share/vm/opto/c2compiler.hpp Mon Apr 18 15:28:31 2016 -0700 5.2 +++ b/src/share/vm/opto/c2compiler.hpp Sun Apr 24 20:50:03 2016 +0100 5.3 @@ -49,6 +49,7 @@ 5.4 // sentinel value used to trigger backtracking in compile_method(). 5.5 static const char* retry_no_subsuming_loads(); 5.6 static const char* retry_no_escape_analysis(); 5.7 + static const char* retry_class_loading_during_parsing(); 5.8 5.9 // Print compilation timers and statistics 5.10 void print_timers();
6.1 --- a/src/share/vm/opto/cfgnode.cpp Mon Apr 18 15:28:31 2016 -0700 6.2 +++ b/src/share/vm/opto/cfgnode.cpp Sun Apr 24 20:50:03 2016 +0100 6.3 @@ -973,7 +973,7 @@ 6.4 #ifdef ASSERT 6.5 // The following logic has been moved into TypeOopPtr::filter. 6.6 const Type* jt = t->join_speculative(_type); 6.7 - if( jt->empty() ) { // Emptied out??? 6.8 + if (jt->empty()) { // Emptied out??? 6.9 6.10 // Check for evil case of 't' being a class and '_type' expecting an 6.11 // interface. This can happen because the bytecodes do not contain 6.12 @@ -984,14 +984,21 @@ 6.13 // be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows 6.14 // into a Phi which "knows" it's an Interface type we'll have to 6.15 // uplift the type. 6.16 - if( !t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface() ) 6.17 - { assert(ft == _type, ""); } // Uplift to interface 6.18 - else if( !t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface() ) 6.19 - { assert(ft == _type, ""); } // Uplift to interface 6.20 - // Otherwise it's something stupid like non-overlapping int ranges 6.21 - // found on dying counted loops. 6.22 - else 6.23 - { assert(ft == Type::TOP, ""); } // Canonical empty value 6.24 + if (!t->empty() && ttip && ttip->is_loaded() && ttip->klass()->is_interface()) { 6.25 + assert(ft == _type, ""); // Uplift to interface 6.26 + } else if (!t->empty() && ttkp && ttkp->is_loaded() && ttkp->klass()->is_interface()) { 6.27 + assert(ft == _type, ""); // Uplift to interface 6.28 + } else { 6.29 + // We also have to handle 'evil cases' of interface- vs. class-arrays 6.30 + Type::get_arrays_base_elements(jt, _type, NULL, &ttip); 6.31 + if (!t->empty() && ttip != NULL && ttip->is_loaded() && ttip->klass()->is_interface()) { 6.32 + assert(ft == _type, ""); // Uplift to array of interface 6.33 + } else { 6.34 + // Otherwise it's something stupid like non-overlapping int ranges 6.35 + // found on dying counted loops. 6.36 + assert(ft == Type::TOP, ""); // Canonical empty value 6.37 + } 6.38 + } 6.39 } 6.40 6.41 else {
7.1 --- a/src/share/vm/opto/compile.cpp Mon Apr 18 15:28:31 2016 -0700 7.2 +++ b/src/share/vm/opto/compile.cpp Sun Apr 24 20:50:03 2016 +0100 7.3 @@ -791,7 +791,9 @@ 7.4 } 7.5 JVMState* jvms = build_start_state(start(), tf()); 7.6 if ((jvms = cg->generate(jvms)) == NULL) { 7.7 - record_method_not_compilable("method parse failed"); 7.8 + if (!failure_reason_is(C2Compiler::retry_class_loading_during_parsing())) { 7.9 + record_method_not_compilable("method parse failed"); 7.10 + } 7.11 return; 7.12 } 7.13 GraphKit kit(jvms);
8.1 --- a/src/share/vm/opto/parse1.cpp Mon Apr 18 15:28:31 2016 -0700 8.2 +++ b/src/share/vm/opto/parse1.cpp Sun Apr 24 20:50:03 2016 +0100 8.3 @@ -27,6 +27,7 @@ 8.4 #include "interpreter/linkResolver.hpp" 8.5 #include "oops/method.hpp" 8.6 #include "opto/addnode.hpp" 8.7 +#include "opto/c2compiler.hpp" 8.8 #include "opto/idealGraphPrinter.hpp" 8.9 #include "opto/locknode.hpp" 8.10 #include "opto/memnode.hpp" 8.11 @@ -988,7 +989,23 @@ 8.12 if (tf()->range()->cnt() > TypeFunc::Parms) { 8.13 const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); 8.14 Node* ret_phi = _gvn.transform( _exits.argument(0) ); 8.15 - assert(_exits.control()->is_top() || !_gvn.type(ret_phi)->empty(), "return value must be well defined"); 8.16 + if (!_exits.control()->is_top() && _gvn.type(ret_phi)->empty()) { 8.17 + // In case of concurrent class loading, the type we set for the 8.18 + // ret_phi in build_exits() may have been too optimistic and the 8.19 + // ret_phi may be top now. 8.20 + // Otherwise, we've encountered an error and have to mark the method as 8.21 + // not compilable. Just using an assertion instead would be dangerous 8.22 + // as this could lead to an infinite compile loop in non-debug builds. 8.23 + { 8.24 + MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag); 8.25 + if (C->env()->system_dictionary_modification_counter_changed()) { 8.26 + C->record_failure(C2Compiler::retry_class_loading_during_parsing()); 8.27 + } else { 8.28 + C->record_method_not_compilable("Can't determine return type."); 8.29 + } 8.30 + } 8.31 + return; 8.32 + } 8.33 if (ret_type->isa_int()) { 8.34 BasicType ret_bt = method()->return_type()->basic_type(); 8.35 ret_phi = mask_int_value(ret_phi, ret_bt, &_gvn); 8.36 @@ -2116,15 +2133,24 @@ 8.37 // here. 8.38 Node* phi = _exits.argument(0); 8.39 const TypeInstPtr *tr = phi->bottom_type()->isa_instptr(); 8.40 - if( tr && tr->klass()->is_loaded() && 8.41 - tr->klass()->is_interface() ) { 8.42 + if (tr && tr->klass()->is_loaded() && 8.43 + tr->klass()->is_interface()) { 8.44 const TypeInstPtr *tp = value->bottom_type()->isa_instptr(); 8.45 if (tp && tp->klass()->is_loaded() && 8.46 !tp->klass()->is_interface()) { 8.47 // sharpen the type eagerly; this eases certain assert checking 8.48 if (tp->higher_equal(TypeInstPtr::NOTNULL)) 8.49 tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr(); 8.50 - value = _gvn.transform(new (C) CheckCastPPNode(0,value,tr)); 8.51 + value = _gvn.transform(new (C) CheckCastPPNode(0, value, tr)); 8.52 + } 8.53 + } else { 8.54 + // Also handle returns of oop-arrays to an arrays-of-interface return 8.55 + const TypeInstPtr* phi_tip; 8.56 + const TypeInstPtr* val_tip; 8.57 + Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tip, &val_tip); 8.58 + if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->klass()->is_interface() && 8.59 + val_tip != NULL && val_tip->is_loaded() && !val_tip->klass()->is_interface()) { 8.60 + value = _gvn.transform(new (C) CheckCastPPNode(0, value, phi->bottom_type())); 8.61 } 8.62 } 8.63 phi->add_req(value);
9.1 --- a/src/share/vm/opto/runtime.cpp Mon Apr 18 15:28:31 2016 -0700 9.2 +++ b/src/share/vm/opto/runtime.cpp Sun Apr 24 20:50:03 2016 +0100 9.3 @@ -231,22 +231,17 @@ 9.4 9.5 // These checks are cheap to make and support reflective allocation. 9.6 int lh = klass->layout_helper(); 9.7 - if (Klass::layout_helper_needs_slow_path(lh) 9.8 - || !InstanceKlass::cast(klass)->is_initialized()) { 9.9 - KlassHandle kh(THREAD, klass); 9.10 - kh->check_valid_for_instantiation(false, THREAD); 9.11 + if (Klass::layout_helper_needs_slow_path(lh) || !InstanceKlass::cast(klass)->is_initialized()) { 9.12 + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive 9.13 + klass->check_valid_for_instantiation(false, THREAD); 9.14 if (!HAS_PENDING_EXCEPTION) { 9.15 - InstanceKlass::cast(kh())->initialize(THREAD); 9.16 - } 9.17 - if (!HAS_PENDING_EXCEPTION) { 9.18 - klass = kh(); 9.19 - } else { 9.20 - klass = NULL; 9.21 + InstanceKlass::cast(klass)->initialize(THREAD); 9.22 } 9.23 } 9.24 9.25 - if (klass != NULL) { 9.26 + if (!HAS_PENDING_EXCEPTION) { 9.27 // Scavenge and allocate an instance. 9.28 + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive 9.29 oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD); 9.30 thread->set_vm_result(result); 9.31 9.32 @@ -286,6 +281,7 @@ 9.33 // Although the oopFactory likes to work with the elem_type, 9.34 // the compiler prefers the array_type, since it must already have 9.35 // that latter value in hand for the fast path. 9.36 + Handle holder(THREAD, array_type->klass_holder()); // keep the array klass alive 9.37 Klass* elem_type = ObjArrayKlass::cast(array_type)->element_klass(); 9.38 result = oopFactory::new_objArray(elem_type, len, THREAD); 9.39 } 9.40 @@ -364,6 +360,7 @@ 9.41 jint dims[2]; 9.42 dims[0] = len1; 9.43 dims[1] = len2; 9.44 + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive 9.45 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD); 9.46 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); 9.47 thread->set_vm_result(obj); 9.48 @@ -380,6 +377,7 @@ 9.49 dims[0] = len1; 9.50 dims[1] = len2; 9.51 dims[2] = len3; 9.52 + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive 9.53 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD); 9.54 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); 9.55 thread->set_vm_result(obj); 9.56 @@ -397,6 +395,7 @@ 9.57 dims[1] = len2; 9.58 dims[2] = len3; 9.59 dims[3] = len4; 9.60 + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive 9.61 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD); 9.62 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); 9.63 thread->set_vm_result(obj); 9.64 @@ -415,6 +414,7 @@ 9.65 dims[2] = len3; 9.66 dims[3] = len4; 9.67 dims[4] = len5; 9.68 + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive 9.69 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD); 9.70 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); 9.71 thread->set_vm_result(obj); 9.72 @@ -432,6 +432,7 @@ 9.73 jint *c_dims = NEW_RESOURCE_ARRAY(jint, len); 9.74 Copy::conjoint_jints_atomic(j_dims, c_dims, len); 9.75 9.76 + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive 9.77 oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); 9.78 deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); 9.79 thread->set_vm_result(obj);
10.1 --- a/src/share/vm/opto/type.cpp Mon Apr 18 15:28:31 2016 -0700 10.2 +++ b/src/share/vm/opto/type.cpp Sun Apr 24 20:50:03 2016 +0100 10.3 @@ -149,6 +149,33 @@ 10.4 return bt; 10.5 } 10.6 10.7 +// For two instance arrays of same dimension, return the base element types. 10.8 +// Otherwise or if the arrays have different dimensions, return NULL. 10.9 +void Type::get_arrays_base_elements(const Type *a1, const Type *a2, 10.10 + const TypeInstPtr **e1, const TypeInstPtr **e2) { 10.11 + 10.12 + if (e1) *e1 = NULL; 10.13 + if (e2) *e2 = NULL; 10.14 + const TypeAryPtr* a1tap = (a1 == NULL) ? NULL : a1->isa_aryptr(); 10.15 + const TypeAryPtr* a2tap = (a2 == NULL) ? NULL : a2->isa_aryptr(); 10.16 + 10.17 + if (a1tap != NULL && a2tap != NULL) { 10.18 + // Handle multidimensional arrays 10.19 + const TypePtr* a1tp = a1tap->elem()->make_ptr(); 10.20 + const TypePtr* a2tp = a2tap->elem()->make_ptr(); 10.21 + while (a1tp && a1tp->isa_aryptr() && a2tp && a2tp->isa_aryptr()) { 10.22 + a1tap = a1tp->is_aryptr(); 10.23 + a2tap = a2tp->is_aryptr(); 10.24 + a1tp = a1tap->elem()->make_ptr(); 10.25 + a2tp = a2tap->elem()->make_ptr(); 10.26 + } 10.27 + if (a1tp && a1tp->isa_instptr() && a2tp && a2tp->isa_instptr()) { 10.28 + if (e1) *e1 = a1tp->is_instptr(); 10.29 + if (e2) *e2 = a2tp->is_instptr(); 10.30 + } 10.31 + } 10.32 +} 10.33 + 10.34 //---------------------------get_typeflow_type--------------------------------- 10.35 // Import a type produced by ciTypeFlow. 10.36 const Type* Type::get_typeflow_type(ciType* type) { 10.37 @@ -1984,7 +2011,11 @@ 10.38 bool TypeAry::interface_vs_oop(const Type *t) const { 10.39 const TypeAry* t_ary = t->is_ary(); 10.40 if (t_ary) { 10.41 - return _elem->interface_vs_oop(t_ary->_elem); 10.42 + const TypePtr* this_ptr = _elem->make_ptr(); // In case we have narrow_oops 10.43 + const TypePtr* t_ptr = t_ary->_elem->make_ptr(); 10.44 + if(this_ptr != NULL && t_ptr != NULL) { 10.45 + return this_ptr->interface_vs_oop(t_ptr); 10.46 + } 10.47 } 10.48 return false; 10.49 } 10.50 @@ -2836,8 +2867,17 @@ 10.51 // be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows 10.52 // into a Phi which "knows" it's an Interface type we'll have to 10.53 // uplift the type. 10.54 - if (!empty() && ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) 10.55 - return kills; // Uplift to interface 10.56 + if (!empty()) { 10.57 + if (ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) { 10.58 + return kills; // Uplift to interface 10.59 + } 10.60 + // Also check for evil cases of 'this' being a class array 10.61 + // and 'kills' expecting an array of interfaces. 10.62 + Type::get_arrays_base_elements(ft, kills, NULL, &ktip); 10.63 + if (ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) { 10.64 + return kills; // Uplift to array of interface 10.65 + } 10.66 + } 10.67 10.68 return Type::TOP; // Canonical empty value 10.69 }
11.1 --- a/src/share/vm/opto/type.hpp Mon Apr 18 15:28:31 2016 -0700 11.2 +++ b/src/share/vm/opto/type.hpp Sun Apr 24 20:50:03 2016 +0100 11.3 @@ -367,6 +367,11 @@ 11.4 return _const_basic_type[type]; 11.5 } 11.6 11.7 + // For two instance arrays of same dimension, return the base element types. 11.8 + // Otherwise or if the arrays have different dimensions, return NULL. 11.9 + static void get_arrays_base_elements(const Type *a1, const Type *a2, 11.10 + const TypeInstPtr **e1, const TypeInstPtr **e2); 11.11 + 11.12 // Mapping to the array element's basic type. 11.13 BasicType array_element_basic_type() const; 11.14
12.1 --- a/src/share/vm/services/heapDumper.cpp Mon Apr 18 15:28:31 2016 -0700 12.2 +++ b/src/share/vm/services/heapDumper.cpp Sun Apr 24 20:50:03 2016 +0100 12.3 @@ -468,7 +468,7 @@ 12.4 // flush and close dump file 12.5 if (is_open()) { 12.6 flush(); 12.7 - os::close(file_descriptor()); 12.8 + ::close(file_descriptor()); 12.9 set_file_descriptor(-1); 12.10 } 12.11 } 12.12 @@ -480,12 +480,11 @@ 12.13 ssize_t n = 0; 12.14 while (len > 0) { 12.15 uint tmp = (uint)MIN2(len, (size_t)UINT_MAX); 12.16 - n = os::write(file_descriptor(), pos, tmp); 12.17 + n = ::write(file_descriptor(), pos, tmp); 12.18 12.19 if (n < 0) { 12.20 - // EINTR cannot happen here, os::write will take care of that 12.21 set_error(strerror(errno)); 12.22 - os::close(file_descriptor()); 12.23 + ::close(file_descriptor()); 12.24 set_file_descriptor(-1); 12.25 return; 12.26 }
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/test/compiler/types/TestMeetIncompatibleInterfaceArrays.java Sun Apr 24 20:50:03 2016 +0100 13.3 @@ -0,0 +1,351 @@ 13.4 +/* 13.5 + * Copyright 2015 SAP AG. All Rights Reserved. 13.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.7 + * 13.8 + * This code is free software; you can redistribute it and/or modify it 13.9 + * under the terms of the GNU General Public License version 2 only, as 13.10 + * published by the Free Software Foundation. 13.11 + * 13.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 13.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13.15 + * version 2 for more details (a copy is included in the LICENSE file that 13.16 + * accompanied this code). 13.17 + * 13.18 + * You should have received a copy of the GNU General Public License version 13.19 + * 2 along with this work; if not, write to the Free Software Foundation, 13.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 13.21 + * 13.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 13.23 + * or visit www.oracle.com if you need additional information or have any 13.24 + * questions. 13.25 + */ 13.26 + 13.27 +/* 13.28 + * @test 13.29 + * @bug 8141551 13.30 + * @summary C2 can not handle returns with inccompatible interface arrays 13.31 + * @library /testlibrary /testlibrary/whitebox/ 13.32 + * @build sun.hotspot.WhiteBox 13.33 + * @run main ClassFileInstaller sun.hotspot.WhiteBox 13.34 + * sun.hotspot.WhiteBox$WhiteBoxPermission 13.35 + * @run main/othervm 13.36 + * -Xbootclasspath/a:. 13.37 + * -XX:+UnlockDiagnosticVMOptions 13.38 + * -XX:+WhiteBoxAPI 13.39 + * -Xbatch 13.40 + * -XX:CompileThreshold=1 13.41 + * -XX:-TieredCompilation 13.42 + * -XX:CICompilerCount=1 13.43 + * -XX:+PrintCompilation 13.44 + * -XX:+PrintInlining 13.45 + * -XX:CompileCommand=compileonly,MeetIncompatibleInterfaceArrays*.run 13.46 + * -XX:CompileCommand=dontinline,TestMeetIncompatibleInterfaceArrays$Helper.createI2* 13.47 + * -XX:CompileCommand=quiet 13.48 + * TestMeetIncompatibleInterfaceArrays 0 13.49 + * @run main/othervm 13.50 + * -Xbootclasspath/a:. 13.51 + * -XX:+UnlockDiagnosticVMOptions 13.52 + * -XX:+WhiteBoxAPI 13.53 + * -Xbatch 13.54 + * -XX:CompileThreshold=1 13.55 + * -XX:-TieredCompilation 13.56 + * -XX:CICompilerCount=1 13.57 + * -XX:+PrintCompilation 13.58 + * -XX:+PrintInlining 13.59 + * -XX:CompileCommand=compileonly,MeetIncompatibleInterfaceArrays*.run 13.60 + * -XX:CompileCommand=inline,TestMeetIncompatibleInterfaceArrays$Helper.createI2* 13.61 + * -XX:CompileCommand=quiet 13.62 + * TestMeetIncompatibleInterfaceArrays 1 13.63 + * @run main/othervm 13.64 + * -Xbootclasspath/a:. 13.65 + * -XX:+UnlockDiagnosticVMOptions 13.66 + * -XX:+WhiteBoxAPI 13.67 + * -Xbatch 13.68 + * -XX:CompileThreshold=1 13.69 + * -XX:Tier0InvokeNotifyFreqLog=0 -XX:Tier2InvokeNotifyFreqLog=0 -XX:Tier3InvokeNotifyFreqLog=0 -XX:Tier23InlineeNotifyFreqLog=0 13.70 + * -XX:Tier3InvocationThreshold=2 -XX:Tier3MinInvocationThreshold=2 -XX:Tier3CompileThreshold=2 13.71 + * -XX:Tier4InvocationThreshold=1 -XX:Tier4MinInvocationThreshold=1 -XX:Tier4CompileThreshold=1 13.72 + * -XX:+TieredCompilation 13.73 + * -XX:CICompilerCount=2 13.74 + * -XX:+PrintCompilation 13.75 + * -XX:+PrintInlining 13.76 + * -XX:CompileCommand=compileonly,MeetIncompatibleInterfaceArrays*.run 13.77 + * -XX:CompileCommand=compileonly,TestMeetIncompatibleInterfaceArrays$Helper.createI2* 13.78 + * -XX:CompileCommand=inline,TestMeetIncompatibleInterfaceArrays$Helper.createI2* 13.79 + * -XX:CompileCommand=quiet 13.80 + * TestMeetIncompatibleInterfaceArrays 2 13.81 + * 13.82 + * @author volker.simonis@gmail.com 13.83 + */ 13.84 + 13.85 +import java.io.FileOutputStream; 13.86 +import java.lang.reflect.InvocationTargetException; 13.87 +import java.lang.reflect.Method; 13.88 +import jdk.internal.org.objectweb.asm.ClassWriter; 13.89 +import jdk.internal.org.objectweb.asm.MethodVisitor; 13.90 +import static jdk.internal.org.objectweb.asm.Opcodes.*; 13.91 +import sun.hotspot.WhiteBox; 13.92 + 13.93 +public class TestMeetIncompatibleInterfaceArrays extends ClassLoader { 13.94 + 13.95 + private static final WhiteBox WB = WhiteBox.getWhiteBox(); 13.96 + 13.97 + public static interface I1 { public String getName(); } 13.98 + public static interface I2 { public String getName(); } 13.99 + public static class I2C implements I2 { public String getName() { return "I2";} } 13.100 + public static class I21C implements I2, I1 { public String getName() { return "I2 and I1";} } 13.101 + 13.102 + public static class Helper { 13.103 + public static I2 createI2Array0() { 13.104 + return new I2C(); 13.105 + } 13.106 + public static I2[] createI2Array1() { 13.107 + return new I2C[] { new I2C() }; 13.108 + } 13.109 + public static I2[][] createI2Array2() { 13.110 + return new I2C[][] { new I2C[] { new I2C() } }; 13.111 + } 13.112 + public static I2[][][] createI2Array3() { 13.113 + return new I2C[][][] { new I2C[][] { new I2C[] { new I2C() } } }; 13.114 + } 13.115 + public static I2[][][][] createI2Array4() { 13.116 + return new I2C[][][][] { new I2C[][][] { new I2C[][] { new I2C[] { new I2C() } } } }; 13.117 + } 13.118 + public static I2[][][][][] createI2Array5() { 13.119 + return new I2C[][][][][] { new I2C[][][][] { new I2C[][][] { new I2C[][] { new I2C[] { new I2C() } } } } }; 13.120 + } 13.121 + public static I2 createI21Array0() { 13.122 + return new I21C(); 13.123 + } 13.124 + public static I2[] createI21Array1() { 13.125 + return new I21C[] { new I21C() }; 13.126 + } 13.127 + public static I2[][] createI21Array2() { 13.128 + return new I21C[][] { new I21C[] { new I21C() } }; 13.129 + } 13.130 + public static I2[][][] createI21Array3() { 13.131 + return new I21C[][][] { new I21C[][] { new I21C[] { new I21C() } } }; 13.132 + } 13.133 + public static I2[][][][] createI21Array4() { 13.134 + return new I21C[][][][] { new I21C[][][] { new I21C[][] { new I21C[] { new I21C() } } } }; 13.135 + } 13.136 + public static I2[][][][][] createI21Array5() { 13.137 + return new I21C[][][][][] { new I21C[][][][] { new I21C[][][] { new I21C[][] { new I21C[] { new I21C() } } } } }; 13.138 + } 13.139 + } 13.140 + 13.141 + // Location for the generated class files 13.142 + public static final String PATH = System.getProperty("test.classes", ".") + java.io.File.separator; 13.143 + 13.144 + /* 13.145 + * With 'good == false' this helper method creates the following classes 13.146 + * (using the nested 'Helper' class and the nested interfaces 'I1' and 'I2'). 13.147 + * For brevity I omit the enclosing class 'TestMeetIncompatibleInterfaceArrays' in the 13.148 + * following examples: 13.149 + * 13.150 + * public class MeetIncompatibleInterfaceArrays0ASM { 13.151 + * public static I1 run() { 13.152 + * return Helper.createI2Array0(); // returns I2 13.153 + * } 13.154 + * public static void test() { 13.155 + * I1 i1 = run(); 13.156 + * System.out.println(i1.getName()); 13.157 + * } 13.158 + * } 13.159 + * public class MeetIncompatibleInterfaceArrays1ASM { 13.160 + * public static I1[] run() { 13.161 + * return Helper.createI2Array1(); // returns I2[] 13.162 + * } 13.163 + * public static void test() { 13.164 + * I1[] i1 = run(); 13.165 + * System.out.println(i1[0].getName()); 13.166 + * } 13.167 + * } 13.168 + * ... 13.169 + * // MeetIncompatibleInterfaceArrays4ASM is special because it creates 13.170 + * // an illegal class which will be rejected by the verifier. 13.171 + * public class MeetIncompatibleInterfaceArrays4ASM { 13.172 + * public static I1[][][][] run() { 13.173 + * return Helper.createI2Array3(); // returns I1[][][] which gives a verifier error because return expects I1[][][][] 13.174 + * } 13.175 + * public static void test() { 13.176 + * I1[][][][][] i1 = run(); 13.177 + * System.out.println(i1[0][0][0][0][0].getName()); 13.178 + * } 13.179 + * ... 13.180 + * public class MeetIncompatibleInterfaceArrays5ASM { 13.181 + * public static I1[][][][][] run() { 13.182 + * return Helper.createI2Array5(); // returns I2[][][][][] 13.183 + * } 13.184 + * public static void test() { 13.185 + * I1[][][][][] i1 = run(); 13.186 + * System.out.println(i1[0][0][0][0][0].getName()); 13.187 + * } 13.188 + * } 13.189 + * 13.190 + * Notice that this is not legal Java code. We would have to use a cast in "run()" to make it legal: 13.191 + * 13.192 + * public static I1[] run() { 13.193 + * return (I1[])Helper.createI2Array1(); // returns I2[] 13.194 + * } 13.195 + * 13.196 + * But in pure bytecode, the "run()" methods are perfectly legal: 13.197 + * 13.198 + * public static I1[] run(); 13.199 + * Code: 13.200 + * 0: invokestatic #16 // Method Helper.createI2Array1:()[LI2; 13.201 + * 3: areturn 13.202 + * 13.203 + * The "test()" method calls the "getName()" function from I1 on the objects returned by "run()". 13.204 + * This will epectedly fail with an "IncompatibleClassChangeError" because the objects returned 13.205 + * by "run()" (and by createI2Array()) are actually of type "I2C" and only implement "I2" but not "I1". 13.206 + * 13.207 + * 13.208 + * With 'good == true' this helper method will create the following classes: 13.209 + * 13.210 + * public class MeetIncompatibleInterfaceArraysGood0ASM { 13.211 + * public static I1 run() { 13.212 + * return Helper.createI21Array0(); // returns I2 13.213 + * } 13.214 + * public static void test() { 13.215 + * I1 i1 = run(); 13.216 + * System.out.println(i1.getName()); 13.217 + * } 13.218 + * } 13.219 + * 13.220 + * Calling "test()" on these objects will succeed and output "I2 and I1" because now the "run()" 13.221 + * method calls "createI21Array()" which actually return an object (or an array of objects) of 13.222 + * type "I21C" which implements both "I2" and "I1". 13.223 + * 13.224 + * Notice that at the bytecode level, the code for the "run()" and "test()" methods in 13.225 + * "MeetIncompatibleInterfaceArraysASM" and "MeetIncompatibleInterfaceArraysGoodASM" look exactly 13.226 + * the same. I.e. the verifier has no chance to verify if the I2 object returned by "createI1Array()" 13.227 + * or "createI21Array()" implements "I1" or not. That's actually the reason why both versions of 13.228 + * generated classes are legal from a verifier point of view. 13.229 + * 13.230 + */ 13.231 + static void generateTestClass(int dim, boolean good) throws Exception { 13.232 + String baseClassName = "MeetIncompatibleInterfaceArrays"; 13.233 + if (good) 13.234 + baseClassName += "Good"; 13.235 + String createName = "createI2" + (good ? "1" : "") + "Array"; 13.236 + String a = ""; 13.237 + for (int i = 0; i < dim; i++) 13.238 + a += "["; 13.239 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); 13.240 + cw.visit(V1_8, ACC_PUBLIC, baseClassName + dim + "ASM", null, "java/lang/Object", null); 13.241 + MethodVisitor constr = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 13.242 + constr.visitCode(); 13.243 + constr.visitVarInsn(ALOAD, 0); 13.244 + constr.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); 13.245 + constr.visitInsn(RETURN); 13.246 + constr.visitMaxs(0, 0); 13.247 + constr.visitEnd(); 13.248 + MethodVisitor run = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "run", 13.249 + "()" + a + "LTestMeetIncompatibleInterfaceArrays$I1;", null, null); 13.250 + run.visitCode(); 13.251 + if (dim == 4) { 13.252 + run.visitMethodInsn(INVOKESTATIC, "TestMeetIncompatibleInterfaceArrays$Helper", createName + 3, 13.253 + "()" + "[[[" + "LTestMeetIncompatibleInterfaceArrays$I2;", false); 13.254 + } else { 13.255 + run.visitMethodInsn(INVOKESTATIC, "TestMeetIncompatibleInterfaceArrays$Helper", createName + dim, 13.256 + "()" + a + "LTestMeetIncompatibleInterfaceArrays$I2;", false); 13.257 + } 13.258 + run.visitInsn(ARETURN); 13.259 + run.visitMaxs(0, 0); 13.260 + run.visitEnd(); 13.261 + MethodVisitor test = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "()V", null, null); 13.262 + test.visitCode(); 13.263 + test.visitMethodInsn(INVOKESTATIC, baseClassName + dim + "ASM", "run", 13.264 + "()" + a + "LTestMeetIncompatibleInterfaceArrays$I1;", false); 13.265 + test.visitVarInsn(ASTORE, 0); 13.266 + if (dim > 0) { 13.267 + test.visitVarInsn(ALOAD, 0); 13.268 + for (int i = 1; i <= dim; i++) { 13.269 + test.visitInsn(ICONST_0); 13.270 + test.visitInsn(AALOAD); 13.271 + } 13.272 + test.visitVarInsn(ASTORE, 1); 13.273 + } 13.274 + test.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 13.275 + test.visitVarInsn(ALOAD, dim > 0 ? 1 : 0); 13.276 + test.visitMethodInsn(INVOKEINTERFACE, "TestMeetIncompatibleInterfaceArrays$I1", "getName", 13.277 + "()Ljava/lang/String;", true); 13.278 + test.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false); 13.279 + test.visitInsn(RETURN); 13.280 + test.visitMaxs(0, 0); 13.281 + test.visitEnd(); 13.282 + 13.283 + // Get the bytes of the class.. 13.284 + byte[] b = cw.toByteArray(); 13.285 + // ..and write them into a class file (for debugging) 13.286 + FileOutputStream fos = new FileOutputStream(PATH + baseClassName + dim + "ASM.class"); 13.287 + fos.write(b); 13.288 + fos.close(); 13.289 + 13.290 + } 13.291 + 13.292 + public static String[][] tier = { { "interpreted", "C2 (tier 4) without inlining", "C2 (tier4) without inlining" }, 13.293 + { "interpreted", "C2 (tier 4) with inlining", "C2 (tier4) with inlining" }, 13.294 + { "interpreted", "C1 (tier 3) with inlining", "C2 (tier4) with inlining" } }; 13.295 + 13.296 + public static void main(String[] args) throws Exception { 13.297 + final int pass = Integer.parseInt(args.length > 0 ? args[0] : "0"); 13.298 + 13.299 + // Load and initialize some classes required for compilation 13.300 + Class.forName("TestMeetIncompatibleInterfaceArrays$I1"); 13.301 + Class.forName("TestMeetIncompatibleInterfaceArrays$I2"); 13.302 + Class.forName("TestMeetIncompatibleInterfaceArrays$Helper"); 13.303 + 13.304 + for (int g = 0; g < 2; g++) { 13.305 + String baseClassName = "MeetIncompatibleInterfaceArrays"; 13.306 + boolean good = (g == 0) ? false : true; 13.307 + if (good) 13.308 + baseClassName += "Good"; 13.309 + for (int i = 0; i < 6; i++) { 13.310 + System.out.println(); 13.311 + System.out.println("Creating " + baseClassName + i + "ASM.class"); 13.312 + System.out.println("========================================" + "=" + "========="); 13.313 + // Create the "MeetIncompatibleInterfaceArrays<i>ASM" class 13.314 + generateTestClass(i, good); 13.315 + Class<?> c = null; 13.316 + try { 13.317 + c = Class.forName(baseClassName + i + "ASM"); 13.318 + } catch (VerifyError ve) { 13.319 + if (i == 4) { 13.320 + System.out.println("OK - must be (" + ve.getMessage() + ")."); 13.321 + } else { 13.322 + throw ve; 13.323 + } 13.324 + continue; 13.325 + } 13.326 + // Call MeetIncompatibleInterfaceArrays<i>ASM.test() 13.327 + Method m = c.getMethod("test"); 13.328 + Method r = c.getMethod("run"); 13.329 + for (int j = 0; j < 3; j++) { 13.330 + System.out.println((j + 1) + ". invokation of " + baseClassName + i + "ASM.test() [should be " 13.331 + + tier[pass][j] + "]"); 13.332 + try { 13.333 + m.invoke(null); 13.334 + } catch (InvocationTargetException ite) { 13.335 + if (good) { 13.336 + throw ite; 13.337 + } else { 13.338 + if (ite.getCause() instanceof IncompatibleClassChangeError) { 13.339 + System.out.println(" OK - catched InvocationTargetException(" 13.340 + + ite.getCause().getMessage() + ")."); 13.341 + } else { 13.342 + throw ite; 13.343 + } 13.344 + } 13.345 + } 13.346 + } 13.347 + System.out.println("Method " + r + (WB.isMethodCompiled(r) ? " has" : " has not") + " been compiled."); 13.348 + if (!WB.isMethodCompiled(r)) { 13.349 + throw new Exception("Method " + r + " must be compiled!"); 13.350 + } 13.351 + } 13.352 + } 13.353 + } 13.354 +}