# HG changeset patch # User neliasso # Date 1352410748 -3600 # Node ID a4e1bd941dedb3e391f319bf63bbc57ccf43ced5 # Parent ead8852dd4ef4b7e9a5ae7804cd463fe84d6b8cc# Parent f3da5ff1514c04a0a2c5fcd3f63f3e68106e4baf Merge diff -r ead8852dd4ef -r a4e1bd941ded src/cpu/x86/vm/vm_version_x86.cpp --- a/src/cpu/x86/vm/vm_version_x86.cpp Wed Nov 07 16:09:20 2012 -0800 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Thu Nov 08 22:39:08 2012 +0100 @@ -488,8 +488,8 @@ } // The AES intrinsic stubs require AES instruction support (of course) - // but also require AVX mode for misaligned SSE access - if (UseAES && (UseAVX > 0)) { + // but also require AVX and sse3 modes for instructions it use. + if (UseAES && (UseAVX > 0) && (UseSSE > 2)) { if (FLAG_IS_DEFAULT(UseAESIntrinsics)) { UseAESIntrinsics = true; } diff -r ead8852dd4ef -r a4e1bd941ded src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Wed Nov 07 16:09:20 2012 -0800 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Thu Nov 08 22:39:08 2012 +0100 @@ -733,12 +733,7 @@ get_index_u2_cpcache(thread, bytecode), bytecode, CHECK); } // end JvmtiHideSingleStepping - cache_entry(thread)->set_method_handle( - pool, - info.resolved_method(), - info.resolved_appendix(), - info.resolved_method_type(), - pool->resolved_references()); + cache_entry(thread)->set_method_handle(pool, info); } IRT_END @@ -762,12 +757,7 @@ } // end JvmtiHideSingleStepping ConstantPoolCacheEntry* cp_cache_entry = pool->invokedynamic_cp_cache_entry_at(index); - cp_cache_entry->set_dynamic_call( - pool, - info.resolved_method(), - info.resolved_appendix(), - info.resolved_method_type(), - pool->resolved_references()); + cp_cache_entry->set_dynamic_call(pool, info); } IRT_END diff -r ead8852dd4ef -r a4e1bd941ded src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Wed Nov 07 16:09:20 2012 -0800 +++ b/src/share/vm/oops/cpCache.cpp Thu Nov 08 22:39:08 2012 +0100 @@ -243,25 +243,17 @@ } -void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, - methodHandle adapter, - Handle appendix, Handle method_type, - objArrayHandle resolved_references) { - set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, method_type, resolved_references); +void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, const CallInfo &call_info) { + set_method_handle_common(cpool, Bytecodes::_invokehandle, call_info); } -void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, - methodHandle adapter, - Handle appendix, Handle method_type, - objArrayHandle resolved_references) { - set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, method_type, resolved_references); +void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, const CallInfo &call_info) { + set_method_handle_common(cpool, Bytecodes::_invokedynamic, call_info); } void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, Bytecodes::Code invoke_code, - methodHandle adapter, - Handle appendix, Handle method_type, - objArrayHandle resolved_references) { + const CallInfo &call_info) { // NOTE: This CPCE can be the subject of data races. // There are three words to update: flags, refs[f2], f1 (in that order). // Writers must store all other values before f1. @@ -276,6 +268,9 @@ return; } + const methodHandle adapter = call_info.resolved_method(); + const Handle appendix = call_info.resolved_appendix(); + const Handle method_type = call_info.resolved_method_type(); const bool has_appendix = appendix.not_null(); const bool has_method_type = method_type.not_null(); @@ -315,6 +310,7 @@ // This allows us to create fewer method oops, while keeping type safety. // + objArrayHandle resolved_references = cpool->resolved_references(); // Store appendix, if any. if (has_appendix) { const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset; diff -r ead8852dd4ef -r a4e1bd941ded src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Wed Nov 07 16:09:20 2012 -0800 +++ b/src/share/vm/oops/cpCache.hpp Thu Nov 08 22:39:08 2012 +0100 @@ -117,6 +117,8 @@ // The fields are volatile so that they are stored in the order written in the // source code. The _indices field with the bytecode must be written last. +class CallInfo; + class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { friend class VMStructs; friend class constantPoolCacheKlass; @@ -223,18 +225,12 @@ void set_method_handle( constantPoolHandle cpool, // holding constant pool (required for locking) - methodHandle method, // adapter for invokeExact, etc. - Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.MethodType - Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType - objArrayHandle resolved_references + const CallInfo &call_info // Call link information ); void set_dynamic_call( constantPoolHandle cpool, // holding constant pool (required for locking) - methodHandle method, // adapter for this call site - Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.CallSite - Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType - objArrayHandle resolved_references + const CallInfo &call_info // Call link information ); // Common code for invokedynamic and MH invocations. @@ -255,10 +251,7 @@ void set_method_handle_common( constantPoolHandle cpool, // holding constant pool (required for locking) Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic - methodHandle adapter, // invoker method (f1) - Handle appendix, // appendix such as CallSite, MethodType, etc. (refs[f2+0]) - Handle method_type, // MethodType (refs[f2+1]) - objArrayHandle resolved_references + const CallInfo &call_info // Call link information ); // invokedynamic and invokehandle call sites have two entries in the diff -r ead8852dd4ef -r a4e1bd941ded src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Wed Nov 07 16:09:20 2012 -0800 +++ b/src/share/vm/opto/escape.cpp Thu Nov 08 22:39:08 2012 +0100 @@ -1386,12 +1386,12 @@ // Non-escaped allocation returned from Java or runtime call have // unknown values in fields. for (EdgeIterator i(pta); i.has_next(); i.next()) { - PointsToNode* ptn = i.get(); - if (ptn->is_Field() && ptn->as_Field()->is_oop()) { - if (add_edge(ptn, phantom_obj)) { + PointsToNode* field = i.get(); + if (field->is_Field() && field->as_Field()->is_oop()) { + if (add_edge(field, phantom_obj)) { // New edge was added new_edges++; - add_field_uses_to_worklist(ptn->as_Field()); + add_field_uses_to_worklist(field->as_Field()); } } } @@ -1413,30 +1413,30 @@ // captured by Initialize node. // for (EdgeIterator i(pta); i.has_next(); i.next()) { - PointsToNode* ptn = i.get(); // Field (AddP) - if (!ptn->is_Field() || !ptn->as_Field()->is_oop()) + PointsToNode* field = i.get(); // Field (AddP) + if (!field->is_Field() || !field->as_Field()->is_oop()) continue; // Not oop field - int offset = ptn->as_Field()->offset(); + int offset = field->as_Field()->offset(); if (offset == Type::OffsetBot) { if (!visited_bottom_offset) { // OffsetBot is used to reference array's element, // always add reference to NULL to all Field nodes since we don't // known which element is referenced. - if (add_edge(ptn, null_obj)) { + if (add_edge(field, null_obj)) { // New edge was added new_edges++; - add_field_uses_to_worklist(ptn->as_Field()); + add_field_uses_to_worklist(field->as_Field()); visited_bottom_offset = true; } } } else { // Check only oop fields. - const Type* adr_type = ptn->ideal_node()->as_AddP()->bottom_type(); + const Type* adr_type = field->ideal_node()->as_AddP()->bottom_type(); if (adr_type->isa_rawptr()) { #ifdef ASSERT // Raw pointers are used for initializing stores so skip it // since it should be recorded already - Node* base = get_addp_base(ptn->ideal_node()); + Node* base = get_addp_base(field->ideal_node()); assert(adr_type->isa_rawptr() && base->is_Proj() && (base->in(0) == alloc),"unexpected pointer type"); #endif @@ -1446,10 +1446,54 @@ offsets_worklist.append(offset); Node* value = NULL; if (ini != NULL) { - BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT; - Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase); - if (store != NULL && store->is_Store()) { + // StoreP::memory_type() == T_ADDRESS + BasicType ft = UseCompressedOops ? T_NARROWOOP : T_ADDRESS; + Node* store = ini->find_captured_store(offset, type2aelembytes(ft, true), phase); + // Make sure initializing store has the same type as this AddP. + // This AddP may reference non existing field because it is on a + // dead branch of bimorphic call which is not eliminated yet. + if (store != NULL && store->is_Store() && + store->as_Store()->memory_type() == ft) { value = store->in(MemNode::ValueIn); +#ifdef ASSERT + if (VerifyConnectionGraph) { + // Verify that AddP already points to all objects the value points to. + PointsToNode* val = ptnode_adr(value->_idx); + assert((val != NULL), "should be processed already"); + PointsToNode* missed_obj = NULL; + if (val->is_JavaObject()) { + if (!field->points_to(val->as_JavaObject())) { + missed_obj = val; + } + } else { + if (!val->is_LocalVar() || (val->edge_count() == 0)) { + tty->print_cr("----------init store has invalid value -----"); + store->dump(); + val->dump(); + assert(val->is_LocalVar() && (val->edge_count() > 0), "should be processed already"); + } + for (EdgeIterator j(val); j.has_next(); j.next()) { + PointsToNode* obj = j.get(); + if (obj->is_JavaObject()) { + if (!field->points_to(obj->as_JavaObject())) { + missed_obj = obj; + break; + } + } + } + } + if (missed_obj != NULL) { + tty->print_cr("----------field---------------------------------"); + field->dump(); + tty->print_cr("----------missed referernce to object-----------"); + missed_obj->dump(); + tty->print_cr("----------object referernced by init store -----"); + store->dump(); + val->dump(); + assert(!field->points_to(missed_obj->as_JavaObject()), "missed JavaObject reference"); + } + } +#endif } else { // There could be initializing stores which follow allocation. // For example, a volatile field store is not collected @@ -1462,10 +1506,10 @@ } if (value == NULL) { // A field's initializing value was not recorded. Add NULL. - if (add_edge(ptn, null_obj)) { + if (add_edge(field, null_obj)) { // New edge was added new_edges++; - add_field_uses_to_worklist(ptn->as_Field()); + add_field_uses_to_worklist(field->as_Field()); } } } @@ -1607,7 +1651,26 @@ } // Verify that all fields have initializing values. if (field->edge_count() == 0) { + tty->print_cr("----------field does not have references----------"); field->dump(); + for (BaseIterator i(field); i.has_next(); i.next()) { + PointsToNode* base = i.get(); + tty->print_cr("----------field has next base---------------------"); + base->dump(); + if (base->is_JavaObject() && (base != phantom_obj) && (base != null_obj)) { + tty->print_cr("----------base has fields-------------------------"); + for (EdgeIterator j(base); j.has_next(); j.next()) { + j.get()->dump(); + } + tty->print_cr("----------base has references---------------------"); + for (UseIterator j(base); j.has_next(); j.next()) { + j.get()->dump(); + } + } + } + for (UseIterator i(field); i.has_next(); i.next()) { + i.get()->dump(); + } assert(field->edge_count() > 0, "sanity"); } } @@ -1967,7 +2030,7 @@ if (is_JavaObject()) { return (this == ptn); } - assert(is_LocalVar(), "sanity"); + assert(is_LocalVar() || is_Field(), "sanity"); for (EdgeIterator i(this); i.has_next(); i.next()) { if (i.get() == ptn) return true; @@ -3127,10 +3190,14 @@ EscapeState fields_es = fields_escape_state(); tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]); if (nt == PointsToNode::JavaObject && !this->scalar_replaceable()) - tty->print("NSR"); + tty->print("NSR "); } if (is_Field()) { FieldNode* f = (FieldNode*)this; + if (f->is_oop()) + tty->print("oop "); + if (f->offset() > 0) + tty->print("+%d ", f->offset()); tty->print("("); for (BaseIterator i(f); i.has_next(); i.next()) { PointsToNode* b = i.get(); diff -r ead8852dd4ef -r a4e1bd941ded test/compiler/8002069/Test8002069.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8002069/Test8002069.java Thu Nov 08 22:39:08 2012 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2012, 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 8002069 + * @summary Assert failed in C2: assert(field->edge_count() > 0) failed: sanity + * + * @run main/othervm -Xmx32m -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:CompileCommand=exclude,Test8002069.dummy Test8002069 + */ + +abstract class O { + int f; + public O() { f = 5; } + abstract void put(int i); + public int foo(int i) { + put(i); + return i; + } +}; + +class A extends O { + int[] a; + public A(int s) { + a = new int[s]; + } + public void put(int i) { + a[i%a.length] = i; + } +} + +class B extends O { + int sz; + int[] a; + public B(int s) { + sz = s; + a = new int[s]; + } + public void put(int i) { + a[i%sz] = i; + } +} + +public class Test8002069 { + public static void main(String args[]) { + int sum = 0; + for (int i=0; i<8000; i++) { + sum += test1(i); + } + for (int i=0; i<100000; i++) { + sum += test2(i); + } + System.out.println("PASSED. sum = " + sum); + } + + private O o; + + private int foo(int i) { + return o.foo(i); + } + static int test1(int i) { + Test8002069 t = new Test8002069(); + t.o = new A(5); + return t.foo(i); + } + static int test2(int i) { + Test8002069 t = new Test8002069(); + t.o = new B(5); + dummy(i); + return t.foo(i); + } + + static int dummy(int i) { + return i*2; + } +} +