Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of git@github.com:eriksoe/erjang

  • Loading branch information...
commit 94da399f3e3d57876430e0f040873bc6e47b20ba 2 parents 6e6c209 + d1eeef0
@eriksoe authored
View
6 erjang_cfg.properties
@@ -1,6 +1,6 @@
-erjang.otp.root = /usr/local/lib/erlang
-erjang.erts.version = 5.7.5
-erjang.otp.version = R13B04
+erjang.otp.root = /Users/krab/Projects/otp-5.8
+erjang.erts.version = 5.8
+erjang.otp.version = R14B
# erjang.debug.port=true
# erjang.debug.inet=true
View
3  src/main/java/erjang/beam/BeamOpcode.java
@@ -154,6 +154,9 @@
bif,
gc_bif,
arithfbif,
+
+ // Synthetic (Erjang-internal) opcodes
+ i_call_fun_last (0xF0),
// illegal op-code
NONE
View
20 src/main/java/erjang/beam/CompilerVisitor.java
@@ -1798,9 +1798,12 @@ public void visitInsn(BeamOpcode opcode, Arg[] in, Arg out) {
mv.visitMethodInsn(INVOKESTATIC, ERT_NAME, "cons", ERT_CONS_SIG);
pop(out, ECONS_TYPE);
return;
- case call_fun: {
- ensure_exception_handler_in_place();
+
+ case call_fun:
+ case i_call_fun_last: {
+ ensure_exception_handler_in_place();
+ boolean is_tail = opcode == BeamOpcode.i_call_fun_last;
int nargs = in.length - 1;
push(in[nargs], EOBJECT_TYPE);
mv.visitInsn(DUP);
@@ -1819,12 +1822,17 @@ public void visitInsn(BeamOpcode opcode, Arg[] in, Arg out) {
push(in[i], EOBJECT_TYPE);
}
- mv.visitMethodInsn(INVOKEVIRTUAL, funtype, "invoke", EUtil
- .getSignature(nargs, true));
- pop(out, EOBJECT_TYPE);
+ mv.visitMethodInsn(INVOKEVIRTUAL, funtype,
+ is_tail ? "invoke_tail" : "invoke",
+ EUtil.getSignature(nargs, true));
+ if (is_tail) {
+ mv.visitInsn(ARETURN);
+ } else {
+ pop(out, EOBJECT_TYPE);
+ }
return;
}
- }
+ }//switch
throw new Error();
}
View
2  src/main/java/erjang/beam/ModuleAnalyzer.java
@@ -245,6 +245,7 @@ public void visitInsn(Insn insn) {
}
case apply_last:
+ case i_call_fun_last: {
if (log.isLoggable(Level.FINE) && !self.call_is_pausable) {
log.fine("call_pausable: " + op);
}
@@ -252,6 +253,7 @@ public void visitInsn(Insn insn) {
self.may_return_tail_marker = true;
self.call_is_pausable = true;
break;
+ }
case call_ext_last:
case call_ext_only:
View
13 src/main/java/erjang/beam/analysis/BeamTypeAnalysis.java
@@ -922,7 +922,8 @@ private void accept_2(BlockVisitor2 vis, BeamExceptionHandler exh) {
break;
}
- case call_fun: {
+ case call_fun:
+ case i_call_fun_last: {
Insn.I insn = (Insn.I) insn_;
int nargs = insn.i1;
Arg[] args = new Arg[nargs + 1];
@@ -2008,14 +2009,19 @@ public void analyze0() {
continue next_insn;
}
- case call_fun: {
+ case call_fun:
+ case i_call_fun_last: {
Insn.I insn = (Insn.I)insn_;
int nargs = insn.i1;
for (int i = 0; i < nargs; i++) {
if (current.getx(i) == null)
throw new Error("uninitialized x" + i);
}
- current = current.setx(0, EOBJECT_TYPE, FV.this);
+ if (code == BeamOpcode.i_call_fun_last) {
+ is_tail_recursive = true;
+ } else {
+ current = current.setx(0, EOBJECT_TYPE, FV.this);
+ }
continue next_insn;
}
@@ -2059,6 +2065,7 @@ boolean is_term(BeamOpcode code) {
case call_ext_only:
case func_info:
case apply_last:
+ case i_call_fun_last:
case wait:
case select_tuple_arity:
View
2  src/main/java/erjang/beam/loader/ErjangBeamDisLoader.java
@@ -32,12 +32,14 @@ public ErjangBeamDisLoader() { }
@Override
public BeamFileData load(File file) throws IOException {
ModuleRepr mod = BeamLoader.read(file.getAbsolutePath());
+ mod.rewrite(new Rewriter());
return mod;
}
@Override
public BeamFileData load(byte[] data) throws IOException {
ModuleRepr mod = BeamLoader.parse(data);
+ mod.rewrite(new Rewriter());
return mod;
}
View
69 src/main/java/erjang/beam/loader/Rewriter.java
@@ -0,0 +1,69 @@
+/** -*- tab-width: 4 -*-
+ * This file is part of Erjang - A JVM-based Erlang VM
+ *
+ * Copyright (c) 2010 by Trifork
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+package erjang.beam.loader;
+
+import erjang.beam.BeamOpcode;
+import erjang.beam.repr.Insn;
+import erjang.beam.repr.Operands.Label;
+import erjang.beam.repr.FunctionInfo;
+import erjang.EAtom;
+
+import java.util.List;
+import java.util.ListIterator;
+
+public class Rewriter {
+ public void rewriteFunctionBody(List<Insn> body, FunctionInfo sig) {
+ ListIterator<Insn> it = body.listIterator();
+ while (it.hasNext()) {
+ final Insn insn = it.next();
+ switch (insn.opcode()) {
+ case call_fun: {
+ int save_pos = savePos(it);
+ boolean trigger = (it.hasNext() &&
+ it.next().opcode() == BeamOpcode.deallocate &&
+ it.hasNext() &&
+ it.next().opcode() == BeamOpcode.K_return);
+ restorePos(it, save_pos);
+ if (trigger) {
+ Insn.I old = (Insn.I)insn;
+ it.set(new Insn.I(BeamOpcode.i_call_fun_last, old.i1)); // We don't care about deallocating.
+ it.next();
+ it.remove();
+ it.next();
+ it.remove();
+ }
+ }//switch
+ }
+ }
+ }
+
+ private int savePos(ListIterator<Insn> it) {return it.nextIndex() - 1;}
+
+ private void restorePos(ListIterator<Insn> it, int save_pos) {
+ // Only works for restoring backwards.
+ int i=0;
+ while (it.previousIndex() >= save_pos) {
+ int pi = it.previousIndex();
+ Insn insn = it.previous(); i++;
+ }
+ if (it.nextIndex() <= save_pos) it.next(); // Turn iterator.
+ }
+
+ private Insn nop() {return new Insn.I(BeamOpcode.label, -1);}
+}
View
4 src/main/java/erjang/beam/repr/FunctionRepr.java
@@ -31,6 +31,7 @@
import erjang.ESmall;
import erjang.ESeq;
+import erjang.beam.loader.Rewriter;
public class FunctionRepr {
protected FunctionInfo sig;
@@ -82,4 +83,7 @@ public ETuple toSymbolic() {
return fun;
}
+ public void rewrite(Rewriter rw) {
+ rw.rewriteFunctionBody(body, sig);
+ }
}
View
7 src/main/java/erjang/beam/repr/ModuleRepr.java
@@ -34,6 +34,8 @@
import erjang.beam.CodeAtoms;
import erjang.beam.ModuleVisitor;
+import erjang.beam.loader.Rewriter;
+
public class ModuleRepr implements BeamFileData {
static Logger log = Logger.getLogger("erjang.beam");
@@ -128,4 +130,9 @@ public ESeq symbolicCode() {
return ESeq.fromList(symFunctions);
}
+ public void rewrite(Rewriter rw) {
+ for (FunctionRepr f : functions) {
+ f.rewrite(rw);
+ }
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.