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; }
private static Type computeElementType(final Expression[] value) { Type widestElementType = Type.INT; for (final Expression elem : value) { if (elem == null) { widestElementType = widestElementType.widest(Type.OBJECT); // no way to represent undefined as number break; } final Type type = elem.getType().isUnknown() ? Type.OBJECT : elem.getType(); if (type.isBoolean()) { // TODO fix this with explicit boolean types widestElementType = widestElementType.widest(Type.OBJECT); break; } widestElementType = widestElementType.widest(type); if (widestElementType.isObject()) { break; } } return widestElementType; }