Skip to content

Commit

Permalink
CArray REPR on JVM, with supporting int and num.
Browse files Browse the repository at this point in the history
  • Loading branch information
arnsholt committed Nov 5, 2013
1 parent a78d074 commit 89cc08f
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 4 deletions.
10 changes: 10 additions & 0 deletions src/vm/jvm/runtime/org/perl6/nqp/runtime/NativeCallOps.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.perl6.nqp.sixmodel.REPRRegistry;
import org.perl6.nqp.sixmodel.SixModelObject;

import org.perl6.nqp.sixmodel.reprs.CArrayInstance;
import org.perl6.nqp.sixmodel.reprs.CPointerInstance;
import org.perl6.nqp.sixmodel.reprs.CStrInstance;
import org.perl6.nqp.sixmodel.reprs.NativeCallInstance;
Expand Down Expand Up @@ -118,6 +119,7 @@ private static Class javaType(ThreadContext tc, ArgType target) {
/* TODO: Handle encodings. */
return String.class;
case CPOINTER:
case CARRAY:
return Pointer.class;
default:
ExceptionHandling.dieInternal(tc, String.format("Don't know correct Java class for %s arguments yet", target));
Expand Down Expand Up @@ -158,6 +160,8 @@ private static Object toJNAType(ThreadContext tc, SixModelObject o, ArgType targ
}
case CPOINTER:
return ((CPointerInstance) o).pointer;
case CARRAY:
return ((CArrayInstance) o).storage;
default:
ExceptionHandling.dieInternal(tc, String.format("Don't know how to convert %s arguments to JNA yet", target));
}
Expand Down Expand Up @@ -220,6 +224,12 @@ private static SixModelObject toNQPType(ThreadContext tc, ArgType target, SixMod
cpointer.pointer = (Pointer) o;
break;
}
case CARRAY: {
CArrayInstance carray = (CArrayInstance) nqpobj;
carray.storage = (Pointer) o;
carray.managed = false;
break;
}
default:
ExceptionHandling.dieInternal(tc, String.format("Don't know how to convert %s arguments to NQP yet", target));
}
Expand Down
72 changes: 69 additions & 3 deletions src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/CArray.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
package org.perl6.nqp.sixmodel.reprs;

import com.sun.jna.Memory;
import com.sun.jna.Native;

import org.perl6.nqp.runtime.CallSiteDescriptor;
import static org.perl6.nqp.runtime.CallSiteDescriptor.*;
import org.perl6.nqp.runtime.ExceptionHandling;
import org.perl6.nqp.runtime.Ops;
import org.perl6.nqp.runtime.ThreadContext;

import org.perl6.nqp.sixmodel.REPR;
import org.perl6.nqp.sixmodel.SerializationReader;
import org.perl6.nqp.sixmodel.SixModelObject;
import org.perl6.nqp.sixmodel.StorageSpec;
import org.perl6.nqp.sixmodel.STable;
import org.perl6.nqp.sixmodel.TypeObject;
import org.perl6.nqp.runtime.ExceptionHandling;
import org.perl6.nqp.runtime.ThreadContext;

import org.perl6.nqp.sixmodel.reprs.CArrayREPRData.ElemKind;

public class CArray extends REPR {
public SixModelObject type_object_for(ThreadContext tc, SixModelObject HOW) {
Expand All @@ -20,11 +29,68 @@ public SixModelObject type_object_for(ThreadContext tc, SixModelObject HOW) {
}

public SixModelObject allocate(ThreadContext tc, STable st) {
SixModelObject obj = new CArrayInstance();
CArrayInstance obj = new CArrayInstance();
obj.managed = true;

if (st.REPRData == null)
fillREPRData(tc, st);

obj.st = st;
return obj;
}

private void fillREPRData(ThreadContext tc, STable st) {
CArrayREPRData data = new CArrayREPRData();

SixModelObject meth = Ops.findmethod(st.WHAT, "of", tc);
if (meth == null)
ExceptionHandling.dieInternal(tc, "CArray representation expects an 'of' method, specifying the element type");

Ops.invokeDirect(tc, meth, new CallSiteDescriptor(new byte[] { ARG_OBJ }, null), new Object[] { st.WHAT });
data.elem_type = Ops.decont(Ops.result_o(tc.resultFrame()), tc);
if (data.elem_type == null)
ExceptionHandling.dieInternal(tc, "CArray representation expects a non-null return value from the 'of' method, specifying the element type");

StorageSpec ss = data.elem_type.st.REPR.get_storage_spec(tc, data.elem_type.st);
data.elem_size = ss.bits;
if (ss.boxed_primitive == StorageSpec.BP_INT) {
if (ss.bits == 8) {
data.jna_size = Native.getNativeSize(Byte.class);
}
else if (ss.bits == 16) {
data.jna_size = Native.getNativeSize(Short.class);
}
else if (ss.bits == 32) {
data.jna_size = Native.getNativeSize(Integer.class);
}
else if (ss.bits == 64) {
data.jna_size = Native.getNativeSize(Long.class);
}
else {
ExceptionHandling.dieInternal(tc, "CArray can only handle 8, 16, 32 and 64 bit ints.");
}
data.elem_kind = ElemKind.INTEGER;
}
else if (ss.boxed_primitive == StorageSpec.BP_NUM) {
if (ss.bits == 32) {
data.jna_size = Native.getNativeSize(Float.class);
}
else if (ss.bits == 64) {
data.jna_size = Native.getNativeSize(Double.class);
}
else {
ExceptionHandling.dieInternal(tc, "CArray can only handle 32 and 64 bit floats.");
}
data.elem_kind = ElemKind.NUMERIC;
}
else {
/* TODO: Remaining cases. */
ExceptionHandling.dieInternal(tc, "CArray only handles ints and nums so far.");
}

st.REPRData = data;
}

public SixModelObject deserialize_stub(ThreadContext tc, STable st) {
/* This REPR can't be serialized. */
ExceptionHandling.dieInternal(tc, "Can't deserialize_stub a CArray object.");
Expand Down
111 changes: 110 additions & 1 deletion src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/CArrayInstance.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,116 @@
package org.perl6.nqp.sixmodel.reprs;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

import org.perl6.nqp.runtime.ExceptionHandling;
import org.perl6.nqp.runtime.ThreadContext;

import org.perl6.nqp.sixmodel.SixModelObject;

import org.perl6.nqp.sixmodel.reprs.CArrayREPRData.ElemKind;

public class CArrayInstance extends SixModelObject {
/* Nothing here yet. */
public Pointer storage;
public boolean managed;
public long allocated;
public long elems;

public void at_pos_native(ThreadContext tc, long index) {
CArrayREPRData repr_data = (CArrayREPRData) st.REPRData;

if (managed && index >= elems) {
if (repr_data.elem_kind == ElemKind.INTEGER) {
tc.native_type = ThreadContext.NATIVE_INT;
tc.native_i = 0;
}
else if (repr_data.elem_kind == ElemKind.NUMERIC) {
tc.native_type = ThreadContext.NATIVE_NUM;
tc.native_n = 0;
}
else {
ExceptionHandling.dieInternal(tc, "CArray can only at_pos_native with ints and nums.");
}
return;
}

if (repr_data.elem_kind == ElemKind.INTEGER) {
tc.native_type = ThreadContext.NATIVE_INT;
if (repr_data.elem_size == 8) {
tc.native_i = storage.getByte(index*repr_data.jna_size);
}
else if (repr_data.elem_size == 16) {
tc.native_i = storage.getShort(index*repr_data.jna_size);
}
else if (repr_data.elem_size == 32) {
tc.native_i = storage.getInt(index*repr_data.jna_size);
}
else if (repr_data.elem_size == 64) {
tc.native_i = storage.getLong(index*repr_data.jna_size);
}
}
else if (repr_data.elem_kind == ElemKind.NUMERIC) {
tc.native_type = ThreadContext.NATIVE_NUM;
if (repr_data.elem_size == 32) {
tc.native_n = storage.getFloat(index*repr_data.jna_size);
}
else if (repr_data.elem_size == 64) {
tc.native_n = storage.getDouble(index*repr_data.jna_size);
}
}
else {
ExceptionHandling.dieInternal(tc, "CArray can only at_pos_native with ints and nums.");
}
}

public void bind_pos_native(ThreadContext tc, long index) {
CArrayREPRData repr_data = (CArrayREPRData) st.REPRData;

if (index >= allocated) {
expand(tc, index+1);
}

if (repr_data.elem_kind == ElemKind.INTEGER) {
tc.native_type = ThreadContext.NATIVE_INT;
if (repr_data.elem_size == 8) {
storage.setByte(index*repr_data.jna_size, (byte) tc.native_i);
}
else if (repr_data.elem_size == 16) {
storage.setShort(index*repr_data.jna_size, (short) tc.native_i);
}
else if (repr_data.elem_size == 32) {
storage.setInt(index*repr_data.jna_size, (int) tc.native_i);
}
else if (repr_data.elem_size == 64) {
storage.setLong(index*repr_data.jna_size, tc.native_i);
}
}
else if (repr_data.elem_kind == ElemKind.NUMERIC) {
tc.native_type = ThreadContext.NATIVE_NUM;
if (repr_data.elem_size == 32) {
storage.setFloat(index*repr_data.jna_size, (float) tc.native_n);
}
else if (repr_data.elem_size == 64) {
storage.setDouble(index*repr_data.jna_size, tc.native_n);
}
}
else {
ExceptionHandling.dieInternal(tc, "CArray can only bind_pos_native with ints and nums.");
}
}

private void expand(ThreadContext tc, long new_size) {
CArrayREPRData repr_data = (CArrayREPRData) st.REPRData;

if (managed) {
Memory new_storage = new Memory(new_size*repr_data.jna_size);
if (storage != null) {
Memory old_storage = (Memory) storage;
new_storage.write(0, old_storage.getByteArray(0, (int) old_storage.size()), 0, (int) old_storage.size());
}
storage = new_storage;
}
elems = new_size;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.perl6.nqp.sixmodel.reprs;

import org.perl6.nqp.sixmodel.SixModelObject;

public class CArrayREPRData {
public short elem_size;
public SixModelObject elem_type;
public ElemKind elem_kind;
public int jna_size;

public enum ElemKind { INTEGER, NUMERIC, STRING, CPOINTER, CARRAY, CSTRUCT }
}

0 comments on commit 89cc08f

Please sign in to comment.