Java Code Examples for jdk.nashorn.internal.codegen.types.Type#widest()

The following examples show how to use jdk.nashorn.internal.codegen.types.Type#widest() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: FunctionNode.java    From openjdk-8-source with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Set the function return type
 * @param lc lexical context
 * @param returnType new return type
 * @return function node or a new one if state was changed
 */
public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
    //we never bother with object types narrower than objects, that will lead to byte code verification errors
    //as for instance even if we know we are returning a string from a method, the code generator will always
    //treat it as an object, at least for now
    if (this.returnType == returnType) {
        return this;
    }
    final Type type = Type.widest(this.returnType, returnType.isObject() ? Type.OBJECT : returnType);
    return Node.replaceInLexicalContext(
        lc,
        this,
        new FunctionNode(
            this,
            lastToken,
            flags,
            name,
            type,
            compileUnit,
            compilationState,
            body.setReturnType(type),
            parameters,
            snapshot,
            hints));
}
 
Example 2
Source File: Attr.java    From nashorn with GNU General Public License v2.0 6 votes vote down vote up
@Override
public Node leaveReturnNode(final ReturnNode returnNode) {
    final Expression expr = returnNode.getExpression();
    final Type returnType;

    if (expr != null) {
        //we can't do parameter specialization if we return something that hasn't been typed yet
        final Symbol symbol = expr.getSymbol();
        if (expr.getType().isUnknown() && symbol.isParam()) {
            symbol.setType(Type.OBJECT);
        }

        returnType = Type.widest(returnTypes.pop(), symbol.getSymbolType());
    } else {
        returnType = Type.OBJECT; //undefined
    }
    LOG.info("Returntype is now ", returnType);
    returnTypes.push(returnType);

    end(returnNode);

    return returnNode;
}
 
Example 3
Source File: FunctionNode.java    From openjdk-8 with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Set the function return type
 * @param lc lexical context
 * @param returnType new return type
 * @return function node or a new one if state was changed
 */
public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
    //we never bother with object types narrower than objects, that will lead to byte code verification errors
    //as for instance even if we know we are returning a string from a method, the code generator will always
    //treat it as an object, at least for now
    if (this.returnType == returnType) {
        return this;
    }
    final Type type = Type.widest(this.returnType, returnType.isObject() ? Type.OBJECT : returnType);
    return Node.replaceInLexicalContext(
        lc,
        this,
        new FunctionNode(
            this,
            lastToken,
            flags,
            name,
            type,
            compileUnit,
            compilationState,
            body.setReturnType(type),
            parameters,
            snapshot,
            hints));
}
 
Example 4
Source File: LiteralNode.java    From jdk8u_nashorn with GNU General Public License v2.0 6 votes vote down vote up
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;
}
 
Example 5
Source File: LiteralNode.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 6 votes vote down vote up
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;
}
 
Example 6
Source File: BinaryNode.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
private static Type decideType(final Type lhsType, final Type rhsType) {
    // Compare this to getWidestOperationType() for ADD and ASSIGN_ADD cases. There's some similar logic, but these
    // are optimistic decisions, meaning that we don't have to treat boolean addition separately (as it'll become
    // int addition in the general case anyway), and that we also don't conservatively widen sums of ints to
    // longs, or sums of longs to doubles.
    if(isString(lhsType) || isString(rhsType)) {
        return Type.CHARSEQUENCE;
    }
    // NOTE: We don't have optimistic object-to-(int, long) conversions. Therefore, if any operand is an Object, we
    // bail out of optimism here and presume a conservative Object return value, as the object's ToPrimitive() can
    // end up returning either a number or a string, and their common supertype is Object, for better or worse.
    final Type widest = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
    return widest.isObject() ? Type.OBJECT : widest;
}
 
Example 7
Source File: RecompilableScriptFunctionData.java    From openjdk-8-source with GNU General Public License v2.0 5 votes vote down vote up
private static boolean canCoerce(final Object arg, final Type type) {
    Type argType = runtimeType(arg);
    if (Type.widest(argType, type) == type || arg == ScriptRuntime.UNDEFINED) {
        return true;
    }
    System.err.println(arg + " does not fit in "+ argType + " " + type + " " + arg.getClass());
    new Throwable().printStackTrace();
    return false;
}
 
Example 8
Source File: CodeGenerator.java    From openjdk-8-source with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterTernaryNode(final TernaryNode ternaryNode) {
    final Expression test      = ternaryNode.getTest();
    final Expression trueExpr  = ternaryNode.getTrueExpression();
    final Expression falseExpr = ternaryNode.getFalseExpression();

    final Symbol symbol     = ternaryNode.getSymbol();
    final Label  falseLabel = new Label("ternary_false");
    final Label  exitLabel  = new Label("ternary_exit");

    Type widest = Type.widest(ternaryNode.getType(), Type.widest(trueExpr.getType(), falseExpr.getType()));
    if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
        widest = Type.OBJECT;
    }

    load(test, Type.BOOLEAN);
    // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17
    // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the
    // symmetry for the temporary slot for this TernaryNode. This is evidence that we assign types and explicit conversions
    // too early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
    // do this property. Then we never need any conversions in CodeGenerator
    method.ifeq(falseLabel);
    load(trueExpr, widest);
    method._goto(exitLabel);
    method.label(falseLabel);
    load(falseExpr, widest);
    method.label(exitLabel);
    method.store(symbol);

    return false;
}
 
Example 9
Source File: CodeGenerator.java    From openjdk-8 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterTernaryNode(final TernaryNode ternaryNode) {
    final Expression test      = ternaryNode.getTest();
    final Expression trueExpr  = ternaryNode.getTrueExpression();
    final Expression falseExpr = ternaryNode.getFalseExpression();

    final Symbol symbol     = ternaryNode.getSymbol();
    final Label  falseLabel = new Label("ternary_false");
    final Label  exitLabel  = new Label("ternary_exit");

    Type widest = Type.widest(ternaryNode.getType(), Type.widest(trueExpr.getType(), falseExpr.getType()));
    if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
        widest = Type.OBJECT;
    }

    load(test, Type.BOOLEAN);
    // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17
    // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the
    // symmetry for the temporary slot for this TernaryNode. This is evidence that we assign types and explicit conversions
    // too early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
    // do this property. Then we never need any conversions in CodeGenerator
    method.ifeq(falseLabel);
    load(trueExpr, widest);
    method._goto(exitLabel);
    method.label(falseLabel);
    load(falseExpr, widest);
    method.label(exitLabel);
    method.store(symbol);

    return false;
}
 
Example 10
Source File: BinaryNode.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
private static Type decideType(final Type lhsType, final Type rhsType) {
    // Compare this to getWidestOperationType() for ADD and ASSIGN_ADD cases. There's some similar logic, but these
    // are optimistic decisions, meaning that we don't have to treat boolean addition separately (as it'll become
    // int addition in the general case anyway), and that we also don't conservatively widen sums of ints to
    // longs, or sums of longs to doubles.
    if(isString(lhsType) || isString(rhsType)) {
        return Type.CHARSEQUENCE;
    }
    // NOTE: We don't have optimistic object-to-(int, long) conversions. Therefore, if any operand is an Object, we
    // bail out of optimism here and presume a conservative Object return value, as the object's ToPrimitive() can
    // end up returning either a number or a string, and their common supertype is Object, for better or worse.
    final Type widest = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
    return widest.isObject() ? Type.OBJECT : widest;
}
 
Example 11
Source File: BinaryNode.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private static Type decideType(final Type lhsType, final Type rhsType) {
    // Compare this to getWidestOperationType() for ADD and ASSIGN_ADD cases. There's some similar logic, but these
    // are optimistic decisions, meaning that we don't have to treat boolean addition separately (as it'll become
    // int addition in the general case anyway), and that we also don't conservatively widen sums of ints to
    // longs, or sums of longs to doubles.
    if(isString(lhsType) || isString(rhsType)) {
        return Type.CHARSEQUENCE;
    }
    // NOTE: We don't have optimistic object-to-(int, long) conversions. Therefore, if any operand is an Object, we
    // bail out of optimism here and presume a conservative Object return value, as the object's ToPrimitive() can
    // end up returning either a number or a string, and their common supertype is Object, for better or worse.
    final Type widest = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
    return widest.isObject() ? Type.OBJECT : widest;
}
 
Example 12
Source File: CompiledFunction.java    From openjdk-8-source with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Check whether a given method descriptor is compatible with this invocation.
 * It is compatible if the types are narrower than the invocation type so that
 * a semantically equivalent linkage can be performed.
 *
 * @param mt type to check against
 * @return true if types are compatible
 */
boolean typeCompatible(final MethodType mt) {
    final int wantedParamCount   = mt.parameterCount();
    final int existingParamCount = type.parameterCount();

    //if we are not examining a varargs type, the number of parameters must be the same
    if (wantedParamCount != existingParamCount && !isVarArgsType(mt)) {
        return false;
    }

    //we only go as far as the shortest array. the only chance to make this work if
    //parameters lengths do not match is if our type ends with a varargs argument.
    //then every trailing parameter in the given callsite can be folded into it, making
    //us compatible (albeit slower than a direct specialization)
    final int lastParamIndex = Math.min(wantedParamCount, existingParamCount);
    for (int i = 0; i < lastParamIndex; i++) {
        final Type w = Type.typeFor(mt.parameterType(i));
        final Type e = Type.typeFor(type.parameterType(i));

        //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
        //we also currently don't support boolean as a javascript function callsite type.
        //it will always box.
        if (w.isBoolean()) {
            return false;
        }

        //This callsite type has a vararg here. it will swallow all remaining args.
        //for consistency, check that it's the last argument
        if (e.isArray()) {
            return true;
        }

        //Our arguments must be at least as wide as the wanted one, if not wider
        if (Type.widest(w, e) != e) {
            //e.g. this invocation takes double and callsite says "object". reject. won't fit
            //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine
            return false;
        }
    }

    return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic.
}
 
Example 13
Source File: CompiledFunction.java    From nashorn with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Check whether a given method descriptor is compatible with this invocation.
 * It is compatible if the types are narrower than the invocation type so that
 * a semantically equivalent linkage can be performed.
 *
 * @param mt type to check against
 * @return
 */
boolean typeCompatible(final MethodType mt) {
    final Class<?>[] wantedParams   = mt.parameterArray();
    final Class<?>[] existingParams = type().parameterArray();

    //if we are not examining a varargs type, the number of parameters must be the same
    if (wantedParams.length != existingParams.length && !isVarArgsType(mt)) {
        return false;
    }

    //we only go as far as the shortest array. the only chance to make this work if
    //parameters lengths do not match is if our type ends with a varargs argument.
    //then every trailing parameter in the given callsite can be folded into it, making
    //us compatible (albeit slower than a direct specialization)
    final int lastParamIndex = Math.min(wantedParams.length, existingParams.length);
    for (int i = 0; i < lastParamIndex; i++) {
        final Type w = Type.typeFor(wantedParams[i]);
        final Type e = Type.typeFor(existingParams[i]);

        //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
        //we also currently don't support boolean as a javascript function callsite type.
        //it will always box.
        if (w.isBoolean()) {
            return false;
        }

        //This callsite type has a vararg here. it will swallow all remaining args.
        //for consistency, check that it's the last argument
        if (e.isArray()) {
            return true;
        }

        //Our arguments must be at least as wide as the wanted one, if not wider
        if (Type.widest(w, e) != e) {
            //e.g. this invocation takes double and callsite says "object". reject. won't fit
            //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine
            return false;
        }
    }

    return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic.
}
 
Example 14
Source File: ContinuousArrayData.java    From openjdk-jdk9 with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Get the widest element type of two arrays. This can be done faster in subclasses, but
 * this works for all ContinuousArrayDatas and for where more optimal checks haven't been
 * implemented.
 *
 * @param otherData another ContinuousArrayData
 * @return the widest boxed element type
 */
public ContinuousArrayData widest(final ContinuousArrayData otherData) {
    final Class<?> elementType = getElementType();
    return Type.widest(elementType, otherData.getElementType()) == elementType ? this : otherData;
}
 
Example 15
Source File: Symbol.java    From nashorn with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Returns true if calling {@link #setType(Type)} on this symbol would effectively change its type.
 * @param newType the new type to test for
 * @return true if setting this symbols type to a new value would effectively change its type.
 */
public boolean wouldChangeType(final Type newType) {
    return Type.widest(this.type, newType) != this.type;
}
 
Example 16
Source File: ContinuousArrayData.java    From hottub with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Get the widest element type of two arrays. This can be done faster in subclasses, but
 * this works for all ContinuousArrayDatas and for where more optimal checks haven't been
 * implemented.
 *
 * @param otherData another ContinuousArrayData
 * @return the widest boxed element type
 */
public ContinuousArrayData widest(final ContinuousArrayData otherData) {
    final Class<?> elementType = getElementType();
    return Type.widest(elementType, otherData.getElementType()) == elementType ? this : otherData;
}
 
Example 17
Source File: Symbol.java    From openjdk-8-source with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Returns true if calling {@link #setType(Type)} on this symbol would effectively change its type.
 * @param newType the new type to test for
 * @return true if setting this symbols type to a new value would effectively change its type.
 */
public boolean wouldChangeType(final Type newType) {
    return Type.widest(this.type, newType) != this.type;
}
 
Example 18
Source File: Symbol.java    From openjdk-8 with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Returns true if calling {@link #setType(Type)} on this symbol would effectively change its type.
 * @param newType the new type to test for
 * @return true if setting this symbols type to a new value would effectively change its type.
 */
public boolean wouldChangeType(final Type newType) {
    return Type.widest(this.type, newType) != this.type;
}
 
Example 19
Source File: ContinuousArrayData.java    From jdk8u_nashorn with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Get the widest element type of two arrays. This can be done faster in subclasses, but
 * this works for all ContinuousArrayDatas and for where more optimal checks haven't been
 * implemented.
 *
 * @param otherData another ContinuousArrayData
 * @return the widest boxed element type
 */
public ContinuousArrayData widest(final ContinuousArrayData otherData) {
    final Class<?> elementType = getElementType();
    return Type.widest(elementType, otherData.getElementType()) == elementType ? this : otherData;
}
 
Example 20
Source File: ContinuousArrayData.java    From TencentKona-8 with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Get the widest element type of two arrays. This can be done faster in subclasses, but
 * this works for all ContinuousArrayDatas and for where more optimal checks haven't been
 * implemented.
 *
 * @param otherData another ContinuousArrayData
 * @return the widest boxed element type
 */
public ContinuousArrayData widest(final ContinuousArrayData otherData) {
    final Class<?> elementType = getElementType();
    return Type.widest(elementType, otherData.getElementType()) == elementType ? this : otherData;
}