From d5ae053f114edca25095544fe029bb8889fd965b Mon Sep 17 00:00:00 2001
From: Joel Dice <joel.dice@gmail.com>
Date: Sat, 26 Mar 2011 23:13:05 -0600
Subject: [PATCH] handle invokevirtual calls to non-virtual methods

OpenJDK's sun.reflect.MethodAccessorGenerator can generate
invokevirtual calls to private methods (which we normally consider
non-virtual); we must compile them as non-virtual calls since they
aren't in the vtable.
---
 src/compile.cpp | 54 ++++++++++++++++++++++++++++---------------------
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/src/compile.cpp b/src/compile.cpp
index e2ffb7c3d5..89f39fe662 100644
--- a/src/compile.cpp
+++ b/src/compile.cpp
@@ -4890,33 +4890,41 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
       if (LIKELY(target)) {
         assert(t, (methodFlags(t, target) & ACC_STATIC) == 0);
 
-        unsigned parameterFootprint = methodParameterFootprint(t, target);
-
-        unsigned offset = ClassVtable
-          + (methodOffset(t, target) * BytesPerWord);
-
-        Compiler::Operand* instance = c->peek(1, parameterFootprint - 1);
-
-        unsigned rSize = resultSize(t, methodReturnCode(t, target));
-
         bool tailCall = isTailCall(t, code, ip, context->method, target);
 
-        Compiler::Operand* result = c->stackCall
-          (c->memory
-           (c->and_
-            (BytesPerWord, c->constant(PointerMask, Compiler::IntegerType),
-             c->memory(instance, Compiler::ObjectType, 0, 0, 1)),
-            Compiler::ObjectType, offset, 0, 1),
-           tailCall ? Compiler::TailJump : 0,
-           frame->trace(0, 0),
-           rSize,
-           operandTypeForFieldCode(t, methodReturnCode(t, target)),
-           parameterFootprint);
+        if (LIKELY(methodVirtual(t, target))) {
+          unsigned parameterFootprint = methodParameterFootprint(t, target);
 
-        frame->pop(parameterFootprint);
+          unsigned offset = ClassVtable
+            + (methodOffset(t, target) * BytesPerWord);
 
-        if (rSize) {
-          pushReturnValue(t, frame, methodReturnCode(t, target), result);
+          Compiler::Operand* instance = c->peek(1, parameterFootprint - 1);
+
+          unsigned rSize = resultSize(t, methodReturnCode(t, target));
+
+          Compiler::Operand* result = c->stackCall
+            (c->memory
+             (c->and_
+              (BytesPerWord, c->constant(PointerMask, Compiler::IntegerType),
+               c->memory(instance, Compiler::ObjectType, 0, 0, 1)),
+              Compiler::ObjectType, offset, 0, 1),
+             tailCall ? Compiler::TailJump : 0,
+             frame->trace(0, 0),
+             rSize,
+             operandTypeForFieldCode(t, methodReturnCode(t, target)),
+             parameterFootprint);
+
+          frame->pop(parameterFootprint);
+
+          if (rSize) {
+            pushReturnValue(t, frame, methodReturnCode(t, target), result);
+          }
+        } else {
+          // OpenJDK generates invokevirtual calls to private methods
+          // (e.g. readObject and writeObject for serialization), so
+          // we must handle such cases here.
+
+          compileDirectInvoke(t, frame, target, tailCall);          
         }
       } else {
         PROTECT(t, reference);