1. void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaCallArguments* args, TRAPS)
    descricao what this does
    1. void CompilationPolicy::compile_if_required(const methodHandle& m, TRAPS)
      descricao what this does
      1. nmethod* CompileBroker::compile_method(...)
        Obtain a reference to a compiler method based on the level of the compilation being performed. Forwards the call to an overload of the same method.
        1. nmethod* CompileBroker::compile_method(...)
          1. void CompileBroker::compile_method_base()
            1. CompileTask* CompileBroker::create_compile_task()
  1. void CompileBroker::compiler_thread_loop()
    xxxxxxxxx
    1. xxxxxxxx
      1. xxxxxxxx
        1. xxxxxxxx
          1. xxxxxxxx
            1. xxxxxxxx
              1. Construct C1 HighLevel IR (IRScope) and apply several optimizations to it, including global value numbering, null check elimination, range check elimination. There are several options for printing information about the IR during its construction. The optimizations are controlled by the UseC1Optimizations flag.
                1. Constructor. Just initializes some fields, notably it creates an new IRScope and assign it to _top_scope.
                  1. Just initialize some fields and then calls build_graph. The nesting level of function calls is tracked.
                    1. Essentially just forward the execution to GraphBuilder constructor by creating a new object and then returns apparently the start node of the graph.
                      1. Checks whether the method to be compiled is annotated with an intrinsic and if so switch the compilation to the intrinsic instead of the method body. Surprisingly there is just about 10 intrinsics for C1, with the exception of one, all are related to performing mathematical operations on double values. In case the method isn't related to an intrinsic the execution proceeds to iterate all blocks of the method.
                        1. This method is essentially a loop that is used to construct "Basic Blocks" iteratively and connect them forming a Control Flow Graph. Each iteration of the loop ends up calling the method iterate_bytecodes_for_block.
                          1. This method is also essentially a loop with a big switch table inside. Each iteration of the loop processes one single bytecode instruction of the method being compiled. The switch table identifies which bytecode is being currently processed and invoke a method to handle that specific bytecode. Each "block" is a list of instructions connected by pointers. During the IR construction a stack is used to push and pop constant values that are instruction operands. When the instruction that uses those constants is being created the operands are popped from the stack and used to construct a node representing the instruction.

                            C1 HIR nodes are described in classes defined in the c1_Instruction.hpp/cpp file. Some simple optimizations, like simplifying shift expressions and local value numbering are performed while constructing the IR. Also, profiling instructions are inserted into the IR when the compilation is in a level that requires profiling.

                            Interestingly, even C1 bails out compilation if a method body is too large!

              2. This method transforms the High Level C1 IR into Low Level C1 IR and then performs register allocation using an implementation of the Linear Scan register allocator algorithm.
                1. Just forward execution to the method below. The closure pointer points to a LIRGenerator object, which is essentially an object able to iterate over IR blocks.
                  1. Iterates over each block of the IR graph and calls closure->block_do on it.
                    1. Iterate over the instructions of a block and calls do_root on instructions that are pinned to the block(?).
                      1. This method is an entry point for starting visiting the High Level IR and converting the nodes to Low Level IR. The method start the conversion process by calling instr->visit(this). Instr is the instruction being converted, for continuing this tutorial I'll assume it is LogicOp. The visit method for each C1 HL IR instruction is constructed with help of the C++ preprocessor; take a look here to see how the LogicOp class is declared and how the visit method is constructed.
                        1. Redirects the call to v->do_LogicOp(this) where v is a pointer to LIRGenerator.
                          1. Note that this method is in c1_LIRGenerator_x86.cpp instead of c1_LIRGenerator.cpp. During the JVM build time, given the values using the configure the project, the build infrastructure will use preprocessor macros to include the correct .cpp file for the target architecture of the JVM - in this case x86_64.

                            This method basically extract the information from the HL IR nodes and create LL IR operand nodes, while doing that the method allocate virtual registers for loading operands and storing results of operations. The call then is forwarded to logic_op which is also part of LIRGenerator.

                            1. Basically a switch based on the opcode of the instruction being converted and dispatching a method to handle that specific Bytecode. Assuming the Bytecode is Bytecodes::_iand the execution will end up in LIR_List::logical_and, which basically construct a Low Level IR binary operator node - LIR_Op2.
                  2. Uses Linear Scan algorithm to assign physical registers to Low Level IR operands.
                  3. xxxxxxxx
              1. Just initialize a lot of structures related to current method compilation.
                  1. As far as I understand at this moment this does nothing besides initializing some structures and updating how many inline operations (and bytecodes) have been performed at each level of a call chain.
                    1. Checks if the method can be parsed and constructs a ParseGenerator object that is able to parse Bytecodes.
                        1. xxxxx
                          1. xxxxx
                              1. Escape Analysis brings benefits only when the code has allocations and/or locks. This method checks if the current method has any of these, if not, no EA is performed.