--- old/make/jprt.properties 2011-10-26 12:57:12.940287700 +0200 +++ new/make/jprt.properties 2011-10-26 12:57:12.503487000 +0200 @@ -541,9 +541,20 @@ ${jprt.my.windows.i586}-*-c2-servertest, \ ${jprt.my.windows.x64}-*-c2-servertest +jprt.make.rule.test.targets.standard.internalvmtests = \ + ${jprt.my.solaris.sparc}-fastdebug-c2-internalvmtests, \ + ${jprt.my.solaris.sparcv9}-fastdebug-c2-internalvmtests, \ + ${jprt.my.solaris.i586}-fastdebug-c2-internalvmtests, \ + ${jprt.my.solaris.x64}-fastdebug-c2-internalvmtests, \ + ${jprt.my.linux.i586}-fastdebug-c2-internalvmtests, \ + ${jprt.my.linux.x64}-fastdebug-c2-internalvmtests, \ + ${jprt.my.windows.i586}-fastdebug-c2-internalvmtests, \ + ${jprt.my.windows.x64}-fastdebug-c2-internalvmtests + jprt.make.rule.test.targets.standard = \ ${jprt.make.rule.test.targets.standard.client}, \ - ${jprt.make.rule.test.targets.standard.server} + ${jprt.make.rule.test.targets.standard.server}, \ + ${jprt.make.rule.test.targets.standard.internalvmtests} jprt.make.rule.test.targets.embedded = \ ${jprt.make.rule.test.targets.standard.client} --- old/src/share/vm/oops/arrayOop.cpp 2011-10-26 12:57:18.712297900 +0200 +++ new/src/share/vm/oops/arrayOop.cpp 2011-10-26 12:57:18.275497100 +0200 @@ -24,8 +24,65 @@ #include "precompiled.hpp" #include "oops/arrayOop.hpp" -#include "oops/objArrayOop.hpp" -#include "oops/oop.inline.hpp" -#include "oops/symbol.hpp" -// <> +#ifndef PRODUCT + +#include "utilities/globalDefinitions.hpp" +// Unit tests + +bool arrayOopDesc::check_overflow(BasicType type) { + int32_t length = max_array_length(type); + size_t bytes_per_element = type2aelembytes(type); + size_t bytes = (size_t)length * bytes_per_element + header_size_in_bytes(); + return (bytes - header_size_in_bytes()) / bytes_per_element == (size_t)length; +} + +// The old implementation of max_array_length. For 64-bit platforms the old +// and new implementations should return the same value. +int32_t arrayOopDesc::old_max_array_length(BasicType type) { + const int bytes_per_element = type2aelembytes(type); + if (bytes_per_element < HeapWordSize) { + return max_jint; + } + const int32_t max_words = align_size_down(max_jint, MinObjAlignment); + const int32_t max_element_words = max_words - header_size(type); + const int32_t words_per_element = bytes_per_element >> LogHeapWordSize; + return max_element_words / words_per_element; +} + +bool arrayOopDesc::test_max_array_length() { + tty->print_cr("test_max_array_length"); + + assert(check_overflow(T_BOOLEAN), "size_t overflow for boolean array"); + assert(check_overflow(T_CHAR), "size_t overflow for char array"); + assert(check_overflow(T_FLOAT), "size_t overflow for float array"); + assert(check_overflow(T_DOUBLE), "size_t overflow for double array"); + assert(check_overflow(T_BYTE), "size_t overflow for byte array"); + assert(check_overflow(T_SHORT), "size_t overflow for short array"); + assert(check_overflow(T_INT), "size_t overflow for int array"); + assert(check_overflow(T_LONG), "size_t overflow for long array"); + assert(check_overflow(T_OBJECT), "size_t overflow for object array"); + assert(check_overflow(T_ARRAY), "size_t overflow for array array"); + assert(check_overflow(T_NARROWOOP), "size_t overflow for narrowOop array"); + + // T_VOID and T_ADDRESS are not supported by max_array_length() + +#ifdef _LP64 + assert(max_array_length(T_BOOLEAN) == old_max_array_length(T_BOOLEAN), "calculation changed for boolean"); + assert(max_array_length(T_CHAR) == old_max_array_length(T_CHAR), "calculation changed for char"); + assert(max_array_length(T_FLOAT) == old_max_array_length(T_FLOAT), "calculation changed for float"); + assert(max_array_length(T_DOUBLE) == old_max_array_length(T_DOUBLE), "calculation changed for double"); + assert(max_array_length(T_BYTE) == old_max_array_length(T_BYTE), "calculation changed for byte"); + assert(max_array_length(T_SHORT) == old_max_array_length(T_SHORT), "calculation changed for short"); + assert(max_array_length(T_INT) == old_max_array_length(T_INT), "calculation changed for int"); + assert(max_array_length(T_LONG) == old_max_array_length(T_LONG), "calculation changed for long"); + assert(max_array_length(T_OBJECT) == old_max_array_length(T_OBJECT), "calculation changed for object"); + assert(max_array_length(T_ARRAY) == old_max_array_length(T_ARRAY), "calculation changed for array"); + assert(max_array_length(T_NARROWOOP) == old_max_array_length(T_NARROWOOP), "calculation changed for narrowOop"); +#endif + + return true; +} + + +#endif //PRODUCT --- old/src/share/vm/oops/arrayOop.hpp 2011-10-26 12:57:24.406307900 +0200 +++ new/src/share/vm/oops/arrayOop.hpp 2011-10-26 12:57:23.969507100 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -113,11 +113,19 @@ return max_jint; } - const int32_t max_words = align_size_down(max_jint, MinObjAlignment); - const int32_t max_element_words = max_words - header_size(type); + const size_t max_words_per_size_t = SIZE_MAX / HeapWordSize; + const int32_t max_words = (int32_t)MIN2((size_t)max_jint, max_words_per_size_t); + const int32_t max_element_words = align_size_down(max_words - header_size(type), MinObjAlignment); const int32_t words_per_element = bytes_per_element >> LogHeapWordSize; return max_element_words / words_per_element; } + +// for unit testing +#ifndef PRODUCT + static bool check_overflow(BasicType type); + static int32_t old_max_array_length(BasicType type); + static bool test_max_array_length(); +#endif }; #endif // SHARE_VM_OOPS_ARRAYOOP_HPP --- old/src/share/vm/prims/jni.cpp 2011-10-26 12:57:30.115917900 +0200 +++ new/src/share/vm/prims/jni.cpp 2011-10-26 12:57:29.679117100 +0200 @@ -5042,7 +5042,8 @@ void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { assert(QuickSort::test_quick_sort(), "test_quick_sort failed"); - tty->print_cr("All tests passed"); + assert(arrayOopDesc::test_max_array_length(), "test_max_array_length failed"); + tty->print_cr("All internal VM tests passed"); } } --- old/src/share/vm/utilities/quickSort.cpp 2011-10-26 12:57:36.340328800 +0200 +++ new/src/share/vm/utilities/quickSort.cpp 2011-10-26 12:57:35.903528100 +0200 @@ -94,7 +94,7 @@ } bool QuickSort::test_quick_sort() { - tty->print_cr("test_quick_sort\n"); + tty->print_cr("test_quick_sort"); { int* test_array = NULL; int* expected_array = NULL; --- old/test/Makefile 2011-10-26 12:57:42.003138800 +0200 +++ new/test/Makefile 2011-10-26 12:57:41.566338000 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1995, 2011, 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 @@ -219,6 +219,15 @@ ################################################################ +# internalvmtests (run internal unit tests inside the VM) + +internalvmtests: prep $(PRODUCT_HOME) + $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -XX:+ExecuteInternalVMTests -version + +PHONY_LIST += internalvmtests + +################################################################ + # packtest # Expect JPRT to set JPRT_PACKTEST_HOME.