Skip to content

Commit

Permalink
feat(objectionary#540): ugly implementation of the worklist
Browse files Browse the repository at this point in the history
  • Loading branch information
volodya-lombrozo committed Oct 8, 2024
1 parent c2ad41f commit e416553
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,11 @@ public boolean isOpcode() {
return false;
}

@Override
public int stackImpact() {
return 0;
}

@Override
public String testCode() {
return "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ public interface BytecodeEntry extends Testable {
boolean isLabel();

boolean isOpcode();

int stackImpact();
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ public boolean isOpcode() {
return false;
}

@Override
public int stackImpact() {
return 0;
}

@Override
public String testCode() {
return String.format(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public String testCode() {
return String.format(".opcode(%s)", args);
}

public int stack() {
public int stackImpact() {
final Instruction instruction = Instruction.find(this.opcode);
switch (instruction) {
case NOP:
Expand Down Expand Up @@ -472,6 +472,110 @@ private int typeSize(final Type type) {
return 1;
}

public boolean isBranchInstruction() {
switch (Instruction.find(this.opcode)) {
case GOTO:
case JSR:
case RET:
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
case IFNULL:
case IFNONNULL:
return true;
default:
return false;
}
}

public boolean isConditionalBranchInstruction() {
switch (Instruction.find(this.opcode)) {
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
case IFNULL:
case IFNONNULL:
return true;
default:
return false;
}
}

public boolean isReturnInstruction() {
switch (Instruction.find(this.opcode)) {
case IRETURN:
case FRETURN:
case ARETURN:
case LRETURN:
case DRETURN:
case RETURN:
return true;
default:
return false;
}
}

public Label offset() {
if (!this.isBranchInstruction()) {
throw new IllegalStateException(
String.format(
"Instruction %s is not a branch instruction",
new OpcodeName(this.opcode).simplified()
)
);
}
switch (Instruction.find(this.opcode)) {
case GOTO:
case JSR:
case IFEQ:
case IFNE:
case IFLT:
case IFGE:
case IFGT:
case IFLE:
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
case IFNULL:
case IFNONNULL:
return (Label) this.args.get(0);
default:
throw new IllegalStateException(
String.format(
"Instruction %s is not a branch instruction",
new OpcodeName(this.opcode).simplified()
)
);
}
}


/**
* Bytecode Instruction.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ public boolean isOpcode() {
return false;
}

@Override
public int stackImpact() {
return 0;
}

@Override
public String testCode() {
return String.format(".label(\"%s\")", this.labels.uid(this.label));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@
*/
package org.eolang.jeo.representation.bytecode;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
import lombok.ToString;
Expand Down Expand Up @@ -424,18 +428,72 @@ DirectivesMethod directives() {
}

private int computeStack() {
int stack = 0;
int max = 0;
for (final BytecodeEntry instruction : this.instructions) {
if (instruction instanceof BytecodeInstruction) {
final BytecodeInstruction var = BytecodeInstruction.class.cast(instruction);
stack += var.stack();
final Deque<Integer> worklist = new ArrayDeque<>(0);
final int length = this.instructions.size();
worklist.add(0);
Map<Integer, Integer> visited = new HashMap<>(0);
while (!worklist.isEmpty()) {
int current = worklist.pop();
int stack = visited.get(current) == null ? 0 : visited.get(current);
while (current < length) {
BytecodeEntry entry = this.instructions.get(current);
stack += entry.stackImpact();
max = Math.max(max, stack);
final int finalStack = stack;
visited.compute(
current, (k, v) -> v == null ? finalStack : Math.max(v, finalStack)
);
if (entry instanceof BytecodeInstruction) {
final BytecodeInstruction var = BytecodeInstruction.class.cast(entry);
// stack += var.stackImpact();
// max = Math.max(max, stack);
// final int finalStack = stack;
// visited.compute(
// current, (k, v) -> v == null ? finalStack : Math.max(v, finalStack)
// );
if (var.isBranchInstruction()) {
final int jump = this.index(var.offset());
if (visited.get(jump) == null || visited.get(jump) < stack) {
worklist.add(jump);
if (var.isConditionalBranchInstruction()) {
final int next = current + 1;
if (visited.get(next) == null || visited.get(next) < stack) {
worklist.add(next);
}
}
}
break;
}
if (var.isReturnInstruction()) {
break;
}
}
current++;
}
}
// for (final BytecodeEntry instruction : this.instructions) {
// if (instruction instanceof BytecodeInstruction) {
// final BytecodeInstruction var = BytecodeInstruction.class.cast(instruction);
// stack += var.stackImpact();
// max = Math.max(max, stack);
// }
// }
return max;
}

private int index(final Label label) {
for (int index = 0; index < this.instructions.size(); index++) {
final BytecodeEntry entry = this.instructions.get(index);
final BytecodeLabel obj = new BytecodeLabel(label, new AllLabels());
final boolean equals = entry.equals(obj);
if (equals) {
return index;
}
}
throw new IllegalStateException("Label not found");
}

/**
* Compute max local variables.
* @return Max local variables.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ public boolean isOpcode() {
return false;
}

@Override
public int stackImpact() {
return 0;
}

@Override
public String testCode() {
return "// Try-catch blocks are not supported in tests yet";
Expand Down

0 comments on commit e416553

Please sign in to comment.