1
package org.perl6.nqp.sixmodel.reprs;
3
import org.objectweb.asm.ClassWriter;
4
import org.objectweb.asm.MethodVisitor;
5
import org.objectweb.asm.Opcodes;
6
import org.objectweb.asm.Type;
7
import org.perl6.nqp.sixmodel.REPR;
8
import org.perl6.nqp.sixmodel.SerializationReader;
9
import org.perl6.nqp.sixmodel.SerializationWriter;
10
import org.perl6.nqp.sixmodel.SixModelObject;
11
import org.perl6.nqp.sixmodel.STable;
12
import org.perl6.nqp.sixmodel.StorageSpec;
13
import org.perl6.nqp.sixmodel.TypeObject;
14
import org.perl6.nqp.runtime.ExceptionHandling;
15
import org.perl6.nqp.runtime.ThreadContext;
18
public class NativeCall extends REPR {
19
public SixModelObject type_object_for(ThreadContext tc, SixModelObject HOW) {
20
STable st = new STable(this, HOW);
21
st.REPRData = null; /* No REPR data needed. */
22
SixModelObject obj = new TypeObject();
28
public SixModelObject allocate(ThreadContext tc, STable st) {
29
NativeCallInstance obj = new NativeCallInstance();
31
obj.body = new NativeCallBody();
35
public StorageSpec get_storage_spec(ThreadContext tc, STable st) {
36
StorageSpec ss = new StorageSpec();
37
ss.inlineable = StorageSpec.INLINED;
42
public void inlineStorage(ThreadContext tc, STable st, ClassWriter cw, String prefix) {
43
cw.visitField(Opcodes.ACC_PUBLIC, prefix, Type.getType(NativeCallBody.class).getDescriptor(), null, null);
46
public void inlineBind(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
47
String nativeCallType = Type.getType(NativeCallBody.class).getDescriptor();
48
String nativeCallIN = Type.getType(NativeCallBody.class).getInternalName();
50
mv.visitVarInsn(Opcodes.ALOAD, 1);
51
mv.visitInsn(Opcodes.ICONST_0 + ThreadContext.NATIVE_JVM_OBJ);
52
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_type", "I");
53
mv.visitVarInsn(Opcodes.ALOAD, 0);
54
mv.visitVarInsn(Opcodes.ALOAD, 1);
55
mv.visitFieldInsn(Opcodes.GETFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_j",
56
Type.getType(Object.class).getDescriptor());
57
mv.visitTypeInsn(Opcodes.CHECKCAST, nativeCallIN);
58
mv.visitFieldInsn(Opcodes.PUTFIELD, className, prefix, nativeCallType);
59
mv.visitInsn(Opcodes.RETURN);
62
public void inlineGet(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
63
mv.visitVarInsn(Opcodes.ALOAD, 1);
64
mv.visitInsn(Opcodes.DUP);
65
mv.visitInsn(Opcodes.ICONST_0 + ThreadContext.NATIVE_JVM_OBJ);
66
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_type", "I");
67
mv.visitVarInsn(Opcodes.ALOAD, 0);
68
mv.visitFieldInsn(Opcodes.GETFIELD, className, prefix,
69
Type.getType(NativeCallBody.class).getDescriptor());
70
mv.visitFieldInsn(Opcodes.PUTFIELD, "org/perl6/nqp/runtime/ThreadContext", "native_j",
71
Type.getType(Object.class).getDescriptor());
72
mv.visitInsn(Opcodes.RETURN);
75
public void inlineDeserialize(ThreadContext tc, STable st, MethodVisitor mv, String className, String prefix) {
79
// XXX This is a hack as it fails to check the REPR ID, but the JVM will
80
// catch any screw-ups and keep us safe.
81
public void generateBoxingMethods(ThreadContext tc, STable st, ClassWriter cw, String className, String prefix) {
82
String nativeCallType = Type.getType(NativeCallBody.class).getDescriptor();
83
String nativeCallIN = Type.getType(NativeCallBody.class).getInternalName();
85
String getDesc = "(Lorg/perl6/nqp/runtime/ThreadContext;J)Ljava/lang/Object;";
86
MethodVisitor getMeth = cw.visitMethod(Opcodes.ACC_PUBLIC, "get_boxing_of", getDesc, null, null);
87
getMeth.visitVarInsn(Opcodes.ALOAD, 0);
88
getMeth.visitFieldInsn(Opcodes.GETFIELD, className, prefix, nativeCallType);
89
getMeth.visitInsn(Opcodes.ARETURN);
90
getMeth.visitMaxs(0, 0);
92
String setDesc = "(Lorg/perl6/nqp/runtime/ThreadContext;JLjava/lang/Object;)V";
93
MethodVisitor setMeth = cw.visitMethod(Opcodes.ACC_PUBLIC, "set_boxing_of", setDesc, null, null);
94
setMeth.visitVarInsn(Opcodes.ALOAD, 0);
95
setMeth.visitVarInsn(Opcodes.ALOAD, 4);
96
setMeth.visitTypeInsn(Opcodes.CHECKCAST, nativeCallIN);
97
setMeth.visitFieldInsn(Opcodes.PUTFIELD, className, prefix, nativeCallType);
98
setMeth.visitInsn(Opcodes.RETURN);
99
setMeth.visitMaxs(0, 0);
102
// We don't depend on any details of the STable, so no description is needed
103
@Override public boolean inline_description(ThreadContext tc, STable st, StringBuilder out) {
106
@Override public boolean box_description(ThreadContext tc, STable st, StringBuilder out) {
110
public SixModelObject deserialize_stub(ThreadContext tc, STable st) {
111
/* This REPR can't be serialized. */
112
ExceptionHandling.dieInternal(tc, "Can't deserialize_stub a NativeCall object.");
116
public void deserialize_finish(ThreadContext tc, STable st, SerializationReader reader, SixModelObject obj) {
117
ExceptionHandling.dieInternal(tc, "Can't deserialize_finish a NativeCall object.");
120
public void serialize_inlined(ThreadContext tc, STable st, SerializationWriter writer,
121
String prefix, SixModelObject obj) {
122
throw ExceptionHandling.dieInternal(tc, "Can't deserialize_stub a NativeCall object.");