From 8e696dc0271299433cb3297e7aafc7bd0ee1b2b7 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Fri, 24 Jul 2009 15:28:16 -0700 Subject: [PATCH] JNI direct buffer function speedup, part 3. 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 | 10 +++++++ .../java/java/nio/CharToByteBufferAdapter.java | 6 +++- .../src/main/java/java/nio/DirectByteBuffer.java | 6 +++- .../java/java/nio/DoubleToByteBufferAdapter.java | 6 +++- .../java/java/nio/FloatToByteBufferAdapter.java | 6 +++- .../main/java/java/nio/IntToByteBufferAdapter.java | 6 +++- .../java/java/nio/LongToByteBufferAdapter.java | 6 +++- .../java/java/nio/MappedByteBufferAdapter.java | 6 +++- .../java/java/nio/ShortToByteBufferAdapter.java | 6 +++- vm/Globals.h | 1 + vm/Jni.c | 34 +++++++++++++++++----- 11 files changed, 78 insertions(+), 15 deletions(-) diff --git a/libcore/nio/src/main/java/java/nio/Buffer.java b/libcore/nio/src/main/java/java/nio/Buffer.java index 9e870e49f..19d89697d 100644 --- a/libcore/nio/src/main/java/java/nio/Buffer.java +++ b/libcore/nio/src/main/java/java/nio/Buffer.java @@ -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 /** diff --git a/libcore/nio/src/main/java/java/nio/CharToByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/CharToByteBufferAdapter.java index 14a48ffc7..bd340bead 100644 --- a/libcore/nio/src/main/java/java/nio/CharToByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/CharToByteBufferAdapter.java @@ -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; diff --git a/libcore/nio/src/main/java/java/nio/DirectByteBuffer.java b/libcore/nio/src/main/java/java/nio/DirectByteBuffer.java index 46529a5a2..dcdb3c1b0 100644 --- a/libcore/nio/src/main/java/java/nio/DirectByteBuffer.java +++ b/libcore/nio/src/main/java/java/nio/DirectByteBuffer.java @@ -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 } /** diff --git a/libcore/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java index 336488b21..70406ba81 100644 --- a/libcore/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java @@ -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; diff --git a/libcore/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java index 97c052842..75b9d84a2 100644 --- a/libcore/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java @@ -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; diff --git a/libcore/nio/src/main/java/java/nio/IntToByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/IntToByteBufferAdapter.java index 91b931127..e77bec696 100644 --- a/libcore/nio/src/main/java/java/nio/IntToByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/IntToByteBufferAdapter.java @@ -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; diff --git a/libcore/nio/src/main/java/java/nio/LongToByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/LongToByteBufferAdapter.java index 0bd3ce4a2..bcdeb2be1 100644 --- a/libcore/nio/src/main/java/java/nio/LongToByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/LongToByteBufferAdapter.java @@ -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; diff --git a/libcore/nio/src/main/java/java/nio/MappedByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/MappedByteBufferAdapter.java index 83a51c1c6..84866dca7 100644 --- a/libcore/nio/src/main/java/java/nio/MappedByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/MappedByteBufferAdapter.java @@ -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() { diff --git a/libcore/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java b/libcore/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java index 41ce50c3d..a608bc9a6 100644 --- a/libcore/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java +++ b/libcore/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java @@ -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; diff --git a/vm/Globals.h b/vm/Globals.h index c85e0ae2b..acaebaab3 100644 --- a/vm/Globals.h +++ b/vm/Globals.h @@ -297,6 +297,7 @@ struct DvmGlobals { Method* methOrgApacheHarmonyLuniPlatformPlatformAddress_on; Method* methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress; int offJavaNioBuffer_capacity; + int offJavaNioBuffer_effectiveDirectAddress; int offOrgApacheHarmonyLuniPlatformPlatformAddress_osaddr; int voffOrgApacheHarmonyLuniPlatformPlatformAddress_toLong; diff --git a/vm/Jni.c b/vm/Jni.c index 6f09acb03..0248e8fc1 100644 --- 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; -- 2.11.0