--- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -1894,6 +1894,22 @@
__ beq(combined_check, slow);
}
+ if (flags & LIR_OpArrayCopy::type_check) {
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {
+ __ load_klass(tmp, dst);
+ __ lwz(tmp2, in_bytes(Klass::layout_helper_offset()), tmp);
+ __ cmpwi(CCR0, tmp2, Klass::_lh_neutral_value);
+ __ bge(CCR0, slow);
+ }
+
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {
+ __ load_klass(tmp, src);
+ __ lwz(tmp2, in_bytes(Klass::layout_helper_offset()), tmp);
+ __ cmpwi(CCR0, tmp2, Klass::_lh_neutral_value);
+ __ bge(CCR0, slow);
+ }
+ }
+
// Higher 32bits must be null.
__ extsw(length, length);
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -2034,6 +2034,27 @@
__ delayed()->nop();
}
+ // If the compiler was not able to prove that exact type of the source or the destination
+ // of the arraycopy is an array type, check at runtime if the source or the destination is
+ // an instance type.
+ if (flags & LIR_OpArrayCopy::type_check) {
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {
+ __ load_klass(dst, tmp);
+ __ lduw(tmp, in_bytes(Klass::layout_helper_offset()), tmp2);
+ __ cmp(tmp2, Klass::_lh_neutral_value);
+ __ br(Assembler::greaterEqual, false, Assembler::pn, *stub->entry());
+ __ delayed()->nop();
+ }
+
+ if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {
+ __ load_klass(src, tmp);
+ __ lduw(tmp, in_bytes(Klass::layout_helper_offset()), tmp2);
+ __ cmp(tmp2, Klass::_lh_neutral_value);
+ __ br(Assembler::greaterEqual, false, Assembler::pn, *stub->entry());
+ __ delayed()->nop();
+ }
+ }
+
if (flags & LIR_OpArrayCopy::src_pos_positive_check) {
// test src_pos register
__ cmp_zero_and_br(Assembler::less, src_pos, *stub->entry());
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -3146,6 +3146,23 @@
__ jcc(Assembler::zero, *stub->entry());
}
+ // If the compiler was not able to prove that exact type of the source or the destination
+ // of the arraycopy is an array type, check at runtime if the source or the destination is
+ // an instance type.
+ if (flags & LIR_OpArrayCopy::type_check) {
+ if (!(flags & LIR_OpArrayCopy::dst_objarray)) {
+ __ load_klass(tmp, dst);
+ __ cmpl(Address(tmp, in_bytes(Klass::layout_helper_offset())), Klass::_lh_neutral_value);
+ __ jcc(Assembler::greaterEqual, *stub->entry());
+ }
+
+ if (!(flags & LIR_OpArrayCopy::src_objarray)) {
+ __ load_klass(tmp, src);
+ __ cmpl(Address(tmp, in_bytes(Klass::layout_helper_offset())), Klass::_lh_neutral_value);
+ __ jcc(Assembler::greaterEqual, *stub->entry());
+ }
+ }
+
// check if negative
if (flags & LIR_OpArrayCopy::src_pos_positive_check) {
__ testl(src_pos, src_pos);
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -5859,6 +5859,11 @@
assert(cp != NULL, "invariant");
assert(_loader_data != NULL, "invariant");
+ if (_class_name == vmSymbols::java_lang_Object()) {
+ check_property(_local_interfaces == Universe::the_empty_klass_array(),
+ "java.lang.Object cannot implement an interface in class file %s",
+ CHECK);
+ }
// We check super class after class file is parsed and format is checked
if (_super_class_index > 0 && NULL ==_super_klass) {
Symbol* const super_class_name = cp->klass_name_at(_super_class_index);
--- a/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/classfile/stackMapTableFormat.hpp Thu Oct 20 20:01:43 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, 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
@@ -203,6 +203,7 @@
inline bool verify(address start, address end) const;
inline void print_on(outputStream* st, int current_offset) const;
+ inline void print_truncated(outputStream* st, int current_offset) const;
// Create as_xxx and is_xxx methods for the subtypes
#define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
@@ -263,6 +264,10 @@
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_frame(@%d)", offset_delta() + current_offset);
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ print_on(st, current_offset);
+ }
};
class same_frame_extended : public stack_map_frame {
@@ -309,6 +314,10 @@
void print_on(outputStream* st, int current_offset = -1) const {
st->print("same_frame_extended(@%d)", offset_delta() + current_offset);
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ print_on(st, current_offset);
+ }
};
class same_locals_1_stack_item_frame : public stack_map_frame {
@@ -381,6 +390,11 @@
types()->print_on(st);
st->print(")");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("same_locals_1_stack_item_frame(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
class same_locals_1_stack_item_extended : public stack_map_frame {
@@ -446,6 +460,11 @@
types()->print_on(st);
st->print(")");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("same_locals_1_stack_item_extended(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
class chop_frame : public stack_map_frame {
@@ -511,6 +530,10 @@
void print_on(outputStream* st, int current_offset = -1) const {
st->print("chop_frame(@%d,%d)", offset_delta() + current_offset, chops());
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ print_on(st, current_offset);
+ }
};
class append_frame : public stack_map_frame {
@@ -619,6 +642,11 @@
}
st->print(")");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("append_frame(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
class full_frame : public stack_map_frame {
@@ -784,6 +812,11 @@
}
st->print("})");
}
+
+ void print_truncated(outputStream* st, int current_offset = -1) const {
+ st->print("full_frame(@%d), output truncated, Stackmap exceeds table size.",
+ offset_delta() + current_offset);
+ }
};
#define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
@@ -841,6 +874,10 @@
FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st, offs));
}
+void stack_map_frame::print_truncated(outputStream* st, int offs = -1) const {
+ FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_truncated, (st, offs));
+}
+
#undef VIRTUAL_DISPATCH
#undef VOID_VIRTUAL_DISPATCH
--- a/hotspot/src/share/vm/classfile/verifier.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -541,8 +541,19 @@
stack_map_frame* sm_frame = sm_table->entries();
streamIndentor si2(ss);
int current_offset = -1;
+ // Subtract two from StackMapAttribute length because the length includes
+ // two bytes for number of table entries.
+ size_t sm_table_space = method->stackmap_data()->length() - 2;
for (u2 i = 0; i < sm_table->number_of_entries(); ++i) {
ss->indent();
+ size_t sm_frame_size = sm_frame->size();
+ // If the size of the next stackmap exceeds the length of the entire
+ // stackmap table then print a truncated message and return.
+ if (sm_frame_size > sm_table_space) {
+ sm_frame->print_truncated(ss, current_offset);
+ return;
+ }
+ sm_table_space -= sm_frame_size;
sm_frame->print_on(ss, current_offset);
ss->cr();
current_offset += sm_frame->offset_delta();
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -2524,7 +2524,6 @@
switch (cp->tag_at(cp_index).value()) {
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Methodref:
- case JVM_CONSTANT_NameAndType: // for invokedynamic
return cp->uncached_name_ref_at(cp_index)->as_utf8();
default:
fatal("JVM_GetCPMethodNameUTF: illegal constant");
@@ -2542,7 +2541,6 @@
switch (cp->tag_at(cp_index).value()) {
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Methodref:
- case JVM_CONSTANT_NameAndType: // for invokedynamic
return cp->uncached_signature_ref_at(cp_index)->as_utf8();
default:
fatal("JVM_GetCPMethodSignatureUTF: illegal constant");
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -794,9 +794,10 @@
} else if (new_len == 0) {
value = old_value;
} else {
- char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtArguments);
+ size_t length = old_len + 1 + new_len + 1;
+ char* buf = NEW_C_HEAP_ARRAY(char, length, mtArguments);
// each new setting adds another LINE to the switch:
- sprintf(buf, "%s\n%s", old_value, new_value);
+ jio_snprintf(buf, length, "%s\n%s", old_value, new_value);
value = buf;
free_this_too = buf;
}
@@ -1014,15 +1015,17 @@
if (args == NULL || count == 0) {
return NULL;
}
- size_t length = strlen(args[0]) + 1; // add 1 for the null terminator
- for (int i = 1; i < count; i++) {
- length += strlen(args[i]) + 1; // add 1 for a space
+ size_t length = 0;
+ for (int i = 0; i < count; i++) {
+ length += strlen(args[i]) + 1; // add 1 for a space or NULL terminating character
}
char* s = NEW_RESOURCE_ARRAY(char, length);
- strcpy(s, args[0]);
- for (int j = 1; j < count; j++) {
- strcat(s, " ");
- strcat(s, args[j]);
+ char* dst = s;
+ for (int j = 0; j < count; j++) {
+ size_t offset = strlen(args[j]) + 1; // add 1 for a space or NULL terminating character
+ jio_snprintf(dst, length, "%s ", args[j]); // jio_snprintf will replace the last space character with NULL character
+ dst += offset;
+ length -= offset;
}
return (const char*) s;
}
@@ -1106,9 +1109,8 @@
// Only make the obsolete check for valid arguments.
if (arg_len <= BUFLEN) {
// Construct a string which consists only of the argument name without '+', '-', or '='.
- char stripped_argname[BUFLEN+1];
- strncpy(stripped_argname, argname, arg_len);
- stripped_argname[arg_len] = '\0'; // strncpy may not null terminate.
+ char stripped_argname[BUFLEN+1]; // +1 for '\0'
+ jio_snprintf(stripped_argname, arg_len+1, "%s", argname); // +1 for '\0'
if (is_obsolete_flag(stripped_argname, &since)) {
char version[256];
since.to_string(version, sizeof(version));
@@ -1260,8 +1262,7 @@
size_t key_len = eq - prop;
char* tmp_key = AllocateHeap(key_len + 1, mtArguments);
- strncpy(tmp_key, prop, key_len);
- tmp_key[key_len] = '\0';
+ jio_snprintf(tmp_key, key_len + 1, "%s", prop);
key = tmp_key;
value = &prop[key_len + 1];
@@ -2256,7 +2257,7 @@
// Feed the cache size setting into the JDK
char buffer[1024];
- sprintf(buffer, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
+ jio_snprintf(buffer, 1024, "java.lang.Integer.IntegerCache.high=" INTX_FORMAT, AutoBoxCacheMax);
if (!add_property(buffer)) {
return JNI_ENOMEM;
}
@@ -2777,8 +2778,8 @@
if (tail != NULL) {
const char* pos = strchr(tail, ':');
size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
- char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtArguments), tail, len);
- name[len] = '\0';
+ char* name = NEW_C_HEAP_ARRAY(char, len + 1, mtArguments);
+ jio_snprintf(name, len + 1, "%s", tail);
char *options = NULL;
if(pos != NULL) {
@@ -2854,7 +2855,9 @@
return JNI_ERR;
#else
if (tail != NULL) {
- char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtArguments), tail);
+ size_t length = strlen(tail) + 1;
+ char *options = NEW_C_HEAP_ARRAY(char, length, mtArguments);
+ jio_snprintf(options, length, "%s", tail);
add_init_agent("instrument", options, false);
// java agents need module java.instrument
if (!create_numbered_property("jdk.module.addmods", "java.instrument", addmods_count++)) {
@@ -3512,7 +3515,7 @@
// check if the default lib/endorsed directory exists; if so, error
char path[JVM_MAXPATHLEN];
const char* fileSep = os::file_separator();
- sprintf(path, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
+ jio_snprintf(path, JVM_MAXPATHLEN, "%s%slib%sendorsed", Arguments::get_java_home(), fileSep, fileSep);
if (CheckEndorsedAndExtDirs) {
int nonEmptyDirs = 0;
@@ -3534,7 +3537,7 @@
return JNI_ERR;
}
- sprintf(path, "%s%slib%sext", Arguments::get_java_home(), fileSep, fileSep);
+ jio_snprintf(path, JVM_MAXPATHLEN, "%s%slib%sext", Arguments::get_java_home(), fileSep, fileSep);
dir = os::opendir(path);
if (dir != NULL) {
jio_fprintf(defaultStream::output_stream(),
@@ -3899,6 +3902,13 @@
void Arguments::set_shared_spaces_flags() {
if (DumpSharedSpaces) {
+ if (FailOverToOldVerifier) {
+ // Don't fall back to the old verifier on verification failure. If a
+ // class fails verification with the split verifier, it might fail the
+ // CDS runtime verifier constraint check. In that case, we don't want
+ // to share the class. We only archive classes that pass the split verifier.
+ FLAG_SET_DEFAULT(FailOverToOldVerifier, false);
+ }
if (RequireSharedSpaces) {
warning("Cannot dump shared archive while using shared archive");
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -2881,8 +2881,6 @@
char *s = sig->as_C_string();
int len = (int)strlen(s);
s++; len--; // Skip opening paren
- char *t = s+len;
- while (*(--t) != ')'); // Find close paren
BasicType *sig_bt = NEW_RESOURCE_ARRAY(BasicType, 256);
VMRegPair *regs = NEW_RESOURCE_ARRAY(VMRegPair, 256);
@@ -2891,7 +2889,7 @@
sig_bt[cnt++] = T_OBJECT; // Receiver is argument 0; not in signature
}
- while (s < t) {
+ while (*s != ')') { // Find closing right paren
switch (*s++) { // Switch on signature character
case 'B': sig_bt[cnt++] = T_BYTE; break;
case 'C': sig_bt[cnt++] = T_CHAR; break;
--- a/hotspot/src/share/vm/runtime/signature.cpp Thu Oct 20 18:38:08 2016 +0000
+++ b/hotspot/src/share/vm/runtime/signature.cpp Thu Oct 20 20:01:43 2016 +0000
@@ -224,7 +224,49 @@
_index = 0;
expect('(');
Symbol* sig = _signature;
- while (sig->byte_at(_index) != ')') _index++;
+ // Need to skip over each type in the signature's argument list until a
+ // closing ')' is found., then get the return type. We cannot just scan
+ // for the first ')' because ')' is a legal character in a type name.
+ while (sig->byte_at(_index) != ')') {
+ switch(sig->byte_at(_index)) {
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':
+ case 'V':
+ {
+ _index++;
+ }
+ break;
+ case 'L':
+ {
+ while (sig->byte_at(_index++) != ';') ;
+ }
+ break;
+ case '[':
+ {
+ int begin = ++_index;
+ skip_optional_size();
+ while (sig->byte_at(_index) == '[') {
+ _index++;
+ skip_optional_size();
+ }
+ if (sig->byte_at(_index) == 'L') {
+ while (sig->byte_at(_index++) != ';') ;
+ } else {
+ _index++;
+ }
+ }
+ break;
+ default:
+ ShouldNotReachHere();
+ break;
+ }
+ }
expect(')');
// Parse return type
_parameter_index = -1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/c1/TestArrayCopyToFromObject.java Thu Oct 20 20:01:43 2016 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, 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 8160591
+ * @summary C1-generated code for System.arraycopy() does not throw an ArrayStoreException if 'dst' is no a "proper" array (i.e., it is java.lang.Object)
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:-UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject.test TestArrayCopyToFromObject
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Xcomp -XX:+UseCompressedClassPointers -XX:CompileOnly=TestArrayCopyToFromObject.test TestArrayCopyToFromObject
+ */
+public class TestArrayCopyToFromObject {
+
+ public void test(Object aArray[]) {
+ Object a = new Object();
+
+ try {
+ System.arraycopy(aArray, 0, a, 0, 1);
+ throw new RuntimeException ("FAILED: Expected ArrayStoreException " +
+ "(due to destination not being an array) " +
+ "was not thrown");
+ } catch (ArrayStoreException e) {
+ System.out.println("PASSED: Expected ArrayStoreException was thrown");
+ }
+
+ try {
+ System.arraycopy(a, 0, aArray, 0, 1);
+ throw new RuntimeException ("FAILED: Expected ArrayStoreException " +
+ "(due to source not being an array) " +
+ "was not thrown");
+ } catch (ArrayStoreException e) {
+ System.out.println("PASSED: Expected ArrayStoreException was thrown");
+ }
+
+ }
+
+ public static void main(String args[]) {
+ System.out.println("TestArrayCopyToFromObject");
+ Object aArray[] = new Object[10];
+ for (int i = 0; i < 10; i++) {
+ aArray[i] = new Object();
+ }
+ new TestArrayCopyToFromObject().test(aArray);
+ }
+}