2201 pushType(Type.OBJECT_ARRAY); |
2201 pushType(Type.OBJECT_ARRAY); |
2202 return this; |
2202 return this; |
2203 } |
2203 } |
2204 |
2204 |
2205 /** |
2205 /** |
2206 * Generate dynamic getter. Pop scope from stack. Push result |
2206 * Generate dynamic getter. Pop object from stack. Push result. |
2207 * |
2207 * |
2208 * @param valueType type of the value to set |
2208 * @param valueType type of the value to set |
2209 * @param name name of property |
2209 * @param name name of property |
2210 * @param flags call site flags |
2210 * @param flags call site flags |
2211 * @param isMethod should it prefer retrieving methods |
2211 * @param isMethod should it prefer retrieving methods |
2222 Type type = valueType; |
2222 Type type = valueType; |
2223 if (type.isObject() || type.isBoolean()) { |
2223 if (type.isObject() || type.isBoolean()) { |
2224 type = Type.OBJECT; //promote e.g strings to object generic setter |
2224 type = Type.OBJECT; //promote e.g strings to object generic setter |
2225 } |
2225 } |
2226 |
2226 |
2227 popType(Type.SCOPE); |
2227 popType(Type.OBJECT); |
2228 method.visitInvokeDynamicInsn(NameCodec.encode(name), |
2228 method.visitInvokeDynamicInsn(NameCodec.encode(name), |
2229 Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, isIndex)); |
2229 Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, isIndex)); |
2230 |
2230 |
2231 pushType(type); |
2231 pushType(type); |
2232 convert(valueType); //most probably a nop |
2232 convert(valueType); //most probably a nop |
2254 if (type.isObject() || type.isBoolean()) { //promote strings to objects etc |
2254 if (type.isObject() || type.isBoolean()) { //promote strings to objects etc |
2255 type = Type.OBJECT; |
2255 type = Type.OBJECT; |
2256 convert(Type.OBJECT); //TODO bad- until we specialize boolean setters, |
2256 convert(Type.OBJECT); //TODO bad- until we specialize boolean setters, |
2257 } |
2257 } |
2258 popType(type); |
2258 popType(type); |
2259 popType(Type.SCOPE); |
2259 popType(Type.OBJECT); |
2260 |
2260 |
2261 method.visitInvokeDynamicInsn(NameCodec.encode(name), |
2261 method.visitInvokeDynamicInsn(NameCodec.encode(name), |
2262 methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags | dynSetOperation(isIndex)); |
2262 methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags | dynSetOperation(isIndex)); |
2263 } |
2263 } |
2264 |
2264 |
2265 /** |
2265 /** |
|
2266 * Generate dynamic remover. Pop object from stack. Push result. |
|
2267 * |
|
2268 * @param name name of property |
|
2269 * @param flags call site flags |
|
2270 * @return the method emitter |
|
2271 */ |
|
2272 MethodEmitter dynamicRemove(final String name, final int flags, final boolean isIndex) { |
|
2273 if (name.length() > LARGE_STRING_THRESHOLD) { // use removeIndex for extremely long names |
|
2274 return load(name).dynamicRemoveIndex(flags); |
|
2275 } |
|
2276 |
|
2277 debug("dynamic_remove", name, Type.BOOLEAN, getProgramPoint(flags)); |
|
2278 |
|
2279 popType(Type.OBJECT); |
|
2280 // Type is widened to OBJECT then coerced back to BOOLEAN |
|
2281 method.visitInvokeDynamicInsn(NameCodec.encode(name), |
|
2282 Type.getMethodDescriptor(Type.OBJECT, Type.OBJECT), LINKERBOOTSTRAP, flags | dynRemoveOperation(isIndex)); |
|
2283 |
|
2284 pushType(Type.OBJECT); |
|
2285 convert(Type.BOOLEAN); //most probably a nop |
|
2286 |
|
2287 return this; |
|
2288 } |
|
2289 |
|
2290 /** |
2266 * Dynamic getter for indexed structures. Pop index and receiver from stack, |
2291 * Dynamic getter for indexed structures. Pop index and receiver from stack, |
2267 * generate appropriate signatures based on types |
2292 * generate appropriate signatures based on types |
2268 * |
2293 * |
2269 * @param result result type for getter |
2294 * @param result result type for getter |
2270 * @param flags call site flags for getter |
2295 * @param flags call site flags for getter |
2337 assert receiver.isObject(); |
2362 assert receiver.isObject(); |
2338 |
2363 |
2339 method.visitInvokeDynamicInsn(EMPTY_NAME, |
2364 method.visitInvokeDynamicInsn(EMPTY_NAME, |
2340 methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), |
2365 methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), |
2341 LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.SET_ELEMENT); |
2366 LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.SET_ELEMENT); |
|
2367 } |
|
2368 |
|
2369 /** |
|
2370 * Dynamic remover for indexed structures. Pop index and receiver from stack, |
|
2371 * generate appropriate signatures based on types |
|
2372 * |
|
2373 * @param flags call site flags for getter |
|
2374 * |
|
2375 * @return the method emitter |
|
2376 */ |
|
2377 MethodEmitter dynamicRemoveIndex(final int flags) { |
|
2378 debug("dynamic_remove_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags)); |
|
2379 |
|
2380 Type index = peekType(); |
|
2381 if (index.isObject() || index.isBoolean()) { |
|
2382 index = Type.OBJECT; //e.g. string->object |
|
2383 convert(Type.OBJECT); |
|
2384 } |
|
2385 popType(); |
|
2386 |
|
2387 popType(Type.OBJECT); |
|
2388 |
|
2389 final String signature = Type.getMethodDescriptor(Type.OBJECT, Type.OBJECT /*e.g STRING->OBJECT*/, index); |
|
2390 |
|
2391 method.visitInvokeDynamicInsn(EMPTY_NAME, signature, LINKERBOOTSTRAP, flags | dynRemoveOperation(true)); |
|
2392 pushType(Type.OBJECT); |
|
2393 convert(Type.BOOLEAN); |
|
2394 |
|
2395 return this; |
2342 } |
2396 } |
2343 |
2397 |
2344 /** |
2398 /** |
2345 * Load a key value in the proper form. |
2399 * Load a key value in the proper form. |
2346 * |
2400 * |
2516 } |
2570 } |
2517 } |
2571 } |
2518 |
2572 |
2519 private static int dynSetOperation(final boolean isIndex) { |
2573 private static int dynSetOperation(final boolean isIndex) { |
2520 return isIndex ? NashornCallSiteDescriptor.SET_ELEMENT : NashornCallSiteDescriptor.SET_PROPERTY; |
2574 return isIndex ? NashornCallSiteDescriptor.SET_ELEMENT : NashornCallSiteDescriptor.SET_PROPERTY; |
|
2575 } |
|
2576 |
|
2577 private static int dynRemoveOperation(final boolean isIndex) { |
|
2578 return isIndex ? NashornCallSiteDescriptor.REMOVE_ELEMENT : NashornCallSiteDescriptor.REMOVE_PROPERTY; |
2521 } |
2579 } |
2522 |
2580 |
2523 private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) { |
2581 private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) { |
2524 final Type from = conversion.getFrom(); |
2582 final Type from = conversion.getFrom(); |
2525 final Type to = conversion.getTo(); |
2583 final Type to = conversion.getTo(); |