Skip to content

[WIP][GR-45250][GR-45734] Reachability proofs for reflective operations #11079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@
import java.util.function.IntConsumer;
import java.util.function.Supplier;

import jdk.graal.compiler.nodes.graphbuilderconf.MethodParsingPlugin;
import org.graalvm.collections.EconomicMap;
import org.graalvm.collections.Equivalence;
import org.graalvm.word.LocationIdentity;
Expand Down Expand Up @@ -1101,6 +1102,10 @@ protected void build(FixedWithNextNode startInstruction, FrameStateBuilder start
graph.recordMethod(method);
}

for (MethodParsingPlugin plugin : graphBuilderConfig.getPlugins().getMethodParsingPlugins()) {
plugin.execute(method, intrinsicContext);
}

// compute the block map, setup exception handlers and get the entrypoint(s)
this.blockMap = generateBlockMap();
this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package jdk.graal.compiler.java.dataflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;

public class AbstractFrame<T> {

private final OperandStack<T> operandStack;
private final LocalVariableTable<T> localVariableTable;

public AbstractFrame() {
this.operandStack = new OperandStack<>();
this.localVariableTable = new LocalVariableTable<>();
}

public AbstractFrame(AbstractFrame<T> state) {
this.operandStack = new OperandStack<>(state.operandStack);
this.localVariableTable = new LocalVariableTable<>(state.localVariableTable);
}

public void mergeWith(AbstractFrame<T> other, BiFunction<T, T, T> mergeFunction) {
operandStack.mergeWith(other.operandStack, mergeFunction);
localVariableTable.mergeWith(other.localVariableTable, mergeFunction);
}

public void transform(Predicate<T> filterFunction, Function<T, T> transformFunction) {
operandStack.transform(filterFunction, transformFunction);
localVariableTable.transform(filterFunction, transformFunction);
}

public OperandStack<T> getOperandStack() {
return operandStack;
}

public LocalVariableTable<T> getLocalVariableTable() {
return localVariableTable;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AbstractFrame<?> that = (AbstractFrame<?>) o;
return Objects.equals(operandStack, that.operandStack) && Objects.equals(localVariableTable, that.localVariableTable);
}

@Override
public int hashCode() {
return Objects.hash(operandStack, localVariableTable);
}

@Override
public String toString() {
return operandStack + "" + localVariableTable;
}

public static final class OperandStack<T> {

private final ArrayList<SizedValue<T>> stack;

public OperandStack() {
this.stack = new ArrayList<>();
}

public OperandStack(OperandStack<T> stack) {
this.stack = new ArrayList<>(stack.stack);
}

public void push(SizedValue<T> value) {
stack.add(value);
}

public SizedValue<T> pop() {
assert !stack.isEmpty() : "Operand stack is empty";
return stack.removeLast();
}

public SizedValue<T> peek(int depth) {
assert size() > depth : "Not enough operands on stack";
return stack.get(stack.size() - depth - 1);
}

public SizedValue<T> peek() {
return peek(0);
}

public void clear() {
stack.clear();
}

public int size() {
return stack.size();
}

public void mergeWith(OperandStack<T> other, BiFunction<T, T, T> mergeFunction) {
assert stack.size() == other.stack.size() : "Operand stack size mismatch";
for (int i = 0; i < stack.size(); i++) {
SizedValue<T> thisValue = stack.get(i);
SizedValue<T> thatValue = other.stack.get(i);
assert thisValue.size() == thatValue.size() : "Value size mismatch upon merging";
SizedValue<T> mergedValue = new SizedValue<>(mergeFunction.apply(thisValue.value(), thatValue.value()), thisValue.size());
stack.set(i, mergedValue);
}
}

public void transform(Predicate<T> filterFunction, Function<T, T> transformFunction) {
for (int i = 0; i < stack.size(); i++) {
SizedValue<T> value = stack.get(i);
if (filterFunction.test(value.value())) {
stack.set(i, new SizedValue<>(transformFunction.apply(value.value()), value.size()));
}
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
OperandStack<?> that = (OperandStack<?>) o;
return Objects.equals(stack, that.stack);
}

@Override
public int hashCode() {
return Objects.hashCode(stack);
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Operand stack:\n");
for (SizedValue<T> value : stack.reversed()) {
builder.append("[").append(value.value()).append("]").append("\n");
}
return builder.toString();
}
}

public static final class LocalVariableTable<T> {

private final Map<Integer, SizedValue<T>> variables;

public LocalVariableTable() {
this.variables = new HashMap<>();
}

public LocalVariableTable(LocalVariableTable<T> localVariableTable) {
this.variables = new HashMap<>(localVariableTable.variables);
}

public void put(int index, SizedValue<T> value) {
variables.put(index, value);
}

public SizedValue<T> get(int index) {
assert variables.containsKey(index) : "Variable table doesn't contain entry for index " + index;
return variables.get(index);
}

public void mergeWith(LocalVariableTable<T> other, BiFunction<T, T, T> mergeFunction) {
for (Map.Entry<Integer, SizedValue<T>> entry : variables.entrySet()) {
SizedValue<T> thisValue = entry.getValue();
SizedValue<T> thatValue = other.variables.get(entry.getKey());
if (thatValue != null) {
assert thisValue.size() == thatValue.size() : "Value size mismatch upon merging";
SizedValue<T> mergedValue = new SizedValue<>(mergeFunction.apply(thisValue.value(), thatValue.value()), thisValue.size());
entry.setValue(mergedValue);
}
}
}

public void transform(Predicate<T> filterFunction, Function<T, T> transformFunction) {
for (Map.Entry<Integer, SizedValue<T>> entry : variables.entrySet()) {
SizedValue<T> value = entry.getValue();
if (filterFunction.test(value.value())) {
entry.setValue(new SizedValue<>(transformFunction.apply(value.value()), value.size()));
}
}
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LocalVariableTable<?> that = (LocalVariableTable<?>) o;
return Objects.equals(variables, that.variables);
}

@Override
public int hashCode() {
return Objects.hashCode(variables);
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Local variable table:\n");
variables.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(
e -> {
Integer varIndex = e.getKey();
SizedValue<T> value = e.getValue();
builder.append(varIndex).append(": ").append(value.value()).append("\n");
}
);
return builder.toString();
}
}

public record SizedValue<T>(T value, Slots size) {
public enum Slots {ONE_SLOT, TWO_SLOTS}
}
}
Loading
Loading