< 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 ***
  
    // 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();
      // 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
--- 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 = 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 ***
      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()) {
      ciInstanceKlass* calling_klass = method()->holder();
      ciInstanceKlass* sender_klass = calling_klass;
      if (sender_klass->is_interface()) {
        receiver_constraint = sender_klass;
      }
--- 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_constructor()) {
      ciInstanceKlass* calling_klass = method()->holder();
      ciInstanceKlass* sender_klass = calling_klass;
      if (sender_klass->is_interface()) {
        receiver_constraint = sender_klass;
      }

*** 640,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()) {
      // 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);
    }
  
--- 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 && !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 ***
        // 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.
            // 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.
--- 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.
            // 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 ***
          } 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)) {
                Node* retnode = pop();
                Node* cast_obj = _gvn.transform(new CheckCastPPNode(control(), retnode, sig_type));
                push(cast_obj);
              }
            }
--- 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 (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 >