nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
changeset 27307 62ed492cbe63
parent 26768 751b0f427090
child 27814 96427359f4fe
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java	Tue Oct 28 17:22:17 2014 +0530
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java	Thu Oct 30 19:55:56 2014 +0100
@@ -102,6 +102,13 @@
     /** Property field number or spill slot. */
     private final int slot;
 
+    /**
+     * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
+     * null means undefined, and primitive types are allowed. The reason a special type is used for
+     * undefined, is that are no bits left to represent it in primitive types
+     */
+    private Class<?> type;
+
     /** SwitchPoint that is invalidated when property is changed, optional */
     protected transient SwitchPoint builtinSwitchPoint;
 
@@ -536,7 +543,7 @@
      * <p>
      * see {@link ObjectClassGenerator#createSetter(Class, Class, MethodHandle, MethodHandle)}
      * if you are interested in the internal details of this. Note that if you
-     * are running in default mode, with {@code -Dnashorn.fields.dual=true}, disabled, the setters
+     * are running with {@code -Dnashorn.fields.objects=true}, the setters
      * will currently never change, as all properties are represented as Object field,
      * the Object fields are Initialized to {@code ScriptRuntime.UNDEFINED} and primitives are
      * boxed/unboxed upon every access, which is not necessarily optimal
@@ -569,7 +576,7 @@
 
     @Override
     public int hashCode() {
-        final Class<?> type = getCurrentType();
+        final Class<?> type = getLocalType();
         return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
     }
 
@@ -586,7 +593,7 @@
         final Property otherProperty = (Property)other;
 
         return equalsWithoutType(otherProperty) &&
-               getCurrentType() == otherProperty.getCurrentType();
+                getLocalType() == otherProperty.getLocalType();
     }
 
     boolean equalsWithoutType(final Property otherProperty) {
@@ -615,7 +622,7 @@
      */
     public final String toStringShort() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getCurrentType();
+        final Class<?>      type = getLocalType();
         sb.append(getKey()).append(" (").append(type(type)).append(')');
         return sb.toString();
     }
@@ -632,7 +639,7 @@
     @Override
     public String toString() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getCurrentType();
+        final Class<?>      type = getLocalType();
 
         sb.append(indent(getKey(), 20)).
             append(" id=").
@@ -656,20 +663,40 @@
     }
 
     /**
-     * Get the current type of this field. If you are not running with dual fields enabled,
+     * Get the current type of this property. If you are running with object fields enabled,
      * this will always be Object.class. See the value representation explanation in
      * {@link Property#getSetter(Class, PropertyMap)} and {@link ObjectClassGenerator}
      * for more information.
      *
+     * <p>Note that for user accessor properties, this returns the type of the last observed
+     * value passed to or returned by a user accessor. Use {@link #getLocalType()} to always get
+     * the type of the actual value stored in the property slot.</p>
+     *
      * @return current type of property, null means undefined
      */
-    public abstract Class<?> getCurrentType();
+    public final Class<?> getType() {
+        return type;
+    }
 
     /**
-     * Reset the current type of this property
-     * @param currentType new current type
+     * Set the type of this property.
+     * @param type new type
      */
-    public abstract void setCurrentType(final Class<?> currentType);
+    public final void setType(final Class<?> type) {
+        assert type != boolean.class : "no boolean storage support yet - fix this";
+        this.type = type == null ? null : type.isPrimitive() ? type : Object.class;
+    }
+
+    /**
+     * Get the type of the value in the local property slot. This returns the same as
+     * {@link #getType()} for normal properties, but always returns {@code Object.class}
+     * for {@link UserAccessorProperty}s as their local type is a pair of accessor references.
+     *
+     * @return the local property type
+     */
+    protected Class<?> getLocalType() {
+        return getType();
+    }
 
     /**
      * Check whether this Property can ever change its type. The default is false, and if