Search code examples
javac++optimizationjvmjvm-hotspot

strange looking allocation and some description for String concatenation optimization code


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?


Solution

  • 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

    1. memory allocation, followed by
    2. implicit cast to the target object type, followed by
    3. invocation of <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.