Skip to content

Commit

Permalink
feat(objectionary#752): beautify MaxStackFlow class
Browse files Browse the repository at this point in the history
  • Loading branch information
volodya-lombrozo committed Oct 11, 2024
1 parent b35719e commit 0f46e82
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 124 deletions.
47 changes: 13 additions & 34 deletions src/main/java/org/eolang/jeo/representation/bytecode/DataFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,27 @@
*/
package org.eolang.jeo.representation.bytecode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.objectweb.asm.Label;

public final class DataFlow<T extends DataFlow.Something<T>> {
public final class DataFlow<T extends DataFlow.Reducible<T>> {
private final InstructionsFlow instructions;

private final List<BytecodeTryCatchBlock> blocks;

private final T initial;

private final Function<BytecodeInstruction, T> generate;

public DataFlow(
final InstructionsFlow instructions,
final List<BytecodeTryCatchBlock> blocks,
final T initial,
Function<BytecodeInstruction, T> generator
) {
this.instructions = instructions;
this.blocks = blocks;
this.initial = initial;
this.generate = generator;
DataFlow(final InstructionsFlow instr, final List<BytecodeTryCatchBlock> catches) {
this.instructions = instr;
this.blocks = new ArrayList<>(catches);
}

// this.blocks.stream()
// .map(BytecodeTryCatchBlock.class::cast)
// .map(BytecodeTryCatchBlock::handlerLabel)
// .map(this.instructions::index)
// .peek(ind -> visited.put(ind, 1))
// .forEach(worklist::add);


public T max() {
public T max(T initial, Function<BytecodeInstruction, T> generator) {
final Map<Integer, T> visited = new HashMap<>(0);
final Map<Integer, T> worklist = new HashMap<>(0);
worklist.put(0, this.initial);
worklist.put(0, initial);
final int total = this.instructions.size();
T current;
while (!worklist.isEmpty()) {
Expand All @@ -83,7 +63,7 @@ public T max() {
final BytecodeEntry entry = this.instructions.get(index);
if (entry instanceof BytecodeInstruction) {
final BytecodeInstruction instruction = BytecodeInstruction.class.cast(entry);
current = current.add(this.generate.apply(instruction));
current = current.add(generator.apply(instruction));
final T updated = current;
if (instruction.isSwitch()) {
final List<Label> offsets = instruction.offsets();
Expand Down Expand Up @@ -112,8 +92,7 @@ public T max() {
break;
}
this.suitableBlocks(index)
.forEach(ind -> worklist.put(ind, updated.initBlock())
);
.forEach(ind -> worklist.put(ind, updated.enterBlock()));
visited.putIfAbsent(index, updated);
visited.computeIfPresent(index, (k, v) -> this.max(v, updated));
} else {
Expand Down Expand Up @@ -142,15 +121,15 @@ private List<Integer> suitableBlocks(final int instruction) {
.collect(Collectors.toList());
}

private T max(final T a, final T b) {
return a.compareTo(b) > 0 ? a : b;
private T max(final T first, final T second) {
return first.compareTo(second) > 0 ? first : second;
}

interface Something<T> extends Comparable<T> {
interface Reducible<T> extends Comparable<T> {

T add(T other);

T initBlock();
T enterBlock();

}
}
101 changes: 11 additions & 90 deletions src/main/java/org/eolang/jeo/representation/bytecode/MaxStackFlow.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,8 @@
*/
package org.eolang.jeo.representation.bytecode;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.TreeMap;
import lombok.ToString;
import org.objectweb.asm.Label;

public final class MaxStackFlow {

Expand Down Expand Up @@ -74,99 +68,23 @@ private MaxStackFlow(
* Compute the maximum stack size.
* @return Maximum stack size.
*/
@SuppressWarnings("PMD.CognitiveComplexity")
public int value() {
return new DataFlow<>(
this.instructions,
this.blocks,
new Stack(0),
Stack::new
).max().value;

// int max = 0;
// final int length = this.instructions.size();
// final Deque<Integer> worklist = new ArrayDeque<>(0);
// worklist.add(0);
// final Map<Integer, Integer> visited = new TreeMap<>();
// this.blocks.stream()
// .map(BytecodeTryCatchBlock.class::cast)
// .map(BytecodeTryCatchBlock::handlerLabel)
// .map(this.instructions::index)
// .peek(ind -> visited.put(ind, 1))
// .forEach(worklist::add);
// while (!worklist.isEmpty()) {
// int current = worklist.pop();
// int stack = visited.get(current) == null ? 0 : visited.get(current);
// while (current < length) {
// final BytecodeEntry entry = this.instructions.get(current);
// stack += entry.impact();
// max = Math.max(max, stack);
// final int fstack = stack;
// visited.compute(
// current, (k, v) -> v == null ? fstack : Math.max(v, fstack)
// );
// if (entry instanceof BytecodeInstruction) {
// final BytecodeInstruction var = BytecodeInstruction.class.cast(entry);
// if (var.isSwitch()) {
// final List<Label> offsets = var.offsets();
// for (final Label offset : offsets) {
// final int target = this.instructions.index(offset);
// if (visited.get(target) == null
// || visited.get(target) < stack
// ) {
// visited.put(target, stack);
// worklist.add(target);
// }
// }
// break;
// } else if (var.isBranch()) {
// final Label label = var.jump();
// final int jump = this.instructions.index(label);
// if (visited.get(jump) == null
// || visited.get(jump) < stack
// ) {
// visited.put(jump, stack);
// worklist.add(jump);
// }
// final int next = current + 1;
// if (visited.get(next) == null
// || visited.get(next) < stack
// ) {
// visited.put(next, stack);
// worklist.add(next);
// }
// break;
// } else if (var.isJump()) {
// final Label label = var.jump();
// final int jump = this.instructions.index(label);
// if (visited.get(jump) == null
// || visited.get(jump) < stack
// ) {
// visited.put(jump, stack);
// worklist.add(jump);
// }
// break;
// } else if (var.isReturn()) {
// break;
// }
// }
// ++current;
// }
// }
// return max;
return new DataFlow<Stack>(this.instructions, this.blocks)
.max(new Stack(0), Stack::new)
.value();
}

@ToString
private static class Stack implements DataFlow.Something<Stack> {
private static class Stack implements DataFlow.Reducible<Stack> {

private final int value;
private final String source;

private Stack(final int value) {
Stack(final int value) {
this(value, "");
}

private Stack(final BytecodeInstruction instruction) {
Stack(final BytecodeInstruction instruction) {
this(instruction.impact(), instruction.testCode());
}

Expand All @@ -175,6 +93,10 @@ private Stack(final int value, final String source) {
this.source = source;
}

int value() {
return this.value;
}

@Override
public int compareTo(final Stack o) {
return Integer.compare(this.value, o.value);
Expand All @@ -186,8 +108,7 @@ public Stack add(final Stack other) {
}

@Override
public Stack initBlock() {
// return this.add(new Stack(1));
public Stack enterBlock() {
return new Stack(1);
}
}
Expand Down

0 comments on commit 0f46e82

Please sign in to comment.