Skip to content

Commit

Permalink
Merge pull request #80 from aya-lang/feature/perf
Browse files Browse the repository at this point in the history
Some Performance Optimizations
  • Loading branch information
nick-paul authored Jun 14, 2023
2 parents b335339 + 5fec5a3 commit 8e6fecb
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 68 deletions.
65 changes: 46 additions & 19 deletions src/aya/CallStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.EmptyStackException;
import java.util.Stack;

import aya.instruction.variable.GetVariableInstruction;

Expand All @@ -14,14 +13,17 @@
*/
public class CallStack {

public static final CallStackFrame CHECKPOINT = new CallStackFrame(null);
private final static int MAX_STACK_DEPTH = 128;

public static class CallStackFrame {
private GetVariableInstruction _instruction;
private boolean _is_checkpoint;


public CallStackFrame(GetVariableInstruction instruction) {
public CallStackFrame() {
reset(null);
}

public void reset(GetVariableInstruction instruction) {
_instruction = instruction;
_is_checkpoint = instruction == null;
}
Expand All @@ -38,55 +40,79 @@ public String toString() {
}
}
}


private Stack<CallStackFrame> _stack;
private CallStackFrame[] _stack;
// Points to the most recently filled stack frame
// -1 for empty stack
private int _stack_index;

public CallStack() {
_stack = new Stack<CallStackFrame>();
_stack = new CallStackFrame[MAX_STACK_DEPTH];
for (int i = 0; i < MAX_STACK_DEPTH; i++) {
_stack[i] = new CallStackFrame();
}
_stack_index = -1;
}

public void push(GetVariableInstruction var) {
_stack.push(new CallStackFrame(var));
if (_stack_index < _stack.length) {
_stack_index++;
_stack[_stack_index].reset(var);
} else {
throw new StackOverflowError("Call stack overflow");
}
}

public void pop() {
_stack.pop();
public CallStackFrame pop() {
// >= : stack_index is allowed to get to -1 (empty stack)
if (_stack_index >= 0) {
CallStackFrame frame = _stack[_stack_index];
_stack_index--;
return frame;
} else {
throw new EmptyStackException();
}
}

public void setCheckpoint() {
_stack.push(CHECKPOINT);
push(null);
}

public void popCheckpoint() {
CallStackFrame csf = _stack.pop();
CallStackFrame csf = pop();
if (!csf.isCheckpoint()) {
throw new RuntimeException("Attempted to pop callstack checkpoint but the top of the stack was " + csf);
}
}

public void rollbackCheckpoint() {
try {
CallStackFrame csf = _stack.pop();
CallStackFrame csf = pop();
// If this loop throws an exception, there is a bug somewhere that
// is either rolling back when there is no checkpoint or removing a checkpoint
// when it should not be
while (!csf.isCheckpoint()) {
csf = _stack.pop();
csf = pop();
}
} catch (EmptyStackException e) {
throw new RuntimeException("Failed attempt to rollback chackpoint in call stack");
throw new RuntimeException("Failed attempt to rollback checkpoint in call stack");
}
}

public void reset() {
_stack.clear();
_stack_index = -1;
}

public int size() {
return _stack_index + 1;
}

public String toString() {
StringBuilder sb = new StringBuilder("Function call traceback:\n Error ");
ArrayList<CallStackFrame> stack_list = new ArrayList<CallStackFrame>(_stack.size());
for (CallStackFrame l : _stack) stack_list.add(l);
Collections.reverse(stack_list);
ArrayList<CallStackFrame> stack_list = new ArrayList<CallStackFrame>(size());
for (int i = size()-1; i >= 0; i--) { stack_list.add(_stack[i]); }

for (CallStackFrame l : stack_list)
{
if (l.isCheckpoint()) continue;
Expand All @@ -99,6 +125,7 @@ public String toString() {
}

public boolean isEmpty() {
return _stack.isEmpty();
// -1 means empty stack
return _stack_index < 0;
}
}
14 changes: 8 additions & 6 deletions src/aya/instruction/variable/GetKeyVariableInstruction.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import aya.obj.dict.Dict;
import aya.obj.symbol.Symbol;
import aya.obj.symbol.SymbolConstants;
import aya.util.Callable;
import aya.util.Casting;

public class GetKeyVariableInstruction extends GetVariableInstruction {

Expand All @@ -23,12 +23,14 @@ public void execute(Block b) {
Dict dict;
dict = (Dict)kv_obj;
Obj o = dict.get(variable_);
Block callable = Callable.getCallable(o);
// If user object function, leave it as the first item on the stack
if (dict.pushSelf() && callable != null) {
b.push(dict);

if (o.isa(Obj.BLOCK)) {
// If user object function, leave it as the first item on the stack
if (dict.pushSelf()) b.push(dict);
dumpBlock(Casting.asBlock(o), b);
} else {
b.push(o);
}
this.addOrDumpVar(o, b, callable);
} else {
Dict builtin_dict = Aya.getInstance().getVars().getBuiltinMeta(kv_obj);
Dict dict = (Dict)builtin_dict;
Expand Down
20 changes: 10 additions & 10 deletions src/aya/instruction/variable/GetVariableInstruction.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import aya.obj.Obj;
import aya.obj.block.Block;
import aya.obj.symbol.Symbol;
import aya.util.Callable;
import aya.util.Casting;

public class GetVariableInstruction extends VariableInstruction {

Expand All @@ -26,19 +26,19 @@ public void execute(Block b) {
* @param b
*/
public void addOrDumpVar(Obj o, Block b) {
addOrDumpVar(o, b, Callable.getCallable(o));
}

public void addOrDumpVar(Obj o, Block b, Block callable) {
if (callable != null) {
Aya.getInstance().getCallStack().push(this);
b.add(PopCallstackInstruction.INSTANCE);
b.getInstructions().addAll(callable.getInstructions().getInstrucionList());
if (o.isa(Obj.BLOCK)) {
dumpBlock(Casting.asBlock(o), b);
} else {
b.push(o);
}
}


public void dumpBlock(Block block_to_dump, Block b) {
Aya.getInstance().getCallStack().push(this);
b.add(PopCallstackInstruction.INSTANCE);
b.getInstructions().addAll(block_to_dump.getInstructions().getInstrucionList());
}

@Override
public ReprStream repr(ReprStream stream) {
stream.print(variable_.name());
Expand Down
10 changes: 6 additions & 4 deletions src/aya/obj/dict/Dict.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import aya.obj.block.Block;
import aya.obj.symbol.Symbol;
import aya.obj.symbol.SymbolConstants;
import aya.util.Callable;
import aya.util.Casting;
import aya.util.Pair;
/**
Expand Down Expand Up @@ -185,6 +184,10 @@ public ArrayList<Obj> values() {
out.addAll(_vars.values());
return out;
}

public Obj getOrNullNoMeta(Symbol key) {
return _vars.get(key);
}

/////////////
// SETTERS //
Expand Down Expand Up @@ -344,9 +347,8 @@ private ReprStream dictRepr(ReprStream stream) {
if (!stream.isSafeMode()) repr = getFromMetaTableOrNull(SymbolConstants.KEYVAR_REPR);

if (repr != null) {
Block callable = Callable.getCallable(repr);
if (callable != null) {
Block blk_repr = callable.duplicate();
if (repr.isa(Obj.BLOCK)) {
Block blk_repr = Casting.asBlock(repr).duplicate();
blk_repr.push(this);
try {
blk_repr.eval();
Expand Down
28 changes: 0 additions & 28 deletions src/aya/util/Callable.java

This file was deleted.

2 changes: 1 addition & 1 deletion src/aya/variable/VariableData.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public Obj getVar(Symbol var) {
private Obj getVarOrNull(Symbol id) {
Obj res = null;
for(int i = _var_sets.size()-1; i >= 0; i--) {
res = _var_sets.get(i).dict.get(id, null);
res = _var_sets.get(i).dict.getOrNullNoMeta(id);
if(res != null) {
return res;
}
Expand Down

0 comments on commit 8e6fecb

Please sign in to comment.