8006220: Simplify PropertyMaps

Tue, 30 Apr 2013 10:05:42 -0300

author
jlaskey
date
Tue, 30 Apr 2013 10:05:42 -0300
changeset 242
b754fb89367d
parent 237
ad28f2b52b12
child 243
80cb02dedc83
child 244
7563c56ca565

8006220: Simplify PropertyMaps
Reviewed-by: hannesw, lagergren
Contributed-by: james.laskey@oracle.com

src/jdk/nashorn/internal/codegen/MapCreator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/codegen/ObjectCreator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeDebug.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeJSAdapter.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/AccessorProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Context.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Property.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyHashMap.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/PropertyMap.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/SetMethodCreator.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/SpillProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/StructureLoader.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/UserAccessorProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/scripts/JO.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/tools/Shell.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/codegen/MapCreator.java	Tue Apr 30 09:42:13 2013 +0200
     1.2 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java	Tue Apr 30 10:05:42 2013 -0300
     1.3 @@ -65,10 +65,12 @@
     1.4       * Constructs a property map based on a set of fields.
     1.5       *
     1.6       * @param hasArguments does the created object have an "arguments" property
     1.7 +     * @param fieldCount    Number of fields in use.
     1.8 +     * @param fieldMaximum Number of fields available.
     1.9       *
    1.10       * @return New map populated with accessor properties.
    1.11       */
    1.12 -    PropertyMap makeMap(final boolean hasArguments) {
    1.13 +    PropertyMap makeMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum) {
    1.14          final List<Property> properties = new ArrayList<>();
    1.15  
    1.16          assert keys != null;
    1.17 @@ -82,7 +84,7 @@
    1.18              }
    1.19          }
    1.20  
    1.21 -        return PropertyMap.newMap(structure, properties);
    1.22 +        return PropertyMap.newMap(structure, properties, fieldCount, fieldMaximum);
    1.23      }
    1.24  
    1.25      /**
     2.1 --- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Tue Apr 30 09:42:13 2013 +0200
     2.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java	Tue Apr 30 10:05:42 2013 -0300
     2.3 @@ -69,6 +69,16 @@
     2.4      static final String SCOPE_MARKER = "P";
     2.5  
     2.6      /**
     2.7 +     * Minimum number of extra fields in an object.
     2.8 +     */
     2.9 +    static final int FIELD_PADDING  = 4;
    2.10 +
    2.11 +    /**
    2.12 +     * Rounding when calculating the number of fields.
    2.13 +     */
    2.14 +    static final int FIELD_ROUNDING = 4;
    2.15 +
    2.16 +    /**
    2.17       * Debug field logger
    2.18       * Should we print debugging information for fields when they are generated and getters/setters are called?
    2.19       */
     3.1 --- a/src/jdk/nashorn/internal/codegen/ObjectCreator.java	Tue Apr 30 09:42:13 2013 +0200
     3.2 +++ b/src/jdk/nashorn/internal/codegen/ObjectCreator.java	Tue Apr 30 10:05:42 2013 -0300
     3.3 @@ -26,6 +26,8 @@
     3.4  package jdk.nashorn.internal.codegen;
     3.5  
     3.6  import java.util.List;
     3.7 +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.FIELD_PADDING;
     3.8 +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.FIELD_ROUNDING;
     3.9  import jdk.nashorn.internal.ir.Symbol;
    3.10  import jdk.nashorn.internal.runtime.Context;
    3.11  import jdk.nashorn.internal.runtime.PropertyMap;
    3.12 @@ -50,6 +52,7 @@
    3.13      private   final boolean       isScope;
    3.14      private   final boolean       hasArguments;
    3.15      private         int           fieldCount;
    3.16 +    private         int           paddedFieldCount;
    3.17      private         int           paramCount;
    3.18      private         String        fieldObjectClassName;
    3.19      private         Class<?>      fieldObjectClass;
    3.20 @@ -88,6 +91,8 @@
    3.21                  }
    3.22              }
    3.23          }
    3.24 +
    3.25 +        paddedFieldCount = (fieldCount + FIELD_PADDING + FIELD_ROUNDING - 1) / FIELD_ROUNDING * FIELD_ROUNDING;
    3.26      }
    3.27  
    3.28      /**
    3.29 @@ -96,7 +101,7 @@
    3.30      private void findClass() {
    3.31          fieldObjectClassName = isScope() ?
    3.32              ObjectClassGenerator.getClassName(fieldCount, paramCount) :
    3.33 -            ObjectClassGenerator.getClassName(fieldCount);
    3.34 +            ObjectClassGenerator.getClassName(paddedFieldCount);
    3.35  
    3.36          try {
    3.37              this.fieldObjectClass = Context.forStructureClass(Compiler.binaryName(fieldObjectClassName));
    3.38 @@ -125,11 +130,7 @@
    3.39       * @return the newly created property map
    3.40       */
    3.41      protected PropertyMap makeMap() {
    3.42 -        if (keys.isEmpty()) { //empty map
    3.43 -            propertyMap = PropertyMap.newMap(fieldObjectClass);
    3.44 -        } else {
    3.45 -            propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments());
    3.46 -        }
    3.47 +        propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments(), fieldCount, paddedFieldCount);
    3.48          return propertyMap;
    3.49      }
    3.50  
     4.1 --- a/src/jdk/nashorn/internal/objects/NativeDebug.java	Tue Apr 30 09:42:13 2013 +0200
     4.2 +++ b/src/jdk/nashorn/internal/objects/NativeDebug.java	Tue Apr 30 10:05:42 2013 -0300
     4.3 @@ -87,66 +87,6 @@
     4.4      }
     4.5  
     4.6      /**
     4.7 -     * Nashorn extension: get embed0 from {@link ScriptObject}
     4.8 -     *
     4.9 -     * @param self self reference
    4.10 -     * @param obj script object
    4.11 -     * @return the embed0 property value for the given ScriptObject
    4.12 -     */
    4.13 -    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    4.14 -    public static Object embed0(final Object self, final Object obj) {
    4.15 -        if (obj instanceof ScriptObject) {
    4.16 -            return ((ScriptObject)obj).embed0;
    4.17 -        }
    4.18 -        return UNDEFINED;
    4.19 -    }
    4.20 -
    4.21 -    /**
    4.22 -     * Nashorn extension: get embed1 from {@link ScriptObject}
    4.23 -     *
    4.24 -     * @param self self reference
    4.25 -     * @param obj script object
    4.26 -     * @return the embed1 property value for the given ScriptObject
    4.27 -     */
    4.28 -    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    4.29 -    public static Object embed1(final Object self, final Object obj) {
    4.30 -        if (obj instanceof ScriptObject) {
    4.31 -            return ((ScriptObject)obj).embed1;
    4.32 -        }
    4.33 -        return UNDEFINED;
    4.34 -    }
    4.35 -
    4.36 -    /**
    4.37 -     * Nashorn extension: get embed2 from {@link ScriptObject}
    4.38 -     *
    4.39 -     * @param self self reference
    4.40 -     * @param obj script object
    4.41 -     * @return the embed2 property value for the given ScriptObject
    4.42 -     */
    4.43 -    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    4.44 -    public static Object embed2(final Object self, final Object obj) {
    4.45 -        if (obj instanceof ScriptObject) {
    4.46 -            return ((ScriptObject)obj).embed2;
    4.47 -        }
    4.48 -        return UNDEFINED;
    4.49 -    }
    4.50 -
    4.51 -    /**
    4.52 -     * Nashorn extension: get embed3 from {@link ScriptObject}
    4.53 -     *
    4.54 -     * @param self self reference
    4.55 -     * @param obj script object
    4.56 -     * @return the embed3 property value for the given ScriptObject
    4.57 -     */
    4.58 -    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
    4.59 -    public static Object embed3(final Object self, final Object obj) {
    4.60 -        if (obj instanceof ScriptObject) {
    4.61 -            return ((ScriptObject)obj).embed3;
    4.62 -        }
    4.63 -        return UNDEFINED;
    4.64 -    }
    4.65 -
    4.66 -    /**
    4.67       * Nashorn extension: get spill vector from {@link ScriptObject}
    4.68       *
    4.69       * @param self self reference
     5.1 --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Tue Apr 30 09:42:13 2013 +0200
     5.2 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java	Tue Apr 30 10:05:42 2013 -0300
     5.3 @@ -620,7 +620,7 @@
     5.4                  // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
     5.5                  return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
     5.6                          func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
     5.7 -                        adaptee.getMap().getProtoGetSwitchPoint(__call__), testJSAdaptor(adaptee, null, null, null));
     5.8 +                        adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), __call__), testJSAdaptor(adaptee, null, null, null));
     5.9              }
    5.10              throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
    5.11          default:
    5.12 @@ -687,7 +687,7 @@
    5.13              if (methodHandle != null) {
    5.14                  return new GuardedInvocation(
    5.15                          methodHandle,
    5.16 -                        adaptee.getMap().getProtoGetSwitchPoint(hook),
    5.17 +                        adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook),
    5.18                          testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
    5.19              }
    5.20          }
    5.21 @@ -699,7 +699,7 @@
    5.22              final MethodHandle methodHandle = hook.equals(__put__) ?
    5.23              MH.asType(Lookup.EMPTY_SETTER, type) :
    5.24              Lookup.emptyGetter(type.returnType());
    5.25 -            return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(hook), testJSAdaptor(adaptee, null, null, null));
    5.26 +            return new GuardedInvocation(methodHandle, adaptee.getMap().getProtoGetSwitchPoint(adaptee.getProto(), hook), testJSAdaptor(adaptee, null, null, null));
    5.27          }
    5.28      }
    5.29  
     6.1 --- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Tue Apr 30 09:42:13 2013 +0200
     6.2 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java	Tue Apr 30 10:05:42 2013 -0300
     6.3 @@ -50,8 +50,6 @@
     6.4  /**
     6.5   * An AccessorProperty is the most generic property type. An AccessorProperty is
     6.6   * represented as fields in a ScriptObject class.
     6.7 - *
     6.8 - * @see SpillProperty
     6.9   */
    6.10  public class AccessorProperty extends Property {
    6.11      private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
    6.12 @@ -77,6 +75,7 @@
    6.13  
    6.14      private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
    6.15      private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
    6.16 +    private static final MethodHandle SPILLGETTER = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), Lookup.GET_OBJECT_TYPE);
    6.17  
    6.18      /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
    6.19      private MethodHandle primitiveGetter;
    6.20 @@ -285,7 +284,7 @@
    6.21                  "get");
    6.22          }
    6.23  
    6.24 -        return getters[i];
    6.25 +        return isSpill() ? MH.filterArguments(getters[i], 0, SPILLGETTER) : getters[i];
    6.26      }
    6.27  
    6.28      private Property getWiderProperty(final Class<?> type) {
    6.29 @@ -327,6 +326,7 @@
    6.30          final Class<?> forType = currentType == null ? type : currentType;
    6.31  
    6.32          //if we are asking for an object setter, but are still a primitive type, we might try to box it
    6.33 +        MethodHandle mh;
    6.34  
    6.35          if (needsInvalidator(i, ci)) {
    6.36              final Property     newProperty = getWiderProperty(type);
    6.37 @@ -335,12 +335,15 @@
    6.38              final MethodHandle explodeTypeSetter = MH.filterArguments(widerSetter, 0, MH.insertArguments(REPLACE_MAP, 1, newMap, getKey(), currentType, type));
    6.39              if (currentType != null && currentType.isPrimitive() && type == Object.class) {
    6.40                  //might try a box check on this to avoid widening field to object storage
    6.41 -                return createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter);
    6.42 +                mh = createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter);
    6.43 +            } else {
    6.44 +                mh = explodeTypeSetter;
    6.45              }
    6.46 -            return explodeTypeSetter;
    6.47 +        } else {
    6.48 +            mh = generateSetter(forType, type);
    6.49          }
    6.50  
    6.51 -        return generateSetter(forType, type);
    6.52 +        return isSpill() ? MH.filterArguments(mh, 0, SPILLGETTER) : mh;
    6.53      }
    6.54  
    6.55      @Override
     7.1 --- a/src/jdk/nashorn/internal/runtime/Context.java	Tue Apr 30 09:42:13 2013 +0200
     7.2 +++ b/src/jdk/nashorn/internal/runtime/Context.java	Tue Apr 30 10:05:42 2013 -0300
     7.3 @@ -201,9 +201,6 @@
     7.4      /** Current error manager. */
     7.5      private final ErrorManager errors;
     7.6  
     7.7 -    /** Empty map used for seed map for JO objects */
     7.8 -    final PropertyMap emptyMap = PropertyMap.newEmptyMap(this);
     7.9 -
    7.10      private static final ClassLoader myLoader = Context.class.getClassLoader();
    7.11      private static final StructureLoader sharedLoader;
    7.12  
     8.1 --- a/src/jdk/nashorn/internal/runtime/Property.java	Tue Apr 30 09:42:13 2013 +0200
     8.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java	Tue Apr 30 10:05:42 2013 -0300
     8.3 @@ -41,7 +41,6 @@
     8.4   *
     8.5   * @see PropertyMap
     8.6   * @see AccessorProperty
     8.7 - * @see SpillProperty
     8.8   * @see UserAccessorProperty
     8.9   */
    8.10  public abstract class Property {
    8.11 @@ -64,7 +63,7 @@
    8.12  
    8.13      private static final int MODIFY_MASK     = 0b0000_0000_1111;
    8.14  
    8.15 -    /** Is this a spill property? See {@link SpillProperty} */
    8.16 +    /** Is this a spill property? See {@link AccessorProperty} */
    8.17      public static final int IS_SPILL         = 0b0000_0001_0000;
    8.18  
    8.19      /** Is this a function parameter? */
    8.20 @@ -88,7 +87,7 @@
    8.21      /** Property flags. */
    8.22      protected int flags;
    8.23  
    8.24 -    /** Property field number or spill slot */
    8.25 +    /** Property field number or spill slot. */
    8.26      private final int slot;
    8.27  
    8.28      /**
    8.29 @@ -248,7 +247,7 @@
    8.30       * Does this property use any slots in the spill array described in
    8.31       * {@link Property#isSpill}? In that case how many. Currently a property
    8.32       * only uses max one spill slot, but this may change in future representations
    8.33 -     * Only {@link SpillProperty} instances use spill slots
    8.34 +     * Only {@link AccessorProperty} instances use spill slots
    8.35       *
    8.36       * @return number of spill slots a property is using
    8.37       */
    8.38 @@ -345,6 +344,14 @@
    8.39      }
    8.40  
    8.41      /**
    8.42 +     * Get the field number or spill slot
    8.43 +     * @return number/slot, -1 if none exists
    8.44 +     */
    8.45 +    public int getSlot() {
    8.46 +        return slot;
    8.47 +    }
    8.48 +
    8.49 +    /**
    8.50       * Abstract method for retrieving the setter for the property. We do not know
    8.51       * anything about the internal representation when we request the setter, we only
    8.52       * know that the setter will take the property as a parameter of the given type.
    8.53 @@ -388,14 +395,6 @@
    8.54          return null;
    8.55      }
    8.56  
    8.57 -    /**
    8.58 -     * Get the field number or spill slot
    8.59 -     * @return number/slot, -1 if none exists
    8.60 -     */
    8.61 -    public int getSlot() {
    8.62 -        return slot;
    8.63 -    }
    8.64 -
    8.65      @Override
    8.66      public int hashCode() {
    8.67          final Class<?> type = getCurrentType();
     9.1 --- a/src/jdk/nashorn/internal/runtime/PropertyHashMap.java	Tue Apr 30 09:42:13 2013 +0200
     9.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyHashMap.java	Tue Apr 30 10:05:42 2013 -0300
     9.3 @@ -110,7 +110,7 @@
     9.4      private static final int LIST_THRESHOLD = 8;
     9.5  
     9.6      /** Initial map. */
     9.7 -    public static final PropertyHashMap EMPTY_MAP = new PropertyHashMap();
     9.8 +    public static final PropertyHashMap EMPTY_HASHMAP = new PropertyHashMap();
     9.9  
    9.10      /** Number of properties in the map. */
    9.11      private final int size;
    9.12 @@ -246,7 +246,7 @@
    9.13              }
    9.14          } else if (findElement(list, key) != null) {
    9.15              final int newSize = size - 1;
    9.16 -            return newSize != 0 ? new PropertyHashMap(newSize, null, removeFromList(list, key)) : EMPTY_MAP;
    9.17 +            return newSize != 0 ? new PropertyHashMap(newSize, null, removeFromList(list, key)) : EMPTY_HASHMAP;
    9.18          }
    9.19          return this;
    9.20      }
    10.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Tue Apr 30 09:42:13 2013 +0200
    10.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Tue Apr 30 10:05:42 2013 -0300
    10.3 @@ -25,7 +25,7 @@
    10.4  
    10.5  package jdk.nashorn.internal.runtime;
    10.6  
    10.7 -import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_MAP;
    10.8 +import static jdk.nashorn.internal.runtime.PropertyHashMap.EMPTY_HASHMAP;
    10.9  
   10.10  import java.lang.invoke.MethodHandle;
   10.11  import java.lang.invoke.SwitchPoint;
   10.12 @@ -49,29 +49,27 @@
   10.13   * will return a new map.
   10.14   */
   10.15  public final class PropertyMap implements Iterable<Object>, PropertyListener {
   10.16 -    /** Is this a prototype PropertyMap? */
   10.17 -    public static final int IS_PROTOTYPE          = 0b0000_0001;
   10.18      /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
   10.19 -    public static final int NOT_EXTENSIBLE        = 0b0000_0010;
   10.20 +    public static final int NOT_EXTENSIBLE        = 0b0000_0001;
   10.21      /** This mask is used to preserve certain flags when cloning the PropertyMap. Others should not be copied */
   10.22      private static final int CLONEABLE_FLAGS_MASK = 0b0000_1111;
   10.23      /** Has a listener been added to this property map. This flag is not copied when cloning a map. See {@link PropertyListener} */
   10.24      public static final int IS_LISTENER_ADDED     = 0b0001_0000;
   10.25  
   10.26 +    /** Empty map used for seed map for JO$ objects */
   10.27 +    private static final PropertyMap EMPTY_MAP = new PropertyMap(EMPTY_HASHMAP);
   10.28 +
   10.29      /** Map status flags. */
   10.30      private int flags;
   10.31  
   10.32 -    /** Class of object referenced.*/
   10.33 -    private final Class<?> structure;
   10.34 -
   10.35 -    /** Context associated with this {@link PropertyMap}. */
   10.36 -    private final Context context;
   10.37 -
   10.38      /** Map of properties. */
   10.39      private final PropertyHashMap properties;
   10.40  
   10.41 -    /** objects proto. */
   10.42 -    private ScriptObject proto;
   10.43 +    /** Number of fields in use. */
   10.44 +    private int fieldCount;
   10.45 +
   10.46 +    /** Number of fields available. */
   10.47 +    private int fieldMaximum;
   10.48  
   10.49      /** Length of spill in use. */
   10.50      private int spillLength;
   10.51 @@ -91,15 +89,15 @@
   10.52      /**
   10.53       * Constructor.
   10.54       *
   10.55 -     * @param structure  Class the map's {@link AccessorProperty}s apply to.
   10.56 -     * @param context    Context associated with this {@link PropertyMap}.
   10.57 -     * @param properties A {@link PropertyHashMap} with initial contents.
   10.58 +     * @param properties    A {@link PropertyHashMap} with initial contents.
   10.59 +     * @param fieldCount    Number of fields in use.
   10.60 +     * @param fieldMaximum Number of fields available.
   10.61       */
   10.62 -    PropertyMap(final Class<?> structure, final Context context, final PropertyHashMap properties) {
   10.63 -        this.structure  = structure;
   10.64 -        this.context    = context;
   10.65 -        this.properties = properties;
   10.66 -        this.hashCode   = computeHashCode();
   10.67 +    private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum) {
   10.68 +        this.properties   = properties;
   10.69 +        this.hashCode     = computeHashCode();
   10.70 +        this.fieldCount   = fieldCount;
   10.71 +        this.fieldMaximum = fieldMaximum;
   10.72  
   10.73          if (Context.DEBUG) {
   10.74              count++;
   10.75 @@ -107,19 +105,27 @@
   10.76      }
   10.77  
   10.78      /**
   10.79 +     * Constructor.
   10.80 +     *
   10.81 +     * @param properties A {@link PropertyHashMap} with initial contents.
   10.82 +     */
   10.83 +    private PropertyMap(final PropertyHashMap properties) {
   10.84 +        this(properties, 0, 0);
   10.85 +    }
   10.86 +
   10.87 +    /**
   10.88       * Cloning constructor.
   10.89       *
   10.90       * @param propertyMap Existing property map.
   10.91       * @param properties  A {@link PropertyHashMap} with a new set of properties.
   10.92       */
   10.93      private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
   10.94 -        this.structure   = propertyMap.structure;
   10.95 -        this.context     = propertyMap.context;
   10.96 -        this.properties  = properties;
   10.97 -        this.flags       = propertyMap.getClonedFlags();
   10.98 -        this.proto       = propertyMap.proto;
   10.99 -        this.spillLength = propertyMap.spillLength;
  10.100 -        this.hashCode    = computeHashCode();
  10.101 +        this.properties   = properties;
  10.102 +        this.flags        = propertyMap.getClonedFlags();
  10.103 +        this.spillLength  = propertyMap.spillLength;
  10.104 +        this.fieldCount   = propertyMap.fieldCount;
  10.105 +        this.fieldMaximum = propertyMap.fieldMaximum;
  10.106 +        this.hashCode     = computeHashCode();
  10.107  
  10.108          if (Context.DEBUG) {
  10.109              count++;
  10.110 @@ -128,6 +134,15 @@
  10.111      }
  10.112  
  10.113      /**
  10.114 +     * Cloning constructor.
  10.115 +     *
  10.116 +     * @param propertyMap Existing property map.
  10.117 +      */
  10.118 +    private PropertyMap(final PropertyMap propertyMap) {
  10.119 +        this(propertyMap, propertyMap.properties);
  10.120 +    }
  10.121 +
  10.122 +    /**
  10.123       * Duplicates this PropertyMap instance. This is used by nasgen generated
  10.124       * prototype and constructor classes. {@link PropertyMap} used for singletons
  10.125       * like these (and global instance) are duplicated using this method and used.
  10.126 @@ -138,7 +153,7 @@
  10.127       * @return Duplicated {@link PropertyMap}.
  10.128       */
  10.129      public PropertyMap duplicate() {
  10.130 -        return new PropertyMap(this.structure, this.context, this.properties);
  10.131 +        return new PropertyMap(this.properties);
  10.132      }
  10.133  
  10.134      /**
  10.135 @@ -146,20 +161,20 @@
  10.136       *
  10.137       * @param structure  Class the map's {@link AccessorProperty}s apply to.
  10.138       * @param properties Collection of initial properties.
  10.139 +     * @param fieldCount    Number of fields in use.
  10.140 +     * @param fieldMaximum Number of fields available.
  10.141       *
  10.142       * @return New {@link PropertyMap}.
  10.143       */
  10.144 -    public static PropertyMap newMap(final Class<?> structure, final Collection<Property> properties) {
  10.145 -        final Context context = Context.fromClass(structure);
  10.146 -
  10.147 +    public static PropertyMap newMap(final Class<?> structure, final Collection<Property> properties, final int fieldCount, final int fieldMaximum) {
  10.148          // Reduce the number of empty maps in the context.
  10.149          if (structure == jdk.nashorn.internal.scripts.JO.class) {
  10.150 -            return context.emptyMap;
  10.151 +            return EMPTY_MAP;
  10.152          }
  10.153  
  10.154 -        PropertyHashMap newProperties = EMPTY_MAP.immutableAdd(properties);
  10.155 +        PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
  10.156  
  10.157 -        return new PropertyMap(structure, context, newProperties);
  10.158 +        return new PropertyMap(newProperties, fieldCount, fieldMaximum);
  10.159      }
  10.160  
  10.161      /**
  10.162 @@ -170,7 +185,7 @@
  10.163       * @return New {@link PropertyMap}.
  10.164       */
  10.165      public static PropertyMap newMap(final Class<?> structure) {
  10.166 -        return newMap(structure, null);
  10.167 +        return newMap(structure, null, 0, 0);
  10.168      }
  10.169  
  10.170      /**
  10.171 @@ -180,7 +195,7 @@
  10.172       * @return New empty {@link PropertyMap}.
  10.173       */
  10.174      public static PropertyMap newEmptyMap(final Context context) {
  10.175 -        return new PropertyMap(jdk.nashorn.internal.scripts.JO.class, context, EMPTY_MAP);
  10.176 +        return new PropertyMap(EMPTY_HASHMAP);
  10.177      }
  10.178  
  10.179      /**
  10.180 @@ -195,11 +210,12 @@
  10.181      /**
  10.182       * Return a SwitchPoint used to track changes of a property in a prototype.
  10.183       *
  10.184 -     * @param key {@link Property} key.
  10.185 +     * @param proto  Object prototype.
  10.186 +     * @param key    {@link Property} key.
  10.187       *
  10.188       * @return A shared {@link SwitchPoint} for the property.
  10.189       */
  10.190 -    public SwitchPoint getProtoGetSwitchPoint(final String key) {
  10.191 +    public SwitchPoint getProtoGetSwitchPoint(final ScriptObject proto, final String key) {
  10.192          if (proto == null) {
  10.193              return null;
  10.194          }
  10.195 @@ -295,6 +311,11 @@
  10.196              final PropertyHashMap newProperties = properties.immutableAdd(property);
  10.197              newMap = new PropertyMap(this, newProperties);
  10.198              addToHistory(property, newMap);
  10.199 +
  10.200 +            if(!property.isSpill()) {
  10.201 +                newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
  10.202 +            }
  10.203 +
  10.204              newMap.spillLength += property.getSpillCount();
  10.205          }
  10.206  
  10.207 @@ -355,7 +376,6 @@
  10.208                  newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
  10.209  
  10.210          newMap.flags = getClonedFlags();
  10.211 -        newMap.proto = proto;
  10.212  
  10.213          /*
  10.214           * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
  10.215 @@ -411,7 +431,7 @@
  10.216       * @return New map with {@link #NOT_EXTENSIBLE} flag set.
  10.217       */
  10.218      PropertyMap preventExtensions() {
  10.219 -        final PropertyMap newMap = new PropertyMap(this, this.properties);
  10.220 +        final PropertyMap newMap = new PropertyMap(this);
  10.221          newMap.flags |= NOT_EXTENSIBLE;
  10.222          return newMap;
  10.223      }
  10.224 @@ -423,7 +443,7 @@
  10.225       * {@link Property#NOT_CONFIGURABLE} set.
  10.226       */
  10.227      PropertyMap seal() {
  10.228 -        PropertyHashMap newProperties = EMPTY_MAP;
  10.229 +        PropertyHashMap newProperties = EMPTY_HASHMAP;
  10.230  
  10.231          for (final Property oldProperty :  properties.getProperties()) {
  10.232              newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
  10.233 @@ -442,7 +462,7 @@
  10.234       * {@link Property#NOT_CONFIGURABLE} and {@link Property#NOT_WRITABLE} set.
  10.235       */
  10.236      PropertyMap freeze() {
  10.237 -        PropertyHashMap newProperties = EMPTY_MAP;
  10.238 +        PropertyHashMap newProperties = EMPTY_HASHMAP;
  10.239  
  10.240          for (Property oldProperty : properties.getProperties()) {
  10.241              int propertyFlags = Property.NOT_CONFIGURABLE;
  10.242 @@ -578,11 +598,7 @@
  10.243       * @return Computed hash code.
  10.244       */
  10.245      private int computeHashCode() {
  10.246 -        int hash = structure.hashCode();
  10.247 -
  10.248 -        if (proto != null) {
  10.249 -            hash ^= proto.hashCode();
  10.250 -        }
  10.251 +        int hash = 0;
  10.252  
  10.253          for (final Property property : getProperties()) {
  10.254              hash = hash << 7 ^ hash >> 7;
  10.255 @@ -605,9 +621,7 @@
  10.256  
  10.257          final PropertyMap otherMap = (PropertyMap)other;
  10.258  
  10.259 -        if (structure != otherMap.structure ||
  10.260 -            proto != otherMap.proto ||
  10.261 -            properties.size() != otherMap.properties.size()) {
  10.262 +        if (properties.size() != otherMap.properties.size()) {
  10.263              return false;
  10.264          }
  10.265  
  10.266 @@ -659,31 +673,6 @@
  10.267      }
  10.268  
  10.269      /**
  10.270 -     * Return map's {@link Context}.
  10.271 -     *
  10.272 -     * @return The {@link Context} where the map originated.
  10.273 -     */
  10.274 -    Context getContext() {
  10.275 -        return context;
  10.276 -    }
  10.277 -
  10.278 -    /**
  10.279 -     * Check if this map is a prototype
  10.280 -     *
  10.281 -     * @return {@code true} if is prototype
  10.282 -     */
  10.283 -    public boolean isPrototype() {
  10.284 -        return (flags & IS_PROTOTYPE) != 0;
  10.285 -    }
  10.286 -
  10.287 -    /**
  10.288 -     * Flag this map as having a prototype.
  10.289 -     */
  10.290 -    private void setIsPrototype() {
  10.291 -        flags |= IS_PROTOTYPE;
  10.292 -    }
  10.293 -
  10.294 -    /**
  10.295       * Check whether a {@link PropertyListener} has been added to this map.
  10.296       *
  10.297       * @return {@code true} if {@link PropertyListener} exists
  10.298 @@ -720,6 +709,22 @@
  10.299      boolean isFrozen() {
  10.300          return !isExtensible() && allFrozen();
  10.301      }
  10.302 +    /**
  10.303 +     * Get the number of fields allocated for this {@link PropertyMap}.
  10.304 +     *
  10.305 +     * @return Number of fields allocated.
  10.306 +     */
  10.307 +    int getFieldCount() {
  10.308 +        return fieldCount;
  10.309 +    }
  10.310 +    /**
  10.311 +     * Get maximum number of fields available for this {@link PropertyMap}.
  10.312 +     *
  10.313 +     * @return Number of fields available.
  10.314 +     */
  10.315 +    int getFieldMaximum() {
  10.316 +        return fieldMaximum;
  10.317 +    }
  10.318  
  10.319      /**
  10.320       * Get length of spill area associated with this {@link PropertyMap}.
  10.321 @@ -731,25 +736,20 @@
  10.322      }
  10.323  
  10.324      /**
  10.325 -     * Return the prototype of objects associated with this {@link PropertyMap}.
  10.326 +     * Change the prototype of objects associated with this {@link PropertyMap}.
  10.327       *
  10.328 -     * @return Prototype object.
  10.329 -     */
  10.330 -    ScriptObject getProto() {
  10.331 -        return proto;
  10.332 -    }
  10.333 -
  10.334 -    /**
  10.335 -     * Set the prototype of objects associated with this {@link PropertyMap}.
  10.336 -     *
  10.337 -     * @param newProto Prototype object to use.
  10.338 +     * @param oldProto Current prototype object.
  10.339 +     * @param newProto New prototype object to replace oldProto.
  10.340       *
  10.341       * @return New {@link PropertyMap} with prototype changed.
  10.342       */
  10.343 -    PropertyMap setProto(final ScriptObject newProto) {
  10.344 -        final ScriptObject oldProto = this.proto;
  10.345 -
  10.346 -        if (oldProto == newProto) {
  10.347 +    PropertyMap changeProto(final ScriptObject oldProto, final ScriptObject newProto) {
  10.348 +        if ((oldProto == newProto) ||
  10.349 +            (size() == 0 &&
  10.350 +             oldProto == null &&
  10.351 +             protoGetSwitches == null &&
  10.352 +             history == null &&
  10.353 +             protoHistory == null)) {
  10.354              return this;
  10.355          }
  10.356  
  10.357 @@ -761,19 +761,10 @@
  10.358          if (Context.DEBUG) {
  10.359              incrementSetProtoNewMapCount();
  10.360          }
  10.361 -        final PropertyMap newMap = new PropertyMap(this, this.properties);
  10.362 +
  10.363 +        final PropertyMap newMap = new PropertyMap(this);
  10.364          addToProtoHistory(newProto, newMap);
  10.365  
  10.366 -        newMap.proto = newProto;
  10.367 -
  10.368 -        if (oldProto != null && newMap.isListenerAdded()) {
  10.369 -            oldProto.removePropertyListener(newMap);
  10.370 -        }
  10.371 -
  10.372 -        if (newProto != null) {
  10.373 -            newProto.getMap().setIsPrototype();
  10.374 -        }
  10.375 -
  10.376          return newMap;
  10.377      }
  10.378  
  10.379 @@ -927,4 +918,3 @@
  10.380          setProtoNewMapCount++;
  10.381      }
  10.382  }
  10.383 -
    11.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Apr 30 09:42:13 2013 +0200
    11.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Tue Apr 30 10:05:42 2013 -0300
    11.3 @@ -104,34 +104,31 @@
    11.4      /** Per ScriptObject flag - is this an arguments object? */
    11.5      public static final int IS_ARGUMENTS   = 0b0000_0100;
    11.6  
    11.7 +    /** Is this a prototype PropertyMap? */
    11.8 +    public static final int IS_PROTOTYPE   = 0b0000_1000;
    11.9 +
   11.10      /** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
   11.11      public static final int SPILL_RATE = 8;
   11.12  
   11.13      /** Map to property information and accessor functions. Ordered by insertion. */
   11.14      private PropertyMap map;
   11.15  
   11.16 +    /** objects proto. */
   11.17 +    private ScriptObject proto;
   11.18 +
   11.19 +    /** Context of the object, lazily cached. */
   11.20 +    private Context context;
   11.21 +
   11.22      /** Object flags. */
   11.23      private int flags;
   11.24  
   11.25 -    /** Area for properties added to object after instantiation, see {@link SpillProperty} */
   11.26 +    /** Area for properties added to object after instantiation, see {@link AccessorProperty} */
   11.27      public Object[] spill;
   11.28  
   11.29 -    /** Local embed area position 0 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
   11.30 -    public Object embed0;
   11.31 -
   11.32 -    /** Local embed area position 1 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
   11.33 -    public Object embed1;
   11.34 -
   11.35 -    /** Local embed area position 2 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
   11.36 -    public Object embed2;
   11.37 -
   11.38 -    /** Local embed area position 3 - used for {@link SpillProperty} before {@link ScriptObject#spill} */
   11.39 -    public Object embed3;
   11.40 -
   11.41      /** Indexed array data. */
   11.42      private ArrayData arrayData;
   11.43  
   11.44 -    static final MethodHandle SETEMBED           = findOwnMH("setEmbed",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, int.class, Object.class, Object.class);
   11.45 +    static final MethodHandle SETFIELD           = findOwnMH("setField",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
   11.46      static final MethodHandle SETSPILL           = findOwnMH("setSpill",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
   11.47      static final MethodHandle SETSPILLWITHNEW    = findOwnMH("setSpillWithNew",  void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
   11.48      static final MethodHandle SETSPILLWITHGROW   = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
   11.49 @@ -783,8 +780,8 @@
   11.50                  // delete getter and setter function references so that we don't leak
   11.51                  if (property instanceof UserAccessorProperty) {
   11.52                      final UserAccessorProperty uc = (UserAccessorProperty) property;
   11.53 -                    setEmbedOrSpill(uc.getGetterSlot(), null);
   11.54 -                    setEmbedOrSpill(uc.getSetterSlot(), null);
   11.55 +                    setSpill(uc.getGetterSlot(), null);
   11.56 +                    setSpill(uc.getSetterSlot(), null);
   11.57                  }
   11.58                  return true;
   11.59              }
   11.60 @@ -809,7 +806,7 @@
   11.61  
   11.62              int getterSlot = uc.getGetterSlot();
   11.63              // clear the old getter and set the new getter
   11.64 -            setEmbedOrSpill(getterSlot, getter);
   11.65 +            setSpill(getterSlot, getter);
   11.66              // if getter function is null, flag the slot to be negative (less by 1)
   11.67              if (getter == null) {
   11.68                  getterSlot = -getterSlot - 1;
   11.69 @@ -817,7 +814,7 @@
   11.70  
   11.71              int setterSlot = uc.getSetterSlot();
   11.72              // clear the old setter and set the new setter
   11.73 -            setEmbedOrSpill(setterSlot, setter);
   11.74 +            setSpill(setterSlot, setter);
   11.75              // if setter function is null, flag the slot to be negative (less by 1)
   11.76              if (setter == null) {
   11.77                  setterSlot = -setterSlot - 1;
   11.78 @@ -1056,8 +1053,11 @@
   11.79       * Return the current context from the object's map.
   11.80       * @return Current context.
   11.81       */
   11.82 -    final Context getContext() {
   11.83 -        return getMap().getContext();
   11.84 +    protected final Context getContext() {
   11.85 +        if (context == null) {
   11.86 +            context = Context.fromClass(getClass());
   11.87 +        }
   11.88 +        return context;
   11.89      }
   11.90  
   11.91      /**
   11.92 @@ -1097,44 +1097,30 @@
   11.93       * @return __proto__ object.
   11.94       */
   11.95      public final ScriptObject getProto() {
   11.96 -        return getMap().getProto();
   11.97 -    }
   11.98 -
   11.99 -    /**
  11.100 -     * Check if this is a prototype
  11.101 -     * @return true if {@link PropertyMap#isPrototype()} is true for this ScriptObject
  11.102 -     */
  11.103 -    public final boolean isPrototype() {
  11.104 -        return getMap().isPrototype();
  11.105 +        return proto;
  11.106      }
  11.107  
  11.108      /**
  11.109       * Set the __proto__ of an object.
  11.110       * @param newProto new __proto__ to set.
  11.111       */
  11.112 -    public final void setProto(final ScriptObject newProto) {
  11.113 -        PropertyMap  oldMap   = getMap();
  11.114 -        ScriptObject oldProto = getProto();
  11.115 -
  11.116 -        while (oldProto != newProto) {
  11.117 -            final PropertyMap newMap = oldMap.setProto(newProto);
  11.118 -
  11.119 -            if (!compareAndSetMap(oldMap, newMap)) {
  11.120 -                oldMap = getMap();
  11.121 -                oldProto = getProto();
  11.122 -            } else {
  11.123 -                if (isPrototype()) {
  11.124 -
  11.125 -                    if (oldProto != null) {
  11.126 -                        oldProto.removePropertyListener(this);
  11.127 -                    }
  11.128 -
  11.129 -                    if (newProto != null) {
  11.130 -                        newProto.addPropertyListener(this);
  11.131 -                    }
  11.132 -                }
  11.133 -
  11.134 -                return;
  11.135 +    public synchronized final void setProto(final ScriptObject newProto) {
  11.136 +        final ScriptObject oldProto = proto;
  11.137 +        map = map.changeProto(oldProto, newProto);
  11.138 +
  11.139 +        if (newProto != null) {
  11.140 +            newProto.setIsPrototype();
  11.141 +        }
  11.142 +
  11.143 +        proto = newProto;
  11.144 +
  11.145 +        if (isPrototype()) {
  11.146 +            if (oldProto != null) {
  11.147 +                oldProto.removePropertyListener(this);
  11.148 +            }
  11.149 +
  11.150 +            if (newProto != null) {
  11.151 +                newProto.addPropertyListener(this);
  11.152              }
  11.153          }
  11.154      }
  11.155 @@ -1327,6 +1313,22 @@
  11.156      }
  11.157  
  11.158      /**
  11.159 +     * Check if this object is a prototype
  11.160 +     *
  11.161 +     * @return {@code true} if is prototype
  11.162 +     */
  11.163 +    public boolean isPrototype() {
  11.164 +        return (flags & IS_PROTOTYPE) != 0;
  11.165 +    }
  11.166 +
  11.167 +    /**
  11.168 +     * Flag this object as having a prototype.
  11.169 +     */
  11.170 +    public void setIsPrototype() {
  11.171 +        flags |= IS_PROTOTYPE;
  11.172 +    }
  11.173 +
  11.174 +    /**
  11.175       * Get the {@link ArrayData} for this ScriptObject if it is an array
  11.176       * @return array data
  11.177       */
  11.178 @@ -1719,11 +1721,11 @@
  11.179              if (!property.hasGetterFunction()) {
  11.180                  methodHandle = bindTo(methodHandle, prototype);
  11.181              }
  11.182 -            return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(name), guard);
  11.183 +            return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard);
  11.184          }
  11.185  
  11.186          assert !NashornCallSiteDescriptor.isFastScope(desc);
  11.187 -        return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(name), guard);
  11.188 +        return new GuardedInvocation(Lookup.emptyGetter(returnType), getMap().getProtoGetSwitchPoint(proto, name), guard);
  11.189      }
  11.190  
  11.191      private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name) {
  11.192 @@ -1822,27 +1824,31 @@
  11.193             }
  11.194             assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
  11.195             final PropertyMap myMap = getMap();
  11.196 -           return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(name), NashornGuards.getMapGuard(myMap));
  11.197 +           return new GuardedInvocation(Lookup.EMPTY_SETTER, myMap.getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(myMap));
  11.198      }
  11.199  
  11.200      @SuppressWarnings("unused")
  11.201 -    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 {
  11.202 +    private static void setField(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final MethodHandle setter, final Object self, final Object value) throws Throwable {
  11.203          final ScriptObject obj = (ScriptObject)self;
  11.204 -        if (obj.trySetEmbedOrSpill(desc, oldMap, newMap, value)) {
  11.205 -            obj.useEmbed(i);
  11.206 +        final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
  11.207 +        if (!obj.isExtensible()) {
  11.208 +            throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
  11.209 +        } else if (obj.compareAndSetMap(oldMap, newMap)) {
  11.210              setter.invokeExact(self, value);
  11.211 +        } else {
  11.212 +            obj.set(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND), value, isStrict);
  11.213          }
  11.214      }
  11.215  
  11.216      @SuppressWarnings("unused")
  11.217      private static void setSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final Object self, final Object value) {
  11.218          final ScriptObject obj = (ScriptObject)self;
  11.219 -        if (obj.trySetEmbedOrSpill(desc, oldMap, newMap, value)) {
  11.220 +        if (obj.trySetSpill(desc, oldMap, newMap, value)) {
  11.221              obj.spill[index] = value;
  11.222          }
  11.223      }
  11.224  
  11.225 -    private boolean trySetEmbedOrSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final Object value) {
  11.226 +    private boolean trySetSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final Object value) {
  11.227          final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
  11.228          if (!isExtensible() && isStrict) {
  11.229              throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(this));
  11.230 @@ -1964,7 +1970,7 @@
  11.231                      methodHandle = bindTo(methodHandle, UNDEFINED);
  11.232                  }
  11.233                  return new GuardedInvocation(methodHandle,
  11.234 -                        find.isInherited()? getMap().getProtoGetSwitchPoint(NO_SUCH_PROPERTY_NAME) : null,
  11.235 +                        find.isInherited()? getMap().getProtoGetSwitchPoint(proto, NO_SUCH_PROPERTY_NAME) : null,
  11.236                          getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
  11.237              }
  11.238          }
  11.239 @@ -1995,7 +2001,7 @@
  11.240      }
  11.241  
  11.242      private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
  11.243 -        return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(name), NashornGuards.getMapGuard(getMap()));
  11.244 +        return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()), getMap().getProtoGetSwitchPoint(proto, name), NashornGuards.getMapGuard(getMap()));
  11.245      }
  11.246  
  11.247      private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
  11.248 @@ -2070,36 +2076,39 @@
  11.249       * @return Added property.
  11.250       */
  11.251      private Property addSpillProperty(final String key, final int propertyFlags) {
  11.252 -        int i = findEmbed();
  11.253 -        Property spillProperty;
  11.254 -
  11.255 -        if (i >= EMBED_SIZE) {
  11.256 -            i = getMap().getSpillLength();
  11.257 +        int fieldCount   = getMap().getFieldCount();
  11.258 +        int fieldMaximum = getMap().getFieldMaximum();
  11.259 +        Property property;
  11.260 +
  11.261 +        if (fieldCount < fieldMaximum) {
  11.262 +            property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
  11.263 +            notifyPropertyAdded(this, property);
  11.264 +            property = addOwnProperty(property);
  11.265 +        } else {
  11.266 +            int i = getMap().getSpillLength();
  11.267              MethodHandle getter = MH.arrayElementGetter(Object[].class);
  11.268              MethodHandle setter = MH.arrayElementSetter(Object[].class);
  11.269              getter = MH.asType(MH.insertArguments(getter, 1, i), Lookup.GET_OBJECT_TYPE);
  11.270              setter = MH.asType(MH.insertArguments(setter, 1, i), Lookup.SET_OBJECT_TYPE);
  11.271 -            spillProperty = new SpillProperty(key, propertyFlags | Property.IS_SPILL, i, getter, setter);
  11.272 -            notifyPropertyAdded(this, spillProperty);
  11.273 -            spillProperty = addOwnProperty(spillProperty);
  11.274 -            i = spillProperty.getSlot();
  11.275 +            property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i, getter, setter);
  11.276 +            notifyPropertyAdded(this, property);
  11.277 +            property = addOwnProperty(property);
  11.278 +            i = property.getSlot();
  11.279  
  11.280              final int newLength = (i + SPILL_RATE) / SPILL_RATE * SPILL_RATE;
  11.281 -            final Object[] newSpill = new Object[newLength];
  11.282 -
  11.283 -            if (spill != null) {
  11.284 -                System.arraycopy(spill, 0, newSpill, 0, spill.length);
  11.285 +
  11.286 +            if (spill == null || newLength > spill.length) {
  11.287 +                final Object[] newSpill = new Object[newLength];
  11.288 +
  11.289 +                if (spill != null) {
  11.290 +                    System.arraycopy(spill, 0, newSpill, 0, spill.length);
  11.291 +                }
  11.292 +
  11.293 +                spill = newSpill;
  11.294              }
  11.295 -
  11.296 -            spill = newSpill;
  11.297 -         } else {
  11.298 -            useEmbed(i);
  11.299 -            spillProperty = new SpillProperty(key, propertyFlags, i, GET_EMBED[i], SET_EMBED[i]);
  11.300 -            notifyPropertyAdded(this, spillProperty);
  11.301 -            spillProperty = addOwnProperty(spillProperty);
  11.302          }
  11.303  
  11.304 -        return spillProperty;
  11.305 +        return property;
  11.306      }
  11.307  
  11.308  
  11.309 @@ -3159,67 +3168,22 @@
  11.310      }
  11.311  
  11.312      /*
  11.313 -     * Embed management
  11.314 -     */
  11.315 -
  11.316 -    /** Number of embed slots */
  11.317 -    public static final int EMBED_SIZE   = 4;
  11.318 -    /** Embed offset */
  11.319 -    public static final int EMBED_OFFSET = 32 - EMBED_SIZE;
  11.320 -
  11.321 -    static final MethodHandle[] GET_EMBED;
  11.322 -    static final MethodHandle[] SET_EMBED;
  11.323 -
  11.324 -    static {
  11.325 -        GET_EMBED = new MethodHandle[EMBED_SIZE];
  11.326 -        SET_EMBED = new MethodHandle[EMBED_SIZE];
  11.327 -
  11.328 -        for (int i = 0; i < EMBED_SIZE; i++) {
  11.329 -            final String name = "embed" + i;
  11.330 -            GET_EMBED[i] = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, name, Object.class), Lookup.GET_OBJECT_TYPE);
  11.331 -            SET_EMBED[i] = MH.asType(MH.setter(MethodHandles.lookup(), ScriptObject.class, name, Object.class), Lookup.SET_OBJECT_TYPE);
  11.332 -        }
  11.333 -    }
  11.334 -
  11.335 -    void useEmbed(final int i) {
  11.336 -        flags |= 1 << (EMBED_OFFSET + i);
  11.337 -    }
  11.338 -
  11.339 -    int findEmbed() {
  11.340 -        final int bits  = ~(flags >>> EMBED_OFFSET);
  11.341 -        final int least = bits ^ -bits;
  11.342 -        final int index = Integer.numberOfTrailingZeros(least) - 1;
  11.343 -
  11.344 -        return index;
  11.345 -    }
  11.346 -
  11.347 -    /*
  11.348       * Make a new UserAccessorProperty property. getter and setter functions are stored in
  11.349       * this ScriptObject and slot values are used in property object.
  11.350       */
  11.351      private UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
  11.352          int oldSpillLength = getMap().getSpillLength();
  11.353  
  11.354 -        int getterSlot = findEmbed();
  11.355 -        if (getterSlot >= EMBED_SIZE) {
  11.356 -            getterSlot = oldSpillLength + EMBED_SIZE;
  11.357 -            ++oldSpillLength;
  11.358 -        } else {
  11.359 -            useEmbed(getterSlot);
  11.360 -        }
  11.361 -        setEmbedOrSpill(getterSlot, getter);
  11.362 +        int getterSlot = oldSpillLength++;
  11.363 +        setSpill(getterSlot, getter);
  11.364          // if getter function is null, flag the slot to be negative (less by 1)
  11.365          if (getter == null) {
  11.366              getterSlot = -getterSlot - 1;
  11.367          }
  11.368  
  11.369 -        int setterSlot = findEmbed();
  11.370 -        if (setterSlot >= EMBED_SIZE) {
  11.371 -            setterSlot = oldSpillLength + EMBED_SIZE;
  11.372 -        } else {
  11.373 -            useEmbed(setterSlot);
  11.374 -        }
  11.375 -        setEmbedOrSpill(setterSlot, setter);
  11.376 +        int setterSlot = oldSpillLength++;
  11.377 +
  11.378 +        setSpill(setterSlot, setter);
  11.379          // if setter function is null, flag the slot to be negative (less by 1)
  11.380          if (setter == null) {
  11.381              setterSlot = -setterSlot - 1;
  11.382 @@ -3228,56 +3192,28 @@
  11.383          return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot);
  11.384      }
  11.385  
  11.386 -    private void setEmbedOrSpill(final int slot, final Object value) {
  11.387 -        switch (slot) {
  11.388 -        case 0:
  11.389 -            embed0 = value;
  11.390 -            break;
  11.391 -        case 1:
  11.392 -            embed1 = value;
  11.393 -            break;
  11.394 -        case 2:
  11.395 -            embed2 = value;
  11.396 -            break;
  11.397 -        case 3:
  11.398 -            embed3 = value;
  11.399 -            break;
  11.400 -        default:
  11.401 -            if (slot >= 0) {
  11.402 -                final int index = (slot - EMBED_SIZE);
  11.403 -                if (spill == null) {
  11.404 -                    // create new spill.
  11.405 -                    spill = new Object[Math.max(index + 1, SPILL_RATE)];
  11.406 -                } else if (index >= spill.length) {
  11.407 -                    // grow spill as needed
  11.408 -                    final Object[] newSpill = new Object[index + 1];
  11.409 -                    System.arraycopy(spill, 0, newSpill, 0, spill.length);
  11.410 -                    spill = newSpill;
  11.411 -                }
  11.412 -
  11.413 -                spill[index] = value;
  11.414 +    private void setSpill(final int slot, final Object value) {
  11.415 +        if (slot >= 0) {
  11.416 +            final int index = slot;
  11.417 +            if (spill == null) {
  11.418 +                // create new spill.
  11.419 +                spill = new Object[Math.max(index + 1, SPILL_RATE)];
  11.420 +            } else if (index >= spill.length) {
  11.421 +                // grow spill as needed
  11.422 +                final Object[] newSpill = new Object[index + 1];
  11.423 +                System.arraycopy(spill, 0, newSpill, 0, spill.length);
  11.424 +                spill = newSpill;
  11.425              }
  11.426 -            break;
  11.427 +
  11.428 +            spill[index] = value;
  11.429          }
  11.430      }
  11.431  
  11.432 -    // user accessors are either stored in embed fields or spill array slots
  11.433 -    // get the accessor value using slot number. Note that slot is either embed
  11.434 -    // field number or (spill array index + embedSize).
  11.435 -    Object getEmbedOrSpill(final int slot) {
  11.436 -        switch (slot) {
  11.437 -        case 0:
  11.438 -            return embed0;
  11.439 -        case 1:
  11.440 -            return embed1;
  11.441 -        case 2:
  11.442 -            return embed2;
  11.443 -        case 3:
  11.444 -            return embed3;
  11.445 -        default:
  11.446 -            final int index = (slot - EMBED_SIZE);
  11.447 -            return (index < 0 || (index >= spill.length)) ? null : spill[index];
  11.448 -        }
  11.449 +    // user accessors are either stored in spill array slots
  11.450 +    // get the accessor value using slot number. Note that slot is spill array index.
  11.451 +    Object getSpill(final int slot) {
  11.452 +        final int index = slot;
  11.453 +        return (index < 0 || (index >= spill.length)) ? null : spill[index];
  11.454      }
  11.455  
  11.456      // User defined getter and setter are always called by "dyn:call". Note that the user
  11.457 @@ -3287,7 +3223,7 @@
  11.458      @SuppressWarnings("unused")
  11.459      private static Object userAccessorGetter(final ScriptObject proto, final int slot, final Object self) {
  11.460          final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
  11.461 -        final Object       func      = container.getEmbedOrSpill(slot);
  11.462 +        final Object       func      = container.getSpill(slot);
  11.463  
  11.464          if (func instanceof ScriptFunction) {
  11.465              try {
  11.466 @@ -3305,7 +3241,7 @@
  11.467      @SuppressWarnings("unused")
  11.468      private static void userAccessorSetter(final ScriptObject proto, final int slot, final String name, final Object self, final Object value) {
  11.469          final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
  11.470 -        final Object       func      = container.getEmbedOrSpill(slot);
  11.471 +        final Object       func      = container.getSpill(slot);
  11.472  
  11.473          if (func instanceof ScriptFunction) {
  11.474              try {
    12.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Tue Apr 30 09:42:13 2013 +0200
    12.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Tue Apr 30 10:05:42 2013 -0300
    12.3 @@ -166,18 +166,20 @@
    12.4      }
    12.5  
    12.6      private SetMethod createNewPropertySetter() {
    12.7 -        final int nextEmbed = sobj.findEmbed();
    12.8 -        final SetMethod sm;
    12.9 -        if (nextEmbed >= ScriptObject.EMBED_SIZE) {
   12.10 -            sm = createNewSpillPropertySetter();
   12.11 -        } else {
   12.12 -            sm = createNewEmbedPropertySetter(nextEmbed);
   12.13 -        }
   12.14 -
   12.15 +        final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
   12.16          sobj.notifyPropertyAdded(sobj, sm.property);
   12.17          return sm;
   12.18      }
   12.19  
   12.20 +    private SetMethod createNewFieldSetter() {
   12.21 +        final PropertyMap oldMap = getMap();
   12.22 +        final Property property = new AccessorProperty(getName(), 0, sobj.getClass(), oldMap.getFieldCount());
   12.23 +        final PropertyMap newMap = oldMap.addProperty(property);
   12.24 +        MethodHandle setter = MH.insertArguments(ScriptObject.SETFIELD, 0, desc, oldMap, newMap, property.getSetter(Object.class, newMap));
   12.25 +
   12.26 +        return new SetMethod(MH.asType(setter, Lookup.SET_OBJECT_TYPE), property);
   12.27 +    }
   12.28 +
   12.29      private SetMethod createNewSpillPropertySetter() {
   12.30          final int nextSpill = getMap().getSpillLength();
   12.31  
   12.32 @@ -189,7 +191,7 @@
   12.33          final MethodHandle getter = MH.asType(MH.insertArguments(MH.arrayElementGetter(Object[].class), 1, nextSpill), Lookup.GET_OBJECT_TYPE);
   12.34          final MethodHandle setter = MH.asType(MH.insertArguments(MH.arrayElementSetter(Object[].class), 1, nextSpill), Lookup.SET_OBJECT_TYPE);
   12.35  
   12.36 -        return new SpillProperty(getName(), Property.IS_SPILL, nextSpill, getter, setter);
   12.37 +        return new AccessorProperty(getName(), Property.IS_SPILL, nextSpill, getter, setter);
   12.38      }
   12.39  
   12.40      private MethodHandle createSpillMethodHandle(final int nextSpill, Property property) {
   12.41 @@ -207,14 +209,6 @@
   12.42          }
   12.43      }
   12.44  
   12.45 -    private SetMethod createNewEmbedPropertySetter(final int nextEmbed) {
   12.46 -        sobj.useEmbed(nextEmbed);
   12.47 -        final Property property = new SpillProperty(getName(), 0, nextEmbed, ScriptObject.GET_EMBED[nextEmbed], ScriptObject.SET_EMBED[nextEmbed]);
   12.48 -        //TODO specfields
   12.49 -        final MethodHandle methodHandle = MH.insertArguments(ScriptObject.SETEMBED, 0, desc, getMap(), getNewMap(property), property.getSetter(Object.class, getMap()), nextEmbed);
   12.50 -        return new SetMethod(methodHandle, property);
   12.51 -    }
   12.52 -
   12.53      private PropertyMap getNewMap(Property property) {
   12.54          return getMap().addProperty(property);
   12.55      }
    13.1 --- a/src/jdk/nashorn/internal/runtime/SpillProperty.java	Tue Apr 30 09:42:13 2013 +0200
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,85 +0,0 @@
    13.4 -/*
    13.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    13.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.7 - *
    13.8 - * This code is free software; you can redistribute it and/or modify it
    13.9 - * under the terms of the GNU General Public License version 2 only, as
   13.10 - * published by the Free Software Foundation.  Oracle designates this
   13.11 - * particular file as subject to the "Classpath" exception as provided
   13.12 - * by Oracle in the LICENSE file that accompanied this code.
   13.13 - *
   13.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   13.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13.17 - * version 2 for more details (a copy is included in the LICENSE file that
   13.18 - * accompanied this code).
   13.19 - *
   13.20 - * You should have received a copy of the GNU General Public License version
   13.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   13.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   13.23 - *
   13.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   13.25 - * or visit www.oracle.com if you need additional information or have any
   13.26 - * questions.
   13.27 - */
   13.28 -
   13.29 -package jdk.nashorn.internal.runtime;
   13.30 -
   13.31 -import static jdk.nashorn.internal.lookup.Lookup.MH;
   13.32 -
   13.33 -import java.lang.invoke.MethodHandle;
   13.34 -import java.lang.invoke.MethodHandles;
   13.35 -import jdk.nashorn.internal.lookup.Lookup;
   13.36 -
   13.37 -/**
   13.38 - * The SpillProperty is a subclass of AccessorProperties. Anything not in the initial property map
   13.39 - * will end up in the embed fields of the ScriptObject or in the Spill, which currently is a growing
   13.40 - * Object only array in ScriptObject
   13.41 - *
   13.42 - * @see AccessorProperty
   13.43 - * @see ScriptObject
   13.44 - */
   13.45 -public final class SpillProperty extends AccessorProperty {
   13.46 -    private static final MethodHandle SPILLGETTER = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), Lookup.GET_OBJECT_TYPE);
   13.47 -
   13.48 -    /**
   13.49 -     * Constructor
   13.50 -     *
   13.51 -     * @param key    property key
   13.52 -     * @param flags  property flags
   13.53 -     * @param slot   property slot/index
   13.54 -     * @param getter getter for property
   13.55 -     * @param setter setter for property, or null if not configurable and writable
   13.56 -     */
   13.57 -    public SpillProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
   13.58 -        super(key, flags, slot, getter, setter);
   13.59 -    }
   13.60 -
   13.61 -    private SpillProperty(final SpillProperty property) {
   13.62 -        super(property);
   13.63 -    }
   13.64 -
   13.65 -    @Override
   13.66 -    protected Property copy() {
   13.67 -        return new SpillProperty(this);
   13.68 -    }
   13.69 -
   13.70 -    @Override
   13.71 -    public MethodHandle getGetter(final Class<?> type) {
   13.72 -        if (isSpill()) {
   13.73 -            return MH.filterArguments(super.getGetter(type), 0, SPILLGETTER);
   13.74 -        }
   13.75 -
   13.76 -        return super.getGetter(type);
   13.77 -    }
   13.78 -
   13.79 -    @Override
   13.80 -    public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
   13.81 -        if (isSpill()) {
   13.82 -            return MH.filterArguments(super.getSetter(type, currentMap), 0, SPILLGETTER);
   13.83 -        }
   13.84 -
   13.85 -        return super.getSetter(type, currentMap);
   13.86 -    }
   13.87 -
   13.88 -}
    14.1 --- a/src/jdk/nashorn/internal/runtime/StructureLoader.java	Tue Apr 30 09:42:13 2013 +0200
    14.2 +++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java	Tue Apr 30 10:05:42 2013 -0300
    14.3 @@ -110,8 +110,7 @@
    14.4      @Override
    14.5      protected Class<?> findClass(final String name) throws ClassNotFoundException {
    14.6          if (name.startsWith(JS_OBJECT_PREFIX_EXTERNAL)) {
    14.7 -            final int start = name.indexOf(JS_OBJECT_PREFIX.symbolName()) + JS_OBJECT_PREFIX.symbolName().length();
    14.8 -            return generateClass(name, name.substring(start, name.length()));
    14.9 +            return generateClass(name, name.substring(JS_OBJECT_PREFIX_EXTERNAL.length()));
   14.10          }
   14.11          return super.findClass(name);
   14.12      }
    15.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Tue Apr 30 09:42:13 2013 +0200
    15.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Tue Apr 30 10:05:42 2013 -0300
    15.3 @@ -67,7 +67,6 @@
    15.4  
    15.5      private UserAccessorProperty(final UserAccessorProperty property) {
    15.6          super(property);
    15.7 -
    15.8          this.getterSlot = property.getterSlot;
    15.9          this.setterSlot = property.setterSlot;
   15.10      }
   15.11 @@ -115,10 +114,10 @@
   15.12      public int getSpillCount() {
   15.13          // calculate how many spill array slots used by this propery.
   15.14          int count = 0;
   15.15 -        if (getGetterSlot() >= ScriptObject.EMBED_SIZE) {
   15.16 +        if (getGetterSlot() >= 0) {
   15.17              count++;
   15.18          }
   15.19 -        if (getSetterSlot() >= ScriptObject.EMBED_SIZE) {
   15.20 +        if (getSetterSlot() >= 0) {
   15.21              count++;
   15.22          }
   15.23          return count;
   15.24 @@ -141,7 +140,7 @@
   15.25  
   15.26      @Override
   15.27      public ScriptFunction getGetterFunction(final ScriptObject obj) {
   15.28 -        final Object value = obj.getEmbedOrSpill(getterSlot);
   15.29 +        final Object value = obj.getSpill(getterSlot);
   15.30          return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
   15.31      }
   15.32  
   15.33 @@ -152,7 +151,7 @@
   15.34  
   15.35      @Override
   15.36      public ScriptFunction getSetterFunction(final ScriptObject obj) {
   15.37 -        final Object value = obj.getEmbedOrSpill(setterSlot);
   15.38 +        final Object value = obj.getSpill(setterSlot);
   15.39          return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
   15.40      }
   15.41  
    16.1 --- a/src/jdk/nashorn/internal/scripts/JO.java	Tue Apr 30 09:42:13 2013 +0200
    16.2 +++ b/src/jdk/nashorn/internal/scripts/JO.java	Tue Apr 30 10:05:42 2013 -0300
    16.3 @@ -32,12 +32,11 @@
    16.4   * Empty object class.
    16.5   */
    16.6  public class JO extends ScriptObject {
    16.7 -
    16.8      /**
    16.9       * Constructor
   16.10       */
   16.11      public JO() {
   16.12 -        super();
   16.13 +        super(PropertyMap.newMap(JO.class));
   16.14      }
   16.15  
   16.16      /**
    17.1 --- a/src/jdk/nashorn/tools/Shell.java	Tue Apr 30 09:42:13 2013 +0200
    17.2 +++ b/src/jdk/nashorn/tools/Shell.java	Tue Apr 30 10:05:42 2013 -0300
    17.3 @@ -343,7 +343,7 @@
    17.4       * @return error code
    17.5       * @throws IOException when any script file read results in I/O error
    17.6       */
    17.7 -    private int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
    17.8 +    private static int runFXScripts(final Context context, final ScriptObject global, final List<String> files) throws IOException {
    17.9          final ScriptObject oldGlobal = Context.getGlobal();
   17.10          final boolean globalChanged = (oldGlobal != global);
   17.11          try {

mercurial