Patch name: tailc.patch

Call Sites

in native code:

Compile to Interpreted Code Adapter C2I

// Before we get into the guts of the C2I adapter, see if we should be here
// at all.  We've come from compiled code and are attempting to jump to the
// interpreter, which means the caller made a static call to get here
// (vcalls always get a compiled target if there is one).  Check for a
// compiled target.  If there is one, we need to patch the caller's call.
                            . ..............
                            .              .  Caller frame
                     .      .              .
                     .      .              .
                     .      .    argn      .
                     .      .    arg1      ........
                   .....    ................      .
                    ...     .    argn+m    . .    .  Created by c2i adapter (m=number of args in regs)
                     .      .    arg1      ........
                            . ..............
                            .   RetAddr    .  InterpreterFrame (Callee) setup will start with
                            .              .  templateInterpreter_x86_32.cpp:
                            .              .   generate_normal_entry(bool synchronized)

Tail Call Situations

Described by three relevant frames. The function performing the tail call is called self. The tail called function is called callee in the following. The function that has called the tail calling function is called calller.

A code example leading to this situation.

public static int caller(int a) {
  int x = self(a);
  return x+1;
}

public static int self(int a) {
  return tail call calllee(a);
}

public static int callee(int a) {
  return a+1;
}

assumption: sibling call (callee less or equal arg space requirement than self)

self: compiled
      callee compiled  /  interpreted
c
a
l c      mov args          mov args + c2i entry
l
e
r
  i      mov args         mov args + c2i entry
      (works because
       of i2c adapter in
       caller. on ret
        interpreter will
         restore sp)


self: interpreted
      callee compiled  /  interpreted
c
a
l c   mov args for compiled   move args for compiled + c2i entry
l       (use old sp)
e
r
  i      mov args int.        mov args int.
      (works because
       of i2c adapter)

interpreter call setup sequence:

registers:
  rsi  during bytecode execution holds bcp/bci

  rdi
  rax
  rbx
  rcx
  rdx
  rbp
  rsp

prepare_invoke(invokevirtual)

state after prepare_invoke

...............
.   RET ADDR  .   ... interpreter entry [numberretaddrs][tos_state]
...............   rbx = method (index or pointer (vfinal))
.  PARAM N    .   rcx = receiver
...............   rdx = cpCache Flags
.  PARM  1    .   rsi = bcp
...............

invokevirtual_helper

...............
.   RET ADDR  .   ... interpreter entry [numberretaddrs][tos_state]
...............   rbx = method (oop ?) pointer
.  PARAM N    .   rcx = receiver
...............   rdx = cpCache Flags (or garbage if profiles)
.  PARM  1    .   rsi = rsp stack pointer
...............   rax = klass ptr
                  rbp = base pointer/ dynlink
                  rsp points to RET ADDR 
                  rdi = garbage 

invoketailcall