Mercurial > hg > graal-compiler
diff graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java @ 13836:64c77f0577bb
More documentation and improvements of Simple Language
author | Christian Wimmer <christian.wimmer@oracle.com> |
---|---|
date | Thu, 30 Jan 2014 17:53:27 -0800 |
parents | b16ec83edc73 |
children | ff3136ecb5a7 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Thu Jan 30 17:52:24 2014 -0800 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java Thu Jan 30 17:53:27 2014 -0800 @@ -29,29 +29,81 @@ import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.sl.nodes.*; +/** + * SL node that performs the "+" operation, which performs addition on arbitrary precision numbers, + * as well as String concatenation if one of the operands is a String. + * <p> + * Type specialization on the input values is essential for the performance. This is achieved via + * node rewriting: specialized subclasses handle just a single type, so that the generic node that + * can handle all types is used only in cases where different types were encountered. The subclasses + * are automatically generated by the Truffle DSL. In addition, a {@link SLAddNodeFactory factory + * class} is generated that provides, e.g., {@link SLAddNodeFactory#create node creation}. + */ @NodeInfo(shortName = "+") public abstract class SLAddNode extends SLBinaryNode { + /** + * Specialization for primitive {@code long} values. This is the fast path of the + * arbitrary-precision arithmetic. We need to check for overflows of the addition, and switch to + * the {@link #add(BigInteger, BigInteger) slow path}. Therefore, we use an + * {@link ExactMath#addExact(long, long) addition method that throws an exception on overflow}. + * The {@code rewriteOn} attribute on the {@link Specialization} annotation automatically + * triggers the node rewriting on the exception. + * <p> + * In compiled code, {@link ExactMath#addExact(long, long) addExact} is compiled to efficient + * machine code that uses the processor's overflow flag. Therefore, this method is compiled to + * only two machine code instructions on the fast path. + * <p> + * This specialization is automatically selected by the Truffle DSL if both the left and right + * operand are {@code long} values. + */ @Specialization(rewriteOn = ArithmeticException.class) protected long add(long left, long right) { return ExactMath.addExact(left, right); } + /** + * This is the slow path of the arbitrary-precision arithmetic. The {@link BigInteger} type of + * Java is doing everything we need. + * <p> + * This specialization is automatically selected by the Truffle DSL if both the left and right + * operand are {@link BigInteger} values. Because the type system defines an + * {@link ImplicitCast implicit conversion} from {@code long} to {@link BigInteger} in + * {@link SLTypes#castBigInteger(long)}, this specialization is also taken if the left or the + * right operand is a {@code long} value. + */ @Specialization protected BigInteger add(BigInteger left, BigInteger right) { return left.add(right); } + /** + * Specialization for String concatenation. This specialization is not strictly necessary, since + * {@link #add(Object, Object)} covers this case too. But it leads to slightly better code, + * since we do not require the {@link Object#toString()} calls in this specialization. + */ @Specialization protected String add(String left, String right) { return left + right; } + /** + * Specialization for String concatenation. The SL specification says that String concatenation + * works if either the left or the right operand is a String. The non-string operand is + * converted then automatically converted to a String. + * <p> + * To implement these semantics, we tell the Truffle DSL to use a custom guard. The guard + * function is defined in {@link #isString this class}, but could also be in any superclass. + */ @Specialization(guards = "isString") protected String add(Object left, Object right) { return left.toString() + right.toString(); } + /** + * Guard for String concatenation: returns true if either the left or the right operand is a + * {@link String}. + */ protected boolean isString(Object a, Object b) { return a instanceof String || b instanceof String; }