diff options
author | Elliott Hughes <enh@google.com> | 2011-01-10 17:32:53 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-01-10 17:32:53 -0800 |
commit | c8dde40c3c62ceb79fc0b62f445d9a539fd470d3 (patch) | |
tree | 4d81aac663cfa78793197c0c2eb019a457a52b0f | |
parent | 5c0408af32a2b1c78b2d5a93cca60b0fffddd7da (diff) | |
parent | 3676bd288bce270a51b1c51f1052b76e83e71412 (diff) | |
download | libcore-c8dde40c3c62ceb79fc0b62f445d9a539fd470d3.zip libcore-c8dde40c3c62ceb79fc0b62f445d9a539fd470d3.tar.gz libcore-c8dde40c3c62ceb79fc0b62f445d9a539fd470d3.tar.bz2 |
Merge "Get memory for direct byte buffers from the Java heap rather than the native heap." into honeycomb
5 files changed, 63 insertions, 93 deletions
diff --git a/dalvik/src/main/java/dalvik/system/VMRuntime.java b/dalvik/src/main/java/dalvik/system/VMRuntime.java index c5350a1..ed859e6 100644 --- a/dalvik/src/main/java/dalvik/system/VMRuntime.java +++ b/dalvik/src/main/java/dalvik/system/VMRuntime.java @@ -189,4 +189,17 @@ public final class VMRuntime { * {@hide} */ public native void disableJitCompilation(); + + /** + * Returns an array allocated in an area of the Java heap where it will never be moved. + * This is used to implement native allocations on the Java heap, such as DirectByteBuffers + * and Bitmaps. + */ + public native Object newNonMovableArray(Class<?> componentType, int length); + + /** + * Returns the address of array[0]. This differs from using JNI in that JNI might lie and + * give you the address of a copy of the array when in forcecopy mode. + */ + public native long addressOf(Object array); } diff --git a/luni/src/main/java/java/nio/MemoryBlock.java b/luni/src/main/java/java/nio/MemoryBlock.java index 84ff683..76a7b36 100644 --- a/luni/src/main/java/java/nio/MemoryBlock.java +++ b/luni/src/main/java/java/nio/MemoryBlock.java @@ -17,6 +17,7 @@ package java.nio; +import dalvik.system.VMRuntime; import java.io.IOException; import java.nio.channels.FileChannel.MapMode; import org.apache.harmony.luni.platform.OSMemory; @@ -43,22 +44,23 @@ class MemoryBlock { } /** - * Handles calling free(3) on a native heap block. + * Non-movable heap blocks are byte arrays on the Java heap that the GC + * guarantees not to move. Used to implement DirectByteBuffer. + * + * Losing the strong reference to the array is sufficient + * to allow the GC to reclaim the storage. No finalizer needed. */ - private static class NativeHeapBlock extends MemoryBlock { - private NativeHeapBlock(int address, long byteCount) { + private static class NonMovableHeapBlock extends MemoryBlock { + private byte[] array; + + private NonMovableHeapBlock(byte[] array, int address, long byteCount) { super(address, byteCount); + this.array = array; } @Override public void free() { - if (address != 0) { - OSMemory.free(address); - address = 0; - } - } - - @Override protected void finalize() throws Throwable { - free(); + array = null; + address = 0; } } @@ -86,7 +88,10 @@ class MemoryBlock { } public static MemoryBlock allocate(int byteCount) { - return new NativeHeapBlock(OSMemory.calloc(byteCount), byteCount); + VMRuntime runtime = VMRuntime.getRuntime(); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, byteCount); + int address = (int) runtime.addressOf(array); + return new NonMovableHeapBlock(array, address, byteCount); } public static MemoryBlock wrapFromJni(int address, long byteCount) { diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java index 721f8d6..c567432 100644 --- a/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java +++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java @@ -139,9 +139,6 @@ public final class OSMemory { } } - public static native int calloc(int byteCount) throws OutOfMemoryError; - public static native void free(int address); - public static native void memmove(int destAddress, int srcAddress, long byteCount); public static native byte peekByte(int address); diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp index 609ce29..5b19626 100644 --- a/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp +++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp @@ -78,21 +78,6 @@ static inline void swapLongs(jlong* dstLongs, const jlong* srcLongs, size_t coun } } -static jint OSMemory_calloc(JNIEnv* env, jclass, jint size) { - // Our only caller wants zero-initialized memory. - // calloc(3) may be faster than malloc(3) followed by memset(3). - void* result = calloc(size, 1); - if (result == NULL) { - jniThrowException(env, "java/lang/OutOfMemoryError", NULL); - return 0; - } - return static_cast<jint>(reinterpret_cast<uintptr_t>(result)); -} - -static void OSMemory_free(JNIEnv*, jclass, jint address) { - free(cast<void*>(address)); -} - static void OSMemory_memmove(JNIEnv*, jclass, jint dstAddress, jint srcAddress, jlong length) { memmove(cast<void*>(dstAddress), cast<const void*>(srcAddress), length); } @@ -401,10 +386,8 @@ static void OSMemory_unsafeBulkPut(JNIEnv* env, jclass, jbyteArray dstArray, jin } static JNINativeMethod gMethods[] = { - NATIVE_METHOD(OSMemory, free, "(I)V"), NATIVE_METHOD(OSMemory, isLoaded, "(IJ)Z"), NATIVE_METHOD(OSMemory, load, "(IJ)V"), - NATIVE_METHOD(OSMemory, calloc, "(I)I"), NATIVE_METHOD(OSMemory, memmove, "(IIJ)V"), NATIVE_METHOD(OSMemory, mmapImpl, "(IJJI)I"), NATIVE_METHOD(OSMemory, msync, "(IJ)V"), diff --git a/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java b/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java index 06b376f..5c283d4 100644 --- a/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java +++ b/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java @@ -17,11 +17,9 @@ package org.apache.harmony.luni.platform; +import dalvik.system.VMRuntime; import junit.framework.TestCase; -/** - * Tests org.apache.harmony.luni.platform.OSMemory. - */ public class OSMemoryTest extends TestCase { public void testSetIntArray() { int[] values = { 3, 7, 31, 127, 8191, 131071, 524287, 2147483647 }; @@ -31,39 +29,26 @@ public class OSMemoryTest extends TestCase { } int scale = 4; - int ptr; + VMRuntime runtime = VMRuntime.getRuntime(); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length); + int ptr = (int) runtime.addressOf(array); - ptr = OSMemory.calloc(scale * values.length); - try { - // Regular copy. - OSMemory.pokeIntArray(ptr, values, 0, values.length, false); - assertIntsEqual(values, ptr, false); - assertIntsEqual(swappedValues, ptr, true); - } finally { - OSMemory.free(ptr); - } + // Regular copy. + OSMemory.pokeIntArray(ptr, values, 0, values.length, false); + assertIntsEqual(values, ptr, false); + assertIntsEqual(swappedValues, ptr, true); - ptr = OSMemory.calloc(scale * values.length); - try { - // Swapped copy. - OSMemory.pokeIntArray(ptr, values, 0, values.length, true); - assertIntsEqual(values, ptr, true); - assertIntsEqual(swappedValues, ptr, false); - } finally { - OSMemory.free(ptr); - } + // Swapped copy. + OSMemory.pokeIntArray(ptr, values, 0, values.length, true); + assertIntsEqual(values, ptr, true); + assertIntsEqual(swappedValues, ptr, false); - ptr = OSMemory.calloc(scale * values.length); - try { - // Swapped copies of slices (to ensure we test non-zero offsets). - for (int i = 0; i < values.length; ++i) { - OSMemory.pokeIntArray(ptr + i * scale, values, i, 1, true); - } - assertIntsEqual(values, ptr, true); - assertIntsEqual(swappedValues, ptr, false); - } finally { - OSMemory.free(ptr); + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + OSMemory.pokeIntArray(ptr + i * scale, values, i, 1, true); } + assertIntsEqual(values, ptr, true); + assertIntsEqual(swappedValues, ptr, false); } private void assertIntsEqual(int[] expectedValues, int ptr, boolean swap) { @@ -77,39 +62,26 @@ public class OSMemoryTest extends TestCase { short[] swappedValues = { 0x0100, 0x2000, 0x0003, 0x0040 }; int scale = 2; - int ptr; + VMRuntime runtime = VMRuntime.getRuntime(); + byte[] array = (byte[]) runtime.newNonMovableArray(byte.class, scale * values.length); + int ptr = (int) runtime.addressOf(array); - ptr = OSMemory.calloc(scale * values.length); - try { - // Regular copy. Memset first so we start from a known state. - OSMemory.pokeShortArray(ptr, values, 0, values.length, false); - assertShortsEqual(values, ptr, false); - assertShortsEqual(swappedValues, ptr, true); - } finally { - OSMemory.free(ptr); - } + // Regular copy. Memset first so we start from a known state. + OSMemory.pokeShortArray(ptr, values, 0, values.length, false); + assertShortsEqual(values, ptr, false); + assertShortsEqual(swappedValues, ptr, true); - ptr = OSMemory.calloc(scale * values.length); - try { - // Swapped copy. - OSMemory.pokeShortArray(ptr, values, 0, values.length, true); - assertShortsEqual(values, ptr, true); - assertShortsEqual(swappedValues, ptr, false); - } finally { - OSMemory.free(ptr); - } + // Swapped copy. + OSMemory.pokeShortArray(ptr, values, 0, values.length, true); + assertShortsEqual(values, ptr, true); + assertShortsEqual(swappedValues, ptr, false); - ptr = OSMemory.calloc(scale * values.length); - try { - // Swapped copies of slices (to ensure we test non-zero offsets). - for (int i = 0; i < values.length; ++i) { - OSMemory.pokeShortArray(ptr + i * scale, values, i, 1, true); - } - assertShortsEqual(values, ptr, true); - assertShortsEqual(swappedValues, ptr, false); - } finally { - OSMemory.free(ptr); + // Swapped copies of slices (to ensure we test non-zero offsets). + for (int i = 0; i < values.length; ++i) { + OSMemory.pokeShortArray(ptr + i * scale, values, i, 1, true); } + assertShortsEqual(values, ptr, true); + assertShortsEqual(swappedValues, ptr, false); } private void assertShortsEqual(short[] expectedValues, int ptr, boolean swap) { |