From 8974ea0654e22bdba115d99e4f7e3a64459dd68d Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 20 Jan 2025 12:10:26 -0600 Subject: [PATCH] CLDC 8: add ByteBuffer --- c/native.c | 88 ++++++-- c/native/memory.c | 198 +++++++++++++++--- c/native/memory.h | 23 +- classes/java/nio/Buffer.java | 69 ++++-- classes/java/nio/ByteBuffer.java | 349 +++++++++++++++++++++++-------- classes/java/nio/ByteOrder.java | 8 + classes/jvm/internal/Memory.java | 18 +- java.mk | 1 + 8 files changed, 578 insertions(+), 176 deletions(-) diff --git a/c/native.c b/c/native.c index ca3a784..bcd1191 100644 --- a/c/native.c +++ b/c/native.c @@ -23,6 +23,7 @@ struct native_method { }; const static struct native_method native_method[] = { + // Math { .class_name = "java/lang/Math", .method_name = "sin", @@ -41,54 +42,92 @@ const static struct native_method native_method[] = { .method_descriptor = "(F)F", .func = native_java_lang_math_abs_1, }, + // Memory { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", .method_name = "putU4", .method_descriptor = "(II)V", - .func = native_java_misc_memory_putU4_2, + .func = native_jvm_internal_memory_putU4_2, }, { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", .method_name = "putU2", - .method_descriptor = "(II)V", - .func = native_java_misc_memory_putU2_2, + .method_descriptor = "(IS)V", + .func = native_jvm_internal_memory_putU2_2, }, { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", .method_name = "putU1", - .method_descriptor = "(II)V", - .func = native_java_misc_memory_putU1_2, + .method_descriptor = "(IB)V", + .func = native_jvm_internal_memory_putU1_2, }, { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", .method_name = "getU4", .method_descriptor = "(I)I", - .func = native_java_misc_memory_getU4_1, + .func = native_jvm_internal_memory_getU4_1, }, { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", .method_name = "getU2", - .method_descriptor = "(I)I", - .func = native_java_misc_memory_getU2_1, + .method_descriptor = "(I)S", + .func = native_jvm_internal_memory_getU2_1, }, { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", .method_name = "getU1", - .method_descriptor = "(I)I", - .func = native_java_misc_memory_getU1_1, + .method_descriptor = "(I)B", + .func = native_jvm_internal_memory_getU1_1, }, { - .class_name = "java/misc/Memory", - .method_name = "putSQ1", - .method_descriptor = "(Ljava/lang/Object;I)V", - .func = native_java_misc_memory_putSQ1_2, + .class_name = "jvm/internal/Memory", + .method_name = "putU4", + .method_descriptor = "(IIZ)V", + .func = native_jvm_internal_memory_putUnalignedU4_3, }, { - .class_name = "java/misc/Memory", + .class_name = "jvm/internal/Memory", + .method_name = "putU2", + .method_descriptor = "(ISZ)V", + .func = native_jvm_internal_memory_putUnalignedU2_3, + }, + { + .class_name = "jvm/internal/Memory", + .method_name = "putF4", + .method_descriptor = "(IFZ)V", + .func = native_jvm_internal_memory_putUnalignedU4_3, + }, + { + .class_name = "jvm/internal/Memory", + .method_name = "getU4", + .method_descriptor = "(IZ)I", + .func = native_jvm_internal_memory_getUnalignedU4_2, + }, + { + .class_name = "jvm/internal/Memory", + .method_name = "getU2", + .method_descriptor = "(IZ)S", + .func = native_jvm_internal_memory_getUnalignedU2_2, + }, + { + .class_name = "jvm/internal/Memory", + .method_name = "getF4", + .method_descriptor = "(IZ)F", + .func = native_jvm_internal_memory_getUnalignedU4_2, + }, + { + .class_name = "jvm/internal/Memory", .method_name = "isBigEndian", .method_descriptor = "()Z", - .func = native_java_misc_memory_isbigendian_0, + .func = native_jvm_internal_memory_isbigendian_0, }, + { + .class_name = "jvm/internal/Memory", + .method_name = "allocate", + .method_descriptor = "(I)I", + .func = native_jvm_internal_memory_allocate_1, + }, + // PrintStream { .class_name = "java/io/PrintStream", .method_name = "_write", @@ -107,6 +146,7 @@ const static struct native_method native_method[] = { .method_descriptor = "(Ljava/lang/String;)V", .func = native_java_io_printstream_write_s_1, }, + // Loader { .class_name = "jvm/internal/Loader", .method_name = "load", @@ -119,6 +159,7 @@ const static struct native_method native_method[] = { .method_descriptor = "()I", .func = native_jvm_internal_loader_getbuffer_0, }, + // Class { .class_name = "java/lang/Class", .method_name = "_getName", @@ -131,12 +172,14 @@ const static struct native_method native_method[] = { .method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;", .func = native_java_lang_class_getsuperclass_1, }, + // Object { .class_name = "java/lang/Object", .method_name = "_getClass", .method_descriptor = "(Ljava/lang/Object;)Ljava/lang/Class;", .func = native_java_lang_object_getclass_1, }, + // Runtime { .class_name = "java/lang/Runtime", .method_name = "_freeMemory", @@ -155,6 +198,7 @@ const static struct native_method native_method[] = { .method_descriptor = "()I", .func = native_java_lang_runtime_totalmemory_0, }, + // System { .class_name = "java/lang/System", .method_name = "_hashCode", diff --git a/c/native/memory.c b/c/native/memory.c index 408521a..0447d41 100644 --- a/c/native/memory.c +++ b/c/native/memory.c @@ -1,75 +1,213 @@ -#include "native_types.h" #include "memory.h" +#include "memory_allocator.h" -void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args) +void native_jvm_internal_memory_putU4_2(struct vm * vm, uint32_t * args) { uint32_t * address = (uint32_t *)args[0]; uint32_t value = args[1]; *address = value; } -void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args) +void native_jvm_internal_memory_putU2_2(struct vm * vm, uint32_t * args) { uint16_t * address = (uint16_t *)args[0]; uint16_t value = args[1]; *address = value; } -void native_java_misc_memory_putU1_2(struct vm * vm, uint32_t * args) +void native_jvm_internal_memory_putU1_2(struct vm * vm, uint32_t * args) { uint8_t * address = (uint8_t *)args[0]; uint8_t value = args[1]; *address = value; } -void native_java_misc_memory_getU4_1(struct vm * vm, uint32_t * args) +void native_jvm_internal_memory_getU4_1(struct vm * vm, uint32_t * args) { uint32_t * address = (uint32_t *)args[0]; uint32_t value = *address; operand_stack_push_u32(vm->current_frame, value); } -void native_java_misc_memory_getU2_1(struct vm * vm, uint32_t * args) +void native_jvm_internal_memory_getU2_1(struct vm * vm, uint32_t * args) { uint16_t * address = (uint16_t *)args[0]; uint16_t value = *address; operand_stack_push_u32(vm->current_frame, value); } -void native_java_misc_memory_getU1_1(struct vm * vm, uint32_t * args) +void native_jvm_internal_memory_getU1_1(struct vm * vm, uint32_t * args) { uint8_t * address = (uint8_t *)args[0]; uint8_t value = *address; operand_stack_push_u32(vm->current_frame, value); } -extern uint32_t store_queue[0x4000000] __asm("store_queue"); - -void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args) +static inline void unaligned_store_u4(uint32_t address, uint32_t value, bool big_endian) { - #if defined(__dreamcast__) - struct objectref * objectref = (struct objectref *)args[0]; - uint32_t address = (uint32_t)args[1]; - store_queue[0] = objectref->u32[0]; - store_queue[1] = objectref->u32[1]; - store_queue[2] = objectref->u32[2]; - store_queue[3] = objectref->u32[3]; - store_queue[4] = objectref->u32[4]; - store_queue[5] = objectref->u32[5]; - store_queue[6] = objectref->u32[6]; - store_queue[7] = objectref->u32[7]; - - *((uint32_t*)0xff000038) = ((address >> 26) & 0b111) << 2; - - __asm__ volatile ("pref @%0" - : // output - : "r" (&store_queue[0]) // input - : "memory"); - #endif + if ((address & 3) == 0) { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + if (big_endian) + *((uint32_t *)address) = value; + else + *((uint32_t *)address) = __builtin_bswap32(value); +#else // LITTLE_ENDIAN + if (!big_endian) + *((uint32_t *)address) = value; + else + *((uint32_t *)address) = __builtin_bswap32(value); +#endif + } else { + if (big_endian) { + ((uint8_t *)address)[0] = (uint8_t)(value >> 24); + ((uint8_t *)address)[1] = (uint8_t)(value >> 16); + ((uint8_t *)address)[2] = (uint8_t)(value >> 8); + ((uint8_t *)address)[3] = (uint8_t)(value >> 0); + } else { + ((uint8_t *)address)[0] = (uint8_t)(value >> 0); + ((uint8_t *)address)[1] = (uint8_t)(value >> 8); + ((uint8_t *)address)[2] = (uint8_t)(value >> 16); + ((uint8_t *)address)[3] = (uint8_t)(value >> 24); + } + } } -void native_java_misc_memory_isbigendian_0(struct vm * vm, uint32_t * args) +static inline void unaligned_store_u2(uint32_t address, uint32_t value, bool big_endian) +{ + if ((address & 1) == 0) { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + if (big_endian) + *((uint16_t *)address) = value; + else + *((uint16_t *)address) = __builtin_bswap16(value); +#else // LITTLE_ENDIAN + if (!big_endian) + *((uint16_t *)address) = value; + else + *((uint16_t *)address) = __builtin_bswap16(value); +#endif + } else { + if (big_endian) { + ((uint8_t *)address)[0] = (uint8_t)(value >> 8); + ((uint8_t *)address)[1] = (uint8_t)(value >> 0); + } else { + ((uint8_t *)address)[0] = (uint8_t)(value >> 0); + ((uint8_t *)address)[1] = (uint8_t)(value >> 8); + } + } +} + +void native_jvm_internal_memory_putUnalignedU4_3(struct vm * vm, uint32_t * args) +{ + uint32_t address = (uint32_t)args[0]; + uint32_t value = args[1]; + bool big_endian = args[2]; + + unaligned_store_u4(address, value, big_endian); +} + +void native_jvm_internal_memory_putUnalignedU2_3(struct vm * vm, uint32_t * args) +{ + uint32_t address = (uint32_t)args[0]; + uint32_t value = args[1]; + bool big_endian = args[2]; + + unaligned_store_u2(address, value, big_endian); +} + +static inline uint32_t unaligned_load_u4(uint32_t address, bool big_endian) +{ + uint32_t value; + if ((address & 3) == 0) { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + if (big_endian) + value = *((uint32_t *)address); + else + value = __builtin_bswap32(*((uint32_t *)address)); +#else // LITTLE_ENDIAN + if (!big_endian) + value = *((uint32_t *)address); + else + value = __builtin_bswap32(*((uint32_t *)address)); +#endif + } else { + if (big_endian) { + value = + ((((uint8_t *)address)[0] << 24) | + (((uint8_t *)address)[1] << 16) | + (((uint8_t *)address)[2] << 8 ) | + (((uint8_t *)address)[3] << 0 )); + } else { + value = + ((((uint8_t *)address)[0] << 0 ) | + (((uint8_t *)address)[1] << 8 ) | + (((uint8_t *)address)[2] << 16) | + (((uint8_t *)address)[3] << 24)); + } + } + return value; +} + +static inline uint32_t unaligned_load_u2(uint32_t address, bool big_endian) +{ + uint32_t value; + if ((address & 1) == 0) { +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + if (big_endian) + value = *((uint32_t *)address); + else + value = __builtin_bswap32(*((uint32_t *)address)); +#else // LITTLE_ENDIAN + if (!big_endian) + value = *((uint32_t *)address); + else + value = __builtin_bswap32(*((uint32_t *)address)); +#endif + } else { + if (big_endian) { + value = + ((((uint8_t *)address)[0] << 8 ) | + (((uint8_t *)address)[1] << 0 )); + } else { + value = + ((((uint8_t *)address)[0] << 0 ) | + (((uint8_t *)address)[1] << 8 )); + } + } + return value; +} + +void native_jvm_internal_memory_getUnalignedU4_2(struct vm * vm, uint32_t * args) +{ + uint32_t address = (uint32_t)args[0]; + bool big_endian = args[1]; + + uint32_t value = unaligned_load_u4(address, big_endian); + + operand_stack_push_u32(vm->current_frame, value); +} + +void native_jvm_internal_memory_getUnalignedU2_2(struct vm * vm, uint32_t * args) +{ + uint32_t address = (uint32_t)args[0]; + bool big_endian = args[1]; + + uint32_t value = unaligned_load_u2(address, big_endian); + + operand_stack_push_u32(vm->current_frame, value); +} + +void native_jvm_internal_memory_isbigendian_0(struct vm * vm, uint32_t * args) { uint32_t value = (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__); operand_stack_push_u32(vm->current_frame, value); } + +void native_jvm_internal_memory_allocate_1(struct vm * vm, uint32_t * args) +{ + uint32_t capacity = (uint32_t)args[0]; + + void * address = memory_allocate(capacity); + + operand_stack_push_u32(vm->current_frame, (uint32_t)address); +} diff --git a/c/native/memory.h b/c/native/memory.h index ddfedc0..e114f61 100644 --- a/c/native/memory.h +++ b/c/native/memory.h @@ -4,11 +4,18 @@ #include "vm.h" -void native_java_misc_memory_putU4_2(struct vm * vm, uint32_t * args); -void native_java_misc_memory_putU2_2(struct vm * vm, uint32_t * args); -void native_java_misc_memory_putU1_2(struct vm * vm, uint32_t * args); -void native_java_misc_memory_getU4_1(struct vm * vm, uint32_t * args); -void native_java_misc_memory_getU2_1(struct vm * vm, uint32_t * args); -void native_java_misc_memory_getU1_1(struct vm * vm, uint32_t * args); -void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args); -void native_java_misc_memory_isbigendian_0(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_putU4_2(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_putU2_2(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_putU1_2(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_getU4_1(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_getU2_1(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_getU1_1(struct vm * vm, uint32_t * args); + +void native_jvm_internal_memory_putUnalignedU4_3(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_putUnalignedU2_3(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_getUnalignedU4_2(struct vm * vm, uint32_t * args); +void native_jvm_internal_memory_getUnalignedU2_2(struct vm * vm, uint32_t * args); + +void native_jvm_internal_memory_isbigendian_0(struct vm * vm, uint32_t * args); + +void native_jvm_internal_memory_allocate_1(struct vm * vm, uint32_t * args); diff --git a/classes/java/nio/Buffer.java b/classes/java/nio/Buffer.java index 6bd9160..9c60429 100644 --- a/classes/java/nio/Buffer.java +++ b/classes/java/nio/Buffer.java @@ -1,38 +1,69 @@ package java.nio; -class Buffer { - protected int mark = -1; - protected int position = 0; - protected int limit; - protected final int capacity; +public abstract class Buffer { + private final int address; + private int position; + private int limit; + private final int capacity; - Buffer(int mark, int position, int limit, int capacity) { - this.mark = mark; + protected Buffer(int address, int position, int limit, int capacity) { + this.address = address; this.position = position; this.limit = limit; this.capacity = capacity; } - public final int position() { - return position; - } - - public final int limit() { - return limit; - } - public final int capacity() { return capacity; } - public Buffer limit(int limit) { - this.limit = limit; - if (position > limit) position = limit; - if (mark > limit) mark = -1; + public final Buffer clear() { + position = 0; + limit = capacity; + return this; + } + + public final Buffer flip() { + limit = position; + position = 0; return this; } public final boolean hasRemaining() { return position < limit; } + + public final int limit() { + return limit; + } + + public Buffer limit(int newLimit) { + if (newLimit < 0 || newLimit > capacity) + throw new IllegalArgumentException(); + this.limit = newLimit; + if (position > newLimit) position = newLimit; + return this; + } + + public final int position() { + return position; + } + + public final Buffer position(int newPosition) { + if (newPosition < 0 || newPosition > limit) + throw new IllegalArgumentException(); + position = newPosition; + } + + public final int remaining() { + int elements = limit - position; + if (elements < 0) + elements = 0; + return elements; + } + + public final Buffer rewind() { + position = 0; + return this; + } } diff --git a/classes/java/nio/ByteBuffer.java b/classes/java/nio/ByteBuffer.java index 2f02349..ffafd1d 100644 --- a/classes/java/nio/ByteBuffer.java +++ b/classes/java/nio/ByteBuffer.java @@ -1,24 +1,162 @@ package java.nio; -public class ByteBuffer extends Buffer { - private int offset; +import jvm.internal.Memory; + +public class ByteBuffer + extends Buffer + implements Comparable { + private boolean bigEndian; - //private boolean sameEndian; - private byte[] array; - - private ByteBuffer(byte[] array, int offset, int length) { - super(-1, 0, length, length); - this.array = array; - this.order(ByteOrder.BIG_ENDIAN); + private ByteBuffer(int address, int position, int limit, int capacity, int bigEndian) { + super(address, position, limit, capacity); + bigEndian = bigEndian; } - public static ByteBuffer wrap(byte[] array) { - return new ByteBuffer(array, 0, array.length); + public static ByteBuffer allocateDirect(int capacity) { + int address = Memory.allocate(capacity); + return new ByteBuffer(address, 0, capacity, capacity, true); } - public static ByteBuffer wrap(byte[] array, int offset, int length) { - return new ByteBuffer(array, offset, length); + public final byte[] array() { + throw new UnsupportedOperationException(); + } + + public final int arrayOffset() { + throw new UnsupportedOperationException(); + } + + private static int mismatch(ByteBuffer a, + ByteBuffer b) + { + int remA = a.limit - a.position; + int remB = b.limit - b.position; + int length = remA > remB ? remB : remA; + int offA = a.position; + int offB = b.position; + for (int i = 0; i < length; i++) { + if (a.get(offA + i) != b.get(offB + i)) + return i; + } + if (remA != remB) + return length; + return -1; + } + + public int compareTo(ByteBuffer that) { + int pos = mismatch(this, that); + if (pos >= 0) { + return this.get(this.position + pos) - that.get(that.position + pos); + } else { + int thisRem = this.limit - this.position; + int thatRem = that.limit - that.position; + return thisRem - thatRem; + } + } + + public boolean equals(Object ob) { + if (this == ob) + return true; + if (!(ob instanceof ByteBuffer)) + return false; + ByteBuffer other = (ByteBuffer)ob; + int pos = ByteBuffer.mismatch(this, other); + return pos == -1; + } + + public byte get() { + if (position >= limit) + throw new IndexOutOfBoundsException(); + byte b = Memory.getU1(address + position); + position += 1; + return b; + } + + public ByteBuffer get(byte[] dst) { + return get(dst, 0, dst.length); + } + + public ByteBuffer get(byte[] dst, + int offset, + int length) { + int rem = limit - position; + if (rem < length) { + throw new BufferUnderflowException(); + } + if (offset < 0 || offset > dst.length || length < 0 || length > (dst.length - offset)) { + throw new IndexOutOfBoundsException(); + } + for (int i = offset; i < offset + length; i++) + dst[i] = get(); + + return this; + } + + public byte get(int index) { + if (index < 0 || index > limit) + throw new IndexOutOfBoundsException(); + return Memory.getU1(address + index); + } + + public float getFloat() { + if (limit - position < 4) + throw new BufferUnderflowException(); + float f = Memory.getUnalignedF4(address + position, bigEndian); + position += 4; + return f; + } + + public float getFloat(int index) { + if (index < 0 || index >= (limit - 3)) + throw new IndexOutOfBoundsException(); + float f = Memory.getUnalignedF4(address + index, bigEndian); + return f; + } + + public int getInt() { + if (limit - position < 4) + throw new BufferUnderflowException(); + int i = Memory.getUnalignedU4(address + position, bigEndian); + position += 4; + return i; + } + + public int getInt(int index) { + if (index < 0 || index >= (limit - 3)) + throw new IndexOutOfBoundsException(); + in i = Memory.getUnalignedU4(address + index, bigEndian); + return i; + } + + public short getShort() { + if (limit - position < 2) + throw new BufferUnderflowException(); + short i = Memory.getUnalignedU2(address + position, bigEndian); + position += 4; + return i; + } + + public short getShort(short index) { + if (index < 0 || index >= (limit - 1)) + throw new IndexOutOfBoundsException(); + in i = Memory.getUnalignedU2(address + index, bigEndian); + return i; + } + + public final boolean hasArray() { + return false; + } + + public int hashCode() { + int h = 1; + int limit = this.limit; + for (int i = position; i < limit; i++) { + h = 31 * h + (int)get(i); + } + } + + public boolean isDirect() { + return true; } public ByteOrder order() { @@ -27,103 +165,128 @@ public class ByteBuffer extends Buffer { public ByteBuffer order(ByteOrder bo) { bigEndian = (bo == ByteOrder.BIG_ENDIAN); - //sameEndian = (bo == ByteOrder.nativeOrder()); return this; } - public ByteBuffer offset(int off) { - offset = off; - return this; - } - - private static int intBE(int i0, int i1, int i2, int i3) { - return ((i0 << 24) - | (i1 << 16) - | (i2 << 8) - | (i3 << 0)); - } - - private static int intLE(int i0, int i1, int i2, int i3) { - return ((i0 << 0) - | (i1 << 8) - | (i2 << 16) - | (i3 << 24)); - } - - private static int shortBE(int i0, int i1) { - return ((i0 << 8) - | (i1 << 0)); - } - - private static int shortLE(int i0, int i1) { - return ((i0 << 0) - | (i1 << 8)); - } - - private int ix(int pos) { - return offset + pos; - } - - public byte get() { - byte i0 = array[ix(position)]; + public ByteBuffer put(byte b) { + if (position >= limit) + throw new IndexOutOfBoundsException(); + Memory.putU1(address + position); position += 1; - return i0; + return this; } - public byte get(int pos) { - byte i0 = array[ix(pos)]; - return i0; + public final ByteBuffer put(byte[] src) { + return put(src, 0, src.length); } - public short getShort() { - int i0 = array[ix(position) + 0]; - int i1 = array[ix(position) + 1]; + public ByteBuffer put(byte[] src, + int offset, + int length) { + int rem = limit - position; + if (rem < length) { + throw new BufferUnderflowException(); + } + if (offset < 0 || offset > src.length || length < 0 || length > (src.length - offset)) { + throw new IndexOutOfBoundsException(); + } + for (int i = offset; i < offset + length; i++) + put(src[i]); + return this; + } - position += 2; - - if (bigEndian) { - return (short)shortBE(i0, i1); - } else { - return (short)shortLE(i0, i1); + public ByteBuffer put(ByteBuffer src) { + int rem = limit - position; + if (rem < src.length) { + throw new BufferUnderflowException(); + } + if (src == this) { + throw new IllegalArgumentException(); + } + for (int i = src.position; i < src.limit; i++) { + put(src.get(i)); } } - public short getShort(int pos) { - int i0 = array[ix(pos) + 0]; - int i1 = array[ix(pos) + 1]; - - if (bigEndian) { - return (short)shortBE(i0, i1); - } else { - return (short)shortLE(i0, i1); - } + public ByteBuffer put(int index, + byte b) { + if (index < 0 || index > limit) + throw new IndexOutOfBoundsException(); + Memory.putU1(address + index, b); + return this; } - public int getInt() { - int i0 = array[ix(position) + 0]; - int i1 = array[ix(position) + 1]; - int i2 = array[ix(position) + 2]; - int i3 = array[ix(position) + 3]; - + public ByteBuffer putFloat(float value) { + if (limit - position < 4) + throw new BufferUnderflowException(); + Memory.putUnalignedF4(address + position, value, bigEndian); position += 4; - - if (bigEndian) { - return intBE(i0, i1, i2, i3); - } else { - return intLE(i0, i1, i2, i3); - } + return this; } - public int getInt(int pos) { - int i0 = array[ix(pos) + 0]; - int i1 = array[ix(pos) + 1]; - int i2 = array[ix(pos) + 2]; - int i3 = array[ix(pos) + 3]; + public ByteBuffer putFloat(int index, + float value) { + if (index < 0 || index >= (limit - 3)) + throw new IndexOutOfBoundsException(); + Memory.putUnalignedF4(address + index, value, bigEndian); + return this; + } - if (bigEndian) { - return intBE(i0, i1, i2, i3); - } else { - return intLE(i0, i1, i2, i3); - } + public ByteBuffer putInt(int value) { + if (limit - position < 4) + throw new BufferUnderflowException(); + Memory.putUnalignedU4(address + position, value, bigEndian); + position += 4; + return this; + } + + public ByteBuffer putInt(int index, + int value) { + if (index < 0 || index >= (limit - 3)) + throw new IndexOutOfBoundsException(); + Memory.putUnalignedU4(address + index, value, bigEndian); + return this; + } + + public ByteBuffer putShort(short value) { + if (limit - position < 4) + throw new BufferUnderflowException(); + Memory.putUnalignedU2(address + position, value, bigEndian); + position += 4; + return this; + } + + public ByteBuffer putShort(int index, + short value) { + if (index < 0 || index >= (limit - 1)) + throw new IndexOutOfBoundsException(); + Memory.putUnalignedU2(address + index, value, bigEndian); + return this; + } + + public ByteBuffer slice() { + return new ByteBuffer(address, + position, + limit, + capacity, + bigEndian); + } + + public String toString() { + return getClass().getName() + + "[pos=" + position + + " lim=" + limit + + " cap=" + capacity + + "]"; + } + + public static ByteBuffer wrap(byte[] array) { + throw new UnsupportedOperationException(); + } + + public static ByteBuffer wrap(byte[] array, + int offset, + int length) { + throw new UnsupportedOperationException(); } } diff --git a/classes/java/nio/ByteOrder.java b/classes/java/nio/ByteOrder.java index caae026..7dd2211 100644 --- a/classes/java/nio/ByteOrder.java +++ b/classes/java/nio/ByteOrder.java @@ -12,4 +12,12 @@ public class ByteOrder { public static ByteOrder nativeOrder() { return NATIVE_ORDER; } + + public String toString() { + if (this == BIG_ENDIAN) { + return "BIG_ENDIAN"; + } else { + return "LITTLE_ENDIAN"; + } + } } diff --git a/classes/jvm/internal/Memory.java b/classes/jvm/internal/Memory.java index 832f52b..85f23ba 100644 --- a/classes/jvm/internal/Memory.java +++ b/classes/jvm/internal/Memory.java @@ -2,14 +2,24 @@ package jvm.internal; public class Memory { public static native void putU4(int address, int value); - public static native void putU2(int address, int value); - public static native void putU1(int address, int value); + public static native void putU2(int address, short value); + public static native void putU1(int address, byte value); public static native int getU4(int address); - public static native int getU2(int address); - public static native int getU1(int address); + public static native short getU2(int address); + public static native byte getU1(int address); + + public static native void putUnalignedU4(int address, int value, boolean bigEndian); + public static native void putUnalignedU2(int address, short value, boolean bigEndian); + public static native void putUnalignedF4(int address, float value, boolean bigEndian); + + public static native int getUnalignedU4(int address, boolean bigEndian); + public static native short getUnalignedU2(int address, boolean bigEndian); + public static native float getUnalignedF4(int address, boolean bigEndian); public static native void putSQ1(Object object, int address); public static native boolean isBigEndian(); + + public static native int allocate(int size); } diff --git a/java.mk b/java.mk index ce4f1fb..2a3247a 100644 --- a/java.mk +++ b/java.mk @@ -47,4 +47,5 @@ MAIN_HOSTED_OBJ = \ PRINT_CLASS_OBJ = \ c/file.o \ + c/native/libcinputstream.o \ c/print_class.o