Merge
authorlana
Thu, 20 Oct 2016 20:01:43 +0000
changeset 41547 9d611e487d3e
parent 41538 73389cad43e0 (current diff)
parent 41546 357406d17607 (diff)
child 41548 715ad3143884
Merge
--- 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);
+    }
+}