changeset 482:4765d908e696

meth: fix C2 typing anomalies around weakly-typed call sites
author jrose
date Mon, 16 Jul 2012 20:40:17 -0700
parents a211c1a525fd
children c489641155e3
files meth-lazy-7023639.review.patch
diffstat 1 files changed, 122 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/meth-lazy-7023639.review.patch	Mon Jul 16 01:12:03 2012 -0700
+++ b/meth-lazy-7023639.review.patch	Mon Jul 16 20:40:17 2012 -0700
@@ -1,6 +1,56 @@
 # HG changeset patch
 # Parent 80f2a5825abb717dc55c38358758a373258beadd
 
+diff --git a/src/share/vm/ci/ciSignature.hpp b/src/share/vm/ci/ciSignature.hpp
+--- a/src/share/vm/ci/ciSignature.hpp
++++ b/src/share/vm/ci/ciSignature.hpp
+@@ -43,6 +43,7 @@
+   int _count;  // number of parameter types in the signature
+ 
+   friend class ciMethod;
++  friend class ciBytecodeStream;
+   friend class ciObjectFactory;
+ 
+   ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature);
+diff --git a/src/share/vm/ci/ciStreams.cpp b/src/share/vm/ci/ciStreams.cpp
+--- a/src/share/vm/ci/ciStreams.cpp
++++ b/src/share/vm/ci/ciStreams.cpp
+@@ -419,6 +419,24 @@
+ }
+ 
+ // ------------------------------------------------------------------
++// ciBytecodeStream::get_declared_method_signature
++//
++// Get the declared signature of the currently referenced method.
++//
++// This is always the same as the signature of the resolved method
++// itself, except for _invokehandle and _invokedynamic calls.
++//
++ciSignature* ciBytecodeStream::get_declared_method_signature() {
++  int sig_index = get_method_signature_index();
++  VM_ENTRY_MARK;
++  ciEnv* env = CURRENT_ENV;
++  constantPoolHandle cpool(_method->get_methodOop()->constants());
++  Symbol* sig_sym = cpool->symbol_at(sig_index);
++  ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass();
++  return new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym));
++}
++
++// ------------------------------------------------------------------
+ // ciBytecodeStream::get_method_signature_index
+ //
+ // Get the constant pool index of the signature of the method
+diff --git a/src/share/vm/ci/ciStreams.hpp b/src/share/vm/ci/ciStreams.hpp
+--- a/src/share/vm/ci/ciStreams.hpp
++++ b/src/share/vm/ci/ciStreams.hpp
+@@ -263,6 +263,7 @@
+   ciObject* get_appendix();
+   ciKlass*  get_declared_method_holder();
+   int       get_method_holder_index();
++  ciSignature* get_declared_method_signature();
+   int       get_method_signature_index();
+ 
+   ciCPCache*  get_cpcache() const;
 diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
 --- a/src/share/vm/classfile/javaClasses.cpp
 +++ b/src/share/vm/classfile/javaClasses.cpp
@@ -42,6 +92,78 @@
  }
  
  // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
+diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp
+--- a/src/share/vm/opto/doCall.cpp
++++ b/src/share/vm/opto/doCall.cpp
+@@ -496,9 +496,58 @@
+     // Round double result after a call from strict to non-strict code
+     round_double_result(cg->method());
+ 
++    ciType* rtype = cg->method()->return_type();
++    if (iter().cur_bc_raw() == Bytecodes::_invokehandle ||
++        iter().cur_bc() == Bytecodes::_invokedynamic) {
++      // Be careful here with return types.
++      ciType* ctype = iter().get_declared_method_signature()->return_type();
++      if (ctype != rtype) {
++        BasicType rt = rtype->basic_type();
++        BasicType ct = ctype->basic_type();
++        Node* retnode = peek();
++        if (rt == T_INT || is_subword_type(rt)) {
++          // FIXME: This logic should be factored out.
++          if (ct == T_BOOLEAN) {
++            retnode = _gvn.transform( new (C, 3) AndINode(retnode, intcon(0x1)) );
++          } else if (ct == T_CHAR) {
++            retnode = _gvn.transform( new (C, 3) AndINode(retnode, intcon(0xFFFF)) );
++          } else if (ct == T_BYTE) {
++            retnode = _gvn.transform( new (C, 3) LShiftINode(retnode, intcon(24)) );
++            retnode = _gvn.transform( new (C, 3) RShiftINode(retnode, intcon(24)) );
++          } else if (ct == T_SHORT) {
++            retnode = _gvn.transform( new (C, 3) LShiftINode(retnode, intcon(16)) );
++            retnode = _gvn.transform( new (C, 3) RShiftINode(retnode, intcon(16)) );
++          } else {
++            assert(ct == T_INT, err_msg("rt=%d, ct=%d", rt, ct));
++          }
++        } else if (rt == T_OBJECT) {
++          assert(ct == T_OBJECT, err_msg("rt=T_OBJECT, ct=%d", ct));
++          if (ctype->is_loaded()) {
++            Node* if_fail = top();
++            retnode = gen_checkcast(retnode, makecon(TypeKlassPtr::make(ctype->as_klass())), &if_fail);
++            if (if_fail != top()) {
++              PreserveJVMState pjvms(this);
++              set_control(if_fail);
++              builtin_throw(Deoptimization::Reason_class_check);
++            }
++            pop();
++            push(retnode);
++          }
++        } else {
++          assert(ct == T_VOID, err_msg("unexpected mismatch rt=%d, ct=%d", rt, ct));
++          // push a zero; it's better than getting an oop/int mismatch
++          retnode = pop_node(rt);
++          retnode = zerocon(ct);
++          push_node(ct, retnode);
++        }
++        // Now that the value is well-behaved, continue with the call-site type.
++        rtype = ctype;
++      }
++    }
++
+     // If the return type of the method is not loaded, assert that the
+     // value we got is a null.  Otherwise, we need to recompile.
+-    if (!cg->method()->return_type()->is_loaded()) {
++    if (!rtype->is_loaded()) {
+ #ifndef PRODUCT
+       if (PrintOpto && (Verbose || WizardMode)) {
+         method()->print_name(); tty->print_cr(" asserting nullness of result at bci: %d", bci());
+@@ -507,7 +556,7 @@
+ #endif
+       if (C->log() != NULL) {
+         C->log()->elem("assert_null reason='return' klass='%d'",
+-                       C->log()->identify(cg->method()->return_type()));
++                       C->log()->identify(rtype));
+       }
+       // If there is going to be a trap, put it at the next bytecode:
+       set_bci(iter().next_bci());
 diff --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp
 --- a/src/share/vm/prims/methodHandles.cpp
 +++ b/src/share/vm/prims/methodHandles.cpp