OSDN Git Service

JNI direct buffer function speedup, part 3.
authorAndy McFadden <fadden@android.com>
Fri, 24 Jul 2009 22:28:16 +0000 (15:28 -0700)
committerAndy McFadden <fadden@android.com>
Fri, 24 Jul 2009 22:28:16 +0000 (15:28 -0700)
This caches the effective address in a new field in the base Buffer
object.  The first time something calls through one of the various
getEffectiveAddress calls, the value is set.  (This seemed easier than
chasing down the constructors and factories, and also prevents bit rot
on the "slow path" in the VM.)

libcore/nio/src/main/java/java/nio/Buffer.java
libcore/nio/src/main/java/java/nio/CharToByteBufferAdapter.java
libcore/nio/src/main/java/java/nio/DirectByteBuffer.java
libcore/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java
libcore/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java
libcore/nio/src/main/java/java/nio/IntToByteBufferAdapter.java
libcore/nio/src/main/java/java/nio/LongToByteBufferAdapter.java
libcore/nio/src/main/java/java/nio/MappedByteBufferAdapter.java
libcore/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java
vm/Globals.h
vm/Jni.c

index 9e870e4..19d8969 100644 (file)
@@ -111,6 +111,16 @@ public abstract class Buffer {
     int _arrayOffset() {
         return 0;
     }
+
+    /**
+     * For direct buffers, the effective address of the data.  This is set
+     * on first use.  If the field is zero, this is either not a direct
+     * buffer or the field has not been initialized, and you need to issue
+     * the getEffectiveAddress() call and use the result of that.
+     *
+     * This is strictly an optimization.
+     */
+    int effectiveDirectAddress = 0;
     // END android-added
 
     /**
index 14a48ff..bd340be 100644 (file)
@@ -65,7 +65,11 @@ final class CharToByteBufferAdapter extends CharBuffer implements DirectBuffer {
         
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            // BEGIN android-changed
+            PlatformAddress addr = ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            effectiveDirectAddress = addr.toInt();
+            return addr;
+            // END android-changed
         } else {
             assert false : byteBuffer;
             return null;
index 46529a5..dcdb3c1 100644 (file)
@@ -247,7 +247,11 @@ abstract class DirectByteBuffer extends BaseByteBuffer implements DirectBuffer {
      *             previously.
      */
     public final PlatformAddress getEffectiveAddress() {
-        return getBaseAddress().offsetBytes(offset);
+        // BEGIN android-changed
+        PlatformAddress addr = getBaseAddress().offsetBytes(offset);
+        effectiveDirectAddress = addr.toInt();
+        return addr;
+        // END android-changed
     }
 
     /**
index 336488b..70406ba 100644 (file)
@@ -65,7 +65,11 @@ final class DoubleToByteBufferAdapter extends DoubleBuffer implements DirectBuff
 
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            // BEGIN android-changed
+            PlatformAddress addr = ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            effectiveDirectAddress = addr.toInt();
+            return addr;
+            // END android-changed
         } else {
             assert false : byteBuffer;
             return null;
index 97c0528..75b9d84 100644 (file)
@@ -65,7 +65,11 @@ final class FloatToByteBufferAdapter extends FloatBuffer implements DirectBuffer
 
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            // BEGIN android-changed
+            PlatformAddress addr = ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            effectiveDirectAddress = addr.toInt();
+            return addr;
+            // END android-changed
         } else {
             assert false : byteBuffer;
             return null;
index 91b9311..e77bec6 100644 (file)
@@ -65,7 +65,11 @@ final class IntToByteBufferAdapter extends IntBuffer implements DirectBuffer {
 
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            // BEGIN android-changed
+            PlatformAddress addr = ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            effectiveDirectAddress = addr.toInt();
+            return addr;
+            // END android-changed
         } else {
             assert false : byteBuffer;
             return null;
index 0bd3ce4..bcdeb2b 100644 (file)
@@ -65,7 +65,11 @@ final class LongToByteBufferAdapter extends LongBuffer implements DirectBuffer {
 
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            // BEGIN android-changed
+            PlatformAddress addr = ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            effectiveDirectAddress = addr.toInt();
+            return addr;
+            // END android-changed
         } else {
             assert false : byteBuffer;
             return null;
index 83a51c1..84866dc 100644 (file)
@@ -148,7 +148,11 @@ final class MappedByteBufferAdapter extends MappedByteBuffer implements DirectBu
     }
 
     public PlatformAddress getEffectiveAddress() {
-        return ((DirectBuffer) this.wrapped).getEffectiveAddress();
+        // BEGIN android-changed
+        PlatformAddress addr = ((DirectBuffer) this.wrapped).getEffectiveAddress();
+        effectiveDirectAddress = addr.toInt();
+        return addr;
+        // END android-changed
     }
 
     public float getFloat() {
index 41ce50c..a608bc9 100644 (file)
@@ -65,7 +65,11 @@ final class ShortToByteBufferAdapter extends ShortBuffer implements DirectBuffer
 
     public PlatformAddress getEffectiveAddress() {
         if (byteBuffer instanceof DirectBuffer) {
-            return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            // BEGIN android-changed
+            PlatformAddress addr = ((DirectBuffer)byteBuffer).getEffectiveAddress();
+            effectiveDirectAddress = addr.toInt();
+            return addr;
+            // END android-changed
         } else {
             assert false : byteBuffer;
             return null;
index c85e0ae..acaebaa 100644 (file)
@@ -297,6 +297,7 @@ struct DvmGlobals {
     Method*     methOrgApacheHarmonyLuniPlatformPlatformAddress_on;
     Method*     methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress;
     int         offJavaNioBuffer_capacity;
+    int         offJavaNioBuffer_effectiveDirectAddress;
     int         offOrgApacheHarmonyLuniPlatformPlatformAddress_osaddr;
     int         voffOrgApacheHarmonyLuniPlatformPlatformAddress_toLong;
 
index 6f09acb..0248e8f 100644 (file)
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -450,6 +450,13 @@ bool dvmJniStartup(void)
         return false;
     }
 
+    gDvm.offJavaNioBuffer_effectiveDirectAddress =
+        dvmFindFieldOffset(bufferClass, "effectiveDirectAddress", "I");
+    if (gDvm.offJavaNioBuffer_effectiveDirectAddress < 0) {
+        LOGE("Unable to find Buffer.effectiveDirectAddress\n");
+        return false;
+    }
+
     return true;
 }
 
@@ -2810,9 +2817,21 @@ static void* GetDirectBufferAddress(JNIEnv* env, jobject buf)
 
     Object* bufObj = (Object*) buf;
     Thread* self = _self /*dvmThreadSelf()*/;
-    Object* platformAddr;
-    JValue callResult;
-    void* result = NULL;
+    void* result;
+
+    /*
+     * All Buffer objects have an effectiveDirectAddress field.  If it's
+     * nonzero, we can just return that value.  If not, we have to call
+     * through DirectBuffer.getEffectiveAddress(), which as a side-effect
+     * will set the effectiveDirectAddress field for direct buffers (and
+     * things that wrap direct buffers).
+     */
+    result = (void*) dvmGetFieldInt(bufObj,
+            gDvm.offJavaNioBuffer_effectiveDirectAddress);
+    if (result != NULL) {
+        //LOGI("fast path for %p\n", buf);
+        goto bail;
+    }
 
     /*
      * Start by determining if the object supports the DirectBuffer
@@ -2829,9 +2848,8 @@ static void* GetDirectBufferAddress(JNIEnv* env, jobject buf)
      *
      * If this isn't a direct buffer, the result will be NULL and/or an
      * exception will have been thrown.
-     *
-     * TODO: eliminate the getEffectiveAddress() method call.
      */
+    JValue callResult;
     const Method* meth = dvmGetVirtualizedMethod(bufObj->clazz,
         gDvm.methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress);
     dvmCallMethodA(self, meth, bufObj, &callResult, NULL);
@@ -2840,9 +2858,9 @@ static void* GetDirectBufferAddress(JNIEnv* env, jobject buf)
         callResult.l = NULL;
     }
 
-    platformAddr = callResult.l;
+    Object* platformAddr = callResult.l;
     if (platformAddr == NULL) {
-        LOGD("Got request for address of non-direct buffer\n");
+        LOGV("Got request for address of non-direct buffer\n");
         goto bail;
     }
 
@@ -2854,6 +2872,8 @@ static void* GetDirectBufferAddress(JNIEnv* env, jobject buf)
     result = (void*) dvmGetFieldInt(platformAddr,
                 gDvm.offOrgApacheHarmonyLuniPlatformPlatformAddress_osaddr);
 
+    //LOGI("slow path for %p --> %p\n", buf, result);
+
 bail:
     JNI_EXIT();
     return result;