# HG changeset patch # User asaha # Date 1403796581 25200 # Node ID 71d4b9b14f9f006f0b88b6b73ab635cdbc72a84f # Parent 220eefb3609e250a0bb0ed26236c1213b8000050# Parent 4af30e82ba9e0cd8d75df2633037631055c90420 Merge diff -r 220eefb3609e -r 71d4b9b14f9f .hgtags --- a/.hgtags Wed Jun 18 13:30:11 2014 -0700 +++ b/.hgtags Thu Jun 26 08:29:41 2014 -0700 @@ -438,6 +438,7 @@ 17a75e692af397532e2b296b24f6b9b6c239c633 jdk8u5-b11 9b289963cb9a14636fbe8faaa2dd6d3678464a7b jdk8u5-b12 8a67179106085689906732013a282efeeb9bd5f4 jdk8u5-b13 +5c7ef8e396835b82c0460b73f23cac86ba34846f jdk8u5-b31 f0d759a6a2309a1c149d530b29db24eda885f267 jdk8u11-b01 3c079aebb516765784dd8097887daadda5a76ac1 jdk8u11-b02 0037e964ce486c009984171f004259263628079f jdk8u11-b03 @@ -488,6 +489,8 @@ 11159d7ec80462a422e39c9b3a39ae932923622d jdk8u20-b18 3e1cec358ab95ef985f821219104141b9ffda83f hs25.20-b19 b15553cde967dfd7781a4a5c669e4cb7db734317 jdk8u20-b19 +4f18dea0312d601d0515976bc0c643ea7acc829d hs25.20-b20 +9e4d27da4ac04c6e19291087f7c68a5c5803c7ca jdk8u20-b20 a4d44dfb7d30eea54bc172e4429a655454ae0bbf jdk8u25-b00 9a2152fbd929b0d8b2f5c326a5526214ae71731a jdk8u25-b01 d3d5604ea0dea3812e87ba76ac199d0a8be6f49f jdk8u25-b02 diff -r 220eefb3609e -r 71d4b9b14f9f agent/src/os/linux/libproc.h --- a/agent/src/os/linux/libproc.h Wed Jun 18 13:30:11 2014 -0700 +++ b/agent/src/os/linux/libproc.h Thu Jun 26 08:29:41 2014 -0700 @@ -34,7 +34,7 @@ #include "libproc_md.h" #endif -#include +#include /************************************************************************************ diff -r 220eefb3609e -r 71d4b9b14f9f make/hotspot_version diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Jun 26 08:29:41 2014 -0700 @@ -432,14 +432,6 @@ return hr; } -void G1CollectedHeap::stop_conc_gc_threads() { - _cg1r->stop(); - _cmThread->stop(); - if (G1StringDedup::is_enabled()) { - G1StringDedup::stop(); - } -} - #ifdef ASSERT // A region is added to the collection set as it is retired // so an address p can point to a region which will be in the @@ -2186,20 +2178,14 @@ } void G1CollectedHeap::stop() { -#if 0 - // Stopping concurrent worker threads is currently disabled until - // some bugs in concurrent mark has been resolve. Without fixing - // those bugs first we risk haning during VM exit when trying to - // stop these threads. - - // Abort any ongoing concurrent root region scanning and stop all - // concurrent threads. We do this to make sure these threads do - // not continue to execute and access resources (e.g. gclog_or_tty) + // Stop all concurrent threads. We do this to make sure these threads + // do not continue to execute and access resources (e.g. gclog_or_tty) // that are destroyed during shutdown. - _cm->root_regions()->abort(); - _cm->root_regions()->wait_until_scan_finished(); - stop_conc_gc_threads(); -#endif + _cg1r->stop(); + _cmThread->stop(); + if (G1StringDedup::is_enabled()) { + G1StringDedup::stop(); + } } size_t G1CollectedHeap::conservative_max_heap_alignment() { diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Jun 26 08:29:41 2014 -0700 @@ -1699,8 +1699,6 @@ void print_all_rsets() PRODUCT_RETURN; public: - void stop_conc_gc_threads(); - size_t pending_card_num(); size_t cards_scanned(); diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/opto/graphKit.cpp Thu Jun 26 08:29:41 2014 -0700 @@ -2458,7 +2458,7 @@ //------------------------------make_slow_call_ex------------------------------ // Make the exception handler hookups for the slow call -void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj) { +void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj, bool deoptimize) { if (stopped()) return; // Make a catch node with just two handlers: fall-through and catch-all @@ -2472,11 +2472,17 @@ set_i_o(i_o); if (excp != top()) { - // Create an exception state also. - // Use an exact type if the caller has specified a specific exception. - const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull); - Node* ex_oop = new (C) CreateExNode(ex_type, control(), i_o); - add_exception_state(make_exception_state(_gvn.transform(ex_oop))); + if (deoptimize) { + // Deoptimize if an exception is caught. Don't construct exception state in this case. + uncommon_trap(Deoptimization::Reason_unhandled, + Deoptimization::Action_none); + } else { + // Create an exception state also. + // Use an exact type if the caller has specified a specific exception. + const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull); + Node* ex_oop = new (C) CreateExNode(ex_type, control(), i_o); + add_exception_state(make_exception_state(_gvn.transform(ex_oop))); + } } } @@ -3290,7 +3296,8 @@ //---------------------------set_output_for_allocation------------------------- Node* GraphKit::set_output_for_allocation(AllocateNode* alloc, - const TypeOopPtr* oop_type) { + const TypeOopPtr* oop_type, + bool deoptimize_on_exception) { int rawidx = Compile::AliasIdxRaw; alloc->set_req( TypeFunc::FramePtr, frameptr() ); add_safepoint_edges(alloc); @@ -3298,7 +3305,7 @@ set_control( _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Control) ) ); // create memory projection for i_o set_memory ( _gvn.transform( new (C) ProjNode(allocx, TypeFunc::Memory, true) ), rawidx ); - make_slow_call_ex(allocx, env()->Throwable_klass(), true); + make_slow_call_ex(allocx, env()->Throwable_klass(), true, deoptimize_on_exception); // create a memory projection as for the normal control path Node* malloc = _gvn.transform(new (C) ProjNode(allocx, TypeFunc::Memory)); @@ -3376,9 +3383,11 @@ // The optional arguments are for specialized use by intrinsics: // - If 'extra_slow_test' if not null is an extra condition for the slow-path. // - If 'return_size_val', report the the total object size to the caller. +// - deoptimize_on_exception controls how Java exceptions are handled (rethrow vs deoptimize) Node* GraphKit::new_instance(Node* klass_node, Node* extra_slow_test, - Node* *return_size_val) { + Node* *return_size_val, + bool deoptimize_on_exception) { // Compute size in doublewords // The size is always an integral number of doublewords, represented // as a positive bytewise size stored in the klass's layout_helper. @@ -3447,7 +3456,7 @@ size, klass_node, initial_slow_test); - return set_output_for_allocation(alloc, oop_type); + return set_output_for_allocation(alloc, oop_type, deoptimize_on_exception); } //-------------------------------new_array------------------------------------- @@ -3457,7 +3466,8 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) Node* length, // number of array elements int nargs, // number of arguments to push back for uncommon trap - Node* *return_size_val) { + Node* *return_size_val, + bool deoptimize_on_exception) { jint layout_con = Klass::_lh_neutral_value; Node* layout_val = get_layout_helper(klass_node, layout_con); int layout_is_con = (layout_val == NULL); @@ -3600,7 +3610,7 @@ ary_type = ary_type->is_aryptr()->cast_to_size(length_type); } - Node* javaoop = set_output_for_allocation(alloc, ary_type); + Node* javaoop = set_output_for_allocation(alloc, ary_type, deoptimize_on_exception); // Cast length on remaining path to be as narrow as possible if (map()->find_edge(length) >= 0) { diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/opto/graphKit.hpp --- a/src/share/vm/opto/graphKit.hpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/opto/graphKit.hpp Thu Jun 26 08:29:41 2014 -0700 @@ -802,7 +802,7 @@ // merge in all memory slices from new_mem, along the given path void merge_memory(Node* new_mem, Node* region, int new_path); - void make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj); + void make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj, bool deoptimize = false); // Helper functions to build synchronizations int next_monitor(); @@ -844,13 +844,16 @@ // implementation of object creation Node* set_output_for_allocation(AllocateNode* alloc, - const TypeOopPtr* oop_type); + const TypeOopPtr* oop_type, + bool deoptimize_on_exception=false); Node* get_layout_helper(Node* klass_node, jint& constant_value); Node* new_instance(Node* klass_node, Node* slow_test = NULL, - Node* *return_size_val = NULL); + Node* *return_size_val = NULL, + bool deoptimize_on_exception = false); Node* new_array(Node* klass_node, Node* count_val, int nargs, - Node* *return_size_val = NULL); + Node* *return_size_val = NULL, + bool deoptimize_on_exception = false); // java.lang.String helpers Node* load_String_offset(Node* ctrl, Node* str); diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/opto/library_call.cpp Thu Jun 26 08:29:41 2014 -0700 @@ -4576,7 +4576,10 @@ // It's an instance, and it passed the slow-path tests. PreserveJVMState pjvms(this); Node* obj_size = NULL; - Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size); + // Need to deoptimize on exception from allocation since Object.clone intrinsic + // is reexecuted if deoptimization occurs and there could be problems when merging + // exception state between multiple Object.clone versions (reexecute=true vs reexecute=false). + Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size, /*deoptimize_on_exception=*/true); copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks()); diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/runtime/java.cpp Thu Jun 26 08:29:41 2014 -0700 @@ -497,9 +497,6 @@ os::infinite_sleep(); } - // Stop any ongoing concurrent GC work - Universe::heap()->stop(); - // Terminate watcher thread - must before disenrolling any periodic task if (PeriodicTask::num_tasks() > 0) WatcherThread::stop(); @@ -514,10 +511,8 @@ StatSampler::disengage(); StatSampler::destroy(); - // We do not need to explicitly stop concurrent GC threads because the - // JVM will be taken down at a safepoint when such threads are inactive -- - // except for some concurrent G1 threads, see (comment in) - // Threads::destroy_vm(). + // Stop concurrent GC threads + Universe::heap()->stop(); // Print GC/heap related information. if (PrintGCDetails) { diff -r 220eefb3609e -r 71d4b9b14f9f src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Wed Jun 18 13:30:11 2014 -0700 +++ b/src/share/vm/runtime/thread.cpp Thu Jun 26 08:29:41 2014 -0700 @@ -4013,14 +4013,8 @@ // GC vm_operations can get caught at the safepoint, and the // heap is unparseable if they are caught. Grab the Heap_lock // to prevent this. The GC vm_operations will not be able to - // queue until after the vm thread is dead. - // After this point, we'll never emerge out of the safepoint before - // the VM exits, so concurrent GC threads do not need to be explicitly - // stopped; they remain inactive until the process exits. - // Note: some concurrent G1 threads may be running during a safepoint, - // but these will not be accessing the heap, just some G1-specific side - // data structures that are not accessed by any other threads but them - // after this point in a terminal safepoint. + // queue until after the vm thread is dead. After this point, + // we'll never emerge out of the safepoint before the VM exits. MutexLocker ml(Heap_lock); diff -r 220eefb3609e -r 71d4b9b14f9f test/compiler/intrinsics/clone/TestObjectClone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/intrinsics/clone/TestObjectClone.java Thu Jun 26 08:29:41 2014 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, 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 8033626 + * @summary assert(ex_map->jvms()->same_calls_as(_exceptions->jvms())) failed: all collected exceptions must come from the same place + * @library /testlibrary + * @run main/othervm -XX:-TieredCompilation -Xbatch -XX:CompileOnly=TestObjectClone::f TestObjectClone + */ +import com.oracle.java.testlibrary.Asserts; + +public class TestObjectClone implements Cloneable { + static class A extends TestObjectClone {} + static class B extends TestObjectClone { + public B clone() { + return (B)TestObjectClone.b; + } + } + static class C extends TestObjectClone { + public C clone() { + return (C)TestObjectClone.c; + } + } + static class D extends TestObjectClone { + public D clone() { + return (D)TestObjectClone.d; + } + } + static TestObjectClone a = new A(), b = new B(), c = new C(), d = new D(); + + public static Object f(TestObjectClone o) throws CloneNotSupportedException { + // Polymorphic call site: >90% Object::clone / <10% other methods + return o.clone(); + } + + public static void main(String[] args) throws Exception { + TestObjectClone[] params1 = {a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, + a, a, a, a, a, a, a, a, a, a, a, + b, c, d}; + + for (int i = 0; i < 15000; i++) { + f(params1[i % params1.length]); + } + + Asserts.assertTrue(f(a) != a); + Asserts.assertTrue(f(b) == b); + Asserts.assertTrue(f(c) == c); + Asserts.assertTrue(f(d) == d); + + try { + f(null); + throw new AssertionError(""); + } catch (NullPointerException e) { /* expected */ } + + System.out.println("TEST PASSED"); + } +}