CLDC 8: add ByteBuffer

This commit is contained in:
Zack Buhman 2025-01-20 12:10:26 -06:00
parent 5fd397563e
commit 0702fcb0f3
7 changed files with 575 additions and 175 deletions

View File

@ -8,6 +8,7 @@
#include "native/loader.h" #include "native/loader.h"
#include "native/math.h" #include "native/math.h"
#include "native/memory.h" #include "native/memory.h"
#include "native/memoryunaligned.h"
#include "native/object.h" #include "native/object.h"
#include "native/printstream.h" #include "native/printstream.h"
#include "native/runtime.h" #include "native/runtime.h"
@ -23,6 +24,7 @@ struct native_method {
}; };
const static struct native_method native_method[] = { const static struct native_method native_method[] = {
// Math
{ {
.class_name = "java/lang/Math", .class_name = "java/lang/Math",
.method_name = "sin", .method_name = "sin",
@ -41,54 +43,92 @@ const static struct native_method native_method[] = {
.method_descriptor = "(F)F", .method_descriptor = "(F)F",
.func = native_java_lang_math_abs_1, .func = native_java_lang_math_abs_1,
}, },
// Memory
{ {
.class_name = "java/misc/Memory", .class_name = "jvm/internal/Memory",
.method_name = "putU4", .method_name = "putU4",
.method_descriptor = "(II)V", .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_name = "putU2",
.method_descriptor = "(II)V", .method_descriptor = "(IS)V",
.func = native_java_misc_memory_putU2_2, .func = native_jvm_internal_memory_putU2_2,
}, },
{ {
.class_name = "java/misc/Memory", .class_name = "jvm/internal/Memory",
.method_name = "putU1", .method_name = "putU1",
.method_descriptor = "(II)V", .method_descriptor = "(IB)V",
.func = native_java_misc_memory_putU1_2, .func = native_jvm_internal_memory_putU1_2,
}, },
{ {
.class_name = "java/misc/Memory", .class_name = "jvm/internal/Memory",
.method_name = "getU4", .method_name = "getU4",
.method_descriptor = "(I)I", .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_name = "getU2",
.method_descriptor = "(I)I", .method_descriptor = "(I)S",
.func = native_java_misc_memory_getU2_1, .func = native_jvm_internal_memory_getU2_1,
}, },
{ {
.class_name = "java/misc/Memory", .class_name = "jvm/internal/Memory",
.method_name = "getU1", .method_name = "getU1",
.method_descriptor = "(I)I", .method_descriptor = "(I)B",
.func = native_java_misc_memory_getU1_1, .func = native_jvm_internal_memory_getU1_1,
}, },
{ {
.class_name = "java/misc/Memory", .class_name = "jvm/internal/Memory",
.method_name = "putSQ1", .method_name = "putU4",
.method_descriptor = "(Ljava/lang/Object;I)V", .method_descriptor = "(IIZ)V",
.func = native_java_misc_memory_putSQ1_2, .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_name = "isBigEndian",
.method_descriptor = "()Z", .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", .class_name = "java/io/PrintStream",
.method_name = "_write", .method_name = "_write",
@ -107,6 +147,7 @@ const static struct native_method native_method[] = {
.method_descriptor = "(Ljava/lang/String;)V", .method_descriptor = "(Ljava/lang/String;)V",
.func = native_java_io_printstream_write_s_1, .func = native_java_io_printstream_write_s_1,
}, },
// Loader
{ {
.class_name = "jvm/internal/Loader", .class_name = "jvm/internal/Loader",
.method_name = "load", .method_name = "load",
@ -119,6 +160,7 @@ const static struct native_method native_method[] = {
.method_descriptor = "()I", .method_descriptor = "()I",
.func = native_jvm_internal_loader_getbuffer_0, .func = native_jvm_internal_loader_getbuffer_0,
}, },
// Class
{ {
.class_name = "java/lang/Class", .class_name = "java/lang/Class",
.method_name = "_getName", .method_name = "_getName",
@ -131,12 +173,14 @@ const static struct native_method native_method[] = {
.method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;", .method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;",
.func = native_java_lang_class_getsuperclass_1, .func = native_java_lang_class_getsuperclass_1,
}, },
// Object
{ {
.class_name = "java/lang/Object", .class_name = "java/lang/Object",
.method_name = "_getClass", .method_name = "_getClass",
.method_descriptor = "(Ljava/lang/Object;)Ljava/lang/Class;", .method_descriptor = "(Ljava/lang/Object;)Ljava/lang/Class;",
.func = native_java_lang_object_getclass_1, .func = native_java_lang_object_getclass_1,
}, },
// Runtime
{ {
.class_name = "java/lang/Runtime", .class_name = "java/lang/Runtime",
.method_name = "_freeMemory", .method_name = "_freeMemory",
@ -155,6 +199,7 @@ const static struct native_method native_method[] = {
.method_descriptor = "()I", .method_descriptor = "()I",
.func = native_java_lang_runtime_totalmemory_0, .func = native_java_lang_runtime_totalmemory_0,
}, },
// System
{ {
.class_name = "java/lang/System", .class_name = "java/lang/System",
.method_name = "_hashCode", .method_name = "_hashCode",

View File

@ -1,75 +1,211 @@
#include "native_types.h"
#include "memory.h" #include "memory.h"
#include "memory_allocate.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 * address = (uint32_t *)args[0];
uint32_t value = args[1]; uint32_t value = args[1];
*address = value; *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 * address = (uint16_t *)args[0];
uint16_t value = args[1]; uint16_t value = args[1];
*address = value; *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 * address = (uint8_t *)args[0];
uint8_t value = args[1]; uint8_t value = args[1];
*address = value; *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 * address = (uint32_t *)args[0];
uint32_t value = *address; uint32_t value = *address;
operand_stack_push_u32(vm->current_frame, value); 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 * address = (uint16_t *)args[0];
uint16_t value = *address; uint16_t value = *address;
operand_stack_push_u32(vm->current_frame, value); 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 * address = (uint8_t *)args[0];
uint8_t value = *address; uint8_t value = *address;
operand_stack_push_u32(vm->current_frame, value); operand_stack_push_u32(vm->current_frame, value);
} }
extern uint32_t store_queue[0x4000000] __asm("store_queue"); #include "memoryunaligned.h"
void native_java_misc_memory_putSQ1_2(struct vm * vm, uint32_t * args) static inline void unaligned_load_u4(uint32_t address, uint32_t value, bool big_endian)
{ {
#if defined(__dreamcast__) if ((address & 3) == 0) {
struct objectref * objectref = (struct objectref *)args[0]; #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
uint32_t address = (uint32_t)args[1]; if (big_endian)
store_queue[0] = objectref->u32[0]; *((uint32_t *)address) = value;
store_queue[1] = objectref->u32[1]; else
store_queue[2] = objectref->u32[2]; *((uint32_t *)address) = __builtin_bswap32(value);
store_queue[3] = objectref->u32[3]; #else // LITTLE_ENDIAN
store_queue[4] = objectref->u32[4]; if (!big_endian)
store_queue[5] = objectref->u32[5]; *((uint32_t *)address) = value;
store_queue[6] = objectref->u32[6]; else
store_queue[7] = objectref->u32[7]; *((uint32_t *)address) = __builtin_bswap32(value);
*((uint32_t*)0xff000038) = ((address >> 26) & 0b111) << 2;
__asm__ volatile ("pref @%0"
: // output
: "r" (&store_queue[0]) // input
: "memory");
#endif #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_load_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_load_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_load_u2(address, value, big_endian);
}
static inline uint32_t unaligned_load_u4(uint32_t address, bool big_endian)
{
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));
}
}
}
static inline uint32_t unaligned_load_u2(uint32_t address, bool big_endian)
{
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 ));
}
}
}
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__); uint32_t value = (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__);
operand_stack_push_u32(vm->current_frame, value); 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)value);
}

View File

@ -4,11 +4,18 @@
#include "vm.h" #include "vm.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);
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);
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);
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);
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);
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);
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_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);

View File

@ -1,38 +1,69 @@
package java.nio; package java.nio;
class Buffer { public abstract class Buffer {
protected int mark = -1; private final int address;
protected int position = 0; private int position;
protected int limit; private int limit;
protected final int capacity; private final int capacity;
Buffer(int mark, int position, int limit, int capacity) { protected Buffer(int address, int position, int limit, int capacity) {
this.mark = mark; this.address = address;
this.position = position; this.position = position;
this.limit = limit; this.limit = limit;
this.capacity = capacity; this.capacity = capacity;
} }
public final int position() {
return position;
}
public final int limit() {
return limit;
}
public final int capacity() { public final int capacity() {
return capacity; return capacity;
} }
public Buffer limit(int limit) { public final Buffer clear() {
this.limit = limit; position = 0;
if (position > limit) position = limit; limit = capacity;
if (mark > limit) mark = -1; return this;
}
public final Buffer flip() {
limit = position;
position = 0;
return this; return this;
} }
public final boolean hasRemaining() { public final boolean hasRemaining() {
return position < limit; 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;
}
} }

View File

@ -1,24 +1,162 @@
package java.nio; package java.nio;
public class ByteBuffer extends Buffer { import jvm.internal.Memory;
private int offset;
public class ByteBuffer
extends Buffer
implements Comparable<ByteBuffer> {
private boolean bigEndian; private boolean bigEndian;
//private boolean sameEndian;
private byte[] array; private ByteBuffer(int address, int position, int limit, int capacity, int bigEndian) {
super(address, position, limit, capacity);
private ByteBuffer(byte[] array, int offset, int length) { bigEndian = bigEndian;
super(-1, 0, length, length);
this.array = array;
this.order(ByteOrder.BIG_ENDIAN);
} }
public static ByteBuffer wrap(byte[] array) { public static ByteBuffer allocateDirect(int capacity) {
return new ByteBuffer(array, 0, array.length); int address = Memory.allocate(capacity);
return new ByteBuffer(address, 0, capacity, capacity, true);
} }
public static ByteBuffer wrap(byte[] array, int offset, int length) { public final byte[] array() {
return new ByteBuffer(array, offset, length); 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() { public ByteOrder order() {
@ -27,103 +165,128 @@ public class ByteBuffer extends Buffer {
public ByteBuffer order(ByteOrder bo) { public ByteBuffer order(ByteOrder bo) {
bigEndian = (bo == ByteOrder.BIG_ENDIAN); bigEndian = (bo == ByteOrder.BIG_ENDIAN);
//sameEndian = (bo == ByteOrder.nativeOrder());
return this; return this;
} }
public ByteBuffer offset(int off) { public ByteBuffer put(byte b) {
offset = off; if (position >= limit)
return this; throw new IndexOutOfBoundsException();
} Memory.putU1(address + position);
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)];
position += 1; position += 1;
return i0; return this;
} }
public byte get(int pos) { public final ByteBuffer put(byte[] src) {
byte i0 = array[ix(pos)]; return put(src, 0, src.length);
return i0;
} }
public short getShort() { public ByteBuffer put(byte[] src,
int i0 = array[ix(position) + 0]; int offset,
int i1 = array[ix(position) + 1]; 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; public ByteBuffer put(ByteBuffer src) {
int rem = limit - position;
if (bigEndian) { if (rem < src.length) {
return (short)shortBE(i0, i1); throw new BufferUnderflowException();
} else { }
return (short)shortLE(i0, i1); if (src == this) {
throw new IllegalArgumentException();
}
for (int i = src.position; i < src.limit; i++) {
put(src.get(i));
} }
} }
public short getShort(int pos) { public ByteBuffer put(int index,
int i0 = array[ix(pos) + 0]; byte b) {
int i1 = array[ix(pos) + 1]; if (index < 0 || index > limit)
throw new IndexOutOfBoundsException();
if (bigEndian) { Memory.putU1(address + index, b);
return (short)shortBE(i0, i1); return this;
} else {
return (short)shortLE(i0, i1);
}
} }
public int getInt() { public ByteBuffer putFloat(float value) {
int i0 = array[ix(position) + 0]; if (limit - position < 4)
int i1 = array[ix(position) + 1]; throw new BufferUnderflowException();
int i2 = array[ix(position) + 2]; Memory.putUnalignedF4(address + position, value, bigEndian);
int i3 = array[ix(position) + 3];
position += 4; position += 4;
return this;
if (bigEndian) {
return intBE(i0, i1, i2, i3);
} else {
return intLE(i0, i1, i2, i3);
}
} }
public int getInt(int pos) { public ByteBuffer putFloat(int index,
int i0 = array[ix(pos) + 0]; float value) {
int i1 = array[ix(pos) + 1]; if (index < 0 || index >= (limit - 3))
int i2 = array[ix(pos) + 2]; throw new IndexOutOfBoundsException();
int i3 = array[ix(pos) + 3]; Memory.putUnalignedF4(address + index, value, bigEndian);
return this;
}
if (bigEndian) { public ByteBuffer putInt(int value) {
return intBE(i0, i1, i2, i3); if (limit - position < 4)
} else { throw new BufferUnderflowException();
return intLE(i0, i1, i2, i3); 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();
} }
} }

View File

@ -12,4 +12,12 @@ public class ByteOrder {
public static ByteOrder nativeOrder() { public static ByteOrder nativeOrder() {
return NATIVE_ORDER; return NATIVE_ORDER;
} }
public String toString() {
if (this == BIG_ENDIAN) {
return "BIG_ENDIAN";
} else {
return "LITTLE_ENDIAN";
}
}
} }

View File

@ -2,14 +2,24 @@ package jvm.internal;
public class Memory { public class Memory {
public static native void putU4(int address, int value); public static native void putU4(int address, int value);
public static native void putU2(int address, int value); public static native void putU2(int address, short value);
public static native void putU1(int address, int value); public static native void putU1(int address, byte value);
public static native int getU4(int address); public static native int getU4(int address);
public static native int getU2(int address); public static native short getU2(int address);
public static native int getU1(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 void putSQ1(Object object, int address);
public static native boolean isBigEndian(); public static native boolean isBigEndian();
public static native int allocate(int size);
} }