< prev index next > src/hotspot/share/opto/doCall.cpp
Print this page
/*
! * Copyright (c) 1998, 2025, 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.
/*
! * Copyright (c) 1998, 2026, 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.
*/
#include "ci/ciCallSite.hpp"
#include "ci/ciMethodHandle.hpp"
#include "ci/ciSymbols.hpp"
+ #include "classfile/vmIntrinsics.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp"
+ #include "jvm_io.h"
#include "logging/log.hpp"
#include "logging/logLevel.hpp"
#include "logging/logMessage.hpp"
#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;
}
// ---------------------
// Decide call tactic.
// This call checks with CHA, the interpreter profile, intrinsics table, etc.
// It decides whether inlining is desirable or not.
CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type);
+ if (failing()) {
+ return;
+ }
+ assert(cg != nullptr, "must find a CallGenerator for callee %s", callee->name()->as_utf8());
// NOTE: Don't use orig_callee and callee after this point! Use cg->method() instead.
orig_callee = callee = nullptr;
// ---------------------
// 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.
}
BasicType ct = ctype->basic_type();
if (is_reference_type(ct)) {
record_profiled_return_for_speculation();
}
+
+ if (!rtype->is_void()) {
+ Node* retnode = peek();
+ const Type* rettype = gvn().type(retnode);
+ if (rettype->is_inlinetypeptr() && !retnode->is_InlineType()) {
+ retnode = InlineTypeNode::make_from_oop(this, retnode, rettype->inline_klass());
+ dec_sp(1);
+ push(retnode);
+ }
+ }
+
+ if (cg->method()->is_object_constructor() && receiver != nullptr && gvn().type(receiver)->is_inlinetypeptr()) {
+ InlineTypeNode* non_larval = InlineTypeNode::make_from_oop(this, receiver, gvn().type(receiver)->inline_klass());
+ // Relinquish the oop input, we will delay the allocation to the point it is needed, see the
+ // comments in InlineTypeNode::Ideal for more details
+ non_larval = non_larval->clone_if_required(&gvn(), nullptr);
+ non_larval->set_oop(gvn(), null());
+ non_larval->set_is_buffered(gvn(), false);
+ non_larval = gvn().transform(non_larval)->as_InlineType();
+ map()->replace_edge(receiver, non_larval);
+ }
}
// Restart record of parsing work after possible inlining of call
#ifndef PRODUCT
parse_histogram()->set_initial_state(bc());
< prev index next >