--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Nov 07 16:09:20 2012 -0800
+++ b/hotspot/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;
}
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Nov 07 16:09:20 2012 -0800
+++ b/hotspot/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
--- a/hotspot/src/share/vm/oops/cpCache.cpp Wed Nov 07 16:09:20 2012 -0800
+++ b/hotspot/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;
--- a/hotspot/src/share/vm/oops/cpCache.hpp Wed Nov 07 16:09:20 2012 -0800
+++ b/hotspot/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
--- a/hotspot/src/share/vm/opto/escape.cpp Wed Nov 07 16:09:20 2012 -0800
+++ b/hotspot/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();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/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;
+ }
+}
+