8008458: Strict functions dont share property map

Wed, 26 Jun 2013 08:36:53 -0300

author
jlaskey
date
Wed, 26 Jun 2013 08:36:53 -0300
changeset 379
682889823712
parent 378
39e17373d8df
child 380
80c66d3fd872

8008458: Strict functions dont share property map
Reviewed-by: sundar, hannesw
Contributed-by: james.laskey@oracle.com

src/jdk/nashorn/internal/objects/NativeStrictArguments.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/FindProperty.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/Property.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/UserAccessorProperty.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/jdk/nashorn/internal/objects/NativeStrictArguments.java	Wed Jun 26 16:36:13 2013 +0530
     1.2 +++ b/src/jdk/nashorn/internal/objects/NativeStrictArguments.java	Wed Jun 26 08:36:53 2013 -0300
     1.3 @@ -57,8 +57,10 @@
     1.4          PropertyMap map = PropertyMap.newMap(NativeStrictArguments.class);
     1.5          map = Lookup.newProperty(map, "length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH);
     1.6          // In strict mode, the caller and callee properties should throw TypeError
     1.7 -        map = ScriptFunctionImpl.newThrowerProperty(map, "caller");
     1.8 -        map = ScriptFunctionImpl.newThrowerProperty(map, "callee");
     1.9 +        // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
    1.10 +        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
    1.11 +        map = map.addProperty(map.newUserAccessors("caller", flags));
    1.12 +        map = map.addProperty(map.newUserAccessors("callee", flags));
    1.13          nasgenmap$ = map;
    1.14      }
    1.15  
     2.1 --- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Wed Jun 26 16:36:13 2013 +0530
     2.2 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Wed Jun 26 08:36:53 2013 -0300
     2.3 @@ -155,8 +155,12 @@
     2.4                  Lookup.TYPE_ERROR_THROWER_GETTER, Lookup.TYPE_ERROR_THROWER_SETTER);
     2.5      }
     2.6  
     2.7 -    private static PropertyMap createStrictModeMap(final PropertyMap functionMap) {
     2.8 -        return newThrowerProperty(newThrowerProperty(functionMap, "arguments"), "caller");
     2.9 +    private static PropertyMap createStrictModeMap(PropertyMap map) {
    2.10 +        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
    2.11 +        // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
    2.12 +        map = map.addProperty(map.newUserAccessors("arguments", flags));
    2.13 +        map = map.addProperty(map.newUserAccessors("caller", flags));
    2.14 +        return map;
    2.15      }
    2.16  
    2.17      // Choose the map based on strict mode!
    2.18 @@ -260,12 +264,15 @@
    2.19          this.setProto(Global.instance().getFunctionPrototype());
    2.20          this.prototype = LAZY_PROTOTYPE;
    2.21  
    2.22 -        if (isStrict()) {
    2.23 -            final ScriptFunction func = getTypeErrorThrower();
    2.24 -            // We have to fill user accessor functions late as these are stored
    2.25 -            // in this object rather than in the PropertyMap of this object.
    2.26 -            setUserAccessors("arguments", func, func);
    2.27 -            setUserAccessors("caller", func, func);
    2.28 +        // We have to fill user accessor functions late as these are stored
    2.29 +        // in this object rather than in the PropertyMap of this object.
    2.30 +
    2.31 +        if (findProperty("arguments", true) != null) {
    2.32 +            setUserAccessors("arguments", getTypeErrorThrower(), getTypeErrorThrower());
    2.33 +        }
    2.34 +
    2.35 +        if (findProperty("caller", true) != null) {
    2.36 +            setUserAccessors("caller", getTypeErrorThrower(), getTypeErrorThrower());
    2.37          }
    2.38      }
    2.39  }
     3.1 --- a/src/jdk/nashorn/internal/runtime/FindProperty.java	Wed Jun 26 16:36:13 2013 +0530
     3.2 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java	Wed Jun 26 08:36:53 2013 -0300
     3.3 @@ -89,7 +89,7 @@
     3.4          MethodHandle setter = property.getSetter(type, getOwner().getMap());
     3.5          if (property instanceof UserAccessorProperty) {
     3.6              final UserAccessorProperty uc = (UserAccessorProperty) property;
     3.7 -            setter = MH.insertArguments(setter, 0, (isInherited() ? getOwner() : null),
     3.8 +            setter = MH.insertArguments(setter, 0, isInherited() ? getOwner() : null,
     3.9                      uc.getSetterSlot(), strict? property.getKey() : null);
    3.10          }
    3.11  
    3.12 @@ -109,7 +109,7 @@
    3.13       * @return appropriate receiver
    3.14       */
    3.15      public ScriptObject getGetterReceiver() {
    3.16 -        return property != null && property.hasGetterFunction() ? self : prototype;
    3.17 +        return property != null && property.hasGetterFunction(prototype) ? self : prototype;
    3.18      }
    3.19  
    3.20     /**
    3.21 @@ -117,7 +117,7 @@
    3.22       * @return appropriate receiver
    3.23       */
    3.24      public ScriptObject getSetterReceiver() {
    3.25 -        return property != null && property.hasSetterFunction() ? self : prototype;
    3.26 +        return property != null && property.hasSetterFunction(prototype) ? self : prototype;
    3.27      }
    3.28  
    3.29      /**
     4.1 --- a/src/jdk/nashorn/internal/runtime/Property.java	Wed Jun 26 16:36:13 2013 +0530
     4.2 +++ b/src/jdk/nashorn/internal/runtime/Property.java	Wed Jun 26 08:36:53 2013 -0300
     4.3 @@ -180,17 +180,19 @@
     4.4  
     4.5      /**
     4.6       * Check whether this property has a user defined getter function. See {@link UserAccessorProperty}
     4.7 +     * @param obj object containing getter
     4.8       * @return true if getter function exists, false is default
     4.9       */
    4.10 -    public boolean hasGetterFunction() {
    4.11 +    public boolean hasGetterFunction(final ScriptObject obj) {
    4.12          return false;
    4.13      }
    4.14  
    4.15      /**
    4.16       * Check whether this property has a user defined setter function. See {@link UserAccessorProperty}
    4.17 +     * @param obj object containing setter
    4.18       * @return true if getter function exists, false is default
    4.19       */
    4.20 -    public boolean hasSetterFunction() {
    4.21 +    public boolean hasSetterFunction(final ScriptObject obj) {
    4.22          return false;
    4.23      }
    4.24  
     5.1 --- a/src/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Jun 26 16:36:13 2013 +0530
     5.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java	Wed Jun 26 08:36:53 2013 -0300
     5.3 @@ -302,7 +302,7 @@
     5.4       *
     5.5       * @return New {@link PropertyMap} with {@link Property} added.
     5.6       */
     5.7 -    PropertyMap addProperty(final Property property) {
     5.8 +    public PropertyMap addProperty(final Property property) {
     5.9          PropertyMap newMap = checkHistory(property);
    5.10  
    5.11          if (newMap == null) {
    5.12 @@ -383,6 +383,21 @@
    5.13          return newMap;
    5.14      }
    5.15  
    5.16 +    /*
    5.17 +     * Make a new UserAccessorProperty property. getter and setter functions are stored in
    5.18 +     * this ScriptObject and slot values are used in property object. Note that slots
    5.19 +     * are assigned speculatively and should be added to map before adding other
    5.20 +     * properties.
    5.21 +     */
    5.22 +    public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
    5.23 +        int oldSpillLength = spillLength;
    5.24 +
    5.25 +        final int getterSlot = oldSpillLength++;
    5.26 +        final int setterSlot = oldSpillLength++;
    5.27 +
    5.28 +        return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot);
    5.29 +    }
    5.30 +
    5.31      /**
    5.32       * Find a property in the map.
    5.33       *
     6.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jun 26 16:36:13 2013 +0530
     6.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java	Wed Jun 26 08:36:53 2013 -0300
     6.3 @@ -777,30 +777,18 @@
     6.4      public final Property modifyOwnProperty(final Property oldProperty, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
     6.5          Property newProperty;
     6.6          if (oldProperty instanceof UserAccessorProperty) {
     6.7 -            // re-use the slots of the old user accessor property.
     6.8              final UserAccessorProperty uc = (UserAccessorProperty) oldProperty;
     6.9 -
    6.10 -            int getterSlot = uc.getGetterSlot();
    6.11 -            // clear the old getter and set the new getter
    6.12 +            final int getterSlot = uc.getGetterSlot();
    6.13 +            final int setterSlot = uc.getSetterSlot();
    6.14              setSpill(getterSlot, getter);
    6.15 -            // if getter function is null, flag the slot to be negative (less by 1)
    6.16 -            if (getter == null) {
    6.17 -                getterSlot = -getterSlot - 1;
    6.18 -            }
    6.19 -
    6.20 -            int setterSlot = uc.getSetterSlot();
    6.21 -            // clear the old setter and set the new setter
    6.22              setSpill(setterSlot, setter);
    6.23 -            // if setter function is null, flag the slot to be negative (less by 1)
    6.24 -            if (setter == null) {
    6.25 -                setterSlot = -setterSlot - 1;
    6.26 -            }
    6.27 -
    6.28 -            newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot);
    6.29 +
    6.30              // if just flipping getter and setter with new functions, no need to change property or map
    6.31 -            if (oldProperty.equals(newProperty)) {
    6.32 +            if (uc.flags == propertyFlags) {
    6.33                  return oldProperty;
    6.34              }
    6.35 +
    6.36 +            newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot);
    6.37          } else {
    6.38              // erase old property value and create new user accessor property
    6.39              erasePropertyValue(oldProperty);
    6.40 @@ -862,12 +850,12 @@
    6.41       */
    6.42      public final void setUserAccessors(final String key, final ScriptFunction getter, final ScriptFunction setter) {
    6.43          final Property oldProperty = getMap().findProperty(key);
    6.44 -        if (oldProperty != null) {
    6.45 -            final UserAccessorProperty newProperty = newUserAccessors(oldProperty.getKey(), oldProperty.getFlags(), getter, setter);
    6.46 -            modifyOwnProperty(oldProperty, newProperty);
    6.47 +        if (oldProperty instanceof UserAccessorProperty) {
    6.48 +            final UserAccessorProperty ua = (UserAccessorProperty)oldProperty;
    6.49 +            setSpill(ua.getGetterSlot(), getter);
    6.50 +            setSpill(ua.getSetterSlot(), setter);
    6.51          } else {
    6.52 -            final UserAccessorProperty newProperty = newUserAccessors(key, 0, getter, setter);
    6.53 -            addOwnProperty(newProperty);
    6.54 +            addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter));
    6.55          }
    6.56      }
    6.57  
    6.58 @@ -1712,7 +1700,7 @@
    6.59  
    6.60              final ScriptObject prototype = find.getOwner();
    6.61  
    6.62 -            if (!property.hasGetterFunction()) {
    6.63 +            if (!property.hasGetterFunction(prototype)) {
    6.64                  methodHandle = bindTo(methodHandle, prototype);
    6.65              }
    6.66              return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard);
    6.67 @@ -3144,49 +3132,30 @@
    6.68       * Make a new UserAccessorProperty property. getter and setter functions are stored in
    6.69       * this ScriptObject and slot values are used in property object.
    6.70       */
    6.71 -    private UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
    6.72 -        int oldSpillLength = getMap().getSpillLength();
    6.73 -
    6.74 -        int getterSlot = oldSpillLength++;
    6.75 -        setSpill(getterSlot, getter);
    6.76 -        // if getter function is null, flag the slot to be negative (less by 1)
    6.77 -        if (getter == null) {
    6.78 -            getterSlot = -getterSlot - 1;
    6.79 +    protected final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
    6.80 +        final UserAccessorProperty property = getMap().newUserAccessors(key, propertyFlags);
    6.81 +        setSpill(property.getGetterSlot(), getter);
    6.82 +        setSpill(property.getSetterSlot(), setter);
    6.83 +
    6.84 +        return property;
    6.85 +    }
    6.86 +
    6.87 +    protected final void setSpill(final int slot, final Object value) {
    6.88 +        if (spill == null) {
    6.89 +            // create new spill.
    6.90 +            spill = new Object[Math.max(slot + 1, SPILL_RATE)];
    6.91 +        } else if (slot >= spill.length) {
    6.92 +            // grow spill as needed
    6.93 +            final Object[] newSpill = new Object[slot + 1];
    6.94 +            System.arraycopy(spill, 0, newSpill, 0, spill.length);
    6.95 +            spill = newSpill;
    6.96          }
    6.97  
    6.98 -        int setterSlot = oldSpillLength++;
    6.99 -
   6.100 -        setSpill(setterSlot, setter);
   6.101 -        // if setter function is null, flag the slot to be negative (less by 1)
   6.102 -        if (setter == null) {
   6.103 -            setterSlot = -setterSlot - 1;
   6.104 -        }
   6.105 -
   6.106 -        return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot);
   6.107 +        spill[slot] = value;
   6.108      }
   6.109  
   6.110 -    private void setSpill(final int slot, final Object value) {
   6.111 -        if (slot >= 0) {
   6.112 -            final int index = slot;
   6.113 -            if (spill == null) {
   6.114 -                // create new spill.
   6.115 -                spill = new Object[Math.max(index + 1, SPILL_RATE)];
   6.116 -            } else if (index >= spill.length) {
   6.117 -                // grow spill as needed
   6.118 -                final Object[] newSpill = new Object[index + 1];
   6.119 -                System.arraycopy(spill, 0, newSpill, 0, spill.length);
   6.120 -                spill = newSpill;
   6.121 -            }
   6.122 -
   6.123 -            spill[index] = value;
   6.124 -        }
   6.125 -    }
   6.126 -
   6.127 -    // user accessors are either stored in spill array slots
   6.128 -    // get the accessor value using slot number. Note that slot is spill array index.
   6.129 -    Object getSpill(final int slot) {
   6.130 -        final int index = slot;
   6.131 -        return (index < 0 || (index >= spill.length)) ? null : spill[index];
   6.132 +    protected Object getSpill(final int slot) {
   6.133 +        return spill != null && slot < spill.length ? spill[slot] : null;
   6.134      }
   6.135  
   6.136      private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
     7.1 --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Wed Jun 26 16:36:13 2013 +0530
     7.2 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java	Wed Jun 26 08:36:53 2013 -0300
     7.3 @@ -151,9 +151,10 @@
     7.4          assert methodHandle != null;
     7.5          assert property     != null;
     7.6  
     7.7 +        final ScriptObject prototype = find.getOwner();
     7.8          final MethodHandle boundHandle;
     7.9 -        if (!property.hasSetterFunction() && find.isInherited()) {
    7.10 -            boundHandle = ScriptObject.bindTo(methodHandle, find.getOwner());
    7.11 +        if (!property.hasSetterFunction(prototype) && find.isInherited()) {
    7.12 +            boundHandle = ScriptObject.bindTo(methodHandle, prototype);
    7.13          } else {
    7.14              boundHandle = methodHandle;
    7.15          }
     8.1 --- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Wed Jun 26 16:36:13 2013 +0530
     8.2 +++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java	Wed Jun 26 08:36:53 2013 -0300
     8.3 @@ -96,19 +96,19 @@
     8.4      }
     8.5  
     8.6      /**
     8.7 -     * Return getter slot for this UserAccessorProperty. Slots start with first embed field.
     8.8 +     * Return getter spill slot for this UserAccessorProperty.
     8.9       * @return getter slot
    8.10       */
    8.11      public int getGetterSlot() {
    8.12 -        return getterSlot < 0 ? -getterSlot - 1 : getterSlot;
    8.13 +        return getterSlot;
    8.14      }
    8.15  
    8.16      /**
    8.17 -     * Return setter slot for this UserAccessorProperty. Slots start with first embed field.
    8.18 +     * Return setter spill slot for this UserAccessorProperty.
    8.19       * @return setter slot
    8.20       */
    8.21      public int getSetterSlot() {
    8.22 -        return setterSlot < 0 ? -setterSlot - 1 : setterSlot;
    8.23 +        return setterSlot;
    8.24      }
    8.25  
    8.26      @Override
    8.27 @@ -124,7 +124,7 @@
    8.28  
    8.29          final UserAccessorProperty uc = (UserAccessorProperty) other;
    8.30          return getterSlot == uc.getterSlot && setterSlot == uc.setterSlot;
    8.31 -     }
    8.32 +    }
    8.33  
    8.34      @Override
    8.35      public int hashCode() {
    8.36 @@ -136,25 +136,17 @@
    8.37       */
    8.38      @Override
    8.39      public int getSpillCount() {
    8.40 -        // calculate how many spill array slots used by this propery.
    8.41 -        int count = 0;
    8.42 -        if (getGetterSlot() >= 0) {
    8.43 -            count++;
    8.44 -        }
    8.45 -        if (getSetterSlot() >= 0) {
    8.46 -            count++;
    8.47 -        }
    8.48 -        return count;
    8.49 +        return 2;
    8.50      }
    8.51  
    8.52      @Override
    8.53 -    public boolean hasGetterFunction() {
    8.54 -        return getterSlot > -1;
    8.55 +    public boolean hasGetterFunction(final ScriptObject obj) {
    8.56 +        return obj.getSpill(getterSlot) != null;
    8.57      }
    8.58  
    8.59      @Override
    8.60 -    public boolean hasSetterFunction() {
    8.61 -        return setterSlot > -1;
    8.62 +    public boolean hasSetterFunction(final ScriptObject obj) {
    8.63 +        return obj.getSpill(setterSlot) != null;
    8.64      }
    8.65  
    8.66      @Override

mercurial