Skip to content

Commit

Permalink
CArray of strings on JVM.
Browse files Browse the repository at this point in the history
  • Loading branch information
arnsholt committed Nov 6, 2013
1 parent 84b433f commit 04bcb40
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/vm/jvm/runtime/org/perl6/nqp/runtime/NativeCallOps.java
Expand Up @@ -129,7 +129,7 @@ private static Class javaType(ThreadContext tc, ArgType target) {
return null;
}

private static Object toJNAType(ThreadContext tc, SixModelObject o, ArgType target) {
public static Object toJNAType(ThreadContext tc, SixModelObject o, ArgType target) {
o = Ops.decont(o, tc);
switch (target) {
case CHAR:
Expand Down Expand Up @@ -170,7 +170,7 @@ private static Object toJNAType(ThreadContext tc, SixModelObject o, ArgType targ
return null;
}

private static SixModelObject toNQPType(ThreadContext tc, ArgType target, SixModelObject type, Object o) {
public static SixModelObject toNQPType(ThreadContext tc, ArgType target, SixModelObject type, Object o) {
SixModelObject nqpobj = null;
if (target != ArgType.VOID)
nqpobj = type.st.REPR.allocate(tc, type.st);
Expand Down
4 changes: 4 additions & 0 deletions src/vm/jvm/runtime/org/perl6/nqp/sixmodel/reprs/CArray.java
Expand Up @@ -83,6 +83,10 @@ else if (ss.bits == 64) {
}
data.elem_kind = ElemKind.NUMERIC;
}
else if ((ss.can_box & StorageSpec.CAN_BOX_STR) != 0) {
data.jna_size = Native.POINTER_SIZE;
data.elem_kind = ElemKind.STRING;
}
else {
/* TODO: Remaining cases. */
ExceptionHandling.dieInternal(tc, "CArray only handles ints and nums so far.");
Expand Down
@@ -1,18 +1,24 @@
package org.perl6.nqp.sixmodel.reprs;

import java.util.Arrays;

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.NativeCallOps;
import org.perl6.nqp.runtime.Ops;
import org.perl6.nqp.runtime.ThreadContext;

import org.perl6.nqp.sixmodel.SixModelObject;

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

public class CArrayInstance extends SixModelObject {
public Pointer storage;
public SixModelObject[] child_objs;
public boolean managed;
public long allocated;
public long elems;
Expand Down Expand Up @@ -64,6 +70,45 @@ else if (repr_data.elem_size == 64) {
}
}

public SixModelObject at_pos_boxed(ThreadContext tc, long index) {
CArrayREPRData repr_data = (CArrayREPRData) st.REPRData;
int intidx = (int) index;

/* TODO: Die if this is a NUMERIC/INTEGER CArray. */

if (managed) {
if (index >= elems)
return repr_data.elem_type;

if (child_objs[intidx] != null) {
return child_objs[intidx];
}
else {
SixModelObject obj = makeObject(tc, storage.getPointer(index*repr_data.jna_size));
child_objs[intidx] = obj;
return obj;
}
}
else {
if (index >= allocated)
expand(tc, index+1);

if (child_objs[intidx] != null)
return child_objs[intidx];
else {
Pointer ptr = storage.getPointer(index*repr_data.jna_size);
if (ptr != null) {
SixModelObject obj = makeObject(tc, ptr);
child_objs[intidx] = obj;
return obj;
}
else {
return repr_data.elem_type;
}
}
}
}

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

Expand Down Expand Up @@ -100,6 +145,31 @@ else if (repr_data.elem_size == 64) {
}
}

public void bind_pos_boxed(ThreadContext tc, long index, SixModelObject value) {
CArrayREPRData repr_data = (CArrayREPRData) st.REPRData;
int intidx = (int) index;

/* TODO: Die if this is a NUMERIC/INTEGER CArray. */
if (index >= allocated)
expand(tc, index+1);

Pointer ptr = null;
if (Ops.isconcrete(value, tc) != 0) {
switch (repr_data.elem_kind) {
case STRING:
byte[] bytes = Native.toByteArray(value.get_str(tc));
ptr = new Memory(bytes.length);
ptr.write(0, bytes, 0, bytes.length);
break;
default:
ExceptionHandling.dieInternal(tc, "CArray.bind_pos_boxed reached its default case. This should never happen.");
}
}

child_objs[intidx] = value;
storage.setPointer(index*repr_data.jna_size, ptr);
}

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

Expand All @@ -111,6 +181,33 @@ private void expand(ThreadContext tc, long new_size) {
}
storage = new_storage;
}

boolean complex = repr_data.elem_kind == ElemKind.CARRAY
|| repr_data.elem_kind == ElemKind.CPOINTER
|| repr_data.elem_kind == ElemKind.CSTRUCT
|| repr_data.elem_kind == ElemKind.STRING;

if (complex) {
child_objs = child_objs == null?
new SixModelObject[(int) new_size]:
Arrays.copyOf(child_objs, (int) new_size);
}

elems = new_size;
allocated = new_size;
}

private SixModelObject makeObject(ThreadContext tc, Pointer ptr) {
CArrayREPRData repr_data = (CArrayREPRData) st.REPRData;

switch (repr_data.elem_kind) {
case STRING:
return NativeCallOps.toNQPType(tc, ArgType.UTF8STR, repr_data.elem_type, ptr.getString(0));
default:
ExceptionHandling.dieInternal(tc, "CArray can only makeObject strings");
}

/* And a dummy return statement to placate Java's flow analysis. */
return null;
}
}

0 comments on commit 04bcb40

Please sign in to comment.