これらは, C2 JIT Compiler 用の高レベル中間語を表すクラス. より具体的に言うと, 「メソッド呼び出し (及びそれに関連する処理)」 を表すクラス.
なおメモリ確保処理(AllocateNode/AllocateArrayNode)や同期排他処理(LockNode/UnlockNode)についても, ランタイム呼び出しを含むコードに展開される(可能性がある)ので CallNode のサブクラスとされている.
MultiNode クラスの具象サブクラスの1つ. メソッドの開始点を表す Node.
RootNode の直下に存在し, メソッド開始時点でのプログラムの状態を表す.
MultiNode クラスなので出力は複数存在し, control flow (制御情報)とメソッドの引数(データ情報)からなる Tuple になっている (なお個々の要素は ProjNode のサブクラスである ParmNode で取り出す).
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// The method start node
class StartNode : public MultiNode {
以下の箇所で(のみ)生成されている.
(control input も含めて) 2つの入力ノードを持つ. それぞれの入力の意味は以下の通り.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
StartNode( Node *root, const TypeTuple *domain ) : MultiNode(2), _domain(domain) {
init_class_id(Class_Start);
init_flags(Flag_is_block_start);
init_req(0,this);
init_req(1,root);
}
See: here for details
特殊な StartNode クラス.
OSR (On Stack Replacement) の場合には StartNode の代わりにこのクラスが使用される. 役割は StartNode とほぼ同様.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// The method start node for on stack replacement code
class StartOSRNode : public StartNode {
Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, bool subsume_loads, bool do_escape_analysis ) 内で(のみ)生成されている.
(control input も含めて) 2つの入力ノードを持つ. それぞれの入力の意味は以下の通り.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
StartOSRNode( Node *root, const TypeTuple *domain ) : StartNode(root, domain) {}
See: here for details
ProjNode クラスのサブクラスの1つ.
StartNode/StartOSRNode から引数を取り出すためのノード.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Incoming parameters
class ParmNode : public ProjNode {
以下の箇所で(のみ)生成されている.
コンパイル対象のメソッドの引数を表す.
生成対象のスタブの引数を表す.
HaltNode の引数 (frameptr) を取得するために生成されている.
HaltNode の引数 (frameptr) を取得するために生成されている.
入力ノードは control input のみ. control input は対応する StartNode/StartOSRNode を示す.
(なお, コンストラクタには対応する StartNode/StartOSRNode と何番目の引数かを示す数字が渡される)
((cite: hotspot/src/share/vm/opto/callnode.hpp))
ParmNode( StartNode *src, uint con ) : ProjNode(src,con) {
init_class_id(Class_Parm);
}
See: here for details
リターン(及びそれによるメソッドの終了処理)を表す Node.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Return from subroutine node
class ReturnNode : public Node {
以下の箇所で(のみ)生成されている.
コンパイル対象のメソッドからのリターンを表す.
生成対象のスタブからのリターンを表す.
(control input も含めて) 5つまたは6つの入力ノードを持つ. 返値がなければ 5個, あれば 6個になる. それぞれの入力の意味は以下の通り.
((cite: hotspot/src/share/vm/opto/callnode.cpp))
ReturnNode::ReturnNode(uint edges, Node *cntrl, Node *i_o, Node *memory, Node *frameptr, Node *retadr ) : Node(edges) {
init_req(TypeFunc::Control,cntrl);
init_req(TypeFunc::I_O,i_o);
init_req(TypeFunc::Memory,memory);
init_req(TypeFunc::FramePtr,frameptr);
init_req(TypeFunc::ReturnAdr,retadr);
}
See: here for details
throws 宣言されている例外による大域脱出処理(及びそれによるメソッドの終了処理)を表す Node.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Rethrow of exception at call site. Ends a procedure before rethrowing;
// ends the current basic block like a ReturnNode. Restores registers and
// unwinds stack. Rethrow happens in the caller's method.
class RethrowNode : public Node {
Compile::rethrow_exceptions() でのみ生成されている.
(control input も含めて) 6つの入力ノードを持つ. それぞれの入力の意味は以下の通り.
((cite: hotspot/src/share/vm/opto/callnode.cpp))
RethrowNode::RethrowNode(
Node* cntrl,
Node* i_o,
Node* memory,
Node* frameptr,
Node* ret_adr,
Node* exception
) : Node(TypeFunc::Parms + 1) {
init_req(TypeFunc::Control , cntrl );
init_req(TypeFunc::I_O , i_o );
init_req(TypeFunc::Memory , memory );
init_req(TypeFunc::FramePtr , frameptr );
init_req(TypeFunc::ReturnAdr, ret_adr);
init_req(TypeFunc::Parms , exception);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Pop stack frame and jump indirect
class TailCallNode : public ReturnNode {
GraphKit::gen_stub() 内で(のみ)生成されている.
(control input も含めて) 7つの入力ノードを持つ. それぞれの入力の意味は以下の通り.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
TailCallNode( Node *cntrl, Node *i_o, Node *memory, Node *frameptr, Node *retadr, Node *target, Node *moop )
: ReturnNode( TypeFunc::Parms+2, cntrl, i_o, memory, frameptr, retadr ) {
init_req(TypeFunc::Parms, target);
init_req(TypeFunc::Parms+1, moop);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Pop stack frame and jump indirect
class TailJumpNode : public ReturnNode {
GraphKit::gen_stub() でのみ生成されている.
(control input も含めて) 7つの入力ノードを持つ. それぞれの入力の意味は以下の通り.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
TailJumpNode( Node *cntrl, Node *i_o, Node *memory, Node *frameptr, Node *target, Node *ex_oop)
: ReturnNode(TypeFunc::Parms+2, cntrl, i_o, memory, frameptr, Compile::current()->top()) {
init_req(TypeFunc::Parms, target);
init_req(TypeFunc::Parms+1, ex_oop);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// A linked list of JVMState nodes captures the whole interpreter state,
// plus GC roots, for all active calls at some call site in this compilation
// unit. (If there is no inlining, then the list has exactly one link.)
// This provides a way to map the optimized program back into the interpreter,
// or to let the GC mark the stack.
class JVMState : public ResourceObj {
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// A SafePointNode is a subclass of a MultiNode for convenience (and
// potential code sharing) only - conceptually it is independent of
// the Node semantics.
class SafePointNode : public MultiNode {
以下の箇所で(のみ)生成されている.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
SafePointNode(uint edges, JVMState* jvms,
// A plain safepoint advertises no memory effects (NULL):
const TypePtr* adr_type = NULL)
: MultiNode( edges ),
_jvms(jvms),
_oop_map(NULL),
_adr_type(adr_type)
{
init_class_id(Class_SafePoint);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// A SafePointScalarObjectNode represents the state of a scalarized object
// at a safepoint.
class SafePointScalarObjectNode: public TypeNode {
((cite: hotspot/src/share/vm/opto/callnode.cpp))
SafePointScalarObjectNode::SafePointScalarObjectNode(const TypeOopPtr* tp,
#ifdef ASSERT
AllocateNode* alloc,
#endif
uint first_index,
uint n_fields) :
TypeNode(tp, 1), // 1 control input -- seems required. Get from root.
#ifdef ASSERT
_alloc(alloc),
#endif
_first_index(first_index),
_n_fields(n_fields)
{
init_class_id(Class_SafePointScalarObject);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Simple container for the outgoing projections of a call. Useful
// for serious surgery on calls.
class CallProjections : public StackObj {
See: here for details
SafePointNode クラスのサブクラスの1つ.
「メソッド呼び出し処理」を表す全ての Node クラスの基底クラス.
なお, このクラス自体は abstract class であり, 実際に使われるのはサブクラス.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Call nodes now subsume the function of debug nodes at callsites, so they
// contain the functionality of a full scope chain of debug nodes.
class CallNode : public SafePointNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallNode(const TypeFunc* tf, address addr, const TypePtr* adr_type)
: SafePointNode(tf->domain()->cnt(), NULL, adr_type),
_tf(tf),
_entry_point(addr),
_cnt(COUNT_UNKNOWN)
{
init_class_id(Class_Call);
init_flags(Flag_is_Call);
}
なお, このクラスは以下のファイル中に書かれている Ideal クラスの一覧には出ていない.
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Make a static or dynamic subroutine call node using Java calling
// convention. (The "Java" calling convention is the compiler's calling
// convention, as opposed to the interpreter's or that of native C.)
class CallJavaNode : public CallNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci)
: CallNode(tf, addr, TypePtr::BOTTOM),
_method(method), _bci(bci),
_optimized_virtual(false),
_method_handle_invoke(false)
{
init_class_id(Class_CallJava);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Make a direct subroutine call using Java calling convention (for static
// calls and optimized virtual calls, plus calls to wrappers for run-time
// routines); generates static stub.
class CallStaticJavaNode : public CallJavaNode {
以下の箇所で(のみ)生成されている.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallStaticJavaNode(const TypeFunc* tf, address addr, ciMethod* method, int bci)
: CallJavaNode(tf, addr, method, bci), _name(NULL) {
init_class_id(Class_CallStaticJava);
}
CallStaticJavaNode(const TypeFunc* tf, address addr, const char* name, int bci,
const TypePtr* adr_type)
: CallJavaNode(tf, addr, NULL, bci), _name(name) {
init_class_id(Class_CallStaticJava);
// This node calls a runtime stub, which often has narrow memory effects.
_adr_type = adr_type;
}
See: here for details
CallJavaNode クラスの具象サブクラスの1つ.
このクラスは, ダイナミックディスパッチが必要なメソッド呼び出し用 (e.g. invokevirtual, invokeinterface).
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Make a dispatched call using Java calling convention.
class CallDynamicJavaNode : public CallJavaNode {
以下の箇所で(のみ)生成されている.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallDynamicJavaNode( const TypeFunc *tf , address addr, ciMethod* method, int vtable_index, int bci ) : CallJavaNode(tf,addr,method,bci), _vtable_index(vtable_index) {
init_class_id(Class_CallDynamicJava);
}
See: here for details
CallNode のサブクラス. ("a direct subroutine call node into compiled C++ code") (#TODO)
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Make a direct subroutine call node into compiled C++ code.
class CallRuntimeNode : public CallNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallRuntimeNode(const TypeFunc* tf, address addr, const char* name,
const TypePtr* adr_type)
: CallNode(tf, addr, adr_type),
_name(name)
{
init_class_id(Class_CallRuntime);
}
See: here for details
CallRuntimeNode のサブクラス. ("a direct subroutine call node into compiled C++ code, without safepoints")
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// Make a direct subroutine call node into compiled C++ code, without
// safepoints
class CallLeafNode : public CallRuntimeNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallLeafNode(const TypeFunc* tf, address addr, const char* name,
const TypePtr* adr_type)
: CallRuntimeNode(tf, addr, name, adr_type)
{
init_class_id(Class_CallLeaf);
}
See: here for details
特殊な CallLeafNode クラス.
浮動小数を使わないケース用("not using floating point or using it in the same manner as the generated code").
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// CallLeafNode, not using floating point or using it in the same manner as
// the generated code
class CallLeafNoFPNode : public CallLeafNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
CallLeafNoFPNode(const TypeFunc* tf, address addr, const char* name,
const TypePtr* adr_type)
: CallLeafNode(tf, addr, name, adr_type)
{
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// High-level memory allocation
//
// AllocateNode and AllocateArrayNode are subclasses of CallNode because they will
// get expanded into a code sequence containing a call. Unlike other CallNodes,
// they have 2 memory projections and 2 i_o projections (which are distinguished by
// the _is_io_use flag in the projection.) This is needed when expanding the node in
// order to differentiate the uses of the projection on the normal control path from
// those on the exception return path.
//
class AllocateNode : public CallNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
AllocateNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
Node *size, Node *klass_node, Node *initial_test);
((cite: hotspot/src/share/vm/opto/callnode.hpp))
enum {
// Output:
RawAddress = TypeFunc::Parms, // the newly-allocated raw address
// Inputs:
AllocSize = TypeFunc::Parms, // size (in bytes) of the new object
KlassNode, // type (maybe dynamic) of the obj.
InitialTest, // slow-path test (may be constant)
ALength, // array length (or TOP if none)
ParmLimit
};
((cite: hotspot/src/share/vm/opto/callnode.cpp))
AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype,
Node *ctrl, Node *mem, Node *abio,
Node *size, Node *klass_node, Node *initial_test)
: CallNode(atype, NULL, TypeRawPtr::BOTTOM)
{
init_class_id(Class_Allocate);
init_flags(Flag_is_macro);
_is_scalar_replaceable = false;
Node *topnode = C->top();
init_req( TypeFunc::Control , ctrl );
init_req( TypeFunc::I_O , abio );
init_req( TypeFunc::Memory , mem );
init_req( TypeFunc::ReturnAdr, topnode );
init_req( TypeFunc::FramePtr , topnode );
init_req( AllocSize , size);
init_req( KlassNode , klass_node);
init_req( InitialTest , initial_test);
init_req( ALength , topnode);
C->add_macro_node(this);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
//
// High-level array allocation
//
class AllocateArrayNode : public AllocateNode {
((cite: hotspot/src/share/vm/opto/callnode.hpp))
AllocateArrayNode(Compile* C, const TypeFunc *atype, Node *ctrl, Node *mem, Node *abio,
Node* size, Node* klass_node, Node* initial_test,
Node* count_val
)
: AllocateNode(C, atype, ctrl, mem, abio, size, klass_node,
initial_test)
{
init_class_id(Class_AllocateArray);
set_req(AllocateNode::ALength, count_val);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
class AbstractLockNode: public CallNode {
通常の CallNode の入力ノードに加えて, 以下のような 3つの入力ノードを持つ.
((cite: hotspot/src/share/vm/opto/callnode.hpp))
Node * obj_node() const {return in(TypeFunc::Parms + 0); }
Node * box_node() const {return in(TypeFunc::Parms + 1); }
Node * fastlock_node() const {return in(TypeFunc::Parms + 2); }
((cite: hotspot/src/share/vm/opto/callnode.hpp))
AbstractLockNode(const TypeFunc *tf)
: CallNode(tf, NULL, TypeRawPtr::BOTTOM),
_coarsened(false),
_eliminate(false)
{
#ifndef PRODUCT
_counter = NULL;
#endif
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// High-level lock operation
//
// This is a subclass of CallNode because it is a macro node which gets expanded
// into a code sequence containing a call. This node takes 3 "parameters":
// 0 - object to lock
// 1 - a BoxLockNode
// 2 - a FastLockNode
//
class LockNode : public AbstractLockNode {
((cite: hotspot/src/share/vm/opto/graphKit.cpp))
FastLockNode* GraphKit::shared_lock(Node* obj) {
...
LockNode *lock = new (C, tf->domain()->cnt()) LockNode(C, tf);
lock->init_req( TypeFunc::Control, control() );
lock->init_req( TypeFunc::Memory , mem );
lock->init_req( TypeFunc::I_O , top() ) ; // does no i/o
lock->init_req( TypeFunc::FramePtr, frameptr() );
lock->init_req( TypeFunc::ReturnAdr, top() );
lock->init_req(TypeFunc::Parms + 0, obj);
lock->init_req(TypeFunc::Parms + 1, box);
lock->init_req(TypeFunc::Parms + 2, flock);
((cite: hotspot/src/share/vm/opto/callnode.hpp))
LockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf ) {
init_class_id(Class_Lock);
init_flags(Flag_is_macro);
C->add_macro_node(this);
}
See: here for details
((cite: hotspot/src/share/vm/opto/callnode.hpp))
// High-level unlock operation
class UnlockNode : public AbstractLockNode {
((cite: hotspot/src/share/vm/opto/graphKit.cpp))
void GraphKit::shared_unlock(Node* box, Node* obj) {
...
UnlockNode *unlock = new (C, tf->domain()->cnt()) UnlockNode(C, tf);
uint raw_idx = Compile::AliasIdxRaw;
unlock->init_req( TypeFunc::Control, control() );
unlock->init_req( TypeFunc::Memory , memory(raw_idx) );
unlock->init_req( TypeFunc::I_O , top() ) ; // does no i/o
unlock->init_req( TypeFunc::FramePtr, frameptr() );
unlock->init_req( TypeFunc::ReturnAdr, top() );
unlock->init_req(TypeFunc::Parms + 0, obj);
unlock->init_req(TypeFunc::Parms + 1, box);
((cite: hotspot/src/share/vm/opto/callnode.hpp))
UnlockNode(Compile* C, const TypeFunc *tf) : AbstractLockNode( tf ) {
init_class_id(Class_Unlock);
init_flags(Flag_is_macro);
C->add_macro_node(this);
}
See: here for details
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.