import jdk.nashorn.internal.codegen.types.Type; //导入方法依赖的package包/类
/**
* 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;
}