< prev index next > src/hotspot/share/opto/doCall.cpp
Print this page
#include "logging/logStream.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"
speculative_receiver_type = receiver_type != nullptr ? receiver_type->speculative_type() : nullptr;
}
// Additional receiver subtype checks for interface calls via invokespecial or invokeinterface.
ciKlass* receiver_constraint = nullptr;
! 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;
}
speculative_receiver_type = receiver_type != nullptr ? receiver_type->speculative_type() : nullptr;
}
// Additional receiver subtype checks for interface calls via invokespecial or invokeinterface.
ciKlass* receiver_constraint = nullptr;
! 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;
}
// 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.
// 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.
} 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 != nullptr && !arg_type->higher_equal(sig_type)) {
Node* retnode = pop();
Node* cast_obj = _gvn.transform(new CheckCastPPNode(control(), retnode, sig_type));
push(cast_obj);
}
}
BasicType ct = ctype->basic_type();
if (is_reference_type(ct)) {
record_profiled_return_for_speculation();
}
+ if (rtype->is_inlinetype() && !peek()->is_InlineType()) {
+ Node* retnode = pop();
+ retnode = InlineTypeNode::make_from_oop(this, retnode, rtype->as_inline_klass(), !gvn().type(retnode)->maybe_null());
+ push_node(T_OBJECT, retnode);
+ }
}
// Restart record of parsing work after possible inlining of call
#ifndef PRODUCT
parse_histogram()->set_initial_state(bc());
< prev index next >