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

The following examples show how to use jdk.nashorn.internal.codegen.types.Type#isEquivalentTo() . 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: CodeGenerator.java    From openjdk-8-source with GNU General Public License v2.0 6 votes vote down vote up
@Override
public boolean enterASSIGN(final BinaryNode binaryNode) {
    final Expression lhs = binaryNode.lhs();
    final Expression rhs = binaryNode.rhs();

    final Type lhsType = lhs.getType();
    final Type rhsType = rhs.getType();

    if (!lhsType.isEquivalentTo(rhsType)) {
        //this is OK if scoped, only locals are wrong
    }

    new Store<BinaryNode>(binaryNode, lhs) {
        @Override
        protected void evaluate() {
            if ((lhs instanceof IdentNode) && !lhs.getSymbol().isScope()) {
                load(rhs, lhsType);
            } else {
                load(rhs);
            }
        }
    }.store();

    return false;
}
 
Example 2
Source File: CodeGenerator.java    From openjdk-8 with GNU General Public License v2.0 6 votes vote down vote up
@Override
public boolean enterASSIGN(final BinaryNode binaryNode) {
    final Expression lhs = binaryNode.lhs();
    final Expression rhs = binaryNode.rhs();

    final Type lhsType = lhs.getType();
    final Type rhsType = rhs.getType();

    if (!lhsType.isEquivalentTo(rhsType)) {
        //this is OK if scoped, only locals are wrong
    }

    new Store<BinaryNode>(binaryNode, lhs) {
        @Override
        protected void evaluate() {
            if ((lhs instanceof IdentNode) && !lhs.getSymbol().isScope()) {
                load(rhs, lhsType);
            } else {
                load(rhs);
            }
        }
    }.store();

    return false;
}
 
Example 3
Source File: CompiledFunction.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    if (csIsVarArg && isApplyToCall()) {
        return false; // apply2call function must be called with exact number of parameters
    }
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 4
Source File: MethodEmitter.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}
 
Example 5
Source File: CompiledFunction.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 6
Source File: MethodEmitter.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}
 
Example 7
Source File: CompiledFunction.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    if (csIsVarArg && isApplyToCall()) {
        return false; // apply2call function must be called with exact number of parameters
    }
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 8
Source File: MethodEmitter.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}
 
Example 9
Source File: CompiledFunction.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    if (csIsVarArg && isApplyToCall()) {
        return false; // apply2call function must be called with exact number of parameters
    }
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 10
Source File: MethodEmitter.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}
 
Example 11
Source File: CompiledFunction.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 12
Source File: MethodEmitter.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}
 
Example 13
Source File: CompiledFunction.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 14
Source File: MethodEmitter.java    From hottub with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}
 
Example 15
Source File: CompiledFunction.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
boolean matchesCallSite(final MethodType other, final boolean pickVarArg) {
    if (other.equals(this.callSiteType)) {
        return true;
    }
    final MethodType type  = type();
    final int fnParamCount = getParamCount(type);
    final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
    if (isVarArg) {
        return pickVarArg;
    }

    final int csParamCount = getParamCount(other);
    final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
    if (csIsVarArg && isApplyToCall()) {
        return false; // apply2call function must be called with exact number of parameters
    }
    final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type

    final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
    final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
    // We must match all incoming parameters, including "this". "this" will usually be Object, but there
    // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
    for(int i = 0; i < minParams; ++i) {
        final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
        final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
        if(!fnType.isEquivalentTo(csType)) {
            return false;
        }
    }

    // Must match any undefined parameters to Object type.
    for(int i = minParams; i < fnParamCountNoCallee; ++i) {
        if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
            return false;
        }
    }

    return true;
}
 
Example 16
Source File: MethodEmitter.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Pop element from stack, convert to given type
 *
 * @param to type to convert to
 *
 * @return the method emitter
 */
MethodEmitter convert(final Type to) {
    final Type from = peekType();
    final Type type = from.convert(method, to);
    if (type != null) {
        if (!from.isEquivalentTo(to)) {
            debug("convert", from, "->", to);
        }
        if (type != from) {
            final int l0 = stack.getTopLocalLoad();
            popType();
            pushType(type);
            // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
            // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
            // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
            // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
            // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
            // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
            // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
            // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
            // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
            // NOTE: as a more general observation, we could theoretically track the operations required to
            // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
            // We won't go there in the current system
            if(!from.isObject()) {
                stack.markLocalLoad(l0);
            }
        }
    }
    return this;
}