8044760: Avoid PropertyMap duplicate for global instances
Reviewed-by: attila, hannesw
This commit is contained in:
parent
ca212c0d9e
commit
8159b11738
nashorn/src/jdk/nashorn/internal
@ -447,12 +447,7 @@ public final class Global extends ScriptObject implements Scope {
|
||||
// null check on context
|
||||
context.getClass();
|
||||
|
||||
/*
|
||||
* Duplicate global's map and use it. This way the initial Map filled
|
||||
* by nasgen (referenced from static field in this class) is retained
|
||||
* 'as is' (as that one is process wide singleton.
|
||||
*/
|
||||
return $nasgenmap$.duplicate();
|
||||
return $nasgenmap$;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,7 +222,6 @@ public final class NativeDebug extends ScriptObject {
|
||||
out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
|
||||
out.println("PropertyMap count " + PropertyMap.getCount());
|
||||
out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
|
||||
out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
|
||||
out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
|
||||
out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
|
||||
out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());
|
||||
|
@ -145,21 +145,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
|
||||
this(propertyMap, propertyMap.properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates this PropertyMap instance. This is used to duplicate 'shared'
|
||||
* maps {@link PropertyMap} used as process wide singletons. Shared maps are
|
||||
* duplicated for every global scope object. That way listeners, proto and property
|
||||
* histories are scoped within a global scope.
|
||||
*
|
||||
* @return Duplicated {@link PropertyMap}.
|
||||
*/
|
||||
public PropertyMap duplicate() {
|
||||
if (Context.DEBUG) {
|
||||
duplicatedCount++;
|
||||
}
|
||||
return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys());
|
||||
}
|
||||
|
||||
private void writeObject(final ObjectOutputStream out) throws IOException {
|
||||
out.defaultWriteObject();
|
||||
out.writeObject(properties.getProperties());
|
||||
@ -968,7 +953,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
|
||||
// counters updated only in debug mode
|
||||
private static int count;
|
||||
private static int clonedCount;
|
||||
private static int duplicatedCount;
|
||||
private static int historyHit;
|
||||
private static int protoInvalidations;
|
||||
private static int protoHistoryHit;
|
||||
@ -988,13 +972,6 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
|
||||
return clonedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of maps that are duplicated.
|
||||
*/
|
||||
public static int getDuplicatedCount() {
|
||||
return duplicatedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of times history was successfully used.
|
||||
*/
|
||||
|
@ -160,7 +160,8 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
|
||||
|
||||
private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
|
||||
private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH_S("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
|
||||
private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
|
||||
private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
|
||||
|
||||
private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
|
||||
|
||||
@ -2271,13 +2272,20 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (scopeAccess && func.isStrict()) {
|
||||
mh = bindTo(mh, UNDEFINED);
|
||||
}
|
||||
|
||||
return new GuardedInvocation(
|
||||
mh,
|
||||
//TODO this always does a scriptobject check
|
||||
getKnownFunctionPropertyGuard(
|
||||
find.isSelf()?
|
||||
getKnownFunctionPropertyGuardSelf(
|
||||
getMap(),
|
||||
find.getGetter(Object.class, INVALID_PROGRAM_POINT),
|
||||
find.getOwner(),
|
||||
func)
|
||||
:
|
||||
//TODO this always does a scriptobject check
|
||||
getKnownFunctionPropertyGuardProto(
|
||||
getMap(),
|
||||
find.getGetter(Object.class, INVALID_PROGRAM_POINT),
|
||||
find.getProtoChainLength(),
|
||||
func),
|
||||
getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
|
||||
//TODO this doesn't need a ClassCastException as guard always checks script object
|
||||
@ -3595,15 +3603,51 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
return MH.findStatic(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
|
||||
}
|
||||
|
||||
private static MethodHandle getKnownFunctionPropertyGuard(final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
|
||||
return MH.insertArguments(KNOWNFUNCPROPGUARD, 1, map, getter, where, func);
|
||||
private static MethodHandle getKnownFunctionPropertyGuardSelf(final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
|
||||
return MH.insertArguments(KNOWNFUNCPROPGUARDSELF, 1, map, getter, func);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean knownFunctionPropertyGuard(final Object self, final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
|
||||
private static boolean knownFunctionPropertyGuardSelf(final Object self, final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
|
||||
if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
|
||||
try {
|
||||
return getter.invokeExact(where) == func;
|
||||
return getter.invokeExact(self) == func;
|
||||
} catch (final RuntimeException | Error e) {
|
||||
throw e;
|
||||
} catch (final Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static MethodHandle getKnownFunctionPropertyGuardProto(final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
|
||||
return MH.insertArguments(KNOWNFUNCPROPGUARDPROTO, 1, map, getter, depth, func);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static ScriptObject getProto(final ScriptObject self, final int depth) {
|
||||
ScriptObject proto = self;
|
||||
for (int d = 0; d < depth; d++) {
|
||||
proto = proto.getProto();
|
||||
if (proto == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean knownFunctionPropertyGuardProto(final Object self, final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
|
||||
if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
|
||||
final ScriptObject proto = getProto((ScriptObject)self, depth);
|
||||
if (proto == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return getter.invokeExact((Object)proto) == func;
|
||||
} catch (final RuntimeException | Error e) {
|
||||
throw e;
|
||||
} catch (final Throwable t) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user