nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java
changeset 27307 62ed492cbe63
parent 26768 751b0f427090
child 27814 96427359f4fe
equal deleted inserted replaced
27306:cfb08ee17d57 27307:62ed492cbe63
   100     private int flags;
   100     private int flags;
   101 
   101 
   102     /** Property field number or spill slot. */
   102     /** Property field number or spill slot. */
   103     private final int slot;
   103     private final int slot;
   104 
   104 
       
   105     /**
       
   106      * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
       
   107      * null means undefined, and primitive types are allowed. The reason a special type is used for
       
   108      * undefined, is that are no bits left to represent it in primitive types
       
   109      */
       
   110     private Class<?> type;
       
   111 
   105     /** SwitchPoint that is invalidated when property is changed, optional */
   112     /** SwitchPoint that is invalidated when property is changed, optional */
   106     protected transient SwitchPoint builtinSwitchPoint;
   113     protected transient SwitchPoint builtinSwitchPoint;
   107 
   114 
   108     private static final long serialVersionUID = 2099814273074501176L;
   115     private static final long serialVersionUID = 2099814273074501176L;
   109 
   116 
   534      * we automatically get a map guard that relinks the call site so that the
   541      * we automatically get a map guard that relinks the call site so that the
   535      * older setter will never be used again.
   542      * older setter will never be used again.
   536      * <p>
   543      * <p>
   537      * see {@link ObjectClassGenerator#createSetter(Class, Class, MethodHandle, MethodHandle)}
   544      * see {@link ObjectClassGenerator#createSetter(Class, Class, MethodHandle, MethodHandle)}
   538      * if you are interested in the internal details of this. Note that if you
   545      * if you are interested in the internal details of this. Note that if you
   539      * are running in default mode, with {@code -Dnashorn.fields.dual=true}, disabled, the setters
   546      * are running with {@code -Dnashorn.fields.objects=true}, the setters
   540      * will currently never change, as all properties are represented as Object field,
   547      * will currently never change, as all properties are represented as Object field,
   541      * the Object fields are Initialized to {@code ScriptRuntime.UNDEFINED} and primitives are
   548      * the Object fields are Initialized to {@code ScriptRuntime.UNDEFINED} and primitives are
   542      * boxed/unboxed upon every access, which is not necessarily optimal
   549      * boxed/unboxed upon every access, which is not necessarily optimal
   543      *
   550      *
   544      * @param type setter parameter type
   551      * @param type setter parameter type
   567         return null;
   574         return null;
   568     }
   575     }
   569 
   576 
   570     @Override
   577     @Override
   571     public int hashCode() {
   578     public int hashCode() {
   572         final Class<?> type = getCurrentType();
   579         final Class<?> type = getLocalType();
   573         return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
   580         return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
   574     }
   581     }
   575 
   582 
   576     @Override
   583     @Override
   577     public boolean equals(final Object other) {
   584     public boolean equals(final Object other) {
   584         }
   591         }
   585 
   592 
   586         final Property otherProperty = (Property)other;
   593         final Property otherProperty = (Property)other;
   587 
   594 
   588         return equalsWithoutType(otherProperty) &&
   595         return equalsWithoutType(otherProperty) &&
   589                getCurrentType() == otherProperty.getCurrentType();
   596                 getLocalType() == otherProperty.getLocalType();
   590     }
   597     }
   591 
   598 
   592     boolean equalsWithoutType(final Property otherProperty) {
   599     boolean equalsWithoutType(final Property otherProperty) {
   593         return getFlags() == otherProperty.getFlags() &&
   600         return getFlags() == otherProperty.getFlags() &&
   594                 getSlot() == otherProperty.getSlot() &&
   601                 getSlot() == otherProperty.getSlot() &&
   613      * Short toString version
   620      * Short toString version
   614      * @return short toString
   621      * @return short toString
   615      */
   622      */
   616     public final String toStringShort() {
   623     public final String toStringShort() {
   617         final StringBuilder sb   = new StringBuilder();
   624         final StringBuilder sb   = new StringBuilder();
   618         final Class<?>      type = getCurrentType();
   625         final Class<?>      type = getLocalType();
   619         sb.append(getKey()).append(" (").append(type(type)).append(')');
   626         sb.append(getKey()).append(" (").append(type(type)).append(')');
   620         return sb.toString();
   627         return sb.toString();
   621     }
   628     }
   622 
   629 
   623     private static String indent(final String str, final int indent) {
   630     private static String indent(final String str, final int indent) {
   630      }
   637      }
   631 
   638 
   632     @Override
   639     @Override
   633     public String toString() {
   640     public String toString() {
   634         final StringBuilder sb   = new StringBuilder();
   641         final StringBuilder sb   = new StringBuilder();
   635         final Class<?>      type = getCurrentType();
   642         final Class<?>      type = getLocalType();
   636 
   643 
   637         sb.append(indent(getKey(), 20)).
   644         sb.append(indent(getKey(), 20)).
   638             append(" id=").
   645             append(" id=").
   639             append(Debug.id(this)).
   646             append(Debug.id(this)).
   640             append(" (0x").
   647             append(" (0x").
   654 
   661 
   655         return sb.toString();
   662         return sb.toString();
   656     }
   663     }
   657 
   664 
   658     /**
   665     /**
   659      * Get the current type of this field. If you are not running with dual fields enabled,
   666      * Get the current type of this property. If you are running with object fields enabled,
   660      * this will always be Object.class. See the value representation explanation in
   667      * this will always be Object.class. See the value representation explanation in
   661      * {@link Property#getSetter(Class, PropertyMap)} and {@link ObjectClassGenerator}
   668      * {@link Property#getSetter(Class, PropertyMap)} and {@link ObjectClassGenerator}
   662      * for more information.
   669      * for more information.
   663      *
   670      *
       
   671      * <p>Note that for user accessor properties, this returns the type of the last observed
       
   672      * value passed to or returned by a user accessor. Use {@link #getLocalType()} to always get
       
   673      * the type of the actual value stored in the property slot.</p>
       
   674      *
   664      * @return current type of property, null means undefined
   675      * @return current type of property, null means undefined
   665      */
   676      */
   666     public abstract Class<?> getCurrentType();
   677     public final Class<?> getType() {
   667 
   678         return type;
   668     /**
   679     }
   669      * Reset the current type of this property
   680 
   670      * @param currentType new current type
   681     /**
   671      */
   682      * Set the type of this property.
   672     public abstract void setCurrentType(final Class<?> currentType);
   683      * @param type new type
       
   684      */
       
   685     public final void setType(final Class<?> type) {
       
   686         assert type != boolean.class : "no boolean storage support yet - fix this";
       
   687         this.type = type == null ? null : type.isPrimitive() ? type : Object.class;
       
   688     }
       
   689 
       
   690     /**
       
   691      * Get the type of the value in the local property slot. This returns the same as
       
   692      * {@link #getType()} for normal properties, but always returns {@code Object.class}
       
   693      * for {@link UserAccessorProperty}s as their local type is a pair of accessor references.
       
   694      *
       
   695      * @return the local property type
       
   696      */
       
   697     protected Class<?> getLocalType() {
       
   698         return getType();
       
   699     }
   673 
   700 
   674     /**
   701     /**
   675      * Check whether this Property can ever change its type. The default is false, and if
   702      * Check whether this Property can ever change its type. The default is false, and if
   676      * you are not running with dual fields, the type is always object and can never change
   703      * you are not running with dual fields, the type is always object and can never change
   677      * @return true if this property can change types
   704      * @return true if this property can change types