diff --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp index 90b8b0c760b2dd349c5295488d6c1cc3d4da23d5..5e3eee4f4050c350ac735d48e98d718630852cb0 100644 --- a/src/share/vm/ci/ciEnv.cpp +++ b/src/share/vm/ci/ciEnv.cpp @@ -385,11 +385,6 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, KILL_COMPILE_ON_FATAL_(fail_type)); } - if (found_klass != NULL) { - // Found it. Build a CI handle. - return get_object(found_klass)->as_klass(); - } - // If we fail to find an array klass, look again for its element type. // The element type may be available either locally or via constraints. // In either case, if we can find the element type in the system dictionary, @@ -414,6 +409,11 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, } } + if (found_klass != NULL) { + // Found it. Build a CI handle. + return get_object(found_klass)->as_klass(); + } + if (require_local) return NULL; // Not yet loaded into the VM, or not governed by loader constraints. // Make a CI representative for it. diff --git a/src/share/vm/classfile/loaderConstraints.cpp b/src/share/vm/classfile/loaderConstraints.cpp index 0a8693403d11007f87e71830c8abe924e2d4e9ca..d4df39e4034b6757ef876301be3ea4095569d748 100644 --- a/src/share/vm/classfile/loaderConstraints.cpp +++ b/src/share/vm/classfile/loaderConstraints.cpp @@ -334,33 +334,6 @@ klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name, return NULL; } - -klassOop LoaderConstraintTable::find_constrained_elem_klass(symbolHandle name, - symbolHandle elem_name, - Handle loader, - TRAPS) { - LoaderConstraintEntry *p = *(find_loader_constraint(name, loader)); - if (p != NULL) { - assert(p->klass() == NULL, "Expecting null array klass"); - - // The array name has a constraint, but it will not have a class. Check - // each loader for an associated elem - for (int i = 0; i < p->num_loaders(); i++) { - Handle no_protection_domain; - - klassOop k = SystemDictionary::find(elem_name, p->loader(i), no_protection_domain, THREAD); - if (k != NULL) { - // Return the first elem klass found. - return k; - } - } - } - - // No constraints, or else no klass loaded yet. - return NULL; -} - - void LoaderConstraintTable::ensure_loader_constraint_capacity( LoaderConstraintEntry *p, int nfree) { diff --git a/src/share/vm/classfile/loaderConstraints.hpp b/src/share/vm/classfile/loaderConstraints.hpp index 53ce146b168f97821c20030dbbfffed90d226790..2ea19ebdaa374b6f9519cce01bec056a27ba845f 100644 --- a/src/share/vm/classfile/loaderConstraints.hpp +++ b/src/share/vm/classfile/loaderConstraints.hpp @@ -66,9 +66,6 @@ public: // bool is_method, TRAPS) klassOop find_constrained_klass(symbolHandle name, Handle loader); - klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name, - Handle loader, TRAPS); - // Class loader constraints diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp index 1db0a5cfb155fa325151cf422886fbdebac2d84f..83f8717cf65692fbaa8dd10863999c2434932e14 100644 --- a/src/share/vm/classfile/systemDictionary.cpp +++ b/src/share/vm/classfile/systemDictionary.cpp @@ -2178,9 +2178,8 @@ klassOop SystemDictionary::find_constrained_instance_or_array_klass( // a loader constraint that would require this loader to return the // klass that is already loaded. if (FieldType::is_array(class_name())) { - // Array classes are hard because their klassOops are not kept in the - // constraint table. The array klass may be constrained, but the elem class - // may not be. + // For array classes, their klassOops are not kept in the + // constraint table. The element klassOops are. jint dimension; symbolOop object_key; BasicType t = FieldType::get_array_info(class_name(), &dimension, @@ -2190,8 +2189,9 @@ klassOop SystemDictionary::find_constrained_instance_or_array_klass( } else { symbolHandle elem_name(THREAD, object_key); MutexLocker mu(SystemDictionary_lock, THREAD); - klass = constraints()->find_constrained_elem_klass(class_name, elem_name, class_loader, THREAD); + klass = constraints()->find_constrained_klass(elem_name, class_loader); } + // If element class already loaded, allocate array klass if (klass != NULL) { klass = Klass::cast(klass)->array_klass_or_null(dimension); } @@ -2209,22 +2209,38 @@ bool SystemDictionary::add_loader_constraint(symbolHandle class_name, Handle class_loader1, Handle class_loader2, Thread* THREAD) { - unsigned int d_hash1 = dictionary()->compute_hash(class_name, class_loader1); + symbolHandle constraint_name; + if (!FieldType::is_array(class_name())) { + constraint_name = class_name; + } else { + // For array classes, their klassOops are not kept in the + // constraint table. The element classes are. + jint dimension; + symbolOop object_key; + BasicType t = FieldType::get_array_info(class_name(), &dimension, + &object_key, CHECK_(false)); + // primitive types always pass + if (t != T_OBJECT) { + return true; + } else { + constraint_name = symbolHandle(THREAD, object_key); + } + } + unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, class_loader1); int d_index1 = dictionary()->hash_to_index(d_hash1); - unsigned int d_hash2 = dictionary()->compute_hash(class_name, class_loader2); + unsigned int d_hash2 = dictionary()->compute_hash(constraint_name, class_loader2); int d_index2 = dictionary()->hash_to_index(d_hash2); - { - MutexLocker mu_s(SystemDictionary_lock, THREAD); + MutexLocker mu_s(SystemDictionary_lock, THREAD); - // Better never do a GC while we're holding these oops - No_Safepoint_Verifier nosafepoint; + // Better never do a GC while we're holding these oops + No_Safepoint_Verifier nosafepoint; - klassOop klass1 = find_class(d_index1, d_hash1, class_name, class_loader1); - klassOop klass2 = find_class(d_index2, d_hash2, class_name, class_loader2); - return constraints()->add_entry(class_name, klass1, class_loader1, - klass2, class_loader2); + klassOop klass1 = find_class(d_index1, d_hash1, constraint_name, class_loader1); + klassOop klass2 = find_class(d_index2, d_hash2, constraint_name, class_loader2); + return constraints()->add_entry(constraint_name, klass1, class_loader1, + klass2, class_loader2); } } @@ -2301,6 +2317,7 @@ symbolOop SystemDictionary::find_resolution_error(constantPoolHandle pool, int w // Returns the name of the type that failed a loader constraint check, or // NULL if no constraint failed. The returned C string needs cleaning up // with a ResourceMark in the caller. No exception except OOME is thrown. +// Arrays are not added to the loader constraint table, their elements are. char* SystemDictionary::check_signature_loaders(symbolHandle signature, Handle loader1, Handle loader2, bool is_method, TRAPS) { diff --git a/src/share/vm/oops/typeArrayKlass.cpp b/src/share/vm/oops/typeArrayKlass.cpp index 68d67f1ccf6eb00440a8be982edd476b65610e47..b9ccd0cbc294539c46745d51c758a48988cf5998 100644 --- a/src/share/vm/oops/typeArrayKlass.cpp +++ b/src/share/vm/oops/typeArrayKlass.cpp @@ -123,16 +123,16 @@ void typeArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos || (((unsigned int) length + (unsigned int) dst_pos) > (unsigned int) d->length()) ) { THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); } + // Check zero copy + if (length == 0) + return; // This is an attempt to make the copy_array fast. - // NB: memmove takes care of overlapping memory segments. - // Potential problem: memmove is not guaranteed to be word atomic - // Revisit in Merlin int l2es = log2_element_size(); int ihs = array_header_in_bytes() / wordSize; - char* src = (char*) ((oop*)s + ihs) + (src_pos << l2es); - char* dst = (char*) ((oop*)d + ihs) + (dst_pos << l2es); - memmove(dst, src, length << l2es); + char* src = (char*) ((oop*)s + ihs) + ((size_t)src_pos << l2es); + char* dst = (char*) ((oop*)d + ihs) + ((size_t)dst_pos << l2es); + Copy::conjoint_memory_atomic(src, dst, (size_t)length << l2es); } diff --git a/src/share/vm/opto/cfgnode.cpp b/src/share/vm/opto/cfgnode.cpp index b1da1c716d9208484e5343d2e7c0d99dad485fa8..383f4f8c989e60f88eda42c931771df1b2b082fe 100644 --- a/src/share/vm/opto/cfgnode.cpp +++ b/src/share/vm/opto/cfgnode.cpp @@ -956,6 +956,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { } if( jtkp && ttkp ) { if( jtkp->is_loaded() && jtkp->klass()->is_interface() && + !jtkp->klass_is_exact() && // Keep exact interface klass (6894807) ttkp->is_loaded() && !ttkp->klass()->is_interface() ) { assert(ft == ttkp->cast_to_ptr_type(jtkp->ptr()) || ft->isa_narrowoop() && ft->make_ptr() == ttkp->cast_to_ptr_type(jtkp->ptr()), ""); diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp index ba1cf3aa12b9fa4df5cbfab848eded08ea9d05f5..53ed304db5610bd7eb8fc7950f02ea4a4059cf81 100644 --- a/src/share/vm/opto/type.cpp +++ b/src/share/vm/opto/type.cpp @@ -2545,12 +2545,15 @@ const Type *TypeOopPtr::filter( const Type *kills ) const { ftip->is_loaded() && ftip->klass()->is_interface() && ktip->is_loaded() && !ktip->klass()->is_interface()) { // Happens in a CTW of rt.jar, 320-341, no extra flags + assert(!ftip->klass_is_exact(), "interface could not be exact"); return ktip->cast_to_ptr_type(ftip->ptr()); } + // Interface klass type could be exact in opposite to interface type, + // return it here instead of incorrect Constant ptr J/L/Object (6894807). if (ftkp != NULL && ktkp != NULL && ftkp->is_loaded() && ftkp->klass()->is_interface() && + !ftkp->klass_is_exact() && // Keep exact interface klass ktkp->is_loaded() && !ktkp->klass()->is_interface()) { - // Happens in a CTW of rt.jar, 320-341, no extra flags return ktkp->cast_to_ptr_type(ftkp->ptr()); } diff --git a/test/compiler/6892265/Test.java b/test/compiler/6892265/Test.java new file mode 100644 index 0000000000000000000000000000000000000000..1b5d6daa9e12c0198c1deacba74d67ac60f9e5e1 --- /dev/null +++ b/test/compiler/6892265/Test.java @@ -0,0 +1,65 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6892265 + * @summary System.arraycopy unable to reference elements beyond Integer.MAX_VALUE bytes + * + * @run main/othervm Test + */ + +public class Test { + static final int NCOPY = 1; + static final int OVERFLOW = 1; + static int[] src2 = new int[NCOPY]; + static int[] dst2; + + static void test() { + int N; + int SIZE; + + N = Integer.MAX_VALUE/4 + OVERFLOW; + System.arraycopy(src2, 0, dst2, N, NCOPY); + System.arraycopy(dst2, N, src2, 0, NCOPY); + } + + public static void main(String[] args) { + try { + dst2 = new int[NCOPY + Integer.MAX_VALUE/4 + OVERFLOW]; + } catch (OutOfMemoryError e) { + System.exit(95); // Not enough memory + } + System.out.println("warmup"); + for (int i=0; i <11000; i++) { + test(); + } + System.out.println("start"); + for (int i=0; i <1000; i++) { + test(); + } + System.out.println("finish"); + } + +}