Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Make EFun{arity}Guard invocation work correctly.

This is done by overriding invoke() rather than go().
  • Loading branch information...
commit 0008f77863971ddfb6966d4c343a177bb960d9ac 1 parent ed9a07d
@eriksoe eriksoe authored
View
7 src/main/java/erjang/EFun.java
@@ -665,9 +665,8 @@ static void make_encode_method_for_exported(ClassWriter cw, String className, in
/* Code template:
* public abstract class EFun{arity}Guard extends EFun{arity} {
* public <init>() {super();}
- * public erjang.EObject invoke(erjang.EProc, erjang.EObject[], kilim.Fiber) throws kilim.Pausable {
- * // Same as EFun.invoke, but without the tail-call loop.
- * }
+ *
+ * // In subclasses: override invoke(), to do a direct call.
* }
*/
@@ -687,8 +686,6 @@ static void make_encode_method_for_exported(ClassWriter cw, String className, in
mv.visitInsn(Opcodes.RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
-
- make_invoke_method_for_guard(cw, self_type, arity);
cw.visitEnd();
byte[] data = cw.toByteArray();
View
59 src/main/java/erjang/beam/CompilerVisitor.java
@@ -3610,7 +3610,7 @@ public Lambda get_lambda_freevars(EAtom fun, int arity_plus) {
return lambdas_xx.get(new FunID(module_name, fun, arity_plus));
}
- static public byte[] make_invoker(String module, String function,
+ public static byte[] make_invoker(String module, String function,
Type self_type, String mname, String fname, int arity,
boolean proc, boolean exported, boolean is_guard,
Lambda lambda, Type return_type,
@@ -3625,15 +3625,18 @@ public Lambda get_lambda_freevars(EAtom fun, int arity_plus) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES
| ClassWriter.COMPUTE_MAXS);
int residual_arity = arity - freevars;
- String super_class_name = EFUN_NAME + residual_arity
- + (is_guard ? "Guard" : exported ? "Exported" : "");
-;
- if (is_guard)
+ final String super_class_name;
+
+ if (is_guard) {
+ super_class_name = EFUN_NAME + residual_arity + "Guard";
EFun.ensure_guard(residual_arity);
- else if (exported)
+ } else if (exported) {
+ super_class_name = EFUN_NAME + residual_arity + "Exported";
EFun.ensure_exported(residual_arity);
- else
+ } else {
+ super_class_name = EFUN_NAME + residual_arity;
EFun.ensure(residual_arity);
+ }
cw.visit(V1_6, ACC_FINAL | ACC_PUBLIC, full_inner_name, null,
super_class_name, null);
@@ -3706,12 +3709,15 @@ else if (exported)
outer_name,
super_class_name, lambda, exported);
- make_go_method(cw, outer_name, fname, full_inner_name, arity, proc,
- freevars, return_type, is_tail_call, is_pausable);
-
- make_go2_method(cw, outer_name, fname, full_inner_name, arity, proc,
- freevars, return_type, is_tail_call, is_pausable);
+ if (is_guard) {
+ make_direct_invoke_method(cw, outer_name, fname, arity, proc, return_type, is_pausable);
+ } else {
+ make_go_method(cw, outer_name, fname, full_inner_name, arity, proc,
+ freevars, return_type, is_tail_call, is_pausable);
+ make_go2_method(cw, outer_name, fname, full_inner_name, arity, proc,
+ freevars, return_type, is_tail_call, is_pausable);
+ }
return cw.toByteArray();
}
@@ -3974,6 +3980,35 @@ private static void make_go2_method(ClassWriter cw, String outer_name,
cw.visitEnd();
}
+ /** make_direct_invoke_method: Perform a direct call, with no
+ * tail-recursino handling.
+ * Used for EFunXxGuard classes.
+ */
+ private static void make_direct_invoke_method(ClassWriter cw, String outer_name,
+ String mname, int arity, boolean proc, Type returnType,
+ boolean isPausable)
+ {
+ MethodVisitor mv;
+ mv = cw.visitMethod(ACC_PUBLIC, "invoke", EUtil.getSignature(arity, true),
+ null,
+ isPausable ? PAUSABLE_EX : null);
+ mv.visitCode();
+ if (proc)
+ mv.visitVarInsn(ALOAD, 1);
+
+ for (int i = 0; i < arity; i++) {
+ mv.visitVarInsn(ALOAD, i+2);
+ }
+
+ mv.visitMethodInsn(INVOKESTATIC, outer_name, mname,
+ EUtil.getSignature(arity, proc, returnType));
+ // TODO: Special handling if returnType != EObject - or assert that this isn't the case.
+ mv.visitInsn(ARETURN);
+ mv.visitMaxs(arity + 2, arity + 2);
+ mv.visitEnd();
+ }
+
+
public void setFunInfos(Map<FunID, FunInfo> funInfos) {
this.funInfos = funInfos;
}
Please sign in to comment.
Something went wrong with that request. Please try again.