diff --git a/.hgtags b/.hgtags index 8bde378841e1c5443f53b22db61c84cf8e0724f2..d686a8fca6361ace4884a8e39828e7a8ef3b12e5 100644 --- a/.hgtags +++ b/.hgtags @@ -861,6 +861,9 @@ a2b0ee820059a44be558a2d435b7d85ed5a8b63a jdk8u76-b10 f3e1e734e2d29101a9537ddeb71ecad413fcd352 jdk8u92-b13 24a09407d71bb2cc4848bfa21660c890b4d722b1 jdk8u92-b14 445941ba41c0e3829fe02140690b144281ac2141 jdk8u92-b31 +f958bebdee267695e37aadd27753ac8b1e1823c8 jdk8u92-b32 +d1bb0e79ff79d21068388d9c62ca01e3c072fd0d jdk8u92-b33 +d0388be32561e4bd00c1a79adbe301cfdd6ba9f2 jdk8u92-b34 b374548dcb4834eb8731a06b52faddd0f10bd45d jdk8u81-b00 ead07188d11107e877e8e4ad215ff6cb238a8a92 jdk8u101-b01 34429bad9986677f4991c80aeb22665842881cba jdk8u101-b02 @@ -891,10 +894,36 @@ b5ecd8067e899c4bfb8d327ee7583a32129772d4 jdk8u102-b09 340e1a736ef7169786e70db7f31ffd32bc3be24d jdk8u102-b12 f6daf04c0f48dab5420ad63d21da82a7fa4e3ad7 jdk8u102-b13 ac29c9c1193aef5d480b200ed94c5d579243c17b jdk8u102-b14 +96e1c72fc617d3c6c125bcfc9182f77fc6aa38e6 jdk8u102-b31 +ceecf88e5c2c09bfabf5926581e6d0b0f65f5148 jdk8u111-b00 +e73d79ce00e4a0451e464c7a73d9c911d01e169a jdk8u111-b01 +d584a614818562e1187e1a15c202aec01491caeb jdk8u111-b02 +a3ede966ecfe6009fe4a58fbd6903c470a059ad3 jdk8u111-b03 +65029655928a834018a6793253c9b2699044af92 jdk8u111-b04 +e4525db272634b980738003eff99ac1588bb79d3 jdk8u111-b05 +019b22dd8128840ecdcd1bfebcf4447e28e45068 jdk8u111-b06 +3f337aaf090769653ee0a746fbe661d09055a883 jdk8u111-b07 +e180e364a40364a059a20c74b97ab4e928e2b676 jdk8u111-b08 +c48b303692bb86c42e928da6dec815e901a24c5b jdk8u111-b09 +96973081eb8a132ca3bfee9249ad99c185b6b130 jdk8u111-b10 +603804f2132ff188a9f3d1c31cca63b47220e2e2 jdk8u111-b11 +055bc2a065a503e8714ff7ad27e6197dc0339efa jdk8u111-b12 +c3b42c43c230f10e79ae850ee9062fe86d3c75c9 jdk8u111-b13 +05a6a5823aa58a0a4720a328a9db484f21d573bc jdk8u111-b14 b09a69142dd3bf78ca66bb0c99046ca7cccbdda9 jdk8u112-b00 cf1faa9100dd8c8df6e1a604aaf613d037f51ebf jdk8u112-b01 f22b5be95347c669a1463d9e05ec3bf11420208e jdk8u112-b02 f2f59d888427b1db336766bc8cd272f2b2d84e1a jdk8u112-b03 c171546c49b5ff57bcb74bb54e8860647f83f268 jdk8u112-b04 +4b7af794466ba22461ed043a1394df43e4993c4f jdk8u112-b06 +55ed9b0a35e4ad4bb5ca3f393f6749e81ad9fef0 jdk8u112-b07 +670f8169b83c6af14339fe37b2a2b8384dc2149b jdk8u112-b08 +1ccd27199595fedefcd1ca4a335e049887c63107 jdk8u112-b09 +2de719469e959ae1f7bd4fd64af8470f1d03d3bb jdk8u112-b10 +c2ca4df6580822835f3b21436b79e123910c4eb5 jdk8u112-b11 +44dcadfb9e7038a1ae288a99a728526ed97d2b7c jdk8u112-b12 +7bc1061f52cfc5ce4cbfd42dd2dcdc91e7efce72 jdk8u112-b13 +c2c4db2a42a215c98a4f027edb8bbb00dd62d9b9 jdk8u112-b14 +b28d012a24cab8f4ceeee0c9d3252969757423ed jdk8u112-b15 5aa8c4ca51f0e666d368a4f119ed734d3ac59d7c jdk8u122-b00 2198ef7e1c1702b3506b95b5d8c886ad5a12bbe5 jdk8u122-b01 diff --git a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 89c1780da3142a3086c5ec932f5550cb9bcb96da..b3b3dcb557046904222e96cc9482cfdf6f2beaa6 100644 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -2168,6 +2168,27 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ 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()); diff --git a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 45fd761970dcc048ceca5c2b7c17099180d049d7..1db53a9ddc073ff75833bf3ca3d188fa2c8c99ad 100644 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -3275,6 +3275,23 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { __ 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); diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp index 9e39ac94daa062b11e90a2d8ef5e2b77f6c3cb12..9678287b8eb4cf3e5fc7aeaa7d693babd5955dec 100644 --- a/src/share/vm/classfile/classFileParser.cpp +++ b/src/share/vm/classfile/classFileParser.cpp @@ -3973,6 +3973,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, // Make sure this is the end of class file stream guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); + 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_(nullHandle)); + } // We check super class after class file is parsed and format is checked if (super_class_index > 0 && super_klass.is_null()) { Symbol* sk = cp->klass_name_at(super_class_index); diff --git a/src/share/vm/classfile/stackMapTableFormat.hpp b/src/share/vm/classfile/stackMapTableFormat.hpp index 8bfa625ca3fe3f156ad6c34308cd74d928340de1..469a6b5adca6dcd138c935010f3ddfb0e45e181b 100644 --- a/src/share/vm/classfile/stackMapTableFormat.hpp +++ b/src/share/vm/classfile/stackMapTableFormat.hpp @@ -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 @@ class stack_map_frame { 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 @@ class same_frame : public stack_map_frame { 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 @@ class same_frame_extended : public stack_map_frame { 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 @@ class same_locals_1_stack_item_frame : public stack_map_frame { 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 @@ class same_locals_1_stack_item_extended : public stack_map_frame { 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 @@ class chop_frame : public stack_map_frame { 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 @@ class append_frame : public stack_map_frame { } 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 @@ class full_frame : public stack_map_frame { } 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 @@ void stack_map_frame::print_on(outputStream* st, int offs = -1) const { 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 diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp index e1f9f23819627d866fe845d486e4ee574502719c..58bd4f7abd9ff7b8f4fd4d6849c10c029878e003 100644 --- a/src/share/vm/classfile/verifier.cpp +++ b/src/share/vm/classfile/verifier.cpp @@ -504,8 +504,19 @@ void ErrorContext::stackmap_details(outputStream* ss, const Method* method) cons 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(); diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp index 6d4498db3d1690afefd9253480422afa10c6453c..f1b13f2b16d991cbb1383f2bf7a7b86e9ab4bd28 100644 --- a/src/share/vm/prims/jvm.cpp +++ b/src/share/vm/prims/jvm.cpp @@ -2630,7 +2630,6 @@ JVM_ENTRY(const char*, JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_i 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"); @@ -2648,7 +2647,6 @@ JVM_ENTRY(const char*, JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint 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"); diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp index a21ce234822ce7aefd8c70e540b2cacd2d178a63..4e269bee1dbc1892c5a6e20d800538e67158982b 100644 --- a/src/share/vm/runtime/arguments.cpp +++ b/src/share/vm/runtime/arguments.cpp @@ -560,8 +560,9 @@ char* SysClassPath::add_jars_to_path(char* path, const char* directory) { (os::file_name_strcmp(ext, ".jar") == 0 || os::file_name_strcmp(ext, ".zip") == 0); if (isJarOrZip) { - char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtInternal); - sprintf(jarpath, "%s%s%s", directory, dir_sep, name); + size_t length = directory_len + 2 + strlen(name); + char* jarpath = NEW_C_HEAP_ARRAY(char, length, mtInternal); + jio_snprintf(jarpath, length, "%s%s%s", directory, dir_sep, name); path = add_to_path(path, jarpath, false); FREE_C_HEAP_ARRAY(char, jarpath, mtInternal); } @@ -704,9 +705,10 @@ static bool append_to_string_flag(char* name, const char* new_value, Flag::Flags } else if (new_len == 0) { value = old_value; } else { - char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtInternal); + size_t length = old_len + 1 + new_len + 1; + char* buf = NEW_C_HEAP_ARRAY(char, length, mtInternal); // 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; } @@ -813,15 +815,17 @@ const char* Arguments::build_resource_string(char** args, int count) { 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; } @@ -1889,7 +1893,7 @@ void Arguments::set_aggressive_opts_flags() { // 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); add_property(buffer); } if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) { @@ -2764,7 +2768,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, char *options = NULL; if(pos != NULL) { - options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(pos + 1) + 1, mtInternal), pos + 1); + size_t length = strlen(pos + 1) + 1; + options = NEW_C_HEAP_ARRAY(char, length, mtInternal); + jio_snprintf(options, length, "%s", pos + 1); } #if !INCLUDE_JVMTI if (valid_hprof_or_jdwp_agent(name, is_absolute_path)) { @@ -2783,7 +2789,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_ERR; #else if(tail != NULL) { - char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail); + size_t length = strlen(tail) + 1; + char *options = NEW_C_HEAP_ARRAY(char, length, mtInternal); + jio_snprintf(options, length, "%s", tail); add_init_agent("instrument", options, false); } #endif // !INCLUDE_JVMTI @@ -3621,8 +3629,7 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req } } else { char buffer[256]; - strcpy(buffer, "java.awt.headless="); - strcat(buffer, envbuffer); + jio_snprintf(buffer, 256, "java.awt.headless=%s", envbuffer); if (!add_property(buffer)) { return JNI_ENOMEM; } @@ -3721,6 +3728,14 @@ jint Arguments::parse_options_environment_variable(const char* name, SysClassPat 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"); } diff --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp index 5638dd5cafcfdecaee0824c0d703633f6af07bdb..e51004245a41f8cf60888ab11702aee070173287 100644 --- a/src/share/vm/runtime/sharedRuntime.cpp +++ b/src/share/vm/runtime/sharedRuntime.cpp @@ -2830,8 +2830,6 @@ VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, 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 ); @@ -2840,7 +2838,7 @@ VMRegPair *SharedRuntime::find_callee_arguments(Symbol* sig, bool has_receiver, 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; diff --git a/src/share/vm/runtime/signature.cpp b/src/share/vm/runtime/signature.cpp index dd3ed8bfcb717c6f6af7f229a90c9bef57410c63..975c1f42e7373244f9c441a7814acb88add2e942 100644 --- a/src/share/vm/runtime/signature.cpp +++ b/src/share/vm/runtime/signature.cpp @@ -225,7 +225,49 @@ void SignatureIterator::iterate_returntype() { _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; diff --git a/test/compiler/c1/TestArrayCopyToFromObject.java b/test/compiler/c1/TestArrayCopyToFromObject.java new file mode 100644 index 0000000000000000000000000000000000000000..e875bd5f7c92e9ddd005a339a7a0c4d42d4b37e5 --- /dev/null +++ b/test/compiler/c1/TestArrayCopyToFromObject.java @@ -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); + } +}