775 * @return new property |
775 * @return new property |
776 */ |
776 */ |
777 public final Property modifyOwnProperty(final Property oldProperty, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { |
777 public final Property modifyOwnProperty(final Property oldProperty, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { |
778 Property newProperty; |
778 Property newProperty; |
779 if (oldProperty instanceof UserAccessorProperty) { |
779 if (oldProperty instanceof UserAccessorProperty) { |
780 // re-use the slots of the old user accessor property. |
|
781 final UserAccessorProperty uc = (UserAccessorProperty) oldProperty; |
780 final UserAccessorProperty uc = (UserAccessorProperty) oldProperty; |
782 |
781 final int getterSlot = uc.getGetterSlot(); |
783 int getterSlot = uc.getGetterSlot(); |
782 final int setterSlot = uc.getSetterSlot(); |
784 // clear the old getter and set the new getter |
|
785 setSpill(getterSlot, getter); |
783 setSpill(getterSlot, getter); |
786 // if getter function is null, flag the slot to be negative (less by 1) |
|
787 if (getter == null) { |
|
788 getterSlot = -getterSlot - 1; |
|
789 } |
|
790 |
|
791 int setterSlot = uc.getSetterSlot(); |
|
792 // clear the old setter and set the new setter |
|
793 setSpill(setterSlot, setter); |
784 setSpill(setterSlot, setter); |
794 // if setter function is null, flag the slot to be negative (less by 1) |
785 |
795 if (setter == null) { |
786 // if just flipping getter and setter with new functions, no need to change property or map |
796 setterSlot = -setterSlot - 1; |
787 if (uc.flags == propertyFlags) { |
|
788 return oldProperty; |
797 } |
789 } |
798 |
790 |
799 newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot); |
791 newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot); |
800 // if just flipping getter and setter with new functions, no need to change property or map |
|
801 if (oldProperty.equals(newProperty)) { |
|
802 return oldProperty; |
|
803 } |
|
804 } else { |
792 } else { |
805 // erase old property value and create new user accessor property |
793 // erase old property value and create new user accessor property |
806 erasePropertyValue(oldProperty); |
794 erasePropertyValue(oldProperty); |
807 newProperty = newUserAccessors(oldProperty.getKey(), propertyFlags, getter, setter); |
795 newProperty = newUserAccessors(oldProperty.getKey(), propertyFlags, getter, setter); |
808 } |
796 } |
860 * @param getter {@link UserAccessorProperty} defined getter, or null if none |
848 * @param getter {@link UserAccessorProperty} defined getter, or null if none |
861 * @param setter {@link UserAccessorProperty} defined setter, or null if none |
849 * @param setter {@link UserAccessorProperty} defined setter, or null if none |
862 */ |
850 */ |
863 public final void setUserAccessors(final String key, final ScriptFunction getter, final ScriptFunction setter) { |
851 public final void setUserAccessors(final String key, final ScriptFunction getter, final ScriptFunction setter) { |
864 final Property oldProperty = getMap().findProperty(key); |
852 final Property oldProperty = getMap().findProperty(key); |
865 if (oldProperty != null) { |
853 if (oldProperty instanceof UserAccessorProperty) { |
866 final UserAccessorProperty newProperty = newUserAccessors(oldProperty.getKey(), oldProperty.getFlags(), getter, setter); |
854 final UserAccessorProperty ua = (UserAccessorProperty)oldProperty; |
867 modifyOwnProperty(oldProperty, newProperty); |
855 setSpill(ua.getGetterSlot(), getter); |
|
856 setSpill(ua.getSetterSlot(), setter); |
868 } else { |
857 } else { |
869 final UserAccessorProperty newProperty = newUserAccessors(key, 0, getter, setter); |
858 addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter)); |
870 addOwnProperty(newProperty); |
|
871 } |
859 } |
872 } |
860 } |
873 |
861 |
874 private static int getIntValue(final FindProperty find) { |
862 private static int getIntValue(final FindProperty find) { |
875 final MethodHandle getter = find.getGetter(int.class); |
863 final MethodHandle getter = find.getGetter(int.class); |
1710 NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard); |
1698 NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType() ? null : guard); |
1711 } |
1699 } |
1712 |
1700 |
1713 final ScriptObject prototype = find.getOwner(); |
1701 final ScriptObject prototype = find.getOwner(); |
1714 |
1702 |
1715 if (!property.hasGetterFunction()) { |
1703 if (!property.hasGetterFunction(prototype)) { |
1716 methodHandle = bindTo(methodHandle, prototype); |
1704 methodHandle = bindTo(methodHandle, prototype); |
1717 } |
1705 } |
1718 return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard); |
1706 return new GuardedInvocation(methodHandle, getMap().getProtoGetSwitchPoint(proto, name), guard); |
1719 } |
1707 } |
1720 |
1708 |
3142 |
3130 |
3143 /* |
3131 /* |
3144 * Make a new UserAccessorProperty property. getter and setter functions are stored in |
3132 * Make a new UserAccessorProperty property. getter and setter functions are stored in |
3145 * this ScriptObject and slot values are used in property object. |
3133 * this ScriptObject and slot values are used in property object. |
3146 */ |
3134 */ |
3147 private UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { |
3135 protected final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) { |
3148 int oldSpillLength = getMap().getSpillLength(); |
3136 final UserAccessorProperty property = getMap().newUserAccessors(key, propertyFlags); |
3149 |
3137 setSpill(property.getGetterSlot(), getter); |
3150 int getterSlot = oldSpillLength++; |
3138 setSpill(property.getSetterSlot(), setter); |
3151 setSpill(getterSlot, getter); |
3139 |
3152 // if getter function is null, flag the slot to be negative (less by 1) |
3140 return property; |
3153 if (getter == null) { |
3141 } |
3154 getterSlot = -getterSlot - 1; |
3142 |
3155 } |
3143 protected final void setSpill(final int slot, final Object value) { |
3156 |
3144 if (spill == null) { |
3157 int setterSlot = oldSpillLength++; |
3145 // create new spill. |
3158 |
3146 spill = new Object[Math.max(slot + 1, SPILL_RATE)]; |
3159 setSpill(setterSlot, setter); |
3147 } else if (slot >= spill.length) { |
3160 // if setter function is null, flag the slot to be negative (less by 1) |
3148 // grow spill as needed |
3161 if (setter == null) { |
3149 final Object[] newSpill = new Object[slot + 1]; |
3162 setterSlot = -setterSlot - 1; |
3150 System.arraycopy(spill, 0, newSpill, 0, spill.length); |
3163 } |
3151 spill = newSpill; |
3164 |
3152 } |
3165 return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot); |
3153 |
3166 } |
3154 spill[slot] = value; |
3167 |
3155 } |
3168 private void setSpill(final int slot, final Object value) { |
3156 |
3169 if (slot >= 0) { |
3157 protected Object getSpill(final int slot) { |
3170 final int index = slot; |
3158 return spill != null && slot < spill.length ? spill[slot] : null; |
3171 if (spill == null) { |
|
3172 // create new spill. |
|
3173 spill = new Object[Math.max(index + 1, SPILL_RATE)]; |
|
3174 } else if (index >= spill.length) { |
|
3175 // grow spill as needed |
|
3176 final Object[] newSpill = new Object[index + 1]; |
|
3177 System.arraycopy(spill, 0, newSpill, 0, spill.length); |
|
3178 spill = newSpill; |
|
3179 } |
|
3180 |
|
3181 spill[index] = value; |
|
3182 } |
|
3183 } |
|
3184 |
|
3185 // user accessors are either stored in spill array slots |
|
3186 // get the accessor value using slot number. Note that slot is spill array index. |
|
3187 Object getSpill(final int slot) { |
|
3188 final int index = slot; |
|
3189 return (index < 0 || (index >= spill.length)) ? null : spill[index]; |
|
3190 } |
3159 } |
3191 |
3160 |
3192 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
3161 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
3193 final Class<?> own = ScriptObject.class; |
3162 final Class<?> own = ScriptObject.class; |
3194 final MethodType mt = MH.type(rtype, types); |
3163 final MethodType mt = MH.type(rtype, types); |