return false;
}
final StrongBox<Variable> v = new StrongBox<>();
final StrongBox<Expression> parent = new StrongBox<>();
final MutableInteger position = new MutableInteger();
if (matchStore(inlinedExpression, v, parent) &&
match(parent.value, AstCode.InitArray) &&
(match(n, AstCode.LoadElement) || match(n, AstCode.StoreElement))) {
//
// Don't allow creation of `(n = new X[] ( ... )[n]`. It's ugly, and I hate it.
//
return false;
}
if (findLoadInNext((Expression) n, variable, inlinedExpression, parent, position) == Boolean.TRUE) {
if (!aggressive &&
!(variable.isGenerated() ||
notFromMetadata(variable) && matchReturnOrThrow(n) /* allow inline to return or throw */) &&
!nonAggressiveInlineInto((Expression) n, parent.get(), inlinedExpression)) {
return false;
}
final List<Expression> parentArguments = parent.get().getArguments();
final Map<Expression, Expression> parentLookup = new IdentityHashMap<>();
for (final Expression node : next.getSelfAndChildrenRecursive(Expression.class)) {
for (final Expression child : node.getArguments()) {
parentLookup.put(child, node);
}
}
final List<Expression> nestedAssignments = inlinedExpression.getSelfAndChildrenRecursive(
Expression.class,
new Predicate<Expression>() {
@Override
public boolean test(final Expression node) {
return node.getCode() == AstCode.Store;
}
}
);
//
// Make sure we do not inline an initialization expression into the left-hand side of an assignment
// whose value references the initialized variable. For example, do not allow inlining in this case:
//
// v = (x = y); v.f = x.f - 1 => (x = y).f = x.f - 1
//
for (final Expression assignment : nestedAssignments) {
Expression lastParent = parentArguments.get(position.getValue());
for (final Expression e : getParents((Expression) n, parentLookup, parentArguments.get(position.getValue()))) {
if (e.getCode().isWriteOperation()) {
boolean lastParentFound = false;
for (final Expression a : e.getArguments()) {
if (lastParentFound) {
if (AstOptimizer.references(a, (Variable) assignment.getOperand())) {
return false;
}
}
else if (a == lastParent) {
lastParentFound = true;
}
}
}
lastParent = e;
}
}
//
// Assign the ranges of the Load instruction.
//
inlinedExpression.getRanges().addAll(
parentArguments.get(position.getValue()).getRanges()
);
parentArguments.set(position.getValue(), inlinedExpression);
return true;
}
return false;