Permalink
Browse files

Implemented serialization of EFunHandler

  • Loading branch information...
1 parent 16abd1b commit e0a132baab07bc3e0a1e4d7adaf2b76a43995690 @edwardw edwardw committed Jun 21, 2011
@@ -268,10 +268,11 @@ private static String erlangNameOfMethod(Method method) {
return data;
}
- static Map<Integer, Constructor<? extends EFun>> handlers = new HashMap<Integer, Constructor<? extends EFun>>();
+ static Map<String, Constructor<? extends EFun>> handlers = new HashMap<String, Constructor<? extends EFun>>();
- public static EFun get_fun_with_handler(int arity, EFunHandler handler, ClassLoader loader) {
- Constructor<? extends EFun> h = handlers.get(arity);
+ public static EFun get_fun_with_handler(String module, String function, int arity, EFunHandler handler, ClassLoader loader) {
+ String signature = module + function + arity;
+ Constructor<? extends EFun> h = handlers.get(signature);
if (h == null) {
@@ -285,24 +286,37 @@ public static EFun get_fun_with_handler(int arity, EFunHandler handler, ClassLoa
super_class_name, null);
// create handler field
- FieldVisitor fv = cw.visitField(ACC_PRIVATE, "handler",
- EFUNHANDLER_TYPE.getDescriptor(), null, null);
- fv.visitEnd();
+ cw.visitField(ACC_PRIVATE, "handler", EFUNHANDLER_TYPE.getDescriptor(), null, null)
+ .visitEnd();
+ cw.visitField(ACC_PRIVATE | ACC_FINAL, "module_name", EATOM_DESC, null, null)
+ .visitEnd();
+ cw.visitField(ACC_PRIVATE | ACC_FINAL, "function_name", EATOM_DESC, null, null)
+ .visitEnd();
+
// make constructor
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "("
+ EFUNHANDLER_TYPE.getDescriptor() + ")V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
- mv
- .visitMethodInsn(INVOKESPECIAL, super_class_name, "<init>",
+ mv.visitMethodInsn(INVOKESPECIAL, super_class_name, "<init>",
"()V");
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(PUTFIELD, self_type, "handler", EFUNHANDLER_TYPE
.getDescriptor());
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitLdcInsn(module);
+ mv.visitMethodInsn(INVOKESTATIC, EATOM_TYPE.getInternalName(),
+ "intern", "(Ljava/lang/String;)Lerjang/EAtom;");
+ mv.visitFieldInsn(PUTFIELD, self_type, "module_name", EATOM_DESC);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitLdcInsn(function);
+ mv.visitMethodInsn(INVOKESTATIC, EATOM_TYPE.getInternalName(),
+ "intern", "(Ljava/lang/String;)Lerjang/EAtom;");
+ mv.visitFieldInsn(PUTFIELD, self_type, "function_name", EATOM_DESC);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
@@ -322,6 +336,7 @@ public static EFun get_fun_with_handler(int arity, EFunHandler handler, ClassLoa
//CompilerVisitor.make_invoketail_method(cw, self_type, arity, 0);
make_invoke_method(cw, self_type, arity);
make_go_method(cw, self_type, arity);
+ make_encode_method(cw, self_type, arity);
cw.visitEnd();
byte[] data = cw.toByteArray();
@@ -336,7 +351,7 @@ public static EFun get_fun_with_handler(int arity, EFunHandler handler, ClassLoa
throw new Error(e);
}
- handlers.put(arity, h);
+ handlers.put(signature, h);
}
try {
@@ -460,6 +475,25 @@ private static void make_invoke_method(ClassWriter cw, String self_type,
mv.visitMaxs(arity + 2, arity + 2);
mv.visitEnd();
}
+
+ static void make_encode_method(ClassWriter cw, String className, int arity) {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "encode", "("+ Type.getDescriptor(EOutputStream.class) +")V", null, null);
+ mv.visitCode();
+
+ mv.visitVarInsn(ALOAD, 1);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, "module_name", EATOM_DESC);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, className, "function_name", EATOM_DESC);
+ mv.visitLdcInsn(new Integer(arity));
+
+ mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(EOutputStream.class), "write_external_fun",
+ "("+EATOM_DESC+EATOM_DESC+"I)V");
+
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(4, 1);
+ mv.visitEnd();
+ }
/*^^^^^^^^^^^^^^^^^^^^ Code generation of EFun{arity} ^^^^^^^^^^^^^^^^^^*/
/*==================== Code generation of EFun{arity}Exported: ==========*/
@@ -117,7 +117,7 @@ private EFun getFunErrorHandler() {
}
private EFun makeErrorHandler() {
- return EFun.get_fun_with_handler(fun.arity,
+ return EFun.get_fun_with_handler(fun.module.toString(), fun.function.toString(), fun.arity,
new EFunHandler() {
@Override
@@ -351,7 +351,7 @@ public EFun resolve(EPID pid, EBinary md5, int index, final int old_uniq, final
if (maker == null || !md5.equals(module_md5)) {
LocalFunID fid = new LocalFunID(module, ERT.am_undefined, arity, old_index, index, old_uniq, md5);
- return EFun.get_fun_with_handler(0, new EFunHandler() {
+ return EFun.get_fun_with_handler(this.module.toString(), "badfun", 0, new EFunHandler() {
@Override
public EObject invoke(EProc proc, EObject[] args) throws Pausable {
throw new ErlangError(am_badfun, args);
@@ -375,7 +375,7 @@ public EFun resolve(final EPID pid, final int old_uniq, final int old_index, fin
if (maker==null) {
LocalFunID fid = new LocalFunID(module, ERT.am_undef, 0, old_index, 0, old_uniq, empty_md5);
- return EFun.get_fun_with_handler(0, new EFunHandler() {
+ return EFun.get_fun_with_handler(module.toString(), "badfun", 0, new EFunHandler() {
@Override
public EObject invoke(EProc proc, EObject[] args) throws Pausable {
throw new ErlangError(am_badfun, args);
@@ -625,7 +625,7 @@ public static EFun resolve_fun(EObject mod, EObject fun, int arity) {
final EFun pfun = EModuleManager.resolve(new FunID(pmod, f, arity+1));
- return EFun.get_fun_with_handler(arity, new EFunHandler() {
+ return EFun.get_fun_with_handler(m.toString(), f.toString(), arity, new EFunHandler() {
@Override
public EObject invoke(EProc proc, EObject[] args) throws Pausable {
EObject[] real_args = new EObject[args.length+1];
@@ -181,7 +181,7 @@ public class Interpreter extends AbstractInterpreter {
int j=0;
for (FunIDWithEntry fi : exports) {
log.finer("INT| Export #"+(j++)+": "+fi);
- EFun fun = EFun.get_fun_with_handler(fi.arity, new Function(fi.start_pc), getModuleClassLoader());
+ EFun fun = EFun.get_fun_with_handler(fi.module.toString(), fi.function.toString(), fi.arity, new Function(fi.start_pc), getModuleClassLoader());
EModuleManager.add_export(this, fi, fun);
}
@@ -268,7 +268,7 @@ public class Interpreter extends AbstractInterpreter {
#INTERPRET<-REGS_AS_SEQ(arity) xregsSeq(reg,arity)#
#INTERPRET<-REGS_AS_ARRAY(arity) xregsArray(reg,arity)#
#INTERPRET<-LOCAL_CALL(keep,label) invoke_local(proc, reg, keep,label)#
-#INTERPRET<-MAKE_CLOSURE(env,arity,label) (EFun.get_fun_with_handler(arity, new Closure(env, label), getModuleClassLoader()))#
+#INTERPRET<-MAKE_CLOSURE(env,arity,label) (EFun.get_fun_with_handler("erlang", "make_fun2", arity, new Closure(env, label), getModuleClassLoader()))#
#INTERPRET<-MAKE_EXH_LINK(new_exh_pc, is_try) (is_try ? new TryExceptionHandler(new_exh_pc, exh) : new CatchExceptionHandler(new_exh_pc, exh))#
#INTERPRET<-RESTORE_EXH(exh_elm) {exh = (ExceptionHandlerStackElement) exh_elm;}#
@@ -131,17 +131,18 @@ public EFun testFunction2(int nargs) {
/** a java.lang.Runnable can be used as a function of 0 arguments */
if ((nargs == 0) && (real_object instanceof Runnable)) {
final Runnable r = (Runnable) real_object;
- return EFun.get_fun_with_handler(0, new EFunHandler() {
- @Override
- public EObject invoke(EProc proc, EObject[] args)
- throws Pausable {
- if (proc != owner)
- throw new ErlangError(ERT.am_badfun, args);
-
- r.run();
- return ERT.am_ok;
- }
- }, getClass().getClassLoader());
+ return EFun.get_fun_with_handler("java.lang.Runnable", "run", 0,
+ new EFunHandler() {
+ @Override
+ public EObject invoke(EProc proc, EObject[] args)
+ throws Pausable {
+ if (proc != owner)
+ throw new ErlangError(ERT.am_badfun, args);
+
+ r.run();
+ return ERT.am_ok;
+ }
+ }, getClass().getClassLoader());
}
@@ -151,22 +152,23 @@ public EObject invoke(EProc proc, EObject[] args)
*/
if ((nargs == 1) && (real_object instanceof java.util.Map<?, ?>)) {
final java.util.Map<?, ?> r = (java.util.Map<?, ?>) real_object;
- return EFun.get_fun_with_handler(0, new EFunHandler() {
- @Override
- public EObject invoke(EProc self, EObject[] args)
- throws Pausable {
- if (self != owner)
- throw new ErlangError(ERT.am_badfun, args);
-
- Object key = JavaObject.unbox(self, Object.class, args[0]);
- if (r.containsKey(key)) {
- return new ETuple2(args[0], JavaObject.box(self, r
- .get(key)));
- } else {
- return am_none;
+ return EFun.get_fun_with_handler("java.util.Map", "get", 0,
+ new EFunHandler() {
+ @Override
+ public EObject invoke(EProc self, EObject[] args)
+ throws Pausable {
+ if (self != owner)
+ throw new ErlangError(ERT.am_badfun, args);
+
+ Object key = JavaObject.unbox(self, Object.class, args[0]);
+ if (r.containsKey(key)) {
+ return new ETuple2(args[0], JavaObject.box(self, r
+ .get(key)));
+ } else {
+ return am_none;
+ }
}
- }
- }, getClass().getClassLoader());
+ }, getClass().getClassLoader());
}
@@ -428,7 +430,7 @@ public Object invoke(Object proxy, final Method method, final Object[] args)
final Mailbox<Object> reply = new Mailbox<Object>(1);
- EFun job = EFun.get_fun_with_handler(0, new EFunHandler() {
+ EFun job = EFun.get_fun_with_handler("erlang", "apply", 0, new EFunHandler() {
@Override
public EObject invoke(EProc proc, EObject[] _) throws Pausable {
@@ -612,7 +614,7 @@ public EFun resolve_fun(final EAtom f, final int arity) {
// TODO: we can make this much much faster!
- return EFun.get_fun_with_handler(arity,
+ return EFun.get_fun_with_handler("java.lang.Object", f.toString(), arity,
new EFunHandler() {
@Override

0 comments on commit e0a132b

Please sign in to comment.