summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2011-01-10 17:32:53 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-01-10 17:32:53 -0800
commitc8dde40c3c62ceb79fc0b62f445d9a539fd470d3 (patch)
tree4d81aac663cfa78793197c0c2eb019a457a52b0f
parent5c0408af32a2b1c78b2d5a93cca60b0fffddd7da (diff)
parent3676bd288bce270a51b1c51f1052b76e83e71412 (diff)
downloadlibcore-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
-rw-r--r--dalvik/src/main/java/dalvik/system/VMRuntime.java13
-rw-r--r--luni/src/main/java/java/nio/MemoryBlock.java29
-rw-r--r--luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java3
-rw-r--r--luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp17
-rw-r--r--luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java94
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) {