< prev index next >
src/hotspot/share/opto/doCall.cpp
Print this page
@@ -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)->is_valuetype()->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
@@ -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);
}
@@ -698,16 +704,20 @@
// 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 >