8006220: Simplify PropertyMaps
Reviewed-by: hannesw, lagergren
Contributed-by: james.laskey@oracle.com
--- a/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java Tue Apr 30 10:05:42 2013 -0300
@@ -65,10 +65,12 @@
* Constructs a property map based on a set of fields.
*
* @param hasArguments does the created object have an "arguments" property
+ * @param fieldCount Number of fields in use.
+ * @param fieldMaximum Number of fields available.
*
* @return New map populated with accessor properties.
*/
- PropertyMap makeMap(final boolean hasArguments) {
+ PropertyMap makeMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum) {
final List<Property> properties = new ArrayList<>();
assert keys != null;
@@ -82,7 +84,7 @@
}
}
- return PropertyMap.newMap(structure, properties);
+ return PropertyMap.newMap(structure, properties, fieldCount, fieldMaximum);
}
/**
--- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Tue Apr 30 10:05:42 2013 -0300
@@ -69,6 +69,16 @@
static final String SCOPE_MARKER = "P";
/**
+ * Minimum number of extra fields in an object.
+ */
+ static final int FIELD_PADDING = 4;
+
+ /**
+ * Rounding when calculating the number of fields.
+ */
+ static final int FIELD_ROUNDING = 4;
+
+ /**
* Debug field logger
* Should we print debugging information for fields when they are generated and getters/setters are called?
*/
--- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java Tue Apr 30 10:05:42 2013 -0300
@@ -26,6 +26,8 @@
package jdk.nashorn.internal.codegen;
import java.util.List;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.FIELD_PADDING;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.FIELD_ROUNDING;
import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -50,6 +52,7 @@
private final boolean isScope;
private final boolean hasArguments;
private int fieldCount;
+ private int paddedFieldCount;
private int paramCount;
private String fieldObjectClassName;
private Class<?> fieldObjectClass;
@@ -88,6 +91,8 @@
}
}
}
+
+ paddedFieldCount = (fieldCount + FIELD_PADDING + FIELD_ROUNDING - 1) / FIELD_ROUNDING * FIELD_ROUNDING;
}
/**
@@ -96,7 +101,7 @@
private void findClass() {
fieldObjectClassName = isScope() ?
ObjectClassGenerator.getClassName(fieldCount, paramCount) :
- ObjectClassGenerator.getClassName(fieldCount);
+ ObjectClassGenerator.getClassName(paddedFieldCount);
try {
this.fieldObjectClass = Context.forStructureClass(Compiler.binaryName(fieldObjectClassName));
@@ -125,11 +130,7 @@
* @return the newly created property map
*/
protected PropertyMap makeMap() {
- if (keys.isEmpty()) { //empty map
- propertyMap = PropertyMap.newMap(fieldObjectClass);
- } else {
- propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments());
- }
+ propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments(), fieldCount, paddedFieldCount);
return propertyMap;
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java Tue Apr 30 10:05:42 2013 -0300
@@ -87,66 +87,6 @@
}
/**
- * Nashorn extension: get embed0 from {@link ScriptObject}
- *
- * @param self self reference
- * @param obj script object
- * @return the embed0 property value for the given ScriptObject
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object embed0(final Object self, final Object obj) {
- if (obj instanceof ScriptObject) {
- return ((ScriptObject)obj).embed0;
- }
- return UNDEFINED;
- }
-
- /**
- * Nashorn extension: get embed1 from {@link ScriptObject}
- *
- * @param self self reference
- * @param obj script object
- * @return the embed1 property value for the given ScriptObject
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object embed1(final Object self, final Object obj) {
- if (obj instanceof ScriptObject) {
- return ((ScriptObject)obj).embed1;
- }
- return UNDEFINED;
- }
-
- /**
- * Nashorn extension: get embed2 from {@link ScriptObject}
- *
- * @param self self reference
- * @param obj script object
- * @return the embed2 property value for the given ScriptObject
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object embed2(final Object self, final Object obj) {
- if (obj instanceof ScriptObject) {
- return ((ScriptObject)obj).embed2;
- }
- return UNDEFINED;
- }
-
- /**
- * Nashorn extension: get embed3 from {@link ScriptObject}
- *
- * @param self self reference
- * @param obj script object
- * @return the embed3 property value for the given ScriptObject
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static Object embed3(final Object self, final Object obj) {
- if (obj instanceof ScriptObject) {
- return ((ScriptObject)obj).embed3;
- }
- return UNDEFINED;
- }
-
- /**
* Nashorn extension: get spill vector from {@link ScriptObject}
*
* @param self self reference
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Tue Apr 30 10:05:42 2013 -0300
@@ -620,7 +620,7 @@
// to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
- adaptee.getMap().getProtoGetSwitchPoint(__call__), testJSAdaptor(adaptee, null, null, null));
+ adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null));
}
throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
default:
@@ -687,7 +687,7 @@
if (methodHandle != null) {
return new GuardedInvocation(
methodHandle,
- adaptee.getMap().getProtoGetSwitchPoint(hook),
+ adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
}
}
@@ -699,7 +699,7 @@
final MethodHandle methodHandle = hook.equals(__put__) ?
MH.asType(Lookup.EMPTY_SETTER, type) :
Lookup.emptyGetter(type.returnType());
- return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(hook), testJSAdaptor(adaptee, null, null, null));
+ return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), testJSAdaptor(adaptee, null, null, null));
}
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Tue Apr 30 10:05:42 2013 -0300
@@ -50,8 +50,6 @@
/**
* An AccessorProperty is the most generic property type. An AccessorProperty is
* represented as fields in a ScriptObject class.
- *
- * @see SpillProperty
*/
public class AccessorProperty extends Property {
private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
@@ -77,6 +75,7 @@
private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
+ private static final MethodHandle SPILLGETTER = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), Lookup.GET_OBJECT_TYPE);
/** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
private MethodHandle primitiveGetter;
@@ -285,7 +284,7 @@
"get");
}
- return getters[i];
+ return isSpill() ? MH.filterArguments(getters[i], 0, SPILLGETTER) : getters[i];
}
private Property getWiderProperty(final Class<?> type) {
@@ -327,6 +326,7 @@
final Class<?> forType = currentType == null ? type : currentType;
//if we are asking for an object setter, but are still a primitive type, we might try to box it
+ MethodHandle mh;
if (needsInvalidator(i, ci)) {
final Property newProperty = getWiderProperty(type);
@@ -335,12 +335,15 @@
final MethodHandle explodeTypeSetter = MH.filterArguments(widerSetter, 0, MH.insertArguments(REPLACE_MAP, 1, newMap, getKey(), currentType, type));
if (currentType != null && currentType.isPrimitive() && type == Object.class) {
//might try a box check on this to avoid widening field to object storage
- return createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter);
+ mh = createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter);
+ } else {
+ mh = explodeTypeSetter;
}
- return explodeTypeSetter;
+ } else {
+ mh = generateSetter(forType, type);
}
- return generateSetter(forType, type);
+ return isSpill() ? MH.filterArguments(mh, 0, SPILLGETTER) : mh;
}
@Override
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java Tue Apr 30 10:05:42 2013 -0300
@@ -201,9 +201,6 @@
/** Current error manager. */
private final ErrorManager errors;
- /** Empty map used for seed map for JO objects */
- final PropertyMap emptyMap = PropertyMap.newEmptyMap(this);
-
private static final ClassLoader myLoader = Context.class.getClassLoader();
private static final StructureLoader sharedLoader;
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java Tue Apr 30 10:05:42 2013 -0300
@@ -41,7 +41,6 @@
*
* @see PropertyMap
* @see AccessorProperty
- * @see SpillProperty
* @see UserAccessorProperty
*/
public abstract class Property {
@@ -64,7 +63,7 @@
private static final int MODIFY_MASK = 0b0000_0000_1111;
- /** Is this a spill property? See {@link SpillProperty} */
+ /** Is this a spill property? See {@link AccessorProperty} */
public static final int IS_SPILL = 0b0000_0001_0000;
/** Is this a function parameter? */
@@ -88,7 +87,7 @@
/** Property flags. */
protected int flags;
- /** Property field number or spill slot */
+ /** Property field number or spill slot. */
private final int slot;
/**
@@ -248,7 +247,7 @@
* Does this property use any slots in the spill array described in
* {@link Property#isSpill}? In that case how many. Currently a property
* only uses max one spill slot, but this may change in future representations
- * Only {@link SpillProperty} instances use spill slots
+ * Only {@link AccessorProperty} instances use spill slots
*
* @return number of spill slots a property is using
*/
@@ -345,6 +344,14 @@
}
/**
+ * Get the field number or spill slot
+ * @return number/slot, -1 if none exists
+ */
+ public int getSlot() {
+ return slot;
+ }
+
+ /**
* Abstract method for retrieving the setter for the property. We do not know
* anything about the internal representation when we request the setter, we only
* know that the setter will take the property as a parameter of the given type.
@@ -388,14 +395,6 @@
return null;
}
- /**
- * Get the field number or spill slot
- * @return number/slot, -1 if none exists
- */
- public int getSlot() {
- return slot;
- }
-
@Override
public int hashCode() {
final Class<?> type = getCurrentType();
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java Tue Apr 30 10:05:42 2013 -0300
@@ -110,7 +110,7 @@
private static final int LIST_THRESHOLD = 8;
/** Initial map. */
- public static final PropertyHashMap EMPTY_MAP = new PropertyHashMap();
+ public static final PropertyHashMap EMPTY_HASHMAP = new PropertyHashMap();
/** Number of properties in the map. */
private final int size;
@@ -246,7 +246,7 @@
}
} else if (findElement(list, key) != null) {
final int newSize = size - 1;
- return newSize != 0 ? new PropertyHashMap(newSize, null, removeFromList(list, key)) : EMPTY_MAP;
+ return newSize != 0 ? new PropertyHashMap(newSize, null, removeFromList(list, key)) : EMPTY_HASHMAP;
}
return this;
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java Tue Apr 30 10:05:42 2013 -0300
@@ -25,7 +25,7 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_MAP;
+import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.SwitchPoint;
@@ -49,29 +49,27 @@
* will return a new map.
*/
public final class PropertyMap implements Iterable<Object>, PropertyListener {
- /** Is this a prototype PropertyMap? */
- public static final int IS_PROTOTYPE = 0b0000_0001;
/** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
- public static final int NOT_EXTENSIBLE = 0b0000_0010;
+ public static final int NOT_EXTENSIBLE = 0b0000_0001;
/** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */
private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111;
/** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */
public static final int IS_LISTENER_ADDED = 0b0001_0000;
+ /** Empty map used for seed map for JO$ objects */
+ private static final PropertyMap EMPTY_MAP = new PropertyMap(EMPTY_HASHMAP);
+
/** Map status flags. */
private int flags;
- /** Class of object referenced.*/
- private final Class<?> structure;
-
- /** Context associated with this {@link PropertyMap}. */
- private final Context context;
-
/** Map of properties. */
private final PropertyHashMap properties;
- /** objects proto. */
- private ScriptObject proto;
+ /** Number of fields in use. */
+ private int fieldCount;
+
+ /** Number of fields available. */
+ private int fieldMaximum;
/** Length of spill in use. */
private int spillLength;
@@ -91,15 +89,15 @@
/**
* Constructor.
*
- * @param structure Class the map's {@link AccessorProperty}s apply to.
- * @param context Context associated with this {@link PropertyMap}.
- * @param properties A {@link PropertyHashMap} with initial contents.
+ * @param properties A {@link PropertyHashMap} with initial contents.
+ * @param fieldCount Number of fields in use.
+ * @param fieldMaximum Number of fields available.
*/
- PropertyMap(final Class<?> structure, final Context context, final PropertyHashMap properties) {
- this.structure = structure;
- this.context = context;
- this.properties = properties;
- this.hashCode = computeHashCode();
+ private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum) {
+ this.properties = properties;
+ this.hashCode = computeHashCode();
+ this.fieldCount = fieldCount;
+ this.fieldMaximum = fieldMaximum;
if (Context.DEBUG) {
count++;
@@ -107,19 +105,27 @@
}
/**
+ * Constructor.
+ *
+ * @param properties A {@link PropertyHashMap} with initial contents.
+ */
+ private PropertyMap(final PropertyHashMap properties) {
+ this(properties, 0, 0);
+ }
+
+ /**
* Cloning constructor.
*
* @param propertyMap Existing property map.
* @param properties A {@link PropertyHashMap} with a new set of properties.
*/
private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
- this.structure = propertyMap.structure;
- this.context = propertyMap.context;
- this.properties = properties;
- this.flags = propertyMap.getClonedFlags();
- this.proto = propertyMap.proto;
- this.spillLength = propertyMap.spillLength;
- this.hashCode = computeHashCode();
+ this.properties = properties;
+ this.flags = propertyMap.getClonedFlags();
+ this.spillLength = propertyMap.spillLength;
+ this.fieldCount = propertyMap.fieldCount;
+ this.fieldMaximum = propertyMap.fieldMaximum;
+ this.hashCode = computeHashCode();
if (Context.DEBUG) {
count++;
@@ -128,6 +134,15 @@
}
/**
+ * Cloning constructor.
+ *
+ * @param propertyMap Existing property map.
+ */
+ private PropertyMap(final PropertyMap propertyMap) {
+ this(propertyMap, propertyMap.properties);
+ }
+
+ /**
* Duplicates this PropertyMap instance. This is used by nasgen generated
* prototype and constructor classes. {@link PropertyMap} used for singletons
* like these (and global instance) are duplicated using this method and used.
@@ -138,7 +153,7 @@
* @return Duplicated {@link PropertyMap}.
*/
public PropertyMap duplicate() {
- return new PropertyMap(this.structure, this.context, this.properties);
+ return new PropertyMap(this.properties);
}
/**
@@ -146,20 +161,20 @@
*
* @param structure Class the map's {@link AccessorProperty}s apply to.
* @param properties Collection of initial properties.
+ * @param fieldCount Number of fields in use.
+ * @param fieldMaximum Number of fields available.
*
* @return New {@link PropertyMap}.
*/
- public static PropertyMap newMap(final Class<?> structure, final Collection<Property> properties) {
- final Context context = Context.fromClass(structure);
-
+ public static PropertyMap newMap(final Class<?> structure, final Collection<Property> properties, final int fieldCount, final int fieldMaximum) {
// Reduce the number of empty maps in the context.
if (structure == jdk.nashorn.internal.scripts.JO.class) {
- return context.emptyMap;
+ return EMPTY_MAP;
}
- PropertyHashMap newProperties = EMPTY_MAP.immutableAdd(properties);
+ PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
- return new PropertyMap(structure, context, newProperties);
+ return new PropertyMap(newProperties, fieldCount, fieldMaximum);
}
/**
@@ -170,7 +185,7 @@
* @return New {@link PropertyMap}.
*/
public static PropertyMap newMap(final Class<?> structure) {
- return newMap(structure, null);
+ return newMap(structure, null, 0, 0);
}
/**
@@ -180,7 +195,7 @@
* @return New empty {@link PropertyMap}.
*/
public static PropertyMap newEmptyMap(final Context context) {
- return new PropertyMap(jdk.nashorn.internal.scripts.JO.class, context, EMPTY_MAP);
+ return new PropertyMap(EMPTY_HASHMAP);
}
/**
@@ -195,11 +210,12 @@
/**
* Return a SwitchPoint used to track changes of a property in a prototype.
*
- * @param key {@link Property} key.
+ * @param proto Object prototype.
+ * @param key {@link Property} key.
*
* @return A shared {@link SwitchPoint} for the property.
*/
- public SwitchPoint getProtoGetSwitchPoint(final String key) {
+ public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) {
if (proto == null) {
return null;
}
@@ -295,6 +311,11 @@
final PropertyHashMap newProperties = properties.immutableAdd(property);
newMap = new PropertyMap(this, newProperties);
addToHistory(property, newMap);
+
+ if(!property.isSpill()) {
+ newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
+ }
+
newMap.spillLength += property.getSpillCount();
}
@@ -355,7 +376,6 @@
newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
newMap.flags = getClonedFlags();
- newMap.proto = proto;
/*
* spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
@@ -411,7 +431,7 @@
* @return New map with {@link #NOT_EXTENSIBLE} flag set.
*/
PropertyMap preventExtensions() {
- final PropertyMap newMap = new PropertyMap(this, this.properties);
+ final PropertyMap newMap = new PropertyMap(this);
newMap.flags |= NOT_EXTENSIBLE;
return newMap;
}
@@ -423,7 +443,7 @@
* {@link Property#NOT_CONFIGURABLE} set.
*/
PropertyMap seal() {
- PropertyHashMap newProperties = EMPTY_MAP;
+ PropertyHashMap newProperties = EMPTY_HASHMAP;
for (final Property oldProperty : properties.getProperties()) {
newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
@@ -442,7 +462,7 @@
* {@link Property#NOT_CONFIGURABLE} and {@link Property#NOT_WRITABLE} set.
*/
PropertyMap freeze() {
- PropertyHashMap newProperties = EMPTY_MAP;
+ PropertyHashMap newProperties = EMPTY_HASHMAP;
for (Property oldProperty : properties.getProperties()) {
int propertyFlags = Property.NOT_CONFIGURABLE;
@@ -578,11 +598,7 @@
* @return Computed hash code.
*/
private int computeHashCode() {
- int hash = structure.hashCode();
-
- if (proto != null) {
- hash ^= proto.hashCode();
- }
+ int hash = 0;
for (final Property property : getProperties()) {
hash = hash << 7 ^ hash >> 7;
@@ -605,9 +621,7 @@
final PropertyMap otherMap = (PropertyMap)other;
- if (structure != otherMap.structure ||
- proto != otherMap.proto ||
- properties.size() != otherMap.properties.size()) {
+ if (properties.size() != otherMap.properties.size()) {
return false;
}
@@ -659,31 +673,6 @@
}
/**
- * Return map's {@link Context}.
- *
- * @return The {@link Context} where the map originated.
- */
- Context getContext() {
- return context;
- }
-
- /**
- * Check if this map is a prototype
- *
- * @return {@code true} if is prototype
- */
- public boolean isPrototype() {
- return (flags & IS_PROTOTYPE) != 0;
- }
-
- /**
- * Flag this map as having a prototype.
- */
- private void setIsPrototype() {
- flags |= IS_PROTOTYPE;
- }
-
- /**
* Check whether a {@link PropertyListener} has been added to this map.
*
* @return {@code true} if {@link PropertyListener} exists
@@ -720,6 +709,22 @@
boolean isFrozen() {
return !isExtensible() && allFrozen();
}
+ /**
+ * Get the number of fields allocated for this {@link PropertyMap}.
+ *
+ * @return Number of fields allocated.
+ */
+ int getFieldCount() {
+ return fieldCount;
+ }
+ /**
+ * Get maximum number of fields available for this {@link PropertyMap}.
+ *
+ * @return Number of fields available.
+ */
+ int getFieldMaximum() {
+ return fieldMaximum;
+ }
/**
* Get length of spill area associated with this {@link PropertyMap}.
@@ -731,25 +736,20 @@
}
/**
- * Return the prototype of objects associated with this {@link PropertyMap}.
+ * Change the prototype of objects associated with this {@link PropertyMap}.
*
- * @return Prototype object.
- */
- ScriptObject getProto() {
- return proto;
- }
-
- /**
- * Set the prototype of objects associated with this {@link PropertyMap}.
- *
- * @param newProto Prototype object to use.
+ * @param oldProto Current prototype object.
+ * @param newProto New prototype object to replace oldProto.
*
* @return New {@link PropertyMap} with prototype changed.
*/
- PropertyMap setProto(final ScriptObject newProto) {
- final ScriptObject oldProto = this.proto;
-
- if (oldProto == newProto) {
+ PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) {
+ if ((oldProto == newProto) ||
+ (size() == 0 &&
+ oldProto == null &&
+ protoGetSwitches == null &&
+ history == null &&
+ protoHistory == null)) {
return this;
}
@@ -761,19 +761,10 @@
if (Context.DEBUG) {
incrementSetProtoNewMapCount();
}
- final PropertyMap newMap = new PropertyMap(this, this.properties);
+
+ final PropertyMap newMap = new PropertyMap(this);
addToProtoHistory(newProto, newMap);
- newMap.proto = newProto;
-
- if (oldProto != null && newMap.isListenerAdded()) {
- oldProto.removePropertyListener(newMap);
- }
-
- if (newProto != null) {
- newProto.getMap().setIsPrototype();
- }
-
return newMap;
}
@@ -927,4 +918,3 @@
setProtoNewMapCount++;
}
}
-
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Tue Apr 30 10:05:42 2013 -0300
@@ -104,34 +104,31 @@
/** Per ScriptObject flag - is this an arguments object? */
public static final int IS_ARGUMENTS = 0b0000_0100;
+ /** Is this a prototype PropertyMap? */
+ public static final int IS_PROTOTYPE = 0b0000_1000;
+
/** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
public static final int SPILL_RATE = 8;
/** Map to property information and accessor functions. Ordered by insertion. */
private PropertyMap map;
+ /** objects proto. */
+ private ScriptObject proto;
+
+ /** Context of the object, lazily cached. */
+ private Context context;
+
/** Object flags. */
private int flags;
- /** Area for properties added to object after instantiation, see {@link SpillProperty} */
+ /** Area for properties added to object after instantiation, see {@link AccessorProperty} */
public Object[] spill;
- /** Local embed area position 0 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
- public Object embed0;
-
- /** Local embed area position 1 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
- public Object embed1;
-
- /** Local embed area position 2 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
- public Object embed2;
-
- /** Local embed area position 3 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
- public Object embed3;
-
/** Indexed array data. */
private ArrayData arrayData;
- static final MethodHandle SETEMBED = findOwnMH("setEmbed", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, int.class, Object.class, Object.class);
+ static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
static final MethodHandle SETSPILLWITHGROW = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
@@ -783,8 +780,8 @@
// delete getter and setter function references so that we don't leak
if (property instanceof UserAccessorProperty) {
final UserAccessorProperty uc = (UserAccessorProperty) property;
- setEmbedOrSpill(uc.getGetterSlot(), null);
- setEmbedOrSpill(uc.getSetterSlot(), null);
+ setSpill(uc.getGetterSlot(), null);
+ setSpill(uc.getSetterSlot(), null);
}
return true;
}
@@ -809,7 +806,7 @@
int getterSlot = uc.getGetterSlot();
// clear the old getter and set the new getter
- setEmbedOrSpill(getterSlot, getter);
+ setSpill(getterSlot, getter);
// if getter function is null, flag the slot to be negative (less by 1)
if (getter == null) {
getterSlot = -getterSlot - 1;
@@ -817,7 +814,7 @@
int setterSlot = uc.getSetterSlot();
// clear the old setter and set the new setter
- setEmbedOrSpill(setterSlot, setter);
+ setSpill(setterSlot, setter);
// if setter function is null, flag the slot to be negative (less by 1)
if (setter == null) {
setterSlot = -setterSlot - 1;
@@ -1056,8 +1053,11 @@
* Return the current context from the object's map.
* @return Current context.
*/
- final Context getContext() {
- return getMap().getContext();
+ protected final Context getContext() {
+ if (context == null) {
+ context = Context.fromClass(getClass());
+ }
+ return context;
}
/**
@@ -1097,44 +1097,30 @@
* @return __proto__ object.
*/
public final ScriptObject getProto() {
- return getMap().getProto();
- }
-
- /**
- * Check if this is a prototype
- * @return true if {@link PropertyMap#isPrototype()} is true for this ScriptObject
- */
- public final boolean isPrototype() {
- return getMap().isPrototype();
+ return proto;
}
/**
* Set the __proto__ of an object.
* @param newProto new __proto__ to set.
*/
- public final void setProto(final ScriptObject newProto) {
- PropertyMap oldMap = getMap();
- ScriptObject oldProto = getProto();
-
- while (oldProto != newProto) {
- final PropertyMap newMap = oldMap.setProto(newProto);
-
- if (!compareAndSetMap(oldMap, newMap)) {
- oldMap = getMap();
- oldProto = getProto();
- } else {
- if (isPrototype()) {
-
- if (oldProto != null) {
- oldProto.removePropertyListener(this);
- }
-
- if (newProto != null) {
- newProto.addPropertyListener(this);
- }
- }
-
- return;
+ public synchronized final void setProto(final ScriptObject newProto) {
+ final ScriptObject oldProto = proto;
+ map = map.changeProto(oldProto, newProto);
+
+ if (newProto != null) {
+ newProto.setIsPrototype();
+ }
+
+ proto = newProto;
+
+ if (isPrototype()) {
+ if (oldProto != null) {
+ oldProto.removePropertyListener(this);
+ }
+
+ if (newProto != null) {
+ newProto.addPropertyListener(this);
}
}
}
@@ -1327,6 +1313,22 @@
}
/**
+ * Check if this object is a prototype
+ *
+ * @return {@code true} if is prototype
+ */
+ public boolean isPrototype() {
+ return (flags & IS_PROTOTYPE) != 0;
+ }
+
+ /**
+ * Flag this object as having a prototype.
+ */
+ public void setIsPrototype() {
+ flags |= IS_PROTOTYPE;
+ }
+
+ /**
* Get the {@link ArrayData} for this ScriptObject if it is an array
* @return array data
*/
@@ -1719,11 +1721,11 @@
if (!property.hasGetterFunction()) {
methodHandle = bindTo(methodHandle, prototype);
}
- return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(name), guard);
+ return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard);
}
assert !NashornCallSiteDescriptor.isFastScope(desc);
- return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(name), guard);
+ return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard);
}
private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name) {
@@ -1822,27 +1824,31 @@
}
assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
final PropertyMap myMap = getMap();
- return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(name), NashornGuards.getMapGuard(myMap));
+ return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(myMap));
}
@SuppressWarnings("unused")
- private static void setEmbed(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final MethodHandle setter, final int i, final Object self, final Object value) throws Throwable {
+ private static void setField(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final MethodHandle setter, final Object self, final Object value) throws Throwable {
final ScriptObject obj = (ScriptObject)self;
- if (obj.trySetEmbedOrSpill(desc, oldMap, newMap, value)) {
- obj.useEmbed(i);
+ final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
+ if (!obj.isExtensible()) {
+ throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
+ } else if (obj.compareAndSetMap(oldMap, newMap)) {
setter.invokeExact(self, value);
+ } else {
+ obj.set(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND), value, isStrict);
}
}
@SuppressWarnings("unused")
private static void setSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final Object self, final Object value) {
final ScriptObject obj = (ScriptObject)self;
- if (obj.trySetEmbedOrSpill(desc, oldMap, newMap, value)) {
+ if (obj.trySetSpill(desc, oldMap, newMap, value)) {
obj.spill[index] = value;
}
}
- private boolean trySetEmbedOrSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final Object value) {
+ private boolean trySetSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final Object value) {
final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
if (!isExtensible() && isStrict) {
throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(this));
@@ -1964,7 +1970,7 @@
methodHandle = bindTo(methodHandle, UNDEFINED);
}
return new GuardedInvocation(methodHandle,
- find.isInherited()? getMap().getProtoGetSwitchPoint(NO_SUCH_PROPERTY_NAME) : null,
+ find.isInherited()? getMap().getProtoGetSwitchPoint(proto, NO_SUCH_PROPERTY_NAME) : null,
getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
}
}
@@ -1995,7 +2001,7 @@
}
private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
- return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(name), NashornGuards.getMapGuard(getMap()));
+ return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap()));
}
private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
@@ -2070,36 +2076,39 @@
* @return Added property.
*/
private Property addSpillProperty(final String key, final int propertyFlags) {
- int i = findEmbed();
- Property spillProperty;
-
- if (i >= EMBED_SIZE) {
- i = getMap().getSpillLength();
+ int fieldCount = getMap().getFieldCount();
+ int fieldMaximum = getMap().getFieldMaximum();
+ Property property;
+
+ if (fieldCount < fieldMaximum) {
+ property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
+ notifyPropertyAdded(this, property);
+ property = addOwnProperty(property);
+ } else {
+ int i = getMap().getSpillLength();
MethodHandle getter = MH.arrayElementGetter(Object[].class);
MethodHandle setter = MH.arrayElementSetter(Object[].class);
getter = MH.asType(MH.insertArguments(getter, 1, i), Lookup.GET_OBJECT_TYPE);
setter = MH.asType(MH.insertArguments(setter, 1, i), Lookup.SET_OBJECT_TYPE);
- spillProperty = new SpillProperty(key, propertyFlags | Property.IS_SPILL, i, getter, setter);
- notifyPropertyAdded(this, spillProperty);
- spillProperty = addOwnProperty(spillProperty);
- i = spillProperty.getSlot();
+ property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i, getter, setter);
+ notifyPropertyAdded(this, property);
+ property = addOwnProperty(property);
+ i = property.getSlot();
final int newLength = (i + SPILL_RATE) / SPILL_RATE * SPILL_RATE;
- final Object[] newSpill = new Object[newLength];
-
- if (spill != null) {
- System.arraycopy(spill, 0, newSpill, 0, spill.length);
+
+ if (spill == null || newLength > spill.length) {
+ final Object[] newSpill = new Object[newLength];
+
+ if (spill != null) {
+ System.arraycopy(spill, 0, newSpill, 0, spill.length);
+ }
+
+ spill = newSpill;
}
-
- spill = newSpill;
- } else {
- useEmbed(i);
- spillProperty = new SpillProperty(key, propertyFlags, i, GET_EMBED[i], SET_EMBED[i]);
- notifyPropertyAdded(this, spillProperty);
- spillProperty = addOwnProperty(spillProperty);
}
- return spillProperty;
+ return property;
}
@@ -3159,67 +3168,22 @@
}
/*
- * Embed management
- */
-
- /** Number of embed slots */
- public static final int EMBED_SIZE = 4;
- /** Embed offset */
- public static final int EMBED_OFFSET = 32 - EMBED_SIZE;
-
- static final MethodHandle[] GET_EMBED;
- static final MethodHandle[] SET_EMBED;
-
- static {
- GET_EMBED = new MethodHandle[EMBED_SIZE];
- SET_EMBED = new MethodHandle[EMBED_SIZE];
-
- for (int i = 0; i < EMBED_SIZE; i++) {
- final String name = "embed" + i;
- GET_EMBED[i] = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, name, Object.class), Lookup.GET_OBJECT_TYPE);
- SET_EMBED[i] = MH.asType(MH.setter(MethodHandles.lookup(), ScriptObject.class, name, Object.class), Lookup.SET_OBJECT_TYPE);
- }
- }
-
- void useEmbed(final int i) {
- flags |= 1 << (EMBED_OFFSET + i);
- }
-
- int findEmbed() {
- final int bits = ~(flags >>> EMBED_OFFSET);
- final int least = bits ^ -bits;
- final int index = Integer.numberOfTrailingZeros(least) - 1;
-
- return index;
- }
-
- /*
* Make a new UserAccessorProperty property. getter and setter functions are stored in
* this ScriptObject and slot values are used in property object.
*/
private UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
int oldSpillLength = getMap().getSpillLength();
- int getterSlot = findEmbed();
- if (getterSlot >= EMBED_SIZE) {
- getterSlot = oldSpillLength + EMBED_SIZE;
- ++oldSpillLength;
- } else {
- useEmbed(getterSlot);
- }
- setEmbedOrSpill(getterSlot, getter);
+ int getterSlot = oldSpillLength++;
+ setSpill(getterSlot, getter);
// if getter function is null, flag the slot to be negative (less by 1)
if (getter == null) {
getterSlot = -getterSlot - 1;
}
- int setterSlot = findEmbed();
- if (setterSlot >= EMBED_SIZE) {
- setterSlot = oldSpillLength + EMBED_SIZE;
- } else {
- useEmbed(setterSlot);
- }
- setEmbedOrSpill(setterSlot, setter);
+ int setterSlot = oldSpillLength++;
+
+ setSpill(setterSlot, setter);
// if setter function is null, flag the slot to be negative (less by 1)
if (setter == null) {
setterSlot = -setterSlot - 1;
@@ -3228,56 +3192,28 @@
return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot);
}
- private void setEmbedOrSpill(final int slot, final Object value) {
- switch (slot) {
- case 0:
- embed0 = value;
- break;
- case 1:
- embed1 = value;
- break;
- case 2:
- embed2 = value;
- break;
- case 3:
- embed3 = value;
- break;
- default:
- if (slot >= 0) {
- final int index = (slot - EMBED_SIZE);
- if (spill == null) {
- // create new spill.
- spill = new Object[Math.max(index + 1, SPILL_RATE)];
- } else if (index >= spill.length) {
- // grow spill as needed
- final Object[] newSpill = new Object[index + 1];
- System.arraycopy(spill, 0, newSpill, 0, spill.length);
- spill = newSpill;
- }
-
- spill[index] = value;
+ private void setSpill(final int slot, final Object value) {
+ if (slot >= 0) {
+ final int index = slot;
+ if (spill == null) {
+ // create new spill.
+ spill = new Object[Math.max(index + 1, SPILL_RATE)];
+ } else if (index >= spill.length) {
+ // grow spill as needed
+ final Object[] newSpill = new Object[index + 1];
+ System.arraycopy(spill, 0, newSpill, 0, spill.length);
+ spill = newSpill;
}
- break;
+
+ spill[index] = value;
}
}
- // user accessors are either stored in embed fields or spill array slots
- // get the accessor value using slot number. Note that slot is either embed
- // field number or (spill array index + embedSize).
- Object getEmbedOrSpill(final int slot) {
- switch (slot) {
- case 0:
- return embed0;
- case 1:
- return embed1;
- case 2:
- return embed2;
- case 3:
- return embed3;
- default:
- final int index = (slot - EMBED_SIZE);
- return (index < 0 || (index >= spill.length)) ? null : spill[index];
- }
+ // user accessors are either stored in spill array slots
+ // get the accessor value using slot number. Note that slot is spill array index.
+ Object getSpill(final int slot) {
+ final int index = slot;
+ return (index < 0 || (index >= spill.length)) ? null : spill[index];
}
// User defined getter and setter are always called by "dyn:call". Note that the user
@@ -3287,7 +3223,7 @@
@SuppressWarnings("unused")
private static Object userAccessorGetter(final ScriptObject proto, final int slot, final Object self) {
final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
- final Object func = container.getEmbedOrSpill(slot);
+ final Object func = container.getSpill(slot);
if (func instanceof ScriptFunction) {
try {
@@ -3305,7 +3241,7 @@
@SuppressWarnings("unused")
private static void userAccessorSetter(final ScriptObject proto, final int slot, final String name, final Object self, final Object value) {
final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
- final Object func = container.getEmbedOrSpill(slot);
+ final Object func = container.getSpill(slot);
if (func instanceof ScriptFunction) {
try {
--- a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Tue Apr 30 10:05:42 2013 -0300
@@ -166,18 +166,20 @@
}
private SetMethod createNewPropertySetter() {
- final int nextEmbed = sobj.findEmbed();
- final SetMethod sm;
- if (nextEmbed >= ScriptObject.EMBED_SIZE) {
- sm = createNewSpillPropertySetter();
- } else {
- sm = createNewEmbedPropertySetter(nextEmbed);
- }
-
+ final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
sobj.notifyPropertyAdded(sobj, sm.property);
return sm;
}
+ private SetMethod createNewFieldSetter() {
+ final PropertyMap oldMap = getMap();
+ final Property property = new AccessorProperty(getName(), 0, sobj.getClass(), oldMap.getFieldCount());
+ final PropertyMap newMap = oldMap.addProperty(property);
+ MethodHandle setter = MH.insertArguments(ScriptObject.SETFIELD, 0, desc, oldMap, newMap, property.getSetter(Object.class, newMap));
+
+ return new SetMethod(MH.asType(setter, Lookup.SET_OBJECT_TYPE), property);
+ }
+
private SetMethod createNewSpillPropertySetter() {
final int nextSpill = getMap().getSpillLength();
@@ -189,7 +191,7 @@
final MethodHandle getter = MH.asType(MH.insertArguments(MH.arrayElementGetter(Object[].class), 1, nextSpill), Lookup.GET_OBJECT_TYPE);
final MethodHandle setter = MH.asType(MH.insertArguments(MH.arrayElementSetter(Object[].class), 1, nextSpill), Lookup.SET_OBJECT_TYPE);
- return new SpillProperty(getName(), Property.IS_SPILL, nextSpill, getter, setter);
+ return new AccessorProperty(getName(), Property.IS_SPILL, nextSpill, getter, setter);
}
private MethodHandle createSpillMethodHandle(final int nextSpill, Property property) {
@@ -207,14 +209,6 @@
}
}
- private SetMethod createNewEmbedPropertySetter(final int nextEmbed) {
- sobj.useEmbed(nextEmbed);
- final Property property = new SpillProperty(getName(), 0, nextEmbed, ScriptObject.GET_EMBED[nextEmbed], ScriptObject.SET_EMBED[nextEmbed]);
- //TODO specfields
- final MethodHandle methodHandle = MH.insertArguments(ScriptObject.SETEMBED, 0, desc, getMap(), getNewMap(property), property.getSetter(Object.class, getMap()), nextEmbed);
- return new SetMethod(methodHandle, property);
- }
-
private PropertyMap getNewMap(Property property) {
return getMap().addProperty(property);
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java Tue Apr 30 09:42:13 2013 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import jdk.nashorn.internal.lookup.Lookup;
-
-/**
- * The SpillProperty is a subclass of AccessorProperties. Anything not in the initial property map
- * will end up in the embed fields of the ScriptObject or in the Spill, which currently is a growing
- * Object only array in ScriptObject
- *
- * @see AccessorProperty
- * @see ScriptObject
- */
-public final class SpillProperty extends AccessorProperty {
- private static final MethodHandle SPILLGETTER = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), Lookup.GET_OBJECT_TYPE);
-
- /**
- * Constructor
- *
- * @param key property key
- * @param flags property flags
- * @param slot property slot/index
- * @param getter getter for property
- * @param setter setter for property, or null if not configurable and writable
- */
- public SpillProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
- super(key, flags, slot, getter, setter);
- }
-
- private SpillProperty(final SpillProperty property) {
- super(property);
- }
-
- @Override
- protected Property copy() {
- return new SpillProperty(this);
- }
-
- @Override
- public MethodHandle getGetter(final Class<?> type) {
- if (isSpill()) {
- return MH.filterArguments(super.getGetter(type), 0, SPILLGETTER);
- }
-
- return super.getGetter(type);
- }
-
- @Override
- public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
- if (isSpill()) {
- return MH.filterArguments(super.getSetter(type, currentMap), 0, SPILLGETTER);
- }
-
- return super.getSetter(type, currentMap);
- }
-
-}
--- a/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java Tue Apr 30 10:05:42 2013 -0300
@@ -110,8 +110,7 @@
@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
if (name.startsWith(JS_OBJECT_PREFIX_EXTERNAL)) {
- final int start = name.indexOf(JS_OBJECT_PREFIX.symbolName()) + JS_OBJECT_PREFIX.symbolName().length();
- return generateClass(name, name.substring(start, name.length()));
+ return generateClass(name, name.substring(JS_OBJECT_PREFIX_EXTERNAL.length()));
}
return super.findClass(name);
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Tue Apr 30 10:05:42 2013 -0300
@@ -67,7 +67,6 @@
private UserAccessorProperty(final UserAccessorProperty property) {
super(property);
-
this.getterSlot = property.getterSlot;
this.setterSlot = property.setterSlot;
}
@@ -115,10 +114,10 @@
public int getSpillCount() {
// calculate how many spill array slots used by this propery.
int count = 0;
- if (getGetterSlot() >= ScriptObject.EMBED_SIZE) {
+ if (getGetterSlot() >= 0) {
count++;
}
- if (getSetterSlot() >= ScriptObject.EMBED_SIZE) {
+ if (getSetterSlot() >= 0) {
count++;
}
return count;
@@ -141,7 +140,7 @@
@Override
public ScriptFunction getGetterFunction(final ScriptObject obj) {
- final Object value = obj.getEmbedOrSpill(getterSlot);
+ final Object value = obj.getSpill(getterSlot);
return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
}
@@ -152,7 +151,7 @@
@Override
public ScriptFunction getSetterFunction(final ScriptObject obj) {
- final Object value = obj.getEmbedOrSpill(setterSlot);
+ final Object value = obj.getSpill(setterSlot);
return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
}
--- a/nashorn/src/jdk/nashorn/internal/scripts/JO.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/scripts/JO.java Tue Apr 30 10:05:42 2013 -0300
@@ -32,12 +32,11 @@
* Empty object class.
*/
public class JO extends ScriptObject {
-
/**
* Constructor
*/
public JO() {
- super();
+ super(PropertyMap.newMap(JO.class));
}
/**
--- a/nashorn/src/jdk/nashorn/tools/Shell.java Tue Apr 30 09:42:13 2013 +0200
+++ b/nashorn/src/jdk/nashorn/tools/Shell.java Tue Apr 30 10:05:42 2013 -0300
@@ -343,7 +343,7 @@
* @return error code
* @throws IOException when any script file read results in I/O error
*/
- private int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
+ private static int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
try {