132 private PropertyMap map;
133
134 /** objects proto. */
135 private ScriptObject proto;
136
137 /** Object flags. */
138 private int flags;
139
140 /** Area for primitive properties added to object after instantiation, see {@link AccessorProperty} */
141 protected long[] primitiveSpill;
142
143 /** Area for reference properties added to object after instantiation, see {@link AccessorProperty} */
144 protected Object[] objectSpill;
145
146 /** Indexed array data. */
147 private ArrayData arrayData;
148
149 /** Method handle to retrieve prototype of this object */
150 public static final MethodHandle GETPROTO = findOwnMH_V("getProto", ScriptObject.class);
151
152 static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
153 static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
154 static final MethodHandle DECLARE_AND_SET = findOwnMH_V("declareAndSet", void.class, String.class, Object.class);
155
156 private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
157 private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
158 private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
159
160 private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
161
162 /** Method handle for getting the array data */
163 public static final Call GET_ARRAY = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArray", ArrayData.class);
164
165 /** Method handle for getting a function argument at a given index. Used from MapCreator */
166 public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
167
168 /** Method handle for setting a function argument at a given index. Used from MapCreator */
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);
2018 mh = Lookup.emptyGetter(returnType);
2019 protoSwitchPoint = getProtoSwitchPoint(name, owner);
2020 } else if (!find.isSelf()) {
2021 assert mh.type().returnType().equals(returnType) :
2022 "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
2023 if (!(property instanceof UserAccessorProperty)) {
2024 // Add a filter that replaces the self object with the prototype owning the property.
2025 mh = addProtoFilter(mh, find.getProtoChainLength());
2026 }
2027 protoSwitchPoint = getProtoSwitchPoint(name, owner);
2028 } else {
2029 protoSwitchPoint = null;
2030 }
2031
2032 final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
2033 return inv.addSwitchPoint(findBuiltinSwitchPoint(name));
2034 }
2035
2036 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
2037 Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
2038 final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
2039 final MethodHandle guard = getScriptObjectGuard(desc.getMethodType(), true);
2040 return new GuardedInvocation(invoker, guard);
2041 }
2042
2043 @SuppressWarnings("unused")
2044 private Object megamorphicGet(final String key, final boolean isMethod) {
2045 final FindProperty find = findProperty(key, true);
2046 if (find != null) {
2047 return find.getObjectValue();
2048 }
2049
2050 return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
2051 }
2052
2053 // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
2054 @SuppressWarnings("unused")
2055 private void declareAndSet(final String key, final Object value) {
2056 final PropertyMap oldMap = getMap();
2057 final FindProperty find = findProperty(key, false);
2058 assert find != null;
2059
2060 final Property property = find.getProperty();
2061 assert property != null;
2062 assert property.needsDeclaration();
2063
2064 final PropertyMap newMap = oldMap.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
2065 setMap(newMap);
2066 set(key, value, 0);
2067 }
2068
2069 /**
2070 * Find the appropriate GETINDEX method for an invoke dynamic call.
2365 getMap(),
2366 find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
2367 find.getProtoChainLength(),
2368 func),
2369 getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
2370 //TODO this doesn't need a ClassCastException as guard always checks script object
2371 null);
2372 }
2373 }
2374
2375 if (scopeAccess) {
2376 throw referenceError("not.defined", name);
2377 }
2378
2379 return createEmptyGetter(desc, explicitInstanceOfCheck(desc, request), name);
2380 }
2381
2382 /**
2383 * Invoke fall back if a property is not found.
2384 * @param name Name of property.
2385 * @param programPoint program point
2386 * @return Result from call.
2387 */
2388 protected Object invokeNoSuchProperty(final String name, final int programPoint) {
2389 final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
2390
2391 Object ret = UNDEFINED;
2392
2393 if (find != null) {
2394 final Object func = find.getObjectValue();
2395
2396 if (func instanceof ScriptFunction) {
2397 ret = ScriptRuntime.apply((ScriptFunction)func, this, name);
2398 }
2399 }
2400
2401 if (isValid(programPoint)) {
2402 throw new UnwarrantedOptimismException(ret, programPoint);
2403 }
2404
2405 return ret;
2406 }
2407
2408
2409 /**
2410 * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
2411 * @param name the method name
2412 * @return the bound function, or undefined
2413 */
2414 private Object getNoSuchMethod(final String name, final int programPoint) {
2415 final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
2416
2417 if (find == null) {
2418 return invokeNoSuchProperty(name, programPoint);
2419 }
2420
2421 final Object value = find.getObjectValue();
2422 if (!(value instanceof ScriptFunction)) {
2423 return UNDEFINED;
2424 }
2425
2426 return ((ScriptFunction)value).createBound(this, new Object[] {name});
2427 }
2428
2429 private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) {
2430 if (NashornCallSiteDescriptor.isOptimistic(desc)) {
2431 throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
2432 }
2433
2434 return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
2435 NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
2436 explicitInstanceOfCheck ? null : ClassCastException.class);
2437 }
2438
2439 private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
2440 protected T[] values;
2441 protected final ScriptObject object;
2442 private int index;
2443
2444 ScriptObjectIterator(final ScriptObject object) {
2445 this.object = object;
2446 }
2721 if ((object = object.getProto()) == null) {
2722 break;
2723 }
2724
2725 final ArrayData array = object.getArray();
2726
2727 if (array.has(index)) {
2728 return isValid(programPoint) ?
2729 array.getIntOptimistic(index, programPoint) :
2730 array.getInt(index);
2731 }
2732 }
2733 } else {
2734 final FindProperty find = findProperty(key, true);
2735
2736 if (find != null) {
2737 return getIntValue(find, programPoint);
2738 }
2739 }
2740
2741 return JSType.toInt32(invokeNoSuchProperty(key, programPoint));
2742 }
2743
2744 @Override
2745 public int getInt(final Object key, final int programPoint) {
2746 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2747 final int index = getArrayIndex(primitiveKey);
2748 final ArrayData array = getArray();
2749
2750 if (array.has(index)) {
2751 return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2752 }
2753
2754 return getInt(index, JSType.toString(primitiveKey), programPoint);
2755 }
2756
2757 @Override
2758 public int getInt(final double key, final int programPoint) {
2759 final int index = getArrayIndex(key);
2760 final ArrayData array = getArray();
2761
2803 if ((object = object.getProto()) == null) {
2804 break;
2805 }
2806
2807 final ArrayData array = object.getArray();
2808
2809 if (array.has(index)) {
2810 return isValid(programPoint) ?
2811 array.getLongOptimistic(index, programPoint) :
2812 array.getLong(index);
2813 }
2814 }
2815 } else {
2816 final FindProperty find = findProperty(key, true);
2817
2818 if (find != null) {
2819 return getLongValue(find, programPoint);
2820 }
2821 }
2822
2823 return JSType.toLong(invokeNoSuchProperty(key, programPoint));
2824 }
2825
2826 @Override
2827 public long getLong(final Object key, final int programPoint) {
2828 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2829 final int index = getArrayIndex(primitiveKey);
2830 final ArrayData array = getArray();
2831
2832 if (array.has(index)) {
2833 return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2834 }
2835
2836 return getLong(index, JSType.toString(primitiveKey), programPoint);
2837 }
2838
2839 @Override
2840 public long getLong(final double key, final int programPoint) {
2841 final int index = getArrayIndex(key);
2842 final ArrayData array = getArray();
2843
2885 if ((object = object.getProto()) == null) {
2886 break;
2887 }
2888
2889 final ArrayData array = object.getArray();
2890
2891 if (array.has(index)) {
2892 return isValid(programPoint) ?
2893 array.getDoubleOptimistic(index, programPoint) :
2894 array.getDouble(index);
2895 }
2896 }
2897 } else {
2898 final FindProperty find = findProperty(key, true);
2899
2900 if (find != null) {
2901 return getDoubleValue(find, programPoint);
2902 }
2903 }
2904
2905 return JSType.toNumber(invokeNoSuchProperty(key, INVALID_PROGRAM_POINT));
2906 }
2907
2908 @Override
2909 public double getDouble(final Object key, final int programPoint) {
2910 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2911 final int index = getArrayIndex(primitiveKey);
2912 final ArrayData array = getArray();
2913
2914 if (array.has(index)) {
2915 return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2916 }
2917
2918 return getDouble(index, JSType.toString(primitiveKey), programPoint);
2919 }
2920
2921 @Override
2922 public double getDouble(final double key, final int programPoint) {
2923 final int index = getArrayIndex(key);
2924 final ArrayData array = getArray();
2925
2966 }
2967
2968 if ((object = object.getProto()) == null) {
2969 break;
2970 }
2971
2972 final ArrayData array = object.getArray();
2973
2974 if (array.has(index)) {
2975 return array.getObject(index);
2976 }
2977 }
2978 } else {
2979 final FindProperty find = findProperty(key, true);
2980
2981 if (find != null) {
2982 return find.getObjectValue();
2983 }
2984 }
2985
2986 return invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
2987 }
2988
2989 @Override
2990 public Object get(final Object key) {
2991 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2992 final int index = getArrayIndex(primitiveKey);
2993 final ArrayData array = getArray();
2994
2995 if (array.has(index)) {
2996 return array.getObject(index);
2997 }
2998
2999 return get(index, JSType.toString(primitiveKey));
3000 }
3001
3002 @Override
3003 public Object get(final double key) {
3004 final int index = getArrayIndex(key);
3005 final ArrayData array = getArray();
3006
|
132 private PropertyMap map;
133
134 /** objects proto. */
135 private ScriptObject proto;
136
137 /** Object flags. */
138 private int flags;
139
140 /** Area for primitive properties added to object after instantiation, see {@link AccessorProperty} */
141 protected long[] primitiveSpill;
142
143 /** Area for reference properties added to object after instantiation, see {@link AccessorProperty} */
144 protected Object[] objectSpill;
145
146 /** Indexed array data. */
147 private ArrayData arrayData;
148
149 /** Method handle to retrieve prototype of this object */
150 public static final MethodHandle GETPROTO = findOwnMH_V("getProto", ScriptObject.class);
151
152 static final MethodHandle MEGAMORPHIC_GET = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
153 static final MethodHandle GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
154 static final MethodHandle DECLARE_AND_SET = findOwnMH_V("declareAndSet", void.class, String.class, Object.class);
155
156 private static final MethodHandle TRUNCATINGFILTER = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
157 private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
158 private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
159
160 private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
161
162 /** Method handle for getting the array data */
163 public static final Call GET_ARRAY = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArray", ArrayData.class);
164
165 /** Method handle for getting a function argument at a given index. Used from MapCreator */
166 public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
167
168 /** Method handle for setting a function argument at a given index. Used from MapCreator */
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);
2018 mh = Lookup.emptyGetter(returnType);
2019 protoSwitchPoint = getProtoSwitchPoint(name, owner);
2020 } else if (!find.isSelf()) {
2021 assert mh.type().returnType().equals(returnType) :
2022 "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
2023 if (!(property instanceof UserAccessorProperty)) {
2024 // Add a filter that replaces the self object with the prototype owning the property.
2025 mh = addProtoFilter(mh, find.getProtoChainLength());
2026 }
2027 protoSwitchPoint = getProtoSwitchPoint(name, owner);
2028 } else {
2029 protoSwitchPoint = null;
2030 }
2031
2032 final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
2033 return inv.addSwitchPoint(findBuiltinSwitchPoint(name));
2034 }
2035
2036 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
2037 Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
2038 final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, NashornCallSiteDescriptor.isScope(desc));
2039 final MethodHandle guard = getScriptObjectGuard(desc.getMethodType(), true);
2040 return new GuardedInvocation(invoker, guard);
2041 }
2042
2043 @SuppressWarnings("unused")
2044 private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
2045 final FindProperty find = findProperty(key, true);
2046 if (find != null) {
2047 return find.getObjectValue();
2048 }
2049
2050 return isMethod ? getNoSuchMethod(key, isScope, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, isScope, INVALID_PROGRAM_POINT);
2051 }
2052
2053 // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
2054 @SuppressWarnings("unused")
2055 private void declareAndSet(final String key, final Object value) {
2056 final PropertyMap oldMap = getMap();
2057 final FindProperty find = findProperty(key, false);
2058 assert find != null;
2059
2060 final Property property = find.getProperty();
2061 assert property != null;
2062 assert property.needsDeclaration();
2063
2064 final PropertyMap newMap = oldMap.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
2065 setMap(newMap);
2066 set(key, value, 0);
2067 }
2068
2069 /**
2070 * Find the appropriate GETINDEX method for an invoke dynamic call.
2365 getMap(),
2366 find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
2367 find.getProtoChainLength(),
2368 func),
2369 getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
2370 //TODO this doesn't need a ClassCastException as guard always checks script object
2371 null);
2372 }
2373 }
2374
2375 if (scopeAccess) {
2376 throw referenceError("not.defined", name);
2377 }
2378
2379 return createEmptyGetter(desc, explicitInstanceOfCheck(desc, request), name);
2380 }
2381
2382 /**
2383 * Invoke fall back if a property is not found.
2384 * @param name Name of property.
2385 * @param isScope is this a scope access?
2386 * @param programPoint program point
2387 * @return Result from call.
2388 */
2389 protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
2390 final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
2391
2392 Object ret = UNDEFINED;
2393
2394 if (find != null) {
2395 final Object func = find.getObjectValue();
2396
2397 if (func instanceof ScriptFunction) {
2398 final ScriptFunction sfunc = (ScriptFunction)func;
2399 final Object self = isScope && sfunc.isStrict()? UNDEFINED : this;
2400 ret = ScriptRuntime.apply(sfunc, self, name);
2401 }
2402 }
2403
2404 if (isValid(programPoint)) {
2405 throw new UnwarrantedOptimismException(ret, programPoint);
2406 }
2407
2408 return ret;
2409 }
2410
2411
2412 /**
2413 * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
2414 * @param name the method name
2415 * @param isScope is this a scope access?
2416 * @return the bound function, or undefined
2417 */
2418 private Object getNoSuchMethod(final String name, final boolean isScope, final int programPoint) {
2419 final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
2420
2421 if (find == null) {
2422 return invokeNoSuchProperty(name, isScope, programPoint);
2423 }
2424
2425 final Object value = find.getObjectValue();
2426 if (!(value instanceof ScriptFunction)) {
2427 return UNDEFINED;
2428 }
2429
2430 final ScriptFunction func = (ScriptFunction)value;
2431 final Object self = isScope && func.isStrict()? UNDEFINED : this;
2432 return func.createBound(self, new Object[] {name});
2433 }
2434
2435 private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) {
2436 if (NashornCallSiteDescriptor.isOptimistic(desc)) {
2437 throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
2438 }
2439
2440 return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
2441 NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
2442 explicitInstanceOfCheck ? null : ClassCastException.class);
2443 }
2444
2445 private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
2446 protected T[] values;
2447 protected final ScriptObject object;
2448 private int index;
2449
2450 ScriptObjectIterator(final ScriptObject object) {
2451 this.object = object;
2452 }
2727 if ((object = object.getProto()) == null) {
2728 break;
2729 }
2730
2731 final ArrayData array = object.getArray();
2732
2733 if (array.has(index)) {
2734 return isValid(programPoint) ?
2735 array.getIntOptimistic(index, programPoint) :
2736 array.getInt(index);
2737 }
2738 }
2739 } else {
2740 final FindProperty find = findProperty(key, true);
2741
2742 if (find != null) {
2743 return getIntValue(find, programPoint);
2744 }
2745 }
2746
2747 return JSType.toInt32(invokeNoSuchProperty(key, false, programPoint));
2748 }
2749
2750 @Override
2751 public int getInt(final Object key, final int programPoint) {
2752 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2753 final int index = getArrayIndex(primitiveKey);
2754 final ArrayData array = getArray();
2755
2756 if (array.has(index)) {
2757 return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2758 }
2759
2760 return getInt(index, JSType.toString(primitiveKey), programPoint);
2761 }
2762
2763 @Override
2764 public int getInt(final double key, final int programPoint) {
2765 final int index = getArrayIndex(key);
2766 final ArrayData array = getArray();
2767
2809 if ((object = object.getProto()) == null) {
2810 break;
2811 }
2812
2813 final ArrayData array = object.getArray();
2814
2815 if (array.has(index)) {
2816 return isValid(programPoint) ?
2817 array.getLongOptimistic(index, programPoint) :
2818 array.getLong(index);
2819 }
2820 }
2821 } else {
2822 final FindProperty find = findProperty(key, true);
2823
2824 if (find != null) {
2825 return getLongValue(find, programPoint);
2826 }
2827 }
2828
2829 return JSType.toLong(invokeNoSuchProperty(key, false, programPoint));
2830 }
2831
2832 @Override
2833 public long getLong(final Object key, final int programPoint) {
2834 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2835 final int index = getArrayIndex(primitiveKey);
2836 final ArrayData array = getArray();
2837
2838 if (array.has(index)) {
2839 return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2840 }
2841
2842 return getLong(index, JSType.toString(primitiveKey), programPoint);
2843 }
2844
2845 @Override
2846 public long getLong(final double key, final int programPoint) {
2847 final int index = getArrayIndex(key);
2848 final ArrayData array = getArray();
2849
2891 if ((object = object.getProto()) == null) {
2892 break;
2893 }
2894
2895 final ArrayData array = object.getArray();
2896
2897 if (array.has(index)) {
2898 return isValid(programPoint) ?
2899 array.getDoubleOptimistic(index, programPoint) :
2900 array.getDouble(index);
2901 }
2902 }
2903 } else {
2904 final FindProperty find = findProperty(key, true);
2905
2906 if (find != null) {
2907 return getDoubleValue(find, programPoint);
2908 }
2909 }
2910
2911 return JSType.toNumber(invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT));
2912 }
2913
2914 @Override
2915 public double getDouble(final Object key, final int programPoint) {
2916 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2917 final int index = getArrayIndex(primitiveKey);
2918 final ArrayData array = getArray();
2919
2920 if (array.has(index)) {
2921 return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2922 }
2923
2924 return getDouble(index, JSType.toString(primitiveKey), programPoint);
2925 }
2926
2927 @Override
2928 public double getDouble(final double key, final int programPoint) {
2929 final int index = getArrayIndex(key);
2930 final ArrayData array = getArray();
2931
2972 }
2973
2974 if ((object = object.getProto()) == null) {
2975 break;
2976 }
2977
2978 final ArrayData array = object.getArray();
2979
2980 if (array.has(index)) {
2981 return array.getObject(index);
2982 }
2983 }
2984 } else {
2985 final FindProperty find = findProperty(key, true);
2986
2987 if (find != null) {
2988 return find.getObjectValue();
2989 }
2990 }
2991
2992 return invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT);
2993 }
2994
2995 @Override
2996 public Object get(final Object key) {
2997 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2998 final int index = getArrayIndex(primitiveKey);
2999 final ArrayData array = getArray();
3000
3001 if (array.has(index)) {
3002 return array.getObject(index);
3003 }
3004
3005 return get(index, JSType.toString(primitiveKey));
3006 }
3007
3008 @Override
3009 public Object get(final double key) {
3010 final int index = getArrayIndex(key);
3011 final ArrayData array = getArray();
3012
|