@Override protected Node leaveDefault(final Node node) { if(node instanceof Optimistic) { return leaveOptimistic((Optimistic)node); } return node; }
private Expression leaveOptimistic(final Optimistic opt) { final int pp = opt.getProgramPoint(); if(isValid(pp) && !neverOptimistic.peek().get(pp)) { return (Expression)opt.setType(compiler.getOptimisticType(opt)); } return (Expression)opt; }
private void tagNeverOptimistic(final Expression expr) { if(expr instanceof Optimistic) { final int pp = ((Optimistic)expr).getProgramPoint(); if(isValid(pp)) { neverOptimistic.peek().set(pp); } } }
Type getOptimisticType(final Optimistic node) { assert compiler.useOptimisticTypes(); final int programPoint = node.getProgramPoint(); final Type validType = compiler.getInvalidatedProgramPointType(programPoint); if (validType != null) { return validType; } final Type mostOptimisticType = node.getMostOptimisticType(); final Type evaluatedType = getEvaluatedType(node); if (evaluatedType != null) { if (evaluatedType.widerThan(mostOptimisticType)) { final Type newValidType = evaluatedType.isObject() || evaluatedType.isBoolean() ? Type.OBJECT : evaluatedType; // Update invalidatedProgramPoints so we don't re-evaluate the expression next time. This is a heuristic // as we're doing a tradeoff. Re-evaluating expressions on each recompile takes time, but it might // notice a widening in the type of the expression and thus prevent an unnecessary deoptimization later. // We'll presume though that the types of expressions are mostly stable, so if we evaluated it in one // compilation, we'll keep to that and risk a low-probability deoptimization if its type gets widened // in the future. compiler.addInvalidatedProgramPoint(node.getProgramPoint(), newValidType); } return evaluatedType; } return mostOptimisticType; }
/** * Check if a property value contains a particular program point * @param value value * @param pp program point * @return true if it's there. */ private static boolean propertyValueContains(final Expression value, final int pp) { return new Supplier<Boolean>() { boolean contains; @Override public Boolean get() { value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { @Override public boolean enterFunctionNode(final FunctionNode functionNode) { return false; } @Override public boolean enterObjectNode(final ObjectNode objectNode) { return false; } @Override public boolean enterDefault(final Node node) { if (contains) { return false; } if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) { contains = true; return false; } return true; } }); return contains; } }.get(); }
/** * Was this expression or any of its subexpressions deoptimized in the current recompilation chain of rest-of methods? * @param rootExpr the expression being tested * @return true if the expression or any of its subexpressions was deoptimized in the current recompilation chain. */ private boolean isDeoptimizedExpression(final Expression rootExpr) { if(!isRestOf()) { return false; } return new Supplier<Boolean>() { boolean contains; @Override public Boolean get() { rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { @Override public boolean enterFunctionNode(final FunctionNode functionNode) { return false; } @Override public boolean enterDefault(final Node node) { if(!contains && node instanceof Optimistic) { final int pp = ((Optimistic)node).getProgramPoint(); contains = isValid(pp) && isContinuationEntryPoint(pp); } return !contains; } }); return contains; } }.get(); }
OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) { this.optimistic = optimistic; this.expression = (Expression)optimistic; this.resultBounds = resultBounds; this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() && // Operation is only effectively optimistic if its type, after being coerced into the result bounds // is narrower than the upper bound. resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest); }
private static boolean isOptimistic(final Optimistic optimistic) { if(!optimistic.canBeOptimistic()) { return false; } final Expression expr = (Expression)optimistic; return expr.getType().narrowerThan(expr.getWidestOperationType()); }
/** * Check if a property value contains a particular program point * @param value value * @param pp program point * @return true if it's there. */ private static boolean propertyValueContains(final Expression value, final int pp) { return new Supplier<Boolean>() { boolean contains; @Override public Boolean get() { value.accept(new SimpleNodeVisitor() { @Override public boolean enterFunctionNode(final FunctionNode functionNode) { return false; } @Override public boolean enterDefault(final Node node) { if (contains) { return false; } if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) { contains = true; return false; } return true; } }); return contains; } }.get(); }
/** * Was this expression or any of its subexpressions deoptimized in the current recompilation chain of rest-of methods? * @param rootExpr the expression being tested * @return true if the expression or any of its subexpressions was deoptimized in the current recompilation chain. */ private boolean isDeoptimizedExpression(final Expression rootExpr) { if(!isRestOf()) { return false; } return new Supplier<Boolean>() { boolean contains; @Override public Boolean get() { rootExpr.accept(new SimpleNodeVisitor() { @Override public boolean enterFunctionNode(final FunctionNode functionNode) { return false; } @Override public boolean enterDefault(final Node node) { if(!contains && node instanceof Optimistic) { final int pp = ((Optimistic)node).getProgramPoint(); contains = isValid(pp) && isContinuationEntryPoint(pp); } return !contains; } }); return contains; } }.get(); }
/** * Check if a property value contains a particular program point * @param value value * @param pp program point * @return true if it's there. */ private static boolean propertyValueContains(final Expression value, final int pp) { return new Supplier<Boolean>() { boolean contains; @Override public Boolean get() { value.accept(new SimpleNodeVisitor() { @Override public boolean enterFunctionNode(final FunctionNode functionNode) { return false; } @Override public boolean enterObjectNode(final ObjectNode objectNode) { return false; } @Override public boolean enterDefault(final Node node) { if (contains) { return false; } if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) { contains = true; return false; } return true; } }); return contains; } }.get(); }