< prev index next >

src/hotspot/share/opto/doCall.cpp

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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.

@@ -36,10 +36,11 @@
 #include "opto/mulnode.hpp"
 #include "opto/parse.hpp"
 #include "opto/rootnode.hpp"
 #include "opto/runtime.hpp"
 #include "opto/subnode.hpp"
+#include "opto/valuetypenode.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/sharedRuntime.hpp"
 
 void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) {
   if (TraceTypeProfile || C->print_inlining()) {

@@ -535,11 +536,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_ValueType()) {
+      receiver_type = TypeInstPtr::make(TypePtr::NotNull, _gvn.type(receiver_node)->value_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

@@ -551,11 +557,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->is_unsafe_anonymous() ? calling_klass->unsafe_anonymous_host() :
                                                calling_klass;
     if (sender_klass->is_interface()) {

@@ -622,11 +628,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_ValueType() && !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);
   }
 

@@ -691,23 +697,27 @@
       // 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.
           assert(ct == T_INT || is_subword_type(ct), "must match: rt=%s, ct=%s", type2name(rt), type2name(ct));
-        } else if (rt == T_OBJECT || rt == T_ARRAY) {
-          assert(ct == T_OBJECT || ct == T_ARRAY, "rt=%s, ct=%s", type2name(rt), type2name(ct));
+        } else if (rt == T_OBJECT || rt == T_ARRAY || rt == T_VALUETYPE) {
+          assert(ct == T_OBJECT || ct == T_ARRAY || ct == T_VALUETYPE, "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_never_null()) {
+              assert(ct == T_VALUETYPE, "should be a value type");
+              sig_type = sig_type->join_speculative(TypePtr::NOTNULL);
+            }
+            if (arg_type != NULL && !arg_type->higher_equal(sig_type) && !peek()->is_ValueType()) {
               Node* retnode = pop();
               Node* cast_obj = _gvn.transform(new CheckCastPPNode(control(), retnode, sig_type));
               push(cast_obj);
             }
           }

@@ -729,10 +739,18 @@
       // 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_VALUETYPE && !peek()->is_ValueType()) {
+      Node* retnode = pop();
+      if (!gvn().type(retnode)->maybe_null() && rtype->as_value_klass()->is_scalarizable()) {
+        retnode = ValueTypeNode::make_from_oop(this, retnode, rtype->as_value_klass());
+      }
+      push_node(T_VALUETYPE, 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 >