Permalink
Browse files

Fix bug in pattern match for tuple size causing VerifierError. Sortin…

…g labels was broken, simplified code.
  • Loading branch information...
1 parent 697a71e commit 2ca53634f8475b604ef341ea97e1d18165bfdbc9 @krestenkrab krestenkrab committed Dec 14, 2009
Showing with 45 additions and 13 deletions.
  1. +45 −13 src/main/java/erjang/beam/CompilerVisitor.java
@@ -1212,7 +1212,6 @@ private void push(Arg value, Type stack_type) {
/**
* @param value
* @param stack_type
- * TODO
*/
private Type push_immediate(EObject value, Type stack_type) {
@@ -2254,31 +2253,64 @@ public int compareTo(Case o) {
return res;
}
+
+ /** class that we use to sort the labels for select_arity switch */
+ class TupleArityLabel implements Comparable<TupleArityLabel> {
+ Label cast_label = new Label();
+ Label target;
+ int arity;
+
+ public TupleArityLabel(int arity, Label target) {
+ this.arity = arity;
+ this.target = target;
+ }
+
+ @Override
+ public int compareTo(TupleArityLabel o) {
+ if (this.arity < o.arity)
+ return -1;
+ if (this.arity == o.arity)
+ return 0;
+ return 1;
+ }
+ }
+ /** Switch based on arity of incoming <code>in</code> tuple value. */
@Override
public void visitSelectTuple(Arg in, int failLabel, int[] arities,
int[] targets) {
push(in, ETUPLE_TYPE);
mv.visitMethodInsn(INVOKEVIRTUAL, ETUPLE_NAME, "arity", "()I");
-
- Label[] targetLabels = new Label[targets.length];
+
+ TupleArityLabel[] cases = new TupleArityLabel[targets.length];
for (int i = 0; i < targets.length; i++) {
- targetLabels[i] = new Label();
+ cases[i] = new TupleArityLabel(arities[i], getLabel(targets[i]));
}
- int[] map = sort(arities, targetLabels);
+ Arrays.sort(cases);
+
+ Label[] casts = new Label[cases.length];
+ int[] values = new int[cases.length];
+
+ for (int i = 0; i < cases.length; i++) {
+ values[i] = cases[i].arity;
+ casts[i] = cases[i].cast_label;
+ }
- mv.visitLookupSwitchInsn(getLabel(failLabel), arities,
- targetLabels);
- for (int i = 0; i < targetLabels.length; i++) {
- mv.visitLabel(targetLabels[i]);
+ mv.visitLookupSwitchInsn(getLabel(failLabel), values, casts);
+ for (int i = 0; i < cases.length; i++) {
+ mv.visitLabel(cases[i].cast_label);
+
+ // NOTE: unfortunately, we have to use a cast here. There
+ // is no real way around it, except maybe make some
+ // special ETuple methods for small tuple sizes?
+ // that is an option for future optimization of pattern match.
push(in, ETUPLE_TYPE);
- mv.visitTypeInsn(CHECKCAST, getTubleType(arities[i])
- .getInternalName());
- pop(in, getTubleType(arities[i]));
- mv.visitJumpInsn(GOTO, getLabel(targets[map[i]]));
+ mv.visitTypeInsn(CHECKCAST, getTubleType(cases[i].arity).getInternalName());
+ pop(in, getTubleType(cases[i].arity));
+ mv.visitJumpInsn(GOTO, cases[i].target);
}
}

0 comments on commit 2ca5363

Please sign in to comment.