src/jdk/nashorn/internal/runtime/WithObject.java

Print this page

        

*** 28,88 **** import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; - /** * This class supports the handling of scope in a with body. * */ public final class WithObject extends ScriptObject implements Scope { ! private static final MethodHandle WITHEXPRESSIONFILTER = findOwnMH("withFilterExpression", Object.class, Object.class); private static final MethodHandle WITHSCOPEFILTER = findOwnMH("withFilterScope", Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression", Object.class, Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_FN = findOwnMH("bindToExpression", Object.class, ScriptFunction.class, Object.class); /** With expression object. */ ! private final Object expression; /** * Constructor * * @param scope scope object * @param expression with expression */ ! WithObject(final ScriptObject scope, final Object expression) { super(scope, null); setIsScope(); this.expression = expression; } /** * Delete a property based on a key. * @param key Any valid JavaScript value. * @param strict strict mode execution. * @return True if deleted. */ @Override public boolean delete(final Object key, final boolean strict) { ! if (expression instanceof ScriptObject) { ! final ScriptObject self = (ScriptObject)expression; final String propName = JSType.toString(key); final FindProperty find = self.findProperty(propName, true); if (find != null) { return self.delete(propName, strict); } - } return false; } --- 28,87 ---- import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; + import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; /** * This class supports the handling of scope in a with body. * */ public final class WithObject extends ScriptObject implements Scope { ! private static final MethodHandle WITHEXPRESSIONGUARD = findOwnMH("withExpressionGuard", boolean.class, Object.class, PropertyMap.class, SwitchPoint.class); private static final MethodHandle WITHEXPRESSIONFILTER = findOwnMH("withFilterExpression", Object.class, Object.class); private static final MethodHandle WITHSCOPEFILTER = findOwnMH("withFilterScope", Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression", Object.class, Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_FN = findOwnMH("bindToExpression", Object.class, ScriptFunction.class, Object.class); /** With expression object. */ ! private final ScriptObject expression; /** * Constructor * * @param scope scope object * @param expression with expression */ ! WithObject(final ScriptObject scope, final ScriptObject expression) { super(scope, null); setIsScope(); this.expression = expression; } + /** * Delete a property based on a key. * @param key Any valid JavaScript value. * @param strict strict mode execution. * @return True if deleted. */ @Override public boolean delete(final Object key, final boolean strict) { ! final ScriptObject self = expression; final String propName = JSType.toString(key); final FindProperty find = self.findProperty(propName, true); if (find != null) { return self.delete(propName, strict); } return false; }
*** 103,114 **** } else { isNamedOperation = false; name = null; } ! if (expression instanceof ScriptObject) { ! self = (ScriptObject)expression; if (isNamedOperation) { find = self.findProperty(name, true); } if (find != null) { --- 102,112 ---- } else { isNamedOperation = false; name = null; } ! self = expression; if (isNamedOperation) { find = self.findProperty(name, true); } if (find != null) {
*** 116,134 **** if (link != null) { return fixExpressionCallSite(ndesc, link); } } - } final ScriptObject scope = getProto(); if (isNamedOperation) { find = scope.findProperty(name, true); } if (find != null) { ! return fixScopeCallSite(scope.lookup(desc, request)); } // the property is not found - now check for // __noSuchProperty__ and __noSuchMethod__ in expression if (self != null) { --- 114,131 ---- if (link != null) { return fixExpressionCallSite(ndesc, link); } } final ScriptObject scope = getProto(); if (isNamedOperation) { find = scope.findProperty(name, true); } if (find != null) { ! return fixScopeCallSite(scope.lookup(desc, request), name); } // the property is not found - now check for // __noSuchProperty__ and __noSuchMethod__ in expression if (self != null) {
*** 176,186 **** // still not found, may be scope can handle with it's own // __noSuchProperty__, __noSuchMethod__ etc. link = scope.lookup(desc, request); if (link != null) { ! return fixScopeCallSite(link); } return null; } --- 173,183 ---- // still not found, may be scope can handle with it's own // __noSuchProperty__, __noSuchMethod__ etc. link = scope.lookup(desc, request); if (link != null) { ! return fixScopeCallSite(link, name); } return null; }
*** 195,210 **** * * @return FindPropertyData or null if not found. */ @Override FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) { ! if (expression instanceof ScriptObject) { ! final FindProperty exprProperty = ((ScriptObject)expression).findProperty(key, deep, stopOnNonScope, start); ! if(exprProperty != null) { return exprProperty; } - } return super.findProperty(key, deep, stopOnNonScope, start); } @Override public void setSplitState(final int state) { --- 192,205 ---- * * @return FindPropertyData or null if not found. */ @Override FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) { ! final FindProperty exprProperty = expression.findProperty(key, deep, stopOnNonScope, start); ! if (exprProperty != null) { return exprProperty; } return super.findProperty(key, deep, stopOnNonScope, start); } @Override public void setSplitState(final int state) {
*** 218,237 **** /** * Get first parent scope that is not an instance of WithObject. */ private Scope getNonWithParent() { ! ScriptObject proto = getProto(); while (proto != null && proto instanceof WithObject) { ! proto = proto.getProto(); } assert proto instanceof Scope : "with scope without parent scope"; return (Scope) proto; } private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { // The receiver may be an Object or a ScriptObject. final MethodType invType = link.getInvocation().type(); final MethodType newInvType = invType.changeParameterType(0, filter.type().returnType()); return link.asType(newInvType); --- 213,233 ---- /** * Get first parent scope that is not an instance of WithObject. */ private Scope getNonWithParent() { ! ScriptObject proto = getParentScope(); while (proto != null && proto instanceof WithObject) { ! proto = ((WithObject)proto).getParentScope(); } assert proto instanceof Scope : "with scope without parent scope"; return (Scope) proto; } + private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { // The receiver may be an Object or a ScriptObject. final MethodType invType = link.getInvocation().type(); final MethodType newInvType = invType.changeParameterType(0, filter.type().returnType()); return link.asType(newInvType);
*** 254,266 **** linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)), // No clever things for the guard -- it is still identically filtered. filterGuard(link, WITHEXPRESSIONFILTER)); } ! private static GuardedInvocation fixScopeCallSite(final GuardedInvocation link) { final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER); ! return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), filterGuard(newLink, WITHSCOPEFILTER)); } private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) { final MethodHandle test = link.getGuard(); return test == null ? null : filter(test, filter); --- 250,266 ---- linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)), // No clever things for the guard -- it is still identically filtered. filterGuard(link, WITHEXPRESSIONFILTER)); } ! private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) { final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER); ! return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), ! MH.guardWithTest( ! expressionGuard(name), ! filterGuard(newLink, WITHSCOPEFILTER), ! MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class))); } private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) { final MethodHandle test = link.getGuard(); return test == null ? null : filter(test, filter);
*** 277,296 **** */ public static Object withFilterExpression(final Object receiver) { return ((WithObject)receiver).expression; } - @SuppressWarnings("unused") private static Object bindToExpression(final Object fn, final Object receiver) { return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn; } private static Object bindToExpression(final ScriptFunction fn, final Object receiver) { return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]); } /** * Drops the WithObject wrapper from the scope. * @param receiver WithObject wrapper. * @return The with scope. */ --- 277,306 ---- */ public static Object withFilterExpression(final Object receiver) { return ((WithObject)receiver).expression; } @SuppressWarnings("unused") private static Object bindToExpression(final Object fn, final Object receiver) { return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn; } private static Object bindToExpression(final ScriptFunction fn, final Object receiver) { return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]); } + private MethodHandle expressionGuard(final String name) { + final PropertyMap map = expression.getMap(); + final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name); + return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp); + } + + @SuppressWarnings("unused") + private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) { + return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated()); + } + /** * Drops the WithObject wrapper from the scope. * @param receiver WithObject wrapper. * @return The with scope. */
*** 300,312 **** /** * Get the with expression for this {@code WithObject} * @return the with expression */ ! public Object getExpression() { return expression; } private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); } } --- 310,326 ---- /** * Get the with expression for this {@code WithObject} * @return the with expression */ ! public ScriptObject getExpression() { return expression; } + public ScriptObject getParentScope() { + return getProto(); + } + private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); } }