Java 类java.lang.invoke.SwitchPoint 实例源码
项目:OpenJSharp
文件:ContinuousArrayData.java
/**
* Return a fast linked array getter, or null if we have to dispatch to super class
* @param desc descriptor
* @param request link request
* @return invocation or null if needs to be sent to slow relink
*/
@Override
public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType callType = desc.getMethodType();
final Class<?> indexType = callType.parameterType(1);
final Class<?> returnType = callType.returnType();
if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
final Object[] args = request.getArguments();
final int index = (int)args[args.length - 1];
if (has(index)) {
final MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT;
MethodHandle getElement = getElementGetter(returnType, programPoint);
if (getElement != null) {
getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz)));
final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class);
}
}
}
return null;
}
项目:OpenJSharp
文件:ContinuousArrayData.java
/**
* Return a fast linked array setter, or null if we have to dispatch to super class
* @param desc descriptor
* @param request link request
* @return invocation or null if needs to be sent to slow relink
*/
@Override
public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
final MethodType callType = desc.getMethodType();
final Class<?> indexType = callType.parameterType(1);
final Class<?> elementType = callType.parameterType(2);
if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
final Object[] args = request.getArguments();
final int index = (int)args[args.length - 2];
if (hasRoomFor(index)) {
MethodHandle setElement = getElementSetter(elementType); //Z(continuousarraydata, int, int), return true if successful
if (setElement != null) {
//else we are dealing with a wider type than supported by this callsite
MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
getArray = MH.asType(getArray, getArray.type().changeReturnType(getClass()));
setElement = MH.filterArguments(setElement, 0, getArray);
final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
return new GuardedInvocation(setElement, guard, (SwitchPoint)null, ClassCastException.class); //CCE if not a scriptObject anymore
}
}
}
return null;
}
项目:OpenJSharp
文件:ScriptObject.java
/**
* Find the appropriate GETINDEX method for an invoke dynamic call.
*
* @param desc the call site descriptor
* @param request the link request
*
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType callType = desc.getMethodType();
final Class<?> returnType = callType.returnType();
final Class<?> returnClass = returnType.isPrimitive() ? returnType : Object.class;
final Class<?> keyClass = callType.parameterType(1);
final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
final String name;
if (returnClass.isPrimitive()) {
//turn e.g. get with a double into getDouble
final String returnTypeName = returnClass.getName();
name = "get" + Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
} else {
name = "get";
}
final MethodHandle mh = findGetIndexMethodHandle(returnClass, name, keyClass, desc);
return new GuardedInvocation(mh, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
项目:OpenJSharp
文件:CompiledFunction.java
/**
* Returns a pair of an invocation created with a passed-in supplier and a non-invalidated switch point for
* optimistic assumptions (or null for the switch point if the function can not be deoptimized). While the method
* makes a best effort to return a non-invalidated switch point (compensating for possible deoptimizing
* recompilation happening on another thread) it is still possible that by the time this method returns the
* switchpoint has been invalidated by a {@code RewriteException} triggered on another thread for this function.
* This is not a problem, though, as these switch points are always used to produce call sites that fall back to
* relinking when they are invalidated, and in this case the execution will end up here again. What this method
* basically does is minimize such busy-loop relinking while the function is being recompiled on a different thread.
* @param invocationSupplier the supplier that constructs the actual invocation method handle; should use the
* {@code CompiledFunction} method itself in some capacity.
* @return a tuple object containing the method handle as created by the supplier and an optimistic assumptions
* switch point that is guaranteed to not have been invalidated before the call to this method (or null if the
* function can't be further deoptimized).
*/
private synchronized HandleAndAssumptions getValidOptimisticInvocation(final Supplier<MethodHandle> invocationSupplier) {
for(;;) {
final MethodHandle handle = invocationSupplier.get();
final SwitchPoint assumptions = canBeDeoptimized() ? optimismInfo.optimisticAssumptions : null;
if(assumptions != null && assumptions.hasBeenInvalidated()) {
// We can be in a situation where one thread is in the middle of a deoptimizing compilation when we hit
// this and thus, it has invalidated the old switch point, but hasn't created the new one yet. Note that
// the behavior of invalidating the old switch point before recompilation, and only creating the new one
// after recompilation is by design. If we didn't wait here for the recompilation to complete, we would
// be busy looping through the fallback path of the invalidated switch point, relinking the call site
// again with the same invalidated switch point, invoking the fallback, etc. stealing CPU cycles from
// the recompilation task we're dependent on. This can still happen if the switch point gets invalidated
// after we grabbed it here, in which case we'll indeed do one busy relink immediately.
try {
wait();
} catch (final InterruptedException e) {
// Intentionally ignored. There's nothing meaningful we can do if we're interrupted
}
} else {
return new HandleAndAssumptions(handle, assumptions);
}
}
}
项目:OpenJSharp
文件:CompiledFunction.java
private static void relinkComposableInvoker(final CallSite cs, final CompiledFunction inv, final boolean constructor) {
final HandleAndAssumptions handleAndAssumptions = inv.getValidOptimisticInvocation(new Supplier<MethodHandle>() {
@Override
public MethodHandle get() {
return inv.getInvokerOrConstructor(constructor);
}
});
final MethodHandle handle = handleAndAssumptions.handle;
final SwitchPoint assumptions = handleAndAssumptions.assumptions;
final MethodHandle target;
if(assumptions == null) {
target = handle;
} else {
final MethodHandle relink = MethodHandles.insertArguments(RELINK_COMPOSABLE_INVOKER, 0, cs, inv, constructor);
target = assumptions.guardWithTest(handle, MethodHandles.foldArguments(cs.dynamicInvoker(), relink));
}
cs.setTarget(target.asType(cs.type()));
}
项目:OpenJSharp
文件:CompiledFunction.java
boolean requestRecompile(final RewriteException e) {
final Type retType = e.getReturnType();
final Type previousFailedType = invalidatedProgramPoints.put(e.getProgramPoint(), retType);
if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) {
final StackTraceElement[] stack = e.getStackTrace();
final String functionId = stack.length == 0 ?
data.getName() :
stack[0].getClassName() + "." + stack[0].getMethodName();
log.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise.");
return false;
}
SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions });
return true;
}
项目:OpenJSharp
文件:GuardedInvocation.java
/**
* Add a switchpoint to this guarded invocation
* @param newSwitchPoint new switchpoint, or null for nop
* @return new guarded invocation with the extra switchpoint
*/
public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) {
if (newSwitchPoint == null) {
return this;
}
final SwitchPoint[] newSwitchPoints;
if (switchPoints != null) {
newSwitchPoints = new SwitchPoint[switchPoints.length + 1];
System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length);
newSwitchPoints[switchPoints.length] = newSwitchPoint;
} else {
newSwitchPoints = new SwitchPoint[] { newSwitchPoint };
}
return new GuardedInvocation(invocation, guard, newSwitchPoints, exception);
}
项目:openjdk-jdk10
文件:ContinuousArrayData.java
/**
* Return a fast linked array getter, or null if we have to dispatch to super class
* @param desc descriptor
* @param request link request
* @return invocation or null if needs to be sent to slow relink
*/
@Override
public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType callType = desc.getMethodType();
final Class<?> indexType = callType.parameterType(1);
final Class<?> returnType = callType.returnType();
if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
final Object[] args = request.getArguments();
final int index = (int)args[args.length - 1];
if (has(index)) {
final MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT;
MethodHandle getElement = getElementGetter(returnType, programPoint);
if (getElement != null) {
getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz)));
final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class);
}
}
}
return null;
}
项目:openjdk-jdk10
文件:ContinuousArrayData.java
/**
* Return a fast linked array setter, or null if we have to dispatch to super class
* @param desc descriptor
* @param request link request
* @return invocation or null if needs to be sent to slow relink
*/
@Override
public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
final MethodType callType = desc.getMethodType();
final Class<?> indexType = callType.parameterType(1);
final Class<?> elementType = callType.parameterType(2);
if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
final Object[] args = request.getArguments();
final int index = (int)args[args.length - 2];
if (hasRoomFor(index)) {
MethodHandle setElement = getElementSetter(elementType); //Z(continuousarraydata, int, int), return true if successful
if (setElement != null) {
//else we are dealing with a wider type than supported by this callsite
MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
getArray = MH.asType(getArray, getArray.type().changeReturnType(getClass()));
setElement = MH.filterArguments(setElement, 0, getArray);
final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
return new GuardedInvocation(setElement, guard, (SwitchPoint)null, ClassCastException.class); //CCE if not a scriptObject anymore
}
}
}
return null;
}
项目:openjdk-jdk10
文件:ScriptObject.java
/**
* Find the appropriate GETINDEX method for an invoke dynamic call.
*
* @param desc the call site descriptor
* @param request the link request
*
* @return GuardedInvocation to be invoked at call site.
*/
protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
final MethodType callType = desc.getMethodType();
final Class<?> returnType = callType.returnType();
final Class<?> returnClass = returnType.isPrimitive() ? returnType : Object.class;
final Class<?> keyClass = callType.parameterType(1);
final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
final String name;
if (returnClass.isPrimitive()) {
//turn e.g. get with a double into getDouble
final String returnTypeName = returnClass.getName();
name = "get" + Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
} else {
name = "get";
}
final MethodHandle mh = findGetIndexMethodHandle(returnClass, name, keyClass, desc);
return new GuardedInvocation(mh, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
项目:openjdk-jdk10
文件:ScriptObject.java
/**
* Get a switch point for a property with the given {@code name} that will be invalidated when
* the property definition is changed in this object's prototype chain. Returns {@code null} if
* the property is defined in this object itself.
*
* @param name the property name
* @param owner the property owner, null if property is not defined
* @return a SwitchPoint or null
*/
public final SwitchPoint[] getProtoSwitchPoints(final String name, final ScriptObject owner) {
if (owner == this || getProto() == null) {
return null;
}
final List<SwitchPoint> switchPoints = new ArrayList<>();
for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
final ScriptObject parent = obj.getProto();
parent.getMap().addListener(name, obj.getMap());
final SwitchPoint sp = parent.getMap().getSharedProtoSwitchPoint();
if (sp != null && !sp.hasBeenInvalidated()) {
switchPoints.add(sp);
}
}
switchPoints.add(getMap().getSwitchPoint(name));
return switchPoints.toArray(new SwitchPoint[0]);
}
项目:openjdk-jdk10
文件:CompiledFunction.java
/**
* Returns a pair of an invocation created with a passed-in supplier and a non-invalidated switch point for
* optimistic assumptions (or null for the switch point if the function can not be deoptimized). While the method
* makes a best effort to return a non-invalidated switch point (compensating for possible deoptimizing
* recompilation happening on another thread) it is still possible that by the time this method returns the
* switchpoint has been invalidated by a {@code RewriteException} triggered on another thread for this function.
* This is not a problem, though, as these switch points are always used to produce call sites that fall back to
* relinking when they are invalidated, and in this case the execution will end up here again. What this method
* basically does is minimize such busy-loop relinking while the function is being recompiled on a different thread.
* @param invocationSupplier the supplier that constructs the actual invocation method handle; should use the
* {@code CompiledFunction} method itself in some capacity.
* @return a tuple object containing the method handle as created by the supplier and an optimistic assumptions
* switch point that is guaranteed to not have been invalidated before the call to this method (or null if the
* function can't be further deoptimized).
*/
private synchronized HandleAndAssumptions getValidOptimisticInvocation(final Supplier<MethodHandle> invocationSupplier) {
for(;;) {
final MethodHandle handle = invocationSupplier.get();
final SwitchPoint assumptions = canBeDeoptimized() ? optimismInfo.optimisticAssumptions : null;
if(assumptions != null && assumptions.hasBeenInvalidated()) {
// We can be in a situation where one thread is in the middle of a deoptimizing compilation when we hit
// this and thus, it has invalidated the old switch point, but hasn't created the new one yet. Note that
// the behavior of invalidating the old switch point before recompilation, and only creating the new one
// after recompilation is by design. If we didn't wait here for the recompilation to complete, we would
// be busy looping through the fallback path of the invalidated switch point, relinking the call site
// again with the same invalidated switch point, invoking the fallback, etc. stealing CPU cycles from
// the recompilation task we're dependent on. This can still happen if the switch point gets invalidated
// after we grabbed it here, in which case we'll indeed do one busy relink immediately.
try {
wait();
} catch (final InterruptedException e) {
// Intentionally ignored. There's nothing meaningful we can do if we're interrupted
}
} else {
return new HandleAndAssumptions(handle, assumptions);
}
}
}
项目:openjdk-jdk10
文件:CompiledFunction.java
private static void relinkComposableInvoker(final CallSite cs, final CompiledFunction inv, final boolean constructor) {
final HandleAndAssumptions handleAndAssumptions = inv.getValidOptimisticInvocation(new Supplier<MethodHandle>() {
@Override
public MethodHandle get() {
return inv.getInvokerOrConstructor(constructor);
}
});
final MethodHandle handle = handleAndAssumptions.handle;
final SwitchPoint assumptions = handleAndAssumptions.assumptions;
final MethodHandle target;
if(assumptions == null) {
target = handle;
} else {
final MethodHandle relink = MethodHandles.insertArguments(RELINK_COMPOSABLE_INVOKER, 0, cs, inv, constructor);
target = assumptions.guardWithTest(handle, MethodHandles.foldArguments(cs.dynamicInvoker(), relink));
}
cs.setTarget(target.asType(cs.type()));
}
项目:openjdk-jdk10
文件:CompiledFunction.java
boolean requestRecompile(final RewriteException e) {
final Type retType = e.getReturnType();
final Type previousFailedType = invalidatedProgramPoints.put(e.getProgramPoint(), retType);
if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) {
final StackTraceElement[] stack = e.getStackTrace();
final String functionId = stack.length == 0 ?
data.getName() :
stack[0].getClassName() + "." + stack[0].getMethodName();
log.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise.");
return false;
}
SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions });
return true;
}
项目:openjdk-jdk10
文件:GuardedInvocation.java
/**
* Create a new guarded invocation with an added switch point.
* @param newSwitchPoint new switch point. Can be null in which case this
* method return the current guarded invocation with no changes.
* @return a guarded invocation with the added switch point.
*/
public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) {
if (newSwitchPoint == null) {
return this;
}
final SwitchPoint[] newSwitchPoints;
if (switchPoints != null) {
newSwitchPoints = new SwitchPoint[switchPoints.length + 1];
System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length);
newSwitchPoints[switchPoints.length] = newSwitchPoint;
} else {
newSwitchPoints = new SwitchPoint[] { newSwitchPoint };
}
return new GuardedInvocation(invocation, guard, newSwitchPoints, exception);
}
项目:OpenJSharp
文件:Global.java
private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
SwitchPoint switchPoint = lexicalScopeSwitchPoint;
if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
}
return switchPoint;
}
项目:OpenJSharp
文件:Global.java
/**
* Given a builtin object, traverse its properties recursively and associate them with a name that
* will be a key to their invalidation switchpoint.
* @param name name for key
* @param func builtin script object
*/
private void tagBuiltinProperties(final String name, final ScriptObject func) {
SwitchPoint sp = context.getBuiltinSwitchPoint(name);
if (sp == null) {
sp = context.newBuiltinSwitchPoint(name);
}
//get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
//one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
prop.setBuiltinSwitchPoint(sp);
}
}
项目:OpenJSharp
文件:GlobalConstants.java
private Access getOrCreateSwitchPoint(final String name) {
Access acc = map.get(name);
if (acc != null) {
return acc;
}
final SwitchPoint sp = new SwitchPoint();
map.put(name, acc = new Access(name, sp));
return acc;
}
项目:OpenJSharp
文件:AccessorProperty.java
@SuppressWarnings("unused")
private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) {
if (!property.builtinSwitchPoint.hasBeenInvalidated()) {
SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint });
}
return obj;
}
项目:OpenJSharp
文件:Context.java
/**
* Create a new builtin switchpoint and return it
* @param name key name
* @return new builtin switchpoint
*/
public SwitchPoint newBuiltinSwitchPoint(final String name) {
assert builtinSwitchPoints.get(name) == null;
final SwitchPoint sp = new BuiltinSwitchPoint();
builtinSwitchPoints.put(name, sp);
return sp;
}
项目:OpenJSharp
文件:ScriptObject.java
private SwitchPoint findBuiltinSwitchPoint(final String key) {
for (ScriptObject myProto = getProto(); myProto != null; myProto = myProto.getProto()) {
final Property prop = myProto.getMap().findProperty(key);
if (prop != null) {
final SwitchPoint sp = prop.getBuiltinSwitchPoint();
if (sp != null && !sp.hasBeenInvalidated()) {
return sp;
}
}
}
return null;
}
项目:OpenJSharp
文件:ScriptObject.java
/**
* Get a switch point for a property with the given {@code name} that will be invalidated when
* the property definition is changed in this object's prototype chain. Returns {@code null} if
* the property is defined in this object itself.
*
* @param name the property name
* @param owner the property owner, null if property is not defined
* @return a SwitchPoint or null
*/
public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
if (owner == this || getProto() == null) {
return null;
}
for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
final ScriptObject parent = obj.getProto();
parent.getMap().addListener(name, obj.getMap());
}
return getMap().getSwitchPoint(name);
}
项目:OpenJSharp
文件:SetMethodCreator.java
/**
* Composes from its components an actual guarded invocation that represents the dynamic setter method for the property.
* @return the composed guarded invocation that represents the dynamic setter method for the property.
*/
GuardedInvocation createGuardedInvocation() {
// getGuard() and getException() either both return null, or neither does. The reason for that is that now
// getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to
// relink on ClassCastException.
final boolean explicitInstanceOfCheck = NashornGuards.explicitInstanceOfCheck(desc, request);
return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck),
(SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
项目:OpenJSharp
文件:SetMethodCreator.java
private SetMethod createSetMethod(final SwitchPoint builtinSwitchPoint) {
if (find != null) {
return createExistingPropertySetter();
}
checkStrictCreateNewVariable();
if (sobj.isScope()) {
return createGlobalPropertySetter();
}
return createNewPropertySetter(builtinSwitchPoint);
}
项目:OpenJSharp
文件:SetMethodCreator.java
private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) {
final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint);
final PropertyListeners listeners = map.getListeners();
if (listeners != null) {
listeners.propertyAdded(sm.property);
}
return sm;
}
项目:OpenJSharp
文件:SetMethodCreator.java
private SetMethod createNewSetter(final Property property, final SwitchPoint builtinSwitchPoint) {
property.setBuiltinSwitchPoint(builtinSwitchPoint);
final PropertyMap oldMap = getMap();
final PropertyMap newMap = getNewMap(property);
final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
//fast type specific setter
final MethodHandle fastSetter = property.getSetter(type, newMap); //0 sobj, 1 value, slot folded for spill property already
//slow setter, that calls ScriptObject.set with appropraite type and key name
MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
slowSetter = MH.insertArguments(slowSetter, 1, name);
slowSetter = MH.asType(slowSetter, slowSetter.type().changeParameterType(0, Object.class));
assert slowSetter.type().equals(fastSetter.type()) : "slow=" + slowSetter + " != fast=" + fastSetter;
//cas map used as guard, if true that means we can do the set fast
MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
casMap = MH.dropArguments(casMap, 1, type);
casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
final MethodHandle casGuard = MH.guardWithTest(casMap, fastSetter, slowSetter);
//outermost level needs an extendable check. if object can be extended, guard is true and
//we can run the cas setter. The setter goes to "nop" VOID_RETURN if false or throws an
//exception if we are in strict mode and object is not extensible
MethodHandle extCheck = MH.insertArguments(ScriptObject.EXTENSION_CHECK, 1, isStrict, name);
extCheck = MH.asType(extCheck, extCheck.type().changeParameterType(0, Object.class));
extCheck = MH.dropArguments(extCheck, 1, type);
MethodHandle nop = JSType.VOID_RETURN.methodHandle();
nop = MH.dropArguments(nop, 0, Object.class, type);
return new SetMethod(MH.asType(MH.guardWithTest(extCheck, casGuard, nop), fastSetter.type()), property);
}
项目:OpenJSharp
文件:PropertyMap.java
/**
* Indicate that a prototype property has changed.
*
* @param property {@link Property} to invalidate.
*/
synchronized void invalidateProtoGetSwitchPoint(final Property property) {
if (protoGetSwitches != null) {
final String key = property.getKey();
final SwitchPoint sp = protoGetSwitches.get(key);
if (sp != null) {
protoGetSwitches.remove(key);
if (Context.DEBUG) {
protoInvalidations++;
}
SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
}
}
}
项目:OpenJSharp
文件:PropertyMap.java
/**
* Indicate that proto itself has changed in hierarchy somewhere.
*/
synchronized void invalidateAllProtoGetSwitchPoints() {
if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) {
if (Context.DEBUG) {
protoInvalidations += protoGetSwitches.size();
}
SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()]));
protoGetSwitches.clear();
}
}
项目:OpenJSharp
文件:GuardedInvocation.java
/**
* Returns true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
* @return true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
*/
public boolean hasBeenInvalidated() {
if (switchPoints == null) {
return false;
}
for (final SwitchPoint sp : switchPoints) {
if (sp.hasBeenInvalidated()) {
return true;
}
}
return false;
}
项目:OpenJSharp
文件:GuardedInvocation.java
/**
* Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
* @param switchpointFallback the fallback method handle in case switchpoint is invalidated.
* @param guardFallback the fallback method handle in case guard returns false.
* @param catchFallback the fallback method in case the exception handler triggers
* @return a composite method handle.
*/
public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) {
final MethodHandle guarded =
guard == null ?
invocation :
MethodHandles.guardWithTest(
guard,
invocation,
guardFallback);
final MethodHandle catchGuarded =
exception == null ?
guarded :
MH.catchException(
guarded,
exception,
MethodHandles.dropArguments(
catchFallback,
0,
exception));
if (switchPoints == null) {
return catchGuarded;
}
MethodHandle spGuarded = catchGuarded;
for (final SwitchPoint sp : switchPoints) {
spGuarded = sp.guardWithTest(spGuarded, switchpointFallback);
}
return spGuarded;
}
项目:openjdk-jdk10
文件:Global.java
private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
SwitchPoint switchPoint = lexicalScopeSwitchPoint;
if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
switchPoint = lexicalScopeSwitchPoint = new SwitchPoint();
}
return switchPoint;
}
项目:openjdk-jdk10
文件:Global.java
/**
* Given a builtin object, traverse its properties recursively and associate them with a name that
* will be a key to their invalidation switchpoint.
* @param name name for key
* @param func builtin script object
*/
private void tagBuiltinProperties(final String name, final ScriptObject func) {
SwitchPoint sp = context.getBuiltinSwitchPoint(name);
if (sp == null) {
sp = context.newBuiltinSwitchPoint(name);
}
//get all builtin properties in this builtin object and register switchpoints keyed on the propery name,
//one overwrite destroys all for now, e.g. Function.prototype.apply = 17; also destroys Function.prototype.call etc
for (final jdk.nashorn.internal.runtime.Property prop : extractBuiltinProperties(name, func)) {
prop.setBuiltinSwitchPoint(sp);
}
}
项目:openjdk-jdk10
文件:GuardedInvocation.java
/**
* Composes the invocation, guard, switch points, and the exception into a
* composite method handle that knows how to fall back when the guard fails
* or the invocation is invalidated.
* @param switchpointFallback the fallback method handle in case a switch
* point is invalidated.
* @param guardFallback the fallback method handle in case guard returns
* false.
* @param catchFallback the fallback method in case the exception handler
* triggers.
* @return a composite method handle.
*/
public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) {
final MethodHandle guarded =
guard == null ?
invocation :
MethodHandles.guardWithTest(
guard,
invocation,
guardFallback);
final MethodHandle catchGuarded =
exception == null ?
guarded :
MethodHandles.catchException(
guarded,
exception,
MethodHandles.dropArguments(
catchFallback,
0,
exception));
if (switchPoints == null) {
return catchGuarded;
}
MethodHandle spGuarded = catchGuarded;
for (final SwitchPoint sp : switchPoints) {
spGuarded = sp.guardWithTest(spGuarded, switchpointFallback);
}
return spGuarded;
}
项目:openjdk-jdk10
文件:AccessorProperty.java
@SuppressWarnings("unused")
private static Object invalidateSwitchPoint(final AccessorProperty property, final Object obj) {
if (!property.builtinSwitchPoint.hasBeenInvalidated()) {
SwitchPoint.invalidateAll(new SwitchPoint[] { property.builtinSwitchPoint });
}
return obj;
}
项目:openjdk-jdk10
文件:Context.java
/**
* Create a new builtin switchpoint and return it
* @param name key name
* @return new builtin switchpoint
*/
public SwitchPoint newBuiltinSwitchPoint(final String name) {
assert builtinSwitchPoints.get(name) == null;
final SwitchPoint sp = new BuiltinSwitchPoint();
builtinSwitchPoints.put(name, sp);
return sp;
}
项目:openjdk-jdk10
文件:ScriptObject.java
private SwitchPoint findBuiltinSwitchPoint(final Object key) {
for (ScriptObject myProto = getProto(); myProto != null; myProto = myProto.getProto()) {
final Property prop = myProto.getMap().findProperty(key);
if (prop != null) {
final SwitchPoint sp = prop.getBuiltinSwitchPoint();
if (sp != null && !sp.hasBeenInvalidated()) {
return sp;
}
}
}
return null;
}
项目:openjdk-jdk10
文件:ScriptObject.java
private SwitchPoint getProtoSwitchPoint(final String name) {
if (getProto() == null) {
return null;
}
for (ScriptObject obj = this; obj.getProto() != null; obj = obj.getProto()) {
final ScriptObject parent = obj.getProto();
parent.getMap().addListener(name, obj.getMap());
}
return getMap().getSwitchPoint(name);
}
项目:openjdk-jdk10
文件:WithObject.java
private static boolean hasBeenInvalidated(final SwitchPoint[] switchPoints) {
if (switchPoints != null) {
for (final SwitchPoint switchPoint : switchPoints) {
if (switchPoint.hasBeenInvalidated()) {
return true;
}
}
}
return false;
}
项目:openjdk-jdk10
文件:SetMethodCreator.java
/**
* Composes from its components an actual guarded invocation that represents the dynamic setter method for the property.
* @return the composed guarded invocation that represents the dynamic setter method for the property.
*/
GuardedInvocation createGuardedInvocation() {
// getGuard() and getException() either both return null, or neither does. The reason for that is that now
// getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to
// relink on ClassCastException.
final boolean explicitInstanceOfCheck = NashornGuards.explicitInstanceOfCheck(desc, request);
return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck),
(SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
}
项目:openjdk-jdk10
文件:SetMethodCreator.java
private SetMethod createSetMethod(final SwitchPoint builtinSwitchPoint) {
if (find != null) {
return createExistingPropertySetter();
}
checkStrictCreateNewVariable();
if (sobj.isScope()) {
return createGlobalPropertySetter();
}
return createNewPropertySetter(builtinSwitchPoint);
}