C2 - Basis
RegionNode
可以合并控制流的特殊节点。顺着regionnode(和if,start),可以抽出一个controlflow subgraph。control从regiona流到regionb就意味着a先于b执行。regionnode在ideal graph里面扮演的其实是basic block的角色。它可以接受多个control的输入,然后输出一个合并后的control(比如循环开始的地方)。
这里合并431#IfFalse和70#IfFalse,最后输出合并后的control给66#Phi,如果是IfTrue那么66#Phi选择第一个值,否则选择第二个。
PhiNode
可以合并数据流的特殊节点。同时读取control和values,然后输出一个value,相当于根据控制流选值作为结果:
比如这里根据65#Region的control输入选择47#ConP或者82#CheckCastPP作为66#Phi的结果。
IfNode与ProjNode
ifnode有一个control和一个predicate的数据输入,根据数据的输入,ifnode可以选择将control传递到true region或者false region。但是问题是,ideal graph的输出是无序的,而且也不能携带信息,这样根本不知道if的out[1]和out[2]哪个是true region哪个是false region,所以需要一个projnode来携带信息,projnode相当于一个label,所以运行时是无开销的。
这里的IfTrue和IfFalse都继承自IfProjNode节点。
StoreNode
StoreNode语义是adr=val,他产生一个memory slice,可能会流入MergeMem。
MergeMem
MergeMem收集所有内存操作产生的memory slice。
OpaqueXNode
除了常量折叠,其他优化比如valuenumbering,ideal,identity都禁止。
CallXNode
一个Call节点有很多projections:
class CallProjections : public StackObj {
public:
Node* fallthrough_proj;
Node* fallthrough_catchproj;
Node* fallthrough_memproj;
Node* fallthrough_ioproj;
Node* catchall_catchproj;
Node* catchall_memproj;
Node* catchall_ioproj;
Node* resproj;
Node* exobj;
};
调用一个java函数Reduced::test,会生成下面这样的call
fallthrough_xx表示这个call不抛异常的常规路径,catchall表示抛一次的路径。
fallthrough_proj -> 139#Proj
fallthrough_catchproj->146#CatchProj
fallthrough_memproj->141#Proj
fallthrough_ioproj->140#Proj
catchall_catchproj->147#CatchProj
catchall_memproj->141#Proj
catchall_ioproj->140#Proj
resproj->143#Proj
exobj->150#CreateEx
其中fallthrough/catchall的io_proj和mem_proj实际上是一样的,这是它们是互斥的,也就是说如果走正常路径,那么就设置fallthrough_ioproj,不设置catchall_ioproj,反之亦然。
Node Inputs
节点的输入分为两种类型:required input和precedence input。required input是构成节点的必要输入,顺序是确定的,比如in(0)必须是控制输入,in(1)必须是内存输入等,它们用set_req等指定。 precedence input主要是控制节点的调度,相当于给它连了一些节点,表明它们的依赖关系,precedence input的顺序是不确定的,也不重要,它们用set_prec/add_prec等指定。
Type Lattice
说白了,type lattice就是对两个值做运算的上下界做预估,保证不管你加减乘除还是啥的,最后的结果都会落在预估的区间。
比如TypeInt[4,6] meet TypeInt[2,7] --> TypeInt[MIN(4,2),MAX(6,7)] --> TypeInt[2,7] 结果是变坏了,因为meet在lattice里面是向下走的。