< 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"

@@ -561,11 +562,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

@@ -577,11 +583,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;
      }

@@ -646,11 +652,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);
    }
  

@@ -707,11 +713,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.

@@ -719,11 +725,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);
              }
            }

@@ -765,10 +774,15 @@
      }
      BasicType ct = ctype->basic_type();
      if (is_reference_type(ct)) {
        record_profiled_return_for_speculation();
      }
+     if (rtype->basic_type() == T_PRIMITIVE_OBJECT && !peek()->is_InlineTypeBase()) {
+       Node* retnode = pop();
+       retnode = InlineTypeNode::make_from_oop(this, retnode, rtype->as_inline_klass(), !gvn().type(retnode)->maybe_null());
+       push_node(T_PRIMITIVE_OBJECT, retnode);
+     }
    }
  
    // Restart record of parsing work after possible inlining of call
  #ifndef PRODUCT
    parse_histogram()->set_initial_state(bc());
< prev index next >