I was reviewing OpenJDK JVM's String concatentation optimization code when I encountered the following:
cnode = recv->isa_CallStaticJava();
if (cnode == NULL) {
alloc = recv->isa_Allocate();
if (alloc == NULL) {
break;
}
// Find the constructor call
Node* result = alloc->result_cast();
if (result == NULL || !result->is_CheckCastPP() || alloc->in(TypeFunc::Memory)->is_top()) {
// strange looking allocation
#ifndef PRODUCT
if (PrintOptimizeStringConcat) {
tty->print("giving up because allocation looks strange ");
alloc->jvms()->dump_spec(tty); tty->cr();
}
#endif
break;
}
First, I'm not sure what is cnode
. I'm thinking cnode
is some type of object representation for a call to the plus sign "+" (for String concatenation). Now, result
is a call to the plus sign's corresponding StringBuilder
's constructor. Ok, not sure again but I think that if there is no node created or the node is not a CheckCastPP or the object representation of the created allocation is on top of the stack, the optimization will not continue.
What is a CheckCastPP and could my interpretation be right?
The function you are looking at - PhaseStringOpts::build_candidate(CallStaticJavaNode* call)
- starts from StringBuilder.toString()
call node and tries to unroll the use chain looking for the typical concatenation pattern:
StringBuilder AllocateNode -> append() CallStaticJavaNode -> ... -> toString()
The fragment you've shown checks the type of the current node in the chain. If it is CallStaticJavaNode
, then it should be a call to StringBuilder.append()
, otherwise it should be AllocateNode
.
On the JVM level a creation of a new object is
<init>
method (the constructor)For the correctly generated bytecode
new java/lang/StringBuilder
dup
invokespecial java/lang/StringBuilder.<init>()V
there will be exactly one use of AllocNode
that casts the result to StringBuilder
.
That's what result->is_CheckCastPP()
asserts.