< prev index next >

src/hotspot/share/opto/doCall.cpp

Print this page
@@ -32,10 +32,11 @@
  #include "interpreter/linkResolver.hpp"
  #include "opto/addnode.hpp"
  #include "opto/callGenerator.hpp"
  #include "opto/castnode.hpp"
  #include "opto/cfgnode.hpp"
+ #include "opto/inlinetypenode.hpp"
  #include "opto/mulnode.hpp"
  #include "opto/parse.hpp"
  #include "opto/rootnode.hpp"
  #include "opto/runtime.hpp"
  #include "opto/subnode.hpp"

@@ -555,11 +556,16 @@
  
    // Speculative type of the receiver if any
    ciKlass* speculative_receiver_type = NULL;
    if (is_virtual_or_interface) {
      Node* receiver_node             = stack(sp() - nargs);
-     const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
+     const TypeOopPtr* receiver_type = NULL;
+     if (receiver_node->is_InlineType()) {
+       receiver_type = TypeInstPtr::make(TypePtr::NotNull, _gvn.type(receiver_node)->inline_klass());
+     } else {
+       receiver_type = _gvn.type(receiver_node)->isa_oopptr();
+     }
      // call_does_dispatch and vtable_index are out-parameters.  They might be changed.
      // For arrays, klass below is Object. When vtable calls are used,
      // resolving the call with Object would allow an illegal call to
      // finalize() on an array. We use holder instead: illegal calls to
      // finalize() won't be compiled as vtable calls (IC call

@@ -571,11 +577,11 @@
      speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL;
    }
  
    // Additional receiver subtype checks for interface calls via invokespecial or invokeinterface.
    ciKlass* receiver_constraint = NULL;
-   if (iter().cur_bc_raw() == Bytecodes::_invokespecial && !orig_callee->is_object_initializer()) {
+   if (iter().cur_bc_raw() == Bytecodes::_invokespecial && !orig_callee->is_object_constructor()) {
      ciInstanceKlass* calling_klass = method()->holder();
      ciInstanceKlass* sender_klass = calling_klass;
      if (sender_klass->is_interface()) {
        receiver_constraint = sender_klass;
      }

@@ -640,11 +646,11 @@
  
    // save across call, for a subsequent cast_not_null.
    Node* receiver = has_receiver ? argument(0) : NULL;
  
    // The extra CheckCastPPs for speculative types mess with PhaseStringOpts
-   if (receiver != NULL && !call_does_dispatch && !cg->is_string_late_inline()) {
+   if (receiver != NULL && !receiver->is_InlineType() && !call_does_dispatch && !cg->is_string_late_inline()) {
      // Feed profiling data for a single receiver to the type system so
      // it can propagate it as a speculative type
      receiver = record_profiled_receiver_for_speculation(receiver);
    }
  

@@ -701,11 +707,11 @@
        // Be careful here with return types.
        if (ctype != rtype) {
          BasicType rt = rtype->basic_type();
          BasicType ct = ctype->basic_type();
          if (ct == T_VOID) {
-           // It's OK for a method  to return a value that is discarded.
+           // It's OK for a method to return a value that is discarded.
            // The discarding does not require any special action from the caller.
            // The Java code knows this, at VerifyType.isNullConversion.
            pop_node(rt);  // whatever it was, pop it
          } else if (rt == T_INT || is_subword_type(rt)) {
            // Nothing.  These cases are handled in lambda form bytecode.

@@ -713,11 +719,14 @@
          } else if (is_reference_type(rt)) {
            assert(is_reference_type(ct), "rt=%s, ct=%s", type2name(rt), type2name(ct));
            if (ctype->is_loaded()) {
              const TypeOopPtr* arg_type = TypeOopPtr::make_from_klass(rtype->as_klass());
              const Type*       sig_type = TypeOopPtr::make_from_klass(ctype->as_klass());
-             if (arg_type != NULL && !arg_type->higher_equal(sig_type)) {
+             if (declared_signature->returns_null_free_inline_type()) {
+               sig_type = sig_type->join_speculative(TypePtr::NOTNULL);
+             }
+             if (arg_type != NULL && !arg_type->higher_equal(sig_type) && !peek()->is_InlineType()) {
                Node* retnode = pop();
                Node* cast_obj = _gvn.transform(new CheckCastPPNode(control(), retnode, sig_type));
                push(cast_obj);
              }
            }

@@ -739,10 +748,16 @@
        // the accessing class).
        assert(!rtype->is_loaded() || !ctype->is_loaded() || rtype == ctype,
               "mismatched return types: rtype=%s, ctype=%s", rtype->name(), ctype->name());
      }
  
+     if (rtype->basic_type() == T_INLINE_TYPE && !peek()->is_InlineType() && !gvn().type(peek())->maybe_null()) {
+       Node* retnode = pop();
+       retnode = InlineTypeNode::make_from_oop(this, retnode, rtype->as_inline_klass());
+       push_node(T_INLINE_TYPE, retnode);
+     }
+ 
      // 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 (!rtype->is_loaded()) {
        if (PrintOpto && (Verbose || WizardMode)) {
          method()->print_name(); tty->print_cr(" asserting nullness of result at bci: %d", bci());
< prev index next >