8006222: Move slot from SpillProperty to Property
Reviewed-by: hannesw, lagergren
Contributed-by: james.laskey@oracle.com
--- a/nashorn/src/jdk/nashorn/internal/codegen/objects/FieldObjectCreator.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/codegen/objects/FieldObjectCreator.java Fri Feb 08 09:19:38 2013 -0400
@@ -75,7 +75,7 @@
* @param symbols symbols for fields in object
* @param values values (or null where no value) to be written to the fields
* @param isScope is this a scope object
- * @param hasArguments does the created object have an "arguments" object
+ * @param hasArguments does the created object have an "arguments" property
*/
public FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values, final boolean isScope, final boolean hasArguments) {
super(codegen, keys, symbols, isScope, hasArguments);
@@ -106,7 +106,7 @@
if (isScope()) {
loadScope(method);
- if (isVarArg()) {
+ if (hasArguments()) {
method.loadArguments();
method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class, ARGUMENTS.type()));
} else {
--- a/nashorn/src/jdk/nashorn/internal/codegen/objects/MapCreator.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/codegen/objects/MapCreator.java Fri Feb 08 09:19:38 2013 -0400
@@ -25,20 +25,12 @@
package jdk.nashorn.internal.codegen.objects;
-import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
-import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.PRIMITIVE_TYPE;
-import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
-import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.runtime.AccessorProperty;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
/**
@@ -72,11 +64,11 @@
/**
* Constructs a property map based on a set of fields.
*
- * @param isVarArg is this a vararg object map
+ * @param hasArguments does the created object have an "arguments" property
*
* @return New map populated with accessor properties.
*/
- public PropertyMap makeMap(final boolean isVarArg) {
+ public PropertyMap makeMap(final boolean hasArguments) {
final List<Property> properties = new ArrayList<>();
assert keys != null;
@@ -86,63 +78,31 @@
final Symbol symbol = symbols[i];
if (symbol != null && !ArrayIndex.isIndexKey(key)) {
- final Property property = initHandle(key, symbol.getFieldIndex(), symbol, isVarArg);
- properties.add(property);
+ properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex()));
}
}
return PropertyMap.newMap(structure, properties);
}
- private Property initHandle(final String key, final int fieldIndex, final Symbol symbol, final boolean isVarArg) {
- assert symbol != null;
- final boolean isParam = symbol.isParam();
-
- final String fieldNameObject = ObjectClassGenerator.getFieldName(fieldIndex, Type.OBJECT);
- final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(fieldIndex, ObjectClassGenerator.PRIMITIVE_TYPE);
-
- MethodHandle primitiveGetter = null;
- MethodHandle primitiveSetter = null;
- MethodHandle objectGetter;
- MethodHandle objectSetter;
-
- final MethodHandles.Lookup lookup = MethodHandles.lookup();
-
- if (isParam && isVarArg) {
- final MethodHandle arguments = MH.getter(MethodHandles.lookup(), structure, "arguments", Object.class);
- final MethodHandle argumentsSO = MH.asType(arguments, arguments.type().changeReturnType(ScriptObject.class));
- objectGetter = MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, fieldIndex);
- objectSetter = MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, fieldIndex);
- } else {
- objectGetter = MH.getter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass());
- objectSetter = MH.setter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass());
- if (!OBJECT_FIELDS_ONLY) {
- primitiveGetter = MH.getter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
- primitiveSetter = MH.setter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
- }
- }
-
- return new AccessorProperty(key, getPropertyFlags(symbol, isVarArg), objectGetter, objectSetter, primitiveGetter, primitiveSetter);
- }
-
/**
* Compute property flags given local state of a field. Maybe be overridden and extended,
* as is the case in {@link ObjectMapCreator}
*
- * @param symbol symbol to check
- * @param isVarArg is this a vararg
+ * @param symbol symbol to check
+ * @param hasArguments does the created object have an "arguments" property
*
* @return flags to use for fields
*/
- protected int getPropertyFlags(final Symbol symbol, final boolean isVarArg) {
- final boolean isParam = symbol.isParam();
+ protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) {
int flags = 0;
- if (isParam || isVarArg) {
- flags |= Property.IS_ALWAYS_OBJECT;
- if (isParam) {
- flags |= Property.IS_PARAMETER;
- }
+ if (symbol.isParam()) {
+ flags |= Property.IS_ALWAYS_OBJECT | Property.IS_PARAMETER;
+ }
+
+ if (hasArguments) {
+ flags |= Property.IS_ALWAYS_OBJECT | Property.HAS_ARGUMENTS;
}
if (symbol.isScope()) {
--- a/nashorn/src/jdk/nashorn/internal/codegen/objects/ObjectCreator.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/codegen/objects/ObjectCreator.java Fri Feb 08 09:19:38 2013 -0400
@@ -52,7 +52,7 @@
protected final CodeGenerator codegen;
private final boolean isScope;
- private final boolean isVarArg;
+ private final boolean hasArguments;
private int fieldCount;
private int paramCount;
private String fieldObjectClassName;
@@ -62,19 +62,19 @@
/**
* Constructor
*
- * @param codegen the code generator
- * @param keys the keys
- * @param symbols the symbols corresponding to keys, same index
- * @param isScope is this object scope
- * @param isVarArg is this object var arg
+ * @param codegen the code generator
+ * @param keys the keys
+ * @param symbols the symbols corresponding to keys, same index
+ * @param isScope is this object scope
+ * @param hasArguments does the created object have an "arguments" property
*/
- protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean isVarArg) {
+ protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean hasArguments) {
this.codegen = codegen;
this.compileUnit = codegen.getCurrentCompileUnit();
this.keys = keys;
this.symbols = symbols;
this.isScope = isScope;
- this.isVarArg = isVarArg;
+ this.hasArguments = hasArguments;
countFields();
findClass();
@@ -86,7 +86,7 @@
private void countFields() {
for (final Symbol symbol : this.symbols) {
if (symbol != null) {
- if (isVarArg() && symbol.isParam()) {
+ if (hasArguments() && symbol.isParam()) {
symbol.setFieldIndex(paramCount++);
} else {
symbol.setFieldIndex(fieldCount++);
@@ -133,7 +133,7 @@
if (keys.isEmpty()) { //empty map
propertyMap = PropertyMap.newMap(fieldObjectClass);
} else {
- propertyMap = newMapCreator(fieldObjectClass).makeMap(isVarArg());
+ propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments());
}
return propertyMap;
}
@@ -167,10 +167,10 @@
}
/**
- * Is this a vararg object
- * @return true if vararg
+ * Does the created object have an "arguments" property
+ * @return true if has an "arguments" property
*/
- protected boolean isVarArg() {
- return isVarArg;
+ protected boolean hasArguments() {
+ return hasArguments;
}
}
--- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Fri Feb 08 09:19:38 2013 -0400
@@ -139,7 +139,7 @@
// add a new property that throws TypeError on get as well as set
static synchronized PropertyMap newThrowerProperty(final PropertyMap map, final String name, final int flags) {
- return map.newProperty(name, flags, Lookup.TYPE_ERROR_THROWER_GETTER, Lookup.TYPE_ERROR_THROWER_SETTER);
+ return map.newProperty(name, flags, -1, Lookup.TYPE_ERROR_THROWER_GETTER, Lookup.TYPE_ERROR_THROWER_SETTER);
}
// property map for strict mode functions - lazily initialized
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java Fri Feb 08 09:19:38 2013 -0400
@@ -29,6 +29,7 @@
import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.DEBUG_FIELDS;
import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.LOG;
import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.PRIMITIVE_TYPE;
import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.createGetter;
import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.createGuardBoxedPrimitiveSetter;
import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.createSetter;
@@ -41,6 +42,7 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.linker.Lookup;
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
@@ -90,49 +92,6 @@
}
/**
- * Constructor
- *
- * primitiveGetter and setter are only used in dual fields mode. Setting them to null also
- * works in dual field mode, it only means that the property never has a primitive
- * representation
- *
- * @param key property key
- * @param flags property flags
- * @param objectGetter seed getter for object field
- * @param objectSetter seed setter for object field
- * @param primitiveGetter seed getter for primitive field (in dual field mode)
- * @param primitiveSetter seed setter for primitive field (in dual field mode)
- */
- public AccessorProperty(final String key, final int flags, final MethodHandle objectGetter, final MethodHandle objectSetter, final MethodHandle primitiveGetter, final MethodHandle primitiveSetter) {
- super(key, flags);
-
- this.objectGetter = objectGetter;
- this.objectSetter = objectSetter;
- this.primitiveGetter = primitiveGetter;
- this.primitiveSetter = primitiveSetter;
-
- Class<?> initialType = null;
-
- if (OBJECT_FIELDS_ONLY || isAlwaysObject()) {
- initialType = Object.class;
- } else {
- if (!canBePrimitive()) {
- info(key + " cannot be primitive");
- initialType = Object.class;
- } else {
- info(key + " CAN be primitive");
- if (!canBeUndefined()) {
- info(key + " is always defined");
- initialType = int.class; //double works too for less type invalidation, but this requires experimentation, e.g. var x = 17; x += 2 will turn it into double now because of lack of range analysis
- }
- }
- }
-
- // is always object means "is never initialized to undefined, and always of object type
- setCurrentType(initialType);
- }
-
- /**
* Delegate constructor. This is used when adding properties to the Global scope, which
* is necessary for outermost levels in a script (the ScriptObject is represented by
* a JO$-prefixed ScriptObject class, but the properties need to be in the Global scope
@@ -161,11 +120,12 @@
*
* @param key the property key
* @param flags the property flags
+ * @param slot the property field number or spill slot
* @param getter the property getter
* @param setter the property setter or null if non writable, non configurable
*/
- public AccessorProperty(final String key, final int flags, final MethodHandle getter, final MethodHandle setter) {
- super(key, flags);
+ public AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
+ super(key, flags, slot);
// we don't need to prep the setters these will never be invalidated as this is a nasgen
// or known type getter/setter. No invalidations will take place
@@ -193,6 +153,66 @@
}
/**
+ * Constructor for dual field AccessorPropertys.
+ *
+ * @param key property key
+ * @param flags property flags
+ * @param structure structure for objects associated with this property
+ * @param slot property field number or spill slot
+ */
+ public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot) {
+ super(key, flags, slot);
+
+ /*
+ *
+ * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also
+ * works in dual field mode, it only means that the property never has a primitive
+ * representation.
+ */
+ primitiveGetter = null;
+ primitiveSetter = null;
+
+ final MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+ if (isParameter() && hasArguments()) {
+ final MethodHandle arguments = MH.getter(MethodHandles.lookup(), structure, "arguments", Object.class);
+ final MethodHandle argumentsSO = MH.asType(arguments, arguments.type().changeReturnType(ScriptObject.class));
+
+ objectGetter = MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot);
+ objectSetter = MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, argumentsSO), 1, slot);
+ } else {
+ final String fieldNameObject = ObjectClassGenerator.getFieldName(slot, Type.OBJECT);
+ final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, ObjectClassGenerator.PRIMITIVE_TYPE);
+
+ objectGetter = MH.getter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass());
+ objectSetter = MH.setter(lookup, structure, fieldNameObject, Type.OBJECT.getTypeClass());
+
+ if (!OBJECT_FIELDS_ONLY) {
+ primitiveGetter = MH.getter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
+ primitiveSetter = MH.setter(lookup, structure, fieldNamePrimitive, PRIMITIVE_TYPE.getTypeClass());
+ }
+ }
+
+ Class<?> initialType = null;
+
+ if (OBJECT_FIELDS_ONLY || isAlwaysObject()) {
+ initialType = Object.class;
+ } else if (!canBePrimitive()) {
+ info(key + " cannot be primitive");
+ initialType = Object.class;
+ } else {
+ info(key + " CAN be primitive");
+ if (!canBeUndefined()) {
+ info(key + " is always defined");
+ initialType = int.class; //double works too for less type invalidation, but this requires experimentation, e.g. var x = 17; x += 2 will turn it into double now because of lack of range analysis
+ }
+ }
+
+ // is always object means "is never initialized to undefined, and always of object type
+ setCurrentType(initialType);
+ }
+
+ /**
* Copy constructor
*
* @param property source property
--- a/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java Fri Feb 08 09:19:38 2013 -0400
@@ -34,53 +34,26 @@
* This class represents the result from a find property search.
*/
public final class FindProperty {
+ /** Object where search began. */
private final ScriptObject self;
+ ;
+ /** Object where search finish. */
private final ScriptObject prototype;
- private final PropertyMap map;
+
+ /** Found property. */
private final Property property;
- private final int depth;
- private final boolean isScope;
/**
* Constructor
*
- * @param self script object where property was found
+ * @param self script object where search began
* @param prototype prototype where property was found, may be {@code self} if not inherited
- * @param map property map for script object
* @param property property that was search result
- * @param depth depth walked in property chain to find result
*/
- public FindProperty(final ScriptObject self, final ScriptObject prototype, final PropertyMap map, final Property property, final int depth) {
+ public FindProperty(final ScriptObject self, final ScriptObject prototype, final Property property) {
this.self = self;
this.prototype = prototype;
- this.map = map;
this.property = property;
- this.depth = depth;
- this.isScope = prototype.isScope();
- }
-
- /**
- * Get ScriptObject for search
- * @return script object
- */
- public ScriptObject getSelf() {
- return self;
- }
-
- /**
- * Get search depth
- * @return depth
- */
- public int getDepth() {
- return depth;
- }
-
- /**
- * Get flags for property that was found
- * @return property flags for property returned in {@link FindProperty#getProperty()}
- */
- public int getFlags() {
- return property.getFlags();
}
/**
@@ -102,20 +75,33 @@
}
/**
- * In certain properties, such as {@link UserAccessorProperty}, getter and setter functions
- * are present. This function gets the getter function as a {@code ScriptFunction}
- * @return getter function, or null if not present
+ * Ask for a setter that sets the given type. The type has nothing to do with the
+ * internal representation of the property. It may be an Object (boxing primitives) or
+ * a primitive (primitive fields with -Dnashorn.fields.dual=true)
+ * @see ObjectClassGenerator
+ *
+ * @param type type of setter, e.g. int.class if we want a function with {@code set(I)V} signature
+ * @param strict are we in strict mode
+ *
+ * @return method handle for the getter
*/
- public ScriptFunction getGetterFunction() {
- return property.getGetterFunction(getOwner());
+ public MethodHandle getSetter(final Class<?> type, final boolean strict) {
+ MethodHandle setter = property.getSetter(type, getOwner().getMap());
+ if (property instanceof UserAccessorProperty) {
+ final UserAccessorProperty uc = (UserAccessorProperty) property;
+ setter = MH.insertArguments(setter, 0, (isInherited() ? getOwner() : null),
+ uc.getSetterSlot(), strict? property.getKey() : null);
+ }
+
+ return setter;
}
/**
- * Return the property map where the property was found
- * @return property map
+ * Return the {@code ScriptObject} owning of the property: this means the prototype.
+ * @return owner of property
*/
- public PropertyMap getMap() {
- return map;
+ public ScriptObject getOwner() {
+ return prototype;
}
/**
@@ -148,62 +134,8 @@
* @return true if on scope
*/
public boolean isScope() {
- return isScope;
- }
-
- /**
- * Return the {@code ScriptObject} owning of the property: this means the prototype.
- * @return owner of property
- */
- public ScriptObject getOwner() {
- return prototype;
+ return prototype.isScope();
}
- /**
- * Ask for a setter that sets the given type. The type has nothing to do with the
- * internal representation of the property. It may be an Object (boxing primitives) or
- * a primitive (primitive fields with -Dnashorn.fields.dual=true)
- * @see ObjectClassGenerator
- *
- * @param type type of setter, e.g. int.class if we want a function with {@code set(I)V} signature
- * @param strict are we in strict mode
- *
- * @return method handle for the getter
- */
- public MethodHandle getSetter(final Class<?> type, final boolean strict) {
- MethodHandle setter = property.getSetter(type, getOwner().getMap());
- if (property instanceof UserAccessorProperty) {
- final UserAccessorProperty uc = (UserAccessorProperty) property;
- setter = MH.insertArguments(setter, 0, (isInherited() ? getOwner() : null),
- uc.getSetterSlot(), strict? property.getKey() : null);
- }
-
- return setter;
- }
-
- /**
- * In certain properties, such as {@link UserAccessorProperty}, getter and setter functions
- * are present. This function gets the setter function as a {@code ScriptFunction}
- * @return setter function, or null if not present
- */
- public ScriptFunction getSetterFunction() {
- return property.getSetterFunction(getOwner());
- }
-
- /**
- * Check if the property found is configurable
- * @return true if configurable
- */
- public boolean isConfigurable() {
- return property.isConfigurable();
- }
-
- /**
- * Check if the property found is writable
- * @return true if writable
- */
- public boolean isWritable() {
- return property.isWritable();
- }
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java Fri Feb 08 09:19:38 2013 -0400
@@ -67,17 +67,20 @@
/** Is this a spill property? See {@link SpillProperty} */
public static final int IS_SPILL = 0b0000_0001_0000;
- /** Is this a function parameter ? */
+ /** Is this a function parameter? */
public static final int IS_PARAMETER = 0b0000_0010_0000;
+ /** Is parameter accessed thru arguments? */
+ public static final int HAS_ARGUMENTS = 0b0000_0100_0000;
+
/** Is this property always represented as an Object? See {@link ObjectClassGenerator} and dual fields flag. */
- public static final int IS_ALWAYS_OBJECT = 0b0000_0100_0000;
+ public static final int IS_ALWAYS_OBJECT = 0b0000_1000_0000;
/** Can this property be primitive? */
- public static final int CAN_BE_PRIMITIVE = 0b0000_1000_0000;
+ public static final int CAN_BE_PRIMITIVE = 0b0001_0000_0000;
/** Can this property be undefined? */
- public static final int CAN_BE_UNDEFINED = 0b0001_0000_0000;
+ public static final int CAN_BE_UNDEFINED = 0b0010_0000_0000;
/** Property key. */
private final String key;
@@ -85,15 +88,21 @@
/** Property flags. */
protected int flags;
+ /** Property field number or spill slot */
+ private final int slot;
+
/**
* Constructor
*
* @param key property key
* @param flags property flags
+ * @param slot property field number or spill slot
*/
- public Property(final String key, final int flags) {
+ public Property(final String key, final int flags, final int slot) {
+ assert key != null;
this.key = key;
this.flags = flags;
+ this.slot = slot;
}
/**
@@ -104,6 +113,7 @@
protected Property(final Property property) {
this.key = property.key;
this.flags = property.flags;
+ this.slot = property.slot;
}
/**
@@ -215,6 +225,14 @@
}
/**
+ * Check whether this property is in an object with arguments field
+ * @return true if has arguments
+ */
+ public boolean hasArguments() {
+ return (flags & HAS_ARGUMENTS) == HAS_ARGUMENTS;
+ }
+
+ /**
* Check whether this is a spill property, i.e. one that will not
* be stored in a specially generated field in the property class.
* The spill pool is maintained separately, as a growing Object array
@@ -371,17 +389,17 @@
}
/**
- * Get the spill slot as described in {@link Property#getSpillCount()}.
- * @return spill slot, -1 if none exists
+ * Get the field number or spill slot
+ * @return number/slot, -1 if none exists
*/
public int getSlot() {
- return -1;
+ return slot;
}
@Override
public int hashCode() {
final Class<?> type = getCurrentType();
- return Objects.hashCode(this.key) ^ flags ^ (type == null ? 0 : type.hashCode());
+ return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
}
@Override
@@ -390,17 +408,16 @@
return true;
}
- if (!(other instanceof Property)) {
+ if (other == null || this.getClass() != other.getClass()) {
return false;
}
final Property otherProperty = (Property)other;
- final Object otherKey = otherProperty.key;
- final Class<?> otherType = otherProperty.getCurrentType();
- return flags == otherProperty.flags &&
- (key == null ? otherKey == null : key.equals(otherKey)) &&
- (getCurrentType() == otherType);
+ return getFlags() == otherProperty.getFlags() &&
+ getSlot() == otherProperty.getSlot() &&
+ getCurrentType() == otherProperty.getCurrentType() &&
+ getKey().equals(otherProperty.getKey());
}
@Override
@@ -417,6 +434,12 @@
append(type == null ? "UNDEFINED" : Type.typeFor(type).getDescriptor()).
append('}');
+ if (slot != -1) {
+ sb.append('[');
+ sb.append(slot);
+ sb.append(']');
+ }
+
return sb.toString();
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java Fri Feb 08 09:19:38 2013 -0400
@@ -271,13 +271,14 @@
*
* @param key {@link Property} key.
* @param propertyFlags {@link Property} flags.
+ * @param slot {@link Property} slot.
* @param getter {@link Property} get accessor method.
* @param setter {@link Property} set accessor method.
*
* @return New {@link PropertyMap} with {@link AccessorProperty} added.
*/
- public PropertyMap newProperty(final String key, final int propertyFlags, final MethodHandle getter, final MethodHandle setter) {
- return newProperty(new AccessorProperty(key, propertyFlags, getter, setter));
+ public PropertyMap newProperty(final String key, final int propertyFlags, final int slot, final MethodHandle getter, final MethodHandle setter) {
+ return newProperty(new AccessorProperty(key, propertyFlags, slot, getter, setter));
}
/**
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Feb 08 09:19:38 2013 -0400
@@ -650,24 +650,23 @@
* @return FindPropertyData or null if not found.
*/
public final FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope) {
- int depth = 0;
-
for (ScriptObject self = this; self != null; self = self.getProto()) {
// if doing deep search, stop search on the first non-scope object if asked to do so
- if (stopOnNonScope && depth != 0 && !self.isScope()) {
- break;
+ if (stopOnNonScope && self != this && !self.isScope()) {
+ return null;
}
+
final PropertyMap selfMap = self.getMap();
final Property property = selfMap.findProperty(key);
if (property != null) {
- return new FindProperty(this, self, selfMap, property, depth);
- } else if (!deep) {
+ return new FindProperty(this, self, property);
+ }
+
+ if (!deep) {
return null;
}
-
- depth++;
- }
+ }
return null;
}
@@ -999,7 +998,7 @@
* @return Value of property.
*/
public final Object getWithProperty(final Property property) {
- return getObjectValue(new FindProperty(this, this, getMap(), property, 0));
+ return getObjectValue(new FindProperty(this, this, property));
}
/**
@@ -1793,7 +1792,7 @@
// If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
// We should still check if inherited data property is not writable
- if (isExtensible() && !find.isWritable()) {
+ if (isExtensible() && !find.getProperty().isWritable()) {
return createEmptySetMethod(desc, "property.not.writable", false);
}
// Otherwise, forget the found property
@@ -1801,7 +1800,7 @@
}
if (find != null) {
- if(!find.isWritable()) {
+ if(!find.getProperty().isWritable()) {
// Existing, non-writable property
return createEmptySetMethod(desc, "property.not.writable", true);
}
@@ -2617,7 +2616,7 @@
MethodHandle setter;
if (f != null) {
- if (!f.isWritable()) {
+ if (!f.getProperty().isWritable()) {
if (strict) {
typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
}
@@ -3120,7 +3119,7 @@
return true;
}
- if (!find.isConfigurable()) {
+ if (!find.getProperty().isConfigurable()) {
if (strict) {
typeError("cant.delete.property", propName, ScriptRuntime.safeToString(this));
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java Fri Feb 08 09:19:38 2013 -0400
@@ -42,9 +42,6 @@
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);
- /** Property slot in spill */
- private final int slot;
-
/**
* Constructor
*
@@ -55,14 +52,11 @@
* @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, getter, setter);
- this.slot = slot;
+ super(key, flags, slot, getter, setter);
}
private SpillProperty(final SpillProperty property) {
super(property);
-
- this.slot = property.slot;
}
@Override
@@ -88,31 +82,4 @@
return super.getSetter(type, currentMap);
}
- @Override
- public int getSlot() {
- return slot;
- }
-
- @Override
- public String toString() {
- return super.toString() + '[' + slot + ']';
- }
-
- @Override
- public int hashCode() {
- return super.hashCode() ^ slot;
- }
-
- @Override
- public boolean equals(final Object other) {
- if (this == other) {
- return true;
- }
-
- if (other instanceof SpillProperty) {
- return super.equals(other) && slot == ((SpillProperty) other).slot;
- }
-
- return false;
- }
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java Fri Feb 08 09:19:38 2013 -0400
@@ -60,7 +60,7 @@
* @param setterSlot setter slot, starting at first embed
*/
public UserAccessorProperty(final String key, final int flags, final int getterSlot, final int setterSlot) {
- super(key, flags);
+ super(key, flags, -1);
this.getterSlot = getterSlot;
this.setterSlot = setterSlot;
}
@@ -95,17 +95,13 @@
@Override
public boolean equals(final Object other) {
- if (this == other) {
- return true;
+ if (!super.equals(other)) {
+ return false;
}
- if (other instanceof UserAccessorProperty) {
- final UserAccessorProperty uc = (UserAccessorProperty) other;
- return super.equals(other) && getterSlot == uc.getterSlot && setterSlot == uc.setterSlot;
- }
-
- return false;
- }
+ final UserAccessorProperty uc = (UserAccessorProperty) other;
+ return getterSlot == uc.getterSlot && setterSlot == uc.setterSlot;
+ }
@Override
public int hashCode() {
@@ -158,6 +154,6 @@
public ScriptFunction getSetterFunction(final ScriptObject obj) {
final Object value = obj.getEmbedOrSpill(setterSlot);
return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
+ }
- }
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/Lookup.java Thu Feb 07 15:33:17 2013 +0100
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/Lookup.java Fri Feb 08 09:19:38 2013 -0400
@@ -160,7 +160,7 @@
throw new IllegalArgumentException("getter/setter has wrong arguments");
}
- return map.newProperty(key, flags, getter, setter);
+ return map.newProperty(key, flags, -1, getter, setter);
}
/**