8161708: javac, consider a different way to handle access code for operators

Reviewed-by: mcimadamore
This commit is contained in:
Vicente Romero 2016-08-01 08:36:02 -07:00
parent e6f3a52942
commit 2bedc263dc
7 changed files with 160 additions and 147 deletions

View File

@ -55,7 +55,9 @@ import com.sun.tools.javac.comp.Attr;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.Tag;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.Name;
@ -64,9 +66,15 @@ import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.FIRSTASGOP;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.FORALL;
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
import static com.sun.tools.javac.jvm.ByteCodes.iadd;
import static com.sun.tools.javac.jvm.ByteCodes.ishll;
import static com.sun.tools.javac.jvm.ByteCodes.lushrl;
import static com.sun.tools.javac.jvm.ByteCodes.lxor;
import static com.sun.tools.javac.jvm.ByteCodes.string_add;
/** Root class for Java symbols. It contains subclasses
* for specific sorts of symbols, such as variables, methods and operators,
@ -1950,15 +1958,90 @@ public abstract class Symbol extends AnnoConstruct implements Element {
public static class OperatorSymbol extends MethodSymbol {
public int opcode;
private int accessCode = Integer.MIN_VALUE;
public OperatorSymbol(Name name, Type type, int opcode, Symbol owner) {
super(PUBLIC | STATIC, name, type, owner);
this.opcode = opcode;
}
@Override
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitOperatorSymbol(this, p);
}
public int getAccessCode(Tag tag) {
if (accessCode != Integer.MIN_VALUE && !tag.isIncOrDecUnaryOp()) {
return accessCode;
}
accessCode = AccessCode.from(tag, opcode);
return accessCode;
}
/** Access codes for dereferencing, assignment,
* and pre/post increment/decrement.
* All access codes for accesses to the current class are even.
* If a member of the superclass should be accessed instead (because
* access was via a qualified super), add one to the corresponding code
* for the current class, making the number odd.
* This numbering scheme is used by the backend to decide whether
* to issue an invokevirtual or invokespecial call.
*
* @see Gen#visitSelect(JCFieldAccess tree)
*/
public enum AccessCode {
UNKNOWN(-1, Tag.NO_TAG),
DEREF(0, Tag.NO_TAG),
ASSIGN(2, Tag.ASSIGN),
PREINC(4, Tag.PREINC),
PREDEC(6, Tag.PREDEC),
POSTINC(8, Tag.POSTINC),
POSTDEC(10, Tag.POSTDEC),
FIRSTASGOP(12, Tag.NO_TAG);
public final int code;
public final Tag tag;
public static final int numberOfAccessCodes = (lushrl - ishll + lxor + 2 - iadd) * 2 + FIRSTASGOP.code + 2;
AccessCode(int code, Tag tag) {
this.code = code;
this.tag = tag;
}
static public AccessCode getFromCode(int code) {
for (AccessCode aCodes : AccessCode.values()) {
if (aCodes.code == code) {
return aCodes;
}
}
return UNKNOWN;
}
static int from(Tag tag, int opcode) {
/** Map bytecode of binary operation to access code of corresponding
* assignment operation. This is always an even number.
*/
switch (tag) {
case PREINC:
return AccessCode.PREINC.code;
case PREDEC:
return AccessCode.PREDEC.code;
case POSTINC:
return AccessCode.POSTINC.code;
case POSTDEC:
return AccessCode.POSTDEC.code;
}
if (iadd <= opcode && opcode <= lxor) {
return (opcode - iadd) * 2 + FIRSTASGOP.code;
} else if (opcode == string_add) {
return (lxor + 1 - iadd) * 2 + FIRSTASGOP.code;
} else if (ishll <= opcode && opcode <= lushrl) {
return (opcode - ishll + lxor + 2 - iadd) * 2 + FIRSTASGOP.code;
}
return -1;
}
}
}
/** Symbol completer interface.

View File

@ -3159,7 +3159,7 @@ public class Attr extends JCTree.Visitor {
Type operand = attribExpr(tree.rhs, env);
// Find operator.
Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag().noAssignOp(), owntype, operand);
if (operator.kind == MTH &&
if (operator != operators.noOpSymbol &&
!owntype.isErroneous() &&
!operand.isErroneous()) {
chk.checkDivZero(tree.rhs.pos(), operator, operand);
@ -3179,7 +3179,7 @@ public class Attr extends JCTree.Visitor {
// Find operator.
Symbol operator = tree.operator = operators.resolveUnary(tree, tree.getTag(), argtype);
Type owntype = types.createErrorType(tree.type);
if (operator.kind == MTH &&
if (operator != operators.noOpSymbol &&
!argtype.isErroneous()) {
owntype = (tree.getTag().isIncOrDecUnaryOp())
? tree.arg.type
@ -3204,7 +3204,7 @@ public class Attr extends JCTree.Visitor {
// Find operator.
Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right);
Type owntype = types.createErrorType(tree.type);
if (operator.kind == MTH &&
if (operator != operators.noOpSymbol &&
!left.isErroneous() &&
!right.isErroneous()) {
owntype = operator.type.getReturnType();

View File

@ -38,6 +38,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.code.Type.*;
@ -49,6 +50,7 @@ import static com.sun.tools.javac.code.Flags.BLOCK;
import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF;
import static com.sun.tools.javac.jvm.ByteCodes.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
@ -816,33 +818,6 @@ public class Lower extends TreeTranslator {
* Access methods
*************************************************************************/
/** Access codes for dereferencing, assignment,
* and pre/post increment/decrement.
* Access codes for assignment operations are determined by method accessCode
* below.
*
* All access codes for accesses to the current class are even.
* If a member of the superclass should be accessed instead (because
* access was via a qualified super), add one to the corresponding code
* for the current class, making the number odd.
* This numbering scheme is used by the backend to decide whether
* to issue an invokevirtual or invokespecial call.
*
* @see Gen#visitSelect(JCFieldAccess tree)
*/
private static final int
DEREFcode = 0,
ASSIGNcode = 2,
PREINCcode = 4,
PREDECcode = 6,
POSTINCcode = 8,
POSTDECcode = 10,
FIRSTASGOPcode = 12;
/** Number of access codes
*/
private static final int NCODES = accessCode(ByteCodes.lushrl) + 2;
/** A mapping from symbols to their access numbers.
*/
private Map<Symbol,Integer> accessNums;
@ -864,20 +839,6 @@ public class Lower extends TreeTranslator {
*/
private ListBuffer<Symbol> accessed;
/** Map bytecode of binary operation to access code of corresponding
* assignment operation. This is always an even number.
*/
private static int accessCode(int bytecode) {
if (ByteCodes.iadd <= bytecode && bytecode <= ByteCodes.lxor)
return (bytecode - iadd) * 2 + FIRSTASGOPcode;
else if (bytecode == ByteCodes.string_add)
return (ByteCodes.lxor + 1 - iadd) * 2 + FIRSTASGOPcode;
else if (ByteCodes.ishll <= bytecode && bytecode <= ByteCodes.lushrl)
return (bytecode - ishll + ByteCodes.lxor + 2 - iadd) * 2 + FIRSTASGOPcode;
else
return -1;
}
/** return access code for identifier,
* @param tree The tree representing the identifier use.
* @param enclOp The closest enclosing operation node of tree,
@ -885,24 +846,24 @@ public class Lower extends TreeTranslator {
*/
private static int accessCode(JCTree tree, JCTree enclOp) {
if (enclOp == null)
return DEREFcode;
return AccessCode.DEREF.code;
else if (enclOp.hasTag(ASSIGN) &&
tree == TreeInfo.skipParens(((JCAssign) enclOp).lhs))
return ASSIGNcode;
return AccessCode.ASSIGN.code;
else if (enclOp.getTag().isIncOrDecUnaryOp() &&
tree == TreeInfo.skipParens(((JCUnary) enclOp).arg))
return mapTagToUnaryOpCode(enclOp.getTag());
return (((JCUnary) enclOp).operator).getAccessCode(enclOp.getTag());
else if (enclOp.getTag().isAssignop() &&
tree == TreeInfo.skipParens(((JCAssignOp) enclOp).lhs))
return accessCode(((OperatorSymbol) ((JCAssignOp) enclOp).operator).opcode);
return (((JCAssignOp) enclOp).operator).getAccessCode(enclOp.getTag());
else
return DEREFcode;
return AccessCode.DEREF.code;
}
/** Return binary operator that corresponds to given access code.
*/
private OperatorSymbol binaryAccessOperator(int acode) {
return (OperatorSymbol)operators.lookupBinaryOp(sym -> accessCode(((OperatorSymbol)sym).opcode) == acode);
private OperatorSymbol binaryAccessOperator(int acode, Tag tag) {
return operators.lookupBinaryOp(op -> op.getAccessCode(tag) == acode);
}
/** Return tree tag for assignment operation corresponding
@ -984,7 +945,7 @@ public class Lower extends TreeTranslator {
if (anum == null) {
anum = accessed.length();
accessNums.put(vsym, anum);
accessSyms.put(vsym, new MethodSymbol[NCODES]);
accessSyms.put(vsym, new MethodSymbol[AccessCode.numberOfAccessCodes]);
accessed.append(vsym);
// System.out.println("accessing " + vsym + " in " + vsym.location());
}
@ -996,13 +957,13 @@ public class Lower extends TreeTranslator {
switch (vsym.kind) {
case VAR:
acode = accessCode(tree, enclOp);
if (acode >= FIRSTASGOPcode) {
OperatorSymbol operator = binaryAccessOperator(acode);
if (acode >= AccessCode.FIRSTASGOP.code) {
OperatorSymbol operator = binaryAccessOperator(acode, enclOp.getTag());
if (operator.opcode == string_add)
argtypes = List.of(syms.objectType);
else
argtypes = operator.type.getParameterTypes().tail;
} else if (acode == ASSIGNcode)
} else if (acode == AccessCode.ASSIGN.code)
argtypes = List.of(vsym.erasure(types));
else
argtypes = List.nil();
@ -1010,7 +971,7 @@ public class Lower extends TreeTranslator {
thrown = List.nil();
break;
case MTH:
acode = DEREFcode;
acode = AccessCode.DEREF.code;
argtypes = vsym.erasure(types).getParameterTypes();
restype = vsym.erasure(types).getReturnType();
thrown = vsym.type.getThrownTypes();
@ -1306,7 +1267,7 @@ public class Lower extends TreeTranslator {
accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
} else {
MethodSymbol[] accessors = accessSyms.get(sym);
for (int i = 0; i < NCODES; i++) {
for (int i = 0; i < AccessCode.numberOfAccessCodes; i++) {
if (accessors[i] != null)
cdef.defs = cdef.defs.prepend(
accessDef(cdef.pos, sym, accessors[i], i));
@ -1314,42 +1275,6 @@ public class Lower extends TreeTranslator {
}
}
/** Maps unary operator integer codes to JCTree.Tag objects
* @param unaryOpCode the unary operator code
*/
private static Tag mapUnaryOpCodeToTag(int unaryOpCode){
switch (unaryOpCode){
case PREINCcode:
return PREINC;
case PREDECcode:
return PREDEC;
case POSTINCcode:
return POSTINC;
case POSTDECcode:
return POSTDEC;
default:
return NO_TAG;
}
}
/** Maps JCTree.Tag objects to unary operator integer codes
* @param tag the JCTree.Tag
*/
private static int mapTagToUnaryOpCode(Tag tag){
switch (tag){
case PREINC:
return PREINCcode;
case PREDEC:
return PREDECcode;
case POSTINC:
return POSTINCcode;
case POSTDEC:
return POSTDECcode;
default:
return -1;
}
}
/** Construct definition of an access method.
* @param pos The source code position of the definition.
* @param vsym The private or protected symbol.
@ -1388,20 +1313,21 @@ public class Lower extends TreeTranslator {
int acode1 = acode - (acode & 1);
JCExpression expr; // The access method's return value.
switch (acode1) {
case DEREFcode:
AccessCode aCode = AccessCode.getFromCode(acode1);
switch (aCode) {
case DEREF:
expr = ref;
break;
case ASSIGNcode:
case ASSIGN:
expr = make.Assign(ref, args.head);
break;
case PREINCcode: case POSTINCcode: case PREDECcode: case POSTDECcode:
expr = makeUnary(mapUnaryOpCodeToTag(acode1), ref);
case PREINC: case POSTINC: case PREDEC: case POSTDEC:
expr = makeUnary(aCode.tag, ref);
break;
default:
expr = make.Assignop(
treeTag(binaryAccessOperator(acode1)), ref, args.head);
((JCAssignOp) expr).operator = binaryAccessOperator(acode1);
treeTag(binaryAccessOperator(acode1, JCTree.Tag.NO_TAG)), ref, args.head);
((JCAssignOp) expr).operator = binaryAccessOperator(acode1, JCTree.Tag.NO_TAG);
}
stat = make.Return(expr.setType(sym.type));
} else {
@ -3275,7 +3201,7 @@ public class Lower extends TreeTranslator {
// tree.lhs. However, we can still get the
// unerased type of tree.lhs as it is stored
// in tree.type in Attr.
Symbol newOperator = operators.resolveBinary(tree,
OperatorSymbol newOperator = operators.resolveBinary(tree,
newTag,
tree.type,
tree.rhs.type);
@ -3304,7 +3230,7 @@ public class Lower extends TreeTranslator {
JCMethodInvocation app = (JCMethodInvocation)tree.lhs;
// if operation is a += on strings,
// make sure to convert argument to string
JCExpression rhs = (((OperatorSymbol)tree.operator).opcode == string_add)
JCExpression rhs = tree.operator.opcode == string_add
? makeString(tree.rhs)
: tree.rhs;
app.args = List.of(rhs).prependList(app.args);

View File

@ -95,6 +95,7 @@ public class Operators {
names = Names.instance(context);
log = Log.instance(context);
types = Types.instance(context);
noOpSymbol = new OperatorSymbol(names.empty, Type.noType, -1, syms.noSymbol);
initOperatorNames();
initUnaryOperators();
initBinaryOperators();
@ -145,7 +146,7 @@ public class Operators {
/**
* Entry point for resolving a unary operator given an operator tag and an argument type.
*/
Symbol resolveUnary(DiagnosticPosition pos, JCTree.Tag tag, Type op) {
OperatorSymbol resolveUnary(DiagnosticPosition pos, JCTree.Tag tag, Type op) {
return resolve(tag,
unaryOperators,
unop -> unop.test(op),
@ -156,7 +157,7 @@ public class Operators {
/**
* Entry point for resolving a binary operator given an operator tag and a pair of argument types.
*/
Symbol resolveBinary(DiagnosticPosition pos, JCTree.Tag tag, Type op1, Type op2) {
OperatorSymbol resolveBinary(DiagnosticPosition pos, JCTree.Tag tag, Type op1, Type op2) {
return resolve(tag,
binaryOperators,
binop -> binop.test(op1, op2),
@ -169,8 +170,8 @@ public class Operators {
* map. If there's a matching operator, its resolve routine is called and the result is returned;
* otherwise the result of a fallback function is returned.
*/
private <O> Symbol resolve(Tag tag, Map<Name, List<O>> opMap, Predicate<O> opTestFunc,
Function<O, Symbol> resolveFunc, Supplier<Symbol> noResultFunc) {
private <O> OperatorSymbol resolve(Tag tag, Map<Name, List<O>> opMap, Predicate<O> opTestFunc,
Function<O, OperatorSymbol> resolveFunc, Supplier<OperatorSymbol> noResultFunc) {
return opMap.get(operatorName(tag)).stream()
.filter(opTestFunc)
.map(resolveFunc)
@ -181,7 +182,7 @@ public class Operators {
/**
* Creates an operator symbol.
*/
private Symbol makeOperator(Name name, List<OperatorType> formals, OperatorType res, int... opcodes) {
private OperatorSymbol makeOperator(Name name, List<OperatorType> formals, OperatorType res, int... opcodes) {
MethodType opType = new MethodType(
formals.stream()
.map(o -> o.asType(syms))
@ -201,10 +202,14 @@ public class Operators {
((opcodes[0] << ByteCodes.preShift) | opcodes[1]);
}
/** A symbol that stands for a missing operator.
*/
public final OperatorSymbol noOpSymbol;
/**
* Report an operator lookup error.
*/
private Symbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
private OperatorSymbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
if (Stream.of(args).noneMatch(Type::isErroneous)) {
Name opName = operatorName(tag);
JCDiagnostic.Error opError = (args.length) == 1 ?
@ -212,7 +217,7 @@ public class Operators {
Errors.OperatorCantBeApplied1(opName, args[0], args[1]);
log.error(pos, opError);
}
return syms.noSymbol;
return noOpSymbol;
}
/**
@ -263,10 +268,10 @@ public class Operators {
final Name name;
/** The list of symbols associated with this operator (lazily populated). */
Optional<Symbol[]> alternatives = Optional.empty();
Optional<OperatorSymbol[]> alternatives = Optional.empty();
/** An array of operator symbol suppliers (used to lazily populate the symbol list). */
List<Supplier<Symbol>> operatorSuppliers = List.nil();
List<Supplier<OperatorSymbol>> operatorSuppliers = List.nil();
@SuppressWarnings("varargs")
OperatorHelper(Tag tag) {
@ -278,21 +283,21 @@ public class Operators {
* using an applicability predicate; if the test suceeds that same operator is returned,
* otherwise a dummy symbol is returned.
*/
final Symbol doLookup(Predicate<Symbol> applicabilityTest) {
final OperatorSymbol doLookup(Predicate<OperatorSymbol> applicabilityTest) {
return Stream.of(alternatives.orElseGet(this::initOperators))
.filter(applicabilityTest)
.findFirst()
.orElse(syms.noSymbol);
.orElse(noOpSymbol);
}
/**
* This routine performs lazy instantiation of the operator symbols supported by this helper.
* After initialization is done, the suppliers are cleared, to free up memory.
*/
private Symbol[] initOperators() {
Symbol[] operators = operatorSuppliers.stream()
private OperatorSymbol[] initOperators() {
OperatorSymbol[] operators = operatorSuppliers.stream()
.map(op -> op.get())
.toArray(Symbol[]::new);
.toArray(OperatorSymbol[]::new);
alternatives = Optional.of(operators);
operatorSuppliers = null; //let GC do its work
return operators;
@ -311,10 +316,10 @@ public class Operators {
/**
* This routine implements the unary operator lookup process. It customizes the behavior
* of the shared lookup routine in {@link OperatorHelper}, by using an unary applicability test
* (see {@link UnaryOperatorHelper#isUnaryOperatorApplicable(OperatorSymbol, Type)}
* (see {@link UnaryOperatorHelper#isUnaryOperatorApplicable(OperatorOperatorSymbol, Type)}
*/
final Symbol doLookup(Type t) {
return doLookup(op -> isUnaryOperatorApplicable((OperatorSymbol)op, t));
final OperatorSymbol doLookup(Type t) {
return doLookup(op -> isUnaryOperatorApplicable(op, t));
}
/**
@ -336,7 +341,7 @@ public class Operators {
* This method will be overridden by unary operator helpers to provide custom resolution
* logic.
*/
abstract Symbol resolve(Type t);
abstract OperatorSymbol resolve(Type t);
}
abstract class BinaryOperatorHelper extends OperatorHelper implements BiPredicate<Type, Type> {
@ -350,8 +355,8 @@ public class Operators {
* of the shared lookup routine in {@link OperatorHelper}, by using an unary applicability test
* (see {@link BinaryOperatorHelper#isBinaryOperatorApplicable(OperatorSymbol, Type, Type)}
*/
final Symbol doLookup(Type t1, Type t2) {
return doLookup(op -> isBinaryOperatorApplicable((OperatorSymbol)op, t1, t2));
final OperatorSymbol doLookup(Type t1, Type t2) {
return doLookup(op -> isBinaryOperatorApplicable(op, t1, t2));
}
/**
@ -375,7 +380,7 @@ public class Operators {
* This method will be overridden by binary operator helpers to provide custom resolution
* logic.
*/
abstract Symbol resolve(Type t1, Type t2);
abstract OperatorSymbol resolve(Type t1, Type t2);
}
/**
@ -393,7 +398,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg) {
public OperatorSymbol resolve(Type arg) {
return doLookup(syms.objectType);
}
}
@ -421,7 +426,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg) {
public OperatorSymbol resolve(Type arg) {
return doLookup(unaryPromotion(arg));
}
}
@ -442,7 +447,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg) {
public OperatorSymbol resolve(Type arg) {
return doLookup(syms.booleanType);
}
}
@ -458,7 +463,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg) {
public OperatorSymbol resolve(Type arg) {
return doLookup(types.unboxedTypeOrType(arg));
}
}
@ -481,7 +486,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg1, Type arg2) {
public OperatorSymbol resolve(Type arg1, Type arg2) {
Type t = binaryPromotion(arg1, arg2);
return doLookup(t, t);
}
@ -504,7 +509,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg1, Type arg2) {
public OperatorSymbol resolve(Type arg1, Type arg2) {
return doLookup(syms.booleanType, syms.booleanType);
}
@ -527,7 +532,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg1, Type arg2) {
public OperatorSymbol resolve(Type arg1, Type arg2) {
return doLookup(stringPromotion(arg1), stringPromotion(arg2));
}
@ -570,7 +575,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type arg1, Type arg2) {
public OperatorSymbol resolve(Type arg1, Type arg2) {
return doLookup(unaryPromotion(arg1), unaryPromotion(arg2));
}
@ -613,7 +618,7 @@ public class Operators {
}
@Override
public Symbol resolve(Type t1, Type t2) {
public OperatorSymbol resolve(Type t1, Type t2) {
ComparisonKind kind = getKind(t1, t2);
Type t = (kind == ComparisonKind.NUMERIC_OR_BOOLEAN) ?
binaryPromotion(t1, t2) :
@ -798,12 +803,12 @@ public class Operators {
.addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, bool_or));
}
Symbol lookupBinaryOp(Predicate<Symbol> applicabilityTest) {
OperatorSymbol lookupBinaryOp(Predicate<OperatorSymbol> applicabilityTest) {
return binaryOperators.values().stream()
.flatMap(List::stream)
.map(helper -> helper.doLookup(applicabilityTest))
.distinct()
.filter(sym -> sym != syms.noSymbol)
.filter(sym -> sym != noOpSymbol)
.findFirst().get();
}

View File

@ -1795,7 +1795,7 @@ public class Gen extends JCTree.Visitor {
}
public void visitAssignop(JCAssignOp tree) {
OperatorSymbol operator = (OperatorSymbol) tree.operator;
OperatorSymbol operator = tree.operator;
Item l;
if (operator.opcode == string_add) {
l = concat.makeConcat(tree);
@ -1827,7 +1827,7 @@ public class Gen extends JCTree.Visitor {
}
public void visitUnary(JCUnary tree) {
OperatorSymbol operator = (OperatorSymbol)tree.operator;
OperatorSymbol operator = tree.operator;
if (tree.hasTag(NOT)) {
CondItem od = genCond(tree.arg, false);
result = od.negate();
@ -1909,7 +1909,7 @@ public class Gen extends JCTree.Visitor {
}
public void visitBinary(JCBinary tree) {
OperatorSymbol operator = (OperatorSymbol)tree.operator;
OperatorSymbol operator = tree.operator;
if (operator.opcode == string_add) {
result = concat.makeConcat(tree);
} else if (tree.hasTag(AND)) {

View File

@ -131,8 +131,7 @@ public abstract class StringConcat {
tree = TreeInfo.skipParens(tree);
if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
JCTree.JCBinary op = (JCTree.JCBinary) tree;
if (op.operator.kind == MTH &&
((Symbol.OperatorSymbol) op.operator).opcode == string_add) {
if (op.operator.kind == MTH && op.operator.opcode == string_add) {
return res
.appendList(collect(op.lhs, res))
.appendList(collect(op.rhs, res));

View File

@ -1876,8 +1876,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
private Tag opcode;
public JCExpression lhs;
public JCExpression rhs;
public Symbol operator;
protected JCAssignOp(Tag opcode, JCTree lhs, JCTree rhs, Symbol operator) {
public OperatorSymbol operator;
protected JCAssignOp(Tag opcode, JCTree lhs, JCTree rhs, OperatorSymbol operator) {
this.opcode = opcode;
this.lhs = (JCExpression)lhs;
this.rhs = (JCExpression)rhs;
@ -1892,7 +1892,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public JCExpression getVariable() { return lhs; }
@DefinedBy(Api.COMPILER_TREE)
public JCExpression getExpression() { return rhs; }
public Symbol getOperator() {
public OperatorSymbol getOperator() {
return operator;
}
@Override @DefinedBy(Api.COMPILER_TREE)
@ -1911,7 +1911,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public static class JCUnary extends JCExpression implements UnaryTree {
private Tag opcode;
public JCExpression arg;
public Symbol operator;
public OperatorSymbol operator;
protected JCUnary(Tag opcode, JCExpression arg) {
this.opcode = opcode;
this.arg = arg;
@ -1923,7 +1923,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public Kind getKind() { return TreeInfo.tagToKind(getTag()); }
@DefinedBy(Api.COMPILER_TREE)
public JCExpression getExpression() { return arg; }
public Symbol getOperator() {
public OperatorSymbol getOperator() {
return operator;
}
@Override @DefinedBy(Api.COMPILER_TREE)
@ -1947,11 +1947,11 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
private Tag opcode;
public JCExpression lhs;
public JCExpression rhs;
public Symbol operator;
public OperatorSymbol operator;
protected JCBinary(Tag opcode,
JCExpression lhs,
JCExpression rhs,
Symbol operator) {
OperatorSymbol operator) {
this.opcode = opcode;
this.lhs = lhs;
this.rhs = rhs;
@ -1966,7 +1966,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public JCExpression getLeftOperand() { return lhs; }
@DefinedBy(Api.COMPILER_TREE)
public JCExpression getRightOperand() { return rhs; }
public Symbol getOperator() {
public OperatorSymbol getOperator() {
return operator;
}
@Override @DefinedBy(Api.COMPILER_TREE)