< prev index next >

src/jdk/nashorn/internal/runtime/ScriptObject.java

Print this page




  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
  31 import static jdk.nashorn.internal.lookup.Lookup.MH;
  32 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
  33 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  34 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
  35 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
  36 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
  37 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
  38 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
  39 import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
  40 import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
  41 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
  42 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
  43 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  44 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  45 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
  46 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
  47 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
  48 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
  49 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
  50 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
  51 
  52 import java.lang.invoke.MethodHandle;
  53 import java.lang.invoke.MethodHandles;
  54 import java.lang.invoke.MethodType;
  55 import java.lang.invoke.SwitchPoint;
  56 import java.util.AbstractMap;


 169     public static final Call SET_ARGUMENT       = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArgument", void.class, int.class, Object.class);
 170 
 171     /** Method handle for getting the proto of a ScriptObject */
 172     public static final Call GET_PROTO          = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
 173 
 174     /** Method handle for getting the proto of a ScriptObject */
 175     public static final Call GET_PROTO_DEPTH    = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class, int.class);
 176 
 177     /** Method handle for setting the proto of a ScriptObject */
 178     public static final Call SET_GLOBAL_OBJECT_PROTO = staticCallNoLookup(ScriptObject.class, "setGlobalObjectProto", void.class, ScriptObject.class);
 179 
 180     /** Method handle for setting the proto of a ScriptObject after checking argument */
 181     public static final Call SET_PROTO_FROM_LITERAL    = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
 182 
 183     /** Method handle for setting the user accessors of a ScriptObject */
 184     //TODO fastpath this
 185     public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 186 
 187     static final MethodHandle[] SET_SLOW = new MethodHandle[] {
 188         findOwnMH_V("set", void.class, Object.class, int.class, int.class),
 189         findOwnMH_V("set", void.class, Object.class, long.class, int.class),
 190         findOwnMH_V("set", void.class, Object.class, double.class, int.class),
 191         findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
 192     };
 193 
 194     /** Method handle to reset the map of this ScriptObject */
 195     public static final Call SET_MAP = virtualCallNoLookup(ScriptObject.class, "setMap", void.class, PropertyMap.class);
 196 
 197     static final MethodHandle CAS_MAP           = findOwnMH_V("compareAndSetMap", boolean.class, PropertyMap.class, PropertyMap.class);
 198     static final MethodHandle EXTENSION_CHECK   = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class);
 199     static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class);
 200 
 201     /**
 202      * Constructor
 203      */
 204     public ScriptObject() {
 205         this(null);
 206     }
 207 
 208     /**
 209     * Constructor


1069         } else {
1070             addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter));
1071         }
1072     }
1073 
1074     private static int getIntValue(final FindProperty find, final int programPoint) {
1075         final MethodHandle getter = find.getGetter(int.class, programPoint, null);
1076         if (getter != null) {
1077             try {
1078                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
1079             } catch (final Error|RuntimeException e) {
1080                 throw e;
1081             } catch (final Throwable e) {
1082                 throw new RuntimeException(e);
1083             }
1084         }
1085 
1086         return UNDEFINED_INT;
1087     }
1088 
1089     private static long getLongValue(final FindProperty find, final int programPoint) {
1090         final MethodHandle getter = find.getGetter(long.class, programPoint, null);
1091         if (getter != null) {
1092             try {
1093                 return (long)getter.invokeExact((Object)find.getGetterReceiver());
1094             } catch (final Error|RuntimeException e) {
1095                 throw e;
1096             } catch (final Throwable e) {
1097                 throw new RuntimeException(e);
1098             }
1099         }
1100 
1101         return UNDEFINED_LONG;
1102     }
1103 
1104     private static double getDoubleValue(final FindProperty find, final int programPoint) {
1105         final MethodHandle getter = find.getGetter(double.class, programPoint, null);
1106         if (getter != null) {
1107             try {
1108                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
1109             } catch (final Error|RuntimeException e) {
1110                 throw e;
1111             } catch (final Throwable e) {
1112                 throw new RuntimeException(e);
1113             }
1114         }
1115 
1116         return UNDEFINED_DOUBLE;
1117     }
1118 
1119     /**
1120      * Return methodHandle of value function for call.
1121      *
1122      * @param find      data from find property.
1123      * @param type      method type of function.


2751         if (array.has(index)) {
2752             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2753         }
2754 
2755         return getInt(index, JSType.toString(primitiveKey), programPoint);
2756     }
2757 
2758     @Override
2759     public int getInt(final double key, final int programPoint) {
2760         final int       index = getArrayIndex(key);
2761         final ArrayData array = getArray();
2762 
2763         if (array.has(index)) {
2764             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2765         }
2766 
2767         return getInt(index, JSType.toString(key), programPoint);
2768     }
2769 
2770     @Override
2771     public int getInt(final long key, final int programPoint) {
2772         final int       index = getArrayIndex(key);
2773         final ArrayData array = getArray();
2774 
2775         if (array.has(index)) {
2776             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2777         }
2778 
2779         return getInt(index, JSType.toString(key), programPoint);
2780     }
2781 
2782     @Override
2783     public int getInt(final int key, final int programPoint) {
2784         final int       index = getArrayIndex(key);
2785         final ArrayData array = getArray();
2786 
2787         if (array.has(index)) {
2788             return isValid(programPoint) ? array.getIntOptimistic(key, programPoint) : array.getInt(key);
2789         }
2790 
2791         return getInt(index, JSType.toString(key), programPoint);
2792     }
2793 
2794     private long getLong(final int index, final String key, final int programPoint) {
2795         if (isValidArrayIndex(index)) {
2796             for (ScriptObject object = this; ; ) {
2797                 if (object.getMap().containsArrayKeys()) {
2798                     final FindProperty find = object.findProperty(key, false, this);
2799                     if (find != null) {
2800                         return getLongValue(find, programPoint);
2801                     }
2802                 }
2803 
2804                 if ((object = object.getProto()) == null) {
2805                     break;
2806                 }
2807 
2808                 final ArrayData array = object.getArray();
2809 
2810                 if (array.has(index)) {
2811                     return isValid(programPoint) ?
2812                         array.getLongOptimistic(index, programPoint) :
2813                         array.getLong(index);
2814                 }
2815             }
2816         } else {
2817             final FindProperty find = findProperty(key, true);
2818 
2819             if (find != null) {
2820                 return getLongValue(find, programPoint);
2821             }
2822         }
2823 
2824         return JSType.toLong(invokeNoSuchProperty(key, false, programPoint));
2825     }
2826 
2827     @Override
2828     public long getLong(final Object key, final int programPoint) {
2829         final Object    primitiveKey = JSType.toPrimitive(key, String.class);
2830         final int       index        = getArrayIndex(primitiveKey);
2831         final ArrayData array        = getArray();
2832 
2833         if (array.has(index)) {
2834             return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2835         }
2836 
2837         return getLong(index, JSType.toString(primitiveKey), programPoint);
2838     }
2839 
2840     @Override
2841     public long getLong(final double key, final int programPoint) {
2842         final int       index = getArrayIndex(key);
2843         final ArrayData array = getArray();
2844 
2845         if (array.has(index)) {
2846             return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2847         }
2848 
2849         return getLong(index, JSType.toString(key), programPoint);
2850     }
2851 
2852     @Override
2853     public long getLong(final long key, final int programPoint) {
2854         final int       index = getArrayIndex(key);
2855         final ArrayData array = getArray();
2856 
2857         if (array.has(index)) {
2858             return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2859         }
2860 
2861         return getLong(index, JSType.toString(key), programPoint);
2862     }
2863 
2864     @Override
2865     public long getLong(final int key, final int programPoint) {
2866         final int       index = getArrayIndex(key);
2867         final ArrayData array = getArray();
2868 
2869         if (array.has(index)) {
2870             return isValid(programPoint) ? array.getLongOptimistic(key, programPoint) : array.getLong(key);
2871         }
2872 
2873         return getLong(index, JSType.toString(key), programPoint);
2874     }
2875 
2876     private double getDouble(final int index, final String key, final int programPoint) {
2877         if (isValidArrayIndex(index)) {
2878             for (ScriptObject object = this; ; ) {
2879                 if (object.getMap().containsArrayKeys()) {
2880                     final FindProperty find = object.findProperty(key, false, this);
2881                     if (find != null) {
2882                         return getDoubleValue(find, programPoint);
2883                     }
2884                 }
2885 
2886                 if ((object = object.getProto()) == null) {
2887                     break;
2888                 }
2889 
2890                 final ArrayData array = object.getArray();
2891 
2892                 if (array.has(index)) {
2893                     return isValid(programPoint) ?
2894                         array.getDoubleOptimistic(index, programPoint) :
2895                         array.getDouble(index);


2915         if (array.has(index)) {
2916             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2917         }
2918 
2919         return getDouble(index, JSType.toString(primitiveKey), programPoint);
2920     }
2921 
2922     @Override
2923     public double getDouble(final double key, final int programPoint) {
2924         final int       index = getArrayIndex(key);
2925         final ArrayData array = getArray();
2926 
2927         if (array.has(index)) {
2928             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2929         }
2930 
2931         return getDouble(index, JSType.toString(key), programPoint);
2932     }
2933 
2934     @Override
2935     public double getDouble(final long key, final int programPoint) {
2936         final int       index = getArrayIndex(key);
2937         final ArrayData array = getArray();
2938 
2939         if (array.has(index)) {
2940             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2941         }
2942 
2943         return getDouble(index, JSType.toString(key), programPoint);
2944     }
2945 
2946     @Override
2947     public double getDouble(final int key, final int programPoint) {
2948         final int       index = getArrayIndex(key);
2949         final ArrayData array = getArray();
2950 
2951         if (array.has(index)) {
2952             return isValid(programPoint) ? array.getDoubleOptimistic(key, programPoint) : array.getDouble(key);
2953         }
2954 
2955         return getDouble(index, JSType.toString(key), programPoint);
2956     }
2957 
2958     private Object get(final int index, final String key) {
2959         if (isValidArrayIndex(index)) {
2960             for (ScriptObject object = this; ; ) {
2961                 if (object.getMap().containsArrayKeys()) {
2962                     final FindProperty find = object.findProperty(key, false, this);
2963 
2964                     if (find != null) {
2965                         return find.getObjectValue();
2966                     }


2996         if (array.has(index)) {
2997             return array.getObject(index);
2998         }
2999 
3000         return get(index, JSType.toString(primitiveKey));
3001     }
3002 
3003     @Override
3004     public Object get(final double key) {
3005         final int index = getArrayIndex(key);
3006         final ArrayData array = getArray();
3007 
3008         if (array.has(index)) {
3009             return array.getObject(index);
3010         }
3011 
3012         return get(index, JSType.toString(key));
3013     }
3014 
3015     @Override
3016     public Object get(final long key) {
3017         final int index = getArrayIndex(key);
3018         final ArrayData array = getArray();
3019 
3020         if (array.has(index)) {
3021             return array.getObject(index);
3022         }
3023 
3024         return get(index, JSType.toString(key));
3025     }
3026 
3027     @Override
3028     public Object get(final int key) {
3029         final int index = getArrayIndex(key);
3030         final ArrayData array = getArray();
3031 
3032         if (array.has(index)) {
3033             return array.getObject(index);
3034         }
3035 
3036         return get(index, JSType.toString(key));
3037     }
3038 
3039     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
3040         if (getMap().containsArrayKeys()) {
3041             final String       key  = JSType.toString(longIndex);
3042             final FindProperty find = findProperty(key, true);
3043             if (find != null) {
3044                 setObject(find, callSiteFlags, key, value);
3045                 return true;
3046             }
3047         }


3090             if (!isExtensible()) {
3091                 if (isStrictFlag(callSiteFlags)) {
3092                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
3093                 }
3094                 return true;
3095             }
3096             setArray(getArray().ensure(longIndex));
3097         }
3098         return false;
3099     }
3100 
3101     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
3102         final long oldLength = getArray().length();
3103         final long longIndex = ArrayIndex.toLongIndex(index);
3104         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3105             final boolean strict = isStrictFlag(callSiteFlags);
3106             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3107         }
3108     }
3109 
3110     private void doesNotHave(final int index, final long value, final int callSiteFlags) {
3111         final long oldLength = getArray().length();
3112         final long longIndex = ArrayIndex.toLongIndex(index);
3113         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3114             final boolean strict = isStrictFlag(callSiteFlags);
3115             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3116         }
3117     }
3118 
3119     private void doesNotHave(final int index, final double value, final int callSiteFlags) {
3120         final long oldLength = getArray().length();
3121         final long longIndex = ArrayIndex.toLongIndex(index);
3122         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3123             final boolean strict = isStrictFlag(callSiteFlags);
3124             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3125         }
3126     }
3127 
3128     private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
3129         final long oldLength = getArray().length();
3130         final long longIndex = ArrayIndex.toLongIndex(index);
3131         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3132             final boolean strict = isStrictFlag(callSiteFlags);
3133             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3134         }
3135     }
3136 
3137     /**
3138      * This is the most generic of all Object setters. Most of the others use this in some form.


3205     public void set(final Object key, final int value, final int callSiteFlags) {
3206         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3207         final int    index        = getArrayIndex(primitiveKey);
3208 
3209         if (isValidArrayIndex(index)) {
3210             final ArrayData data = getArray();
3211             if (data.has(index)) {
3212                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3213             } else {
3214                 doesNotHave(index, value, callSiteFlags);
3215             }
3216 
3217             return;
3218         }
3219 
3220         final String propName = JSType.toString(primitiveKey);
3221         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3222     }
3223 
3224     @Override
3225     public void set(final Object key, final long value, final int callSiteFlags) {
3226         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3227         final int    index        = getArrayIndex(primitiveKey);
3228 
3229         if (isValidArrayIndex(index)) {
3230             final ArrayData data = getArray();
3231             if (data.has(index)) {
3232                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3233             } else {
3234                 doesNotHave(index, value, callSiteFlags);
3235             }
3236 
3237             return;
3238         }
3239 
3240         final String propName = JSType.toString(primitiveKey);
3241         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3242     }
3243 
3244     @Override
3245     public void set(final Object key, final double value, final int callSiteFlags) {
3246         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3247         final int    index        = getArrayIndex(primitiveKey);
3248 
3249         if (isValidArrayIndex(index)) {
3250             final ArrayData data = getArray();
3251             if (data.has(index)) {
3252                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3253             } else {
3254                 doesNotHave(index, value, callSiteFlags);
3255             }
3256 
3257             return;
3258         }
3259 
3260         final String propName = JSType.toString(primitiveKey);
3261         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3262     }
3263 
3264     @Override


3284     @Override
3285     public void set(final double key, final int value, final int callSiteFlags) {
3286         final int index = getArrayIndex(key);
3287 
3288         if (isValidArrayIndex(index)) {
3289             final ArrayData data = getArray();
3290             if (data.has(index)) {
3291                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3292             } else {
3293                 doesNotHave(index, value, callSiteFlags);
3294             }
3295 
3296             return;
3297         }
3298 
3299         final String propName = JSType.toString(key);
3300         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3301     }
3302 
3303     @Override
3304     public void set(final double key, final long value, final int callSiteFlags) {
3305         final int index = getArrayIndex(key);
3306 
3307         if (isValidArrayIndex(index)) {
3308             final ArrayData data = getArray();
3309             if (data.has(index)) {
3310                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3311             } else {
3312                 doesNotHave(index, value, callSiteFlags);
3313             }
3314 
3315             return;
3316         }
3317 
3318         final String propName = JSType.toString(key);
3319         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3320     }
3321 
3322     @Override
3323     public void set(final double key, final double value, final int callSiteFlags) {
3324         final int index = getArrayIndex(key);
3325 
3326         if (isValidArrayIndex(index)) {
3327             final ArrayData data = getArray();
3328             if (data.has(index)) {
3329                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3330             } else {
3331                 doesNotHave(index, value, callSiteFlags);
3332             }
3333 
3334             return;
3335         }
3336 
3337         final String propName = JSType.toString(key);
3338         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3339     }
3340 
3341     @Override
3342     public void set(final double key, final Object value, final int callSiteFlags) {
3343         final int index = getArrayIndex(key);
3344 
3345         if (isValidArrayIndex(index)) {
3346             final ArrayData data = getArray();
3347             if (data.has(index)) {
3348                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3349             } else {
3350                 doesNotHave(index, value, callSiteFlags);
3351             }
3352 
3353             return;
3354         }
3355 
3356         final String propName = JSType.toString(key);
3357         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3358     }
3359 
3360     @Override
3361     public void set(final long key, final int value, final int callSiteFlags) {
3362         final int index = getArrayIndex(key);
3363 
3364         if (isValidArrayIndex(index)) {
3365             final ArrayData data = getArray();
3366             if (data.has(index)) {
3367                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3368             } else {
3369                 doesNotHave(index, value, callSiteFlags);
3370             }
3371 
3372             return;
3373         }
3374 
3375         final String propName = JSType.toString(key);
3376         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3377     }
3378 
3379     @Override
3380     public void set(final long key, final long value, final int callSiteFlags) {
3381         final int index = getArrayIndex(key);
3382 
3383         if (isValidArrayIndex(index)) {
3384             final ArrayData data = getArray();
3385             if (data.has(index)) {
3386                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3387             } else {
3388                 doesNotHave(index, value, callSiteFlags);
3389             }
3390 
3391             return;
3392         }
3393 
3394         final String propName = JSType.toString(key);
3395         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3396     }
3397 
3398     @Override
3399     public void set(final long key, final double value, final int callSiteFlags) {
3400         final int index = getArrayIndex(key);
3401 
3402         if (isValidArrayIndex(index)) {
3403             final ArrayData data = getArray();
3404             if (data.has(index)) {
3405                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3406             } else {
3407                 doesNotHave(index, value, callSiteFlags);
3408             }
3409 
3410             return;
3411         }
3412 
3413         final String propName = JSType.toString(key);
3414         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3415     }
3416 
3417     @Override
3418     public void set(final long key, final Object value, final int callSiteFlags) {
3419         final int index = getArrayIndex(key);
3420 
3421         if (isValidArrayIndex(index)) {
3422             final ArrayData data = getArray();
3423             if (data.has(index)) {
3424                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3425             } else {
3426                 doesNotHave(index, value, callSiteFlags);
3427             }
3428 
3429             return;
3430         }
3431 
3432         final String propName = JSType.toString(key);
3433         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3434     }
3435 
3436     @Override
3437     public void set(final int key, final int value, final int callSiteFlags) {
3438         final int index = getArrayIndex(key);
3439         if (isValidArrayIndex(index)) {
3440             if (getArray().has(index)) {
3441                 final ArrayData data = getArray();
3442                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3443             } else {
3444                 doesNotHave(index, value, callSiteFlags);
3445             }
3446             return;
3447         }
3448 
3449         final String propName = JSType.toString(key);
3450         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3451     }
3452 
3453     @Override
3454     public void set(final int key, final long value, final int callSiteFlags) {
3455         final int index = getArrayIndex(key);
3456 
3457         if (isValidArrayIndex(index)) {
3458             final ArrayData data = getArray();
3459             if (data.has(index)) {
3460                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3461             } else {
3462                 doesNotHave(index, value, callSiteFlags);
3463             }
3464 
3465             return;
3466         }
3467 
3468         final String propName = JSType.toString(key);
3469         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3470     }
3471 
3472     @Override
3473     public void set(final int key, final double value, final int callSiteFlags) {
3474         final int index = getArrayIndex(key);
3475 
3476         if (isValidArrayIndex(index)) {
3477             final ArrayData data = getArray();
3478             if (data.has(index)) {
3479                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3480             } else {
3481                 doesNotHave(index, value, callSiteFlags);
3482             }
3483 
3484             return;
3485         }
3486 
3487         final String propName = JSType.toString(key);
3488         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3489     }
3490 
3491     @Override
3492     public void set(final int key, final Object value, final int callSiteFlags) {


3504         }
3505 
3506         final String propName = JSType.toString(key);
3507         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3508     }
3509 
3510     @Override
3511     public boolean has(final Object key) {
3512         final Object primitiveKey = JSType.toPrimitive(key);
3513         final int    index        = getArrayIndex(primitiveKey);
3514         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), true);
3515     }
3516 
3517     @Override
3518     public boolean has(final double key) {
3519         final int index = getArrayIndex(key);
3520         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3521     }
3522 
3523     @Override
3524     public boolean has(final long key) {
3525         final int index = getArrayIndex(key);
3526         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3527     }
3528 
3529     @Override
3530     public boolean has(final int key) {
3531         final int index = getArrayIndex(key);
3532         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3533     }
3534 
3535     private boolean hasArrayProperty(final int index) {
3536         boolean hasArrayKeys = false;
3537 
3538         for (ScriptObject self = this; self != null; self = self.getProto()) {
3539             if (self.getArray().has(index)) {
3540                 return true;
3541             }
3542             hasArrayKeys = hasArrayKeys || self.getMap().containsArrayKeys();
3543         }
3544 
3545         return hasArrayKeys && hasProperty(ArrayIndex.toKey(index), true);
3546     }
3547 
3548     @Override
3549     public boolean hasOwnProperty(final Object key) {
3550         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3551         final int    index        = getArrayIndex(primitiveKey);
3552         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), false);
3553     }
3554 
3555     @Override
3556     public boolean hasOwnProperty(final int key) {
3557         final int index = getArrayIndex(key);
3558         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3559     }
3560 
3561     @Override
3562     public boolean hasOwnProperty(final long key) {
3563         final int index = getArrayIndex(key);
3564         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3565     }
3566 
3567     @Override
3568     public boolean hasOwnProperty(final double key) {
3569         final int index = getArrayIndex(key);
3570         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3571     }
3572 
3573     private boolean hasOwnArrayProperty(final int index) {
3574         return getArray().has(index) || getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false);
3575     }
3576 
3577     @Override
3578     public boolean delete(final int key, final boolean strict) {
3579         final int index = getArrayIndex(key);
3580         final ArrayData array = getArray();
3581 
3582         if (array.has(index)) {
3583             if (array.canDelete(index, strict)) {
3584                 setArray(array.delete(index));
3585                 return true;
3586             }
3587             return false;
3588         }
3589         return deleteObject(JSType.toObject(key), strict);
3590     }
3591 
3592     @Override
3593     public boolean delete(final long key, final boolean strict) {
3594         final int index = getArrayIndex(key);
3595         final ArrayData array = getArray();
3596 
3597         if (array.has(index)) {
3598             if (array.canDelete(index, strict)) {
3599                 setArray(array.delete(index));
3600                 return true;
3601             }
3602             return false;
3603         }
3604 
3605         return deleteObject(JSType.toObject(key), strict);
3606     }
3607 
3608     @Override
3609     public boolean delete(final double key, final boolean strict) {
3610         final int index = getArrayIndex(key);
3611         final ArrayData array = getArray();
3612 
3613         if (array.has(index)) {
3614             if (array.canDelete(index, strict)) {
3615                 setArray(array.delete(index));
3616                 return true;
3617             }
3618             return false;
3619         }
3620 
3621         return deleteObject(JSType.toObject(key), strict);
3622     }
3623 
3624     @Override




  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
  31 import static jdk.nashorn.internal.lookup.Lookup.MH;
  32 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
  33 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  34 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
  35 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;

  36 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
  37 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
  38 import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
  39 import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
  40 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
  41 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
  42 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  43 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  44 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
  45 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
  46 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
  47 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
  48 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
  49 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
  50 
  51 import java.lang.invoke.MethodHandle;
  52 import java.lang.invoke.MethodHandles;
  53 import java.lang.invoke.MethodType;
  54 import java.lang.invoke.SwitchPoint;
  55 import java.util.AbstractMap;


 168     public static final Call SET_ARGUMENT       = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArgument", void.class, int.class, Object.class);
 169 
 170     /** Method handle for getting the proto of a ScriptObject */
 171     public static final Call GET_PROTO          = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
 172 
 173     /** Method handle for getting the proto of a ScriptObject */
 174     public static final Call GET_PROTO_DEPTH    = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class, int.class);
 175 
 176     /** Method handle for setting the proto of a ScriptObject */
 177     public static final Call SET_GLOBAL_OBJECT_PROTO = staticCallNoLookup(ScriptObject.class, "setGlobalObjectProto", void.class, ScriptObject.class);
 178 
 179     /** Method handle for setting the proto of a ScriptObject after checking argument */
 180     public static final Call SET_PROTO_FROM_LITERAL    = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
 181 
 182     /** Method handle for setting the user accessors of a ScriptObject */
 183     //TODO fastpath this
 184     public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 185 
 186     static final MethodHandle[] SET_SLOW = new MethodHandle[] {
 187         findOwnMH_V("set", void.class, Object.class, int.class, int.class),

 188         findOwnMH_V("set", void.class, Object.class, double.class, int.class),
 189         findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
 190     };
 191 
 192     /** Method handle to reset the map of this ScriptObject */
 193     public static final Call SET_MAP = virtualCallNoLookup(ScriptObject.class, "setMap", void.class, PropertyMap.class);
 194 
 195     static final MethodHandle CAS_MAP           = findOwnMH_V("compareAndSetMap", boolean.class, PropertyMap.class, PropertyMap.class);
 196     static final MethodHandle EXTENSION_CHECK   = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class);
 197     static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class);
 198 
 199     /**
 200      * Constructor
 201      */
 202     public ScriptObject() {
 203         this(null);
 204     }
 205 
 206     /**
 207     * Constructor


1067         } else {
1068             addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter));
1069         }
1070     }
1071 
1072     private static int getIntValue(final FindProperty find, final int programPoint) {
1073         final MethodHandle getter = find.getGetter(int.class, programPoint, null);
1074         if (getter != null) {
1075             try {
1076                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
1077             } catch (final Error|RuntimeException e) {
1078                 throw e;
1079             } catch (final Throwable e) {
1080                 throw new RuntimeException(e);
1081             }
1082         }
1083 
1084         return UNDEFINED_INT;
1085     }
1086 















1087     private static double getDoubleValue(final FindProperty find, final int programPoint) {
1088         final MethodHandle getter = find.getGetter(double.class, programPoint, null);
1089         if (getter != null) {
1090             try {
1091                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
1092             } catch (final Error|RuntimeException e) {
1093                 throw e;
1094             } catch (final Throwable e) {
1095                 throw new RuntimeException(e);
1096             }
1097         }
1098 
1099         return UNDEFINED_DOUBLE;
1100     }
1101 
1102     /**
1103      * Return methodHandle of value function for call.
1104      *
1105      * @param find      data from find property.
1106      * @param type      method type of function.


2734         if (array.has(index)) {
2735             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2736         }
2737 
2738         return getInt(index, JSType.toString(primitiveKey), programPoint);
2739     }
2740 
2741     @Override
2742     public int getInt(final double key, final int programPoint) {
2743         final int       index = getArrayIndex(key);
2744         final ArrayData array = getArray();
2745 
2746         if (array.has(index)) {
2747             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2748         }
2749 
2750         return getInt(index, JSType.toString(key), programPoint);
2751     }
2752 
2753     @Override












2754     public int getInt(final int key, final int programPoint) {
2755         final int       index = getArrayIndex(key);
2756         final ArrayData array = getArray();
2757 
2758         if (array.has(index)) {
2759             return isValid(programPoint) ? array.getIntOptimistic(key, programPoint) : array.getInt(key);
2760         }
2761 
2762         return getInt(index, JSType.toString(key), programPoint);
2763     }
2764 


















































































2765     private double getDouble(final int index, final String key, final int programPoint) {
2766         if (isValidArrayIndex(index)) {
2767             for (ScriptObject object = this; ; ) {
2768                 if (object.getMap().containsArrayKeys()) {
2769                     final FindProperty find = object.findProperty(key, false, this);
2770                     if (find != null) {
2771                         return getDoubleValue(find, programPoint);
2772                     }
2773                 }
2774 
2775                 if ((object = object.getProto()) == null) {
2776                     break;
2777                 }
2778 
2779                 final ArrayData array = object.getArray();
2780 
2781                 if (array.has(index)) {
2782                     return isValid(programPoint) ?
2783                         array.getDoubleOptimistic(index, programPoint) :
2784                         array.getDouble(index);


2804         if (array.has(index)) {
2805             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2806         }
2807 
2808         return getDouble(index, JSType.toString(primitiveKey), programPoint);
2809     }
2810 
2811     @Override
2812     public double getDouble(final double key, final int programPoint) {
2813         final int       index = getArrayIndex(key);
2814         final ArrayData array = getArray();
2815 
2816         if (array.has(index)) {
2817             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2818         }
2819 
2820         return getDouble(index, JSType.toString(key), programPoint);
2821     }
2822 
2823     @Override












2824     public double getDouble(final int key, final int programPoint) {
2825         final int       index = getArrayIndex(key);
2826         final ArrayData array = getArray();
2827 
2828         if (array.has(index)) {
2829             return isValid(programPoint) ? array.getDoubleOptimistic(key, programPoint) : array.getDouble(key);
2830         }
2831 
2832         return getDouble(index, JSType.toString(key), programPoint);
2833     }
2834 
2835     private Object get(final int index, final String key) {
2836         if (isValidArrayIndex(index)) {
2837             for (ScriptObject object = this; ; ) {
2838                 if (object.getMap().containsArrayKeys()) {
2839                     final FindProperty find = object.findProperty(key, false, this);
2840 
2841                     if (find != null) {
2842                         return find.getObjectValue();
2843                     }


2873         if (array.has(index)) {
2874             return array.getObject(index);
2875         }
2876 
2877         return get(index, JSType.toString(primitiveKey));
2878     }
2879 
2880     @Override
2881     public Object get(final double key) {
2882         final int index = getArrayIndex(key);
2883         final ArrayData array = getArray();
2884 
2885         if (array.has(index)) {
2886             return array.getObject(index);
2887         }
2888 
2889         return get(index, JSType.toString(key));
2890     }
2891 
2892     @Override












2893     public Object get(final int key) {
2894         final int index = getArrayIndex(key);
2895         final ArrayData array = getArray();
2896 
2897         if (array.has(index)) {
2898             return array.getObject(index);
2899         }
2900 
2901         return get(index, JSType.toString(key));
2902     }
2903 
2904     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
2905         if (getMap().containsArrayKeys()) {
2906             final String       key  = JSType.toString(longIndex);
2907             final FindProperty find = findProperty(key, true);
2908             if (find != null) {
2909                 setObject(find, callSiteFlags, key, value);
2910                 return true;
2911             }
2912         }


2955             if (!isExtensible()) {
2956                 if (isStrictFlag(callSiteFlags)) {
2957                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
2958                 }
2959                 return true;
2960             }
2961             setArray(getArray().ensure(longIndex));
2962         }
2963         return false;
2964     }
2965 
2966     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
2967         final long oldLength = getArray().length();
2968         final long longIndex = ArrayIndex.toLongIndex(index);
2969         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
2970             final boolean strict = isStrictFlag(callSiteFlags);
2971             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
2972         }
2973     }
2974 









2975     private void doesNotHave(final int index, final double value, final int callSiteFlags) {
2976         final long oldLength = getArray().length();
2977         final long longIndex = ArrayIndex.toLongIndex(index);
2978         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
2979             final boolean strict = isStrictFlag(callSiteFlags);
2980             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
2981         }
2982     }
2983 
2984     private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
2985         final long oldLength = getArray().length();
2986         final long longIndex = ArrayIndex.toLongIndex(index);
2987         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
2988             final boolean strict = isStrictFlag(callSiteFlags);
2989             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
2990         }
2991     }
2992 
2993     /**
2994      * This is the most generic of all Object setters. Most of the others use this in some form.


3061     public void set(final Object key, final int value, final int callSiteFlags) {
3062         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3063         final int    index        = getArrayIndex(primitiveKey);
3064 
3065         if (isValidArrayIndex(index)) {
3066             final ArrayData data = getArray();
3067             if (data.has(index)) {
3068                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3069             } else {
3070                 doesNotHave(index, value, callSiteFlags);
3071             }
3072 
3073             return;
3074         }
3075 
3076         final String propName = JSType.toString(primitiveKey);
3077         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3078     }
3079 
3080     @Override




















3081     public void set(final Object key, final double value, final int callSiteFlags) {
3082         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3083         final int    index        = getArrayIndex(primitiveKey);
3084 
3085         if (isValidArrayIndex(index)) {
3086             final ArrayData data = getArray();
3087             if (data.has(index)) {
3088                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3089             } else {
3090                 doesNotHave(index, value, callSiteFlags);
3091             }
3092 
3093             return;
3094         }
3095 
3096         final String propName = JSType.toString(primitiveKey);
3097         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3098     }
3099 
3100     @Override


3120     @Override
3121     public void set(final double key, final int value, final int callSiteFlags) {
3122         final int index = getArrayIndex(key);
3123 
3124         if (isValidArrayIndex(index)) {
3125             final ArrayData data = getArray();
3126             if (data.has(index)) {
3127                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3128             } else {
3129                 doesNotHave(index, value, callSiteFlags);
3130             }
3131 
3132             return;
3133         }
3134 
3135         final String propName = JSType.toString(key);
3136         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3137     }
3138 
3139     @Override



















3140     public void set(final double key, final double value, final int callSiteFlags) {
3141         final int index = getArrayIndex(key);
3142 
3143         if (isValidArrayIndex(index)) {
3144             final ArrayData data = getArray();
3145             if (data.has(index)) {
3146                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3147             } else {
3148                 doesNotHave(index, value, callSiteFlags);
3149             }
3150 
3151             return;
3152         }
3153 
3154         final String propName = JSType.toString(key);
3155         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3156     }
3157 
3158     @Override
3159     public void set(final double key, final Object value, final int callSiteFlags) {
3160         final int index = getArrayIndex(key);
3161 
3162         if (isValidArrayIndex(index)) {
3163             final ArrayData data = getArray();
3164             if (data.has(index)) {
3165                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3166             } else {
3167                 doesNotHave(index, value, callSiteFlags);
3168             }
3169 
3170             return;
3171         }
3172 
3173         final String propName = JSType.toString(key);
3174         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3175     }
3176 
3177     @Override












































































3178     public void set(final int key, final int value, final int callSiteFlags) {
3179         final int index = getArrayIndex(key);
3180         if (isValidArrayIndex(index)) {
3181             if (getArray().has(index)) {
3182                 final ArrayData data = getArray();
3183                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3184             } else {
3185                 doesNotHave(index, value, callSiteFlags);
3186             }
3187             return;
3188         }
3189 
3190         final String propName = JSType.toString(key);
3191         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3192     }
3193 
3194     @Override



















3195     public void set(final int key, final double value, final int callSiteFlags) {
3196         final int index = getArrayIndex(key);
3197 
3198         if (isValidArrayIndex(index)) {
3199             final ArrayData data = getArray();
3200             if (data.has(index)) {
3201                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3202             } else {
3203                 doesNotHave(index, value, callSiteFlags);
3204             }
3205 
3206             return;
3207         }
3208 
3209         final String propName = JSType.toString(key);
3210         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3211     }
3212 
3213     @Override
3214     public void set(final int key, final Object value, final int callSiteFlags) {


3226         }
3227 
3228         final String propName = JSType.toString(key);
3229         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3230     }
3231 
3232     @Override
3233     public boolean has(final Object key) {
3234         final Object primitiveKey = JSType.toPrimitive(key);
3235         final int    index        = getArrayIndex(primitiveKey);
3236         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), true);
3237     }
3238 
3239     @Override
3240     public boolean has(final double key) {
3241         final int index = getArrayIndex(key);
3242         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3243     }
3244 
3245     @Override






3246     public boolean has(final int key) {
3247         final int index = getArrayIndex(key);
3248         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3249     }
3250 
3251     private boolean hasArrayProperty(final int index) {
3252         boolean hasArrayKeys = false;
3253 
3254         for (ScriptObject self = this; self != null; self = self.getProto()) {
3255             if (self.getArray().has(index)) {
3256                 return true;
3257             }
3258             hasArrayKeys = hasArrayKeys || self.getMap().containsArrayKeys();
3259         }
3260 
3261         return hasArrayKeys && hasProperty(ArrayIndex.toKey(index), true);
3262     }
3263 
3264     @Override
3265     public boolean hasOwnProperty(final Object key) {
3266         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3267         final int    index        = getArrayIndex(primitiveKey);
3268         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), false);
3269     }
3270 
3271     @Override
3272     public boolean hasOwnProperty(final int key) {
3273         final int index = getArrayIndex(key);
3274         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3275     }
3276 
3277     @Override






3278     public boolean hasOwnProperty(final double key) {
3279         final int index = getArrayIndex(key);
3280         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3281     }
3282 
3283     private boolean hasOwnArrayProperty(final int index) {
3284         return getArray().has(index) || getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false);
3285     }
3286 
3287     @Override
3288     public boolean delete(final int key, final boolean strict) {
3289         final int index = getArrayIndex(key);
3290         final ArrayData array = getArray();
3291 
3292         if (array.has(index)) {
3293             if (array.canDelete(index, strict)) {
3294                 setArray(array.delete(index));
3295                 return true;
3296             }
3297             return false;
3298         }
















3299         return deleteObject(JSType.toObject(key), strict);
3300     }
3301 
3302     @Override
3303     public boolean delete(final double key, final boolean strict) {
3304         final int index = getArrayIndex(key);
3305         final ArrayData array = getArray();
3306 
3307         if (array.has(index)) {
3308             if (array.canDelete(index, strict)) {
3309                 setArray(array.delete(index));
3310                 return true;
3311             }
3312             return false;
3313         }
3314 
3315         return deleteObject(JSType.toObject(key), strict);
3316     }
3317 
3318     @Override


< prev index next >