
org.mozilla.javascript.optimizer.DoubleLinker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rhino Show documentation
Show all versions of rhino Show documentation
Rhino is an open-source implementation of JavaScript written entirely in Java. It is typically
embedded into Java applications to provide scripting to end users.
The newest version!
package org.mozilla.javascript.optimizer;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.LinkRequest;
import jdk.dynalink.linker.LinkerServices;
import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.dynalink.linker.support.Guards;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ScriptRuntime;
/**
* This linker optimizes a suite of math operations when the LHS is a Double object, and the RHS (if
* any) is either a Double or an Integer. It avoids a gigantic set of "if...then" statements in
* ScriptRuntime for the generic case.
*/
@SuppressWarnings("AndroidJdkLibsChecker")
class DoubleLinker implements TypeBasedGuardingDynamicLinker {
@Override
public boolean canLinkType(Class> type) {
return Double.class.equals(type);
}
@Override
public GuardedInvocation getGuardedInvocation(LinkRequest req, LinkerServices svc)
throws Exception {
if (req.isCallSiteUnstable()) {
return null;
}
ParsedOperation op = new ParsedOperation(req.getCallSiteDescriptor().getOperation());
MethodHandle mh = null;
MethodHandle guard = null;
if (op.isNamespace(RhinoNamespace.MATH)) {
Object arg2 = null;
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mType = req.getCallSiteDescriptor().getMethodType();
if (req.getArguments().length > 1) {
arg2 = req.getArguments()[1];
}
if (op.isOperation(RhinoOperation.ADD) && arg2 instanceof Double) {
mh = lookup.findStatic(DoubleLinker.class, "add", mType);
MethodType guardType = mType.changeReturnType(Boolean.TYPE);
guard = lookup.findStatic(DoubleLinker.class, "testAdd", guardType);
} else if (op.isOperation(RhinoOperation.ADD) && arg2 instanceof Integer) {
mh = lookup.findStatic(DoubleLinker.class, "addInt", mType);
MethodType guardType = mType.changeReturnType(Boolean.TYPE);
guard = lookup.findStatic(DoubleLinker.class, "testAddInt", guardType);
} else if (op.isOperation(RhinoOperation.EQ, RhinoOperation.SHALLOWEQ)
&& arg2 instanceof Double) {
mh = lookup.findStatic(DoubleLinker.class, "eq", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwo", mType);
} else if (op.isOperation(RhinoOperation.EQ, RhinoOperation.SHALLOWEQ)
&& arg2 instanceof Integer) {
mh = lookup.findStatic(DoubleLinker.class, "eqInt", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwoInt", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_LT) && arg2 instanceof Double) {
mh = lookup.findStatic(DoubleLinker.class, "compareLT", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwo", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_GT) && arg2 instanceof Double) {
mh = lookup.findStatic(DoubleLinker.class, "compareGT", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwo", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_LE) && arg2 instanceof Double) {
mh = lookup.findStatic(DoubleLinker.class, "compareLE", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwo", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_GE) && arg2 instanceof Double) {
mh = lookup.findStatic(DoubleLinker.class, "compareGE", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwo", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_LT) && arg2 instanceof Integer) {
mh = lookup.findStatic(DoubleLinker.class, "compareLTInt", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwoInt", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_GT) && arg2 instanceof Integer) {
mh = lookup.findStatic(DoubleLinker.class, "compareGTInt", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwoInt", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_LE) && arg2 instanceof Integer) {
mh = lookup.findStatic(DoubleLinker.class, "compareLEInt", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwoInt", mType);
} else if (op.isOperation(RhinoOperation.COMPARE_GE) && arg2 instanceof Integer) {
mh = lookup.findStatic(DoubleLinker.class, "compareGEInt", mType);
guard = lookup.findStatic(DoubleLinker.class, "testTwoInt", mType);
} else if (op.isOperation(RhinoOperation.TOBOOLEAN)) {
mh = lookup.findStatic(DoubleLinker.class, "toBoolean", mType);
guard = Guards.getInstanceOfGuard(Double.class);
} else if (op.isOperation(RhinoOperation.TONUMBER)) {
mh = lookup.findStatic(DoubleLinker.class, "toNumber", mType);
guard = Guards.getInstanceOfGuard(Double.class);
} else if (op.isOperation(RhinoOperation.TONUMERIC)) {
mh = lookup.findStatic(DoubleLinker.class, "toNumeric", mType);
guard = Guards.getInstanceOfGuard(Double.class);
} else if (op.isOperation(RhinoOperation.TOINT32)) {
mh = lookup.findStatic(DoubleLinker.class, "toInt32", mType);
guard = Guards.getInstanceOfGuard(Double.class);
} else if (op.isOperation(RhinoOperation.TOUINT32)) {
mh = lookup.findStatic(DoubleLinker.class, "toUint32", mType);
guard = Guards.getInstanceOfGuard(Double.class);
}
}
if (mh != null) {
assert guard != null;
if (DefaultLinker.DEBUG) {
System.out.println(op + " double operation");
}
return new GuardedInvocation(mh, guard);
}
return null;
}
@SuppressWarnings("unused")
private static boolean testAdd(Object lval, Object rval, Context cx) {
return lval instanceof Double && rval instanceof Double;
}
@SuppressWarnings("unused")
private static Object add(Object lval, Object rval, Context cx) {
return ((Double) lval) + ((Double) rval);
}
@SuppressWarnings("unused")
private static boolean testAddInt(Object lval, Object rval, Context cx) {
return lval instanceof Double && rval instanceof Integer;
}
@SuppressWarnings("unused")
private static Object addInt(Object lval, Object rval, Context cx) {
return (Double) lval + (Integer) rval;
}
@SuppressWarnings("unused")
private static boolean testTwo(Object lval, Object rval) {
return lval instanceof Double && rval instanceof Double;
}
@SuppressWarnings("unused")
private static boolean testTwoInt(Object lval, Object rval) {
return lval instanceof Double && rval instanceof Integer;
}
@SuppressWarnings("unused")
private static boolean eq(Object lval, Object rval) {
return ((Double) lval).doubleValue() == ((Double) rval).doubleValue();
}
@SuppressWarnings("unused")
private static boolean eqInt(Object lval, Object rval) {
return ((Double) lval) == ((Integer) rval).doubleValue();
}
@SuppressWarnings("unused")
private static boolean compareLT(Object lval, Object rval) {
return ((Double) lval) < ((Double) rval);
}
@SuppressWarnings("unused")
private static boolean compareGT(Object lval, Object rval) {
return ((Double) lval) > ((Double) rval);
}
@SuppressWarnings("unused")
private static boolean compareLE(Object lval, Object rval) {
return ((Double) lval) <= ((Double) rval);
}
@SuppressWarnings("unused")
private static boolean compareGE(Object lval, Object rval) {
return ((Double) lval) >= ((Double) rval);
}
@SuppressWarnings("unused")
private static boolean compareLTInt(Object lval, Object rval) {
return ((Double) lval) < ((Integer) rval).doubleValue();
}
@SuppressWarnings("unused")
private static boolean compareGTInt(Object lval, Object rval) {
return ((Double) lval) > ((Integer) rval).doubleValue();
}
@SuppressWarnings("unused")
private static boolean compareLEInt(Object lval, Object rval) {
return ((Double) lval) <= ((Integer) rval).doubleValue();
}
@SuppressWarnings("unused")
private static boolean compareGEInt(Object lval, Object rval) {
return ((Double) lval) >= ((Integer) rval).doubleValue();
}
@SuppressWarnings("unused")
private static double toNumber(Object raw) {
return (Double) raw;
}
@SuppressWarnings("unused")
private static Number toNumeric(Object raw) {
return (Double) raw;
}
@SuppressWarnings("unused")
private static boolean toBoolean(Object raw) {
double v = (Double) raw;
if (Double.isNaN(v)) {
return false;
}
return v != 0.0;
}
@SuppressWarnings("unused")
private static int toInt32(Object raw) {
return ScriptRuntime.toInt32(((Double) raw).doubleValue());
}
@SuppressWarnings("unused")
private static long toUint32(Object raw) {
return ScriptRuntime.toUint32(((Double) raw).doubleValue());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy