1574 * @param table label table
1575 */
1576 void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) {
1577 debug("tableswitch", peekType());
1578 adjustStackForSwitch(defaultLabel, table);
1579 method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table));
1580 doesNotContinueSequentially();
1581 }
1582
1583 private void adjustStackForSwitch(final Label defaultLabel, final Label... table) {
1584 popType(Type.INT);
1585 joinTo(defaultLabel);
1586 for(final Label label: table) {
1587 joinTo(label);
1588 }
1589 }
1590
1591 /**
1592 * Abstraction for performing a conditional jump of any type
1593 *
1594 * @see MethodEmitter.Condition
1595 *
1596 * @param cond the condition to test
1597 * @param trueLabel the destination label is condition is true
1598 */
1599 void conditionalJump(final Condition cond, final Label trueLabel) {
1600 conditionalJump(cond, cond != Condition.GT && cond != Condition.GE, trueLabel);
1601 }
1602
1603 /**
1604 * Abstraction for performing a conditional jump of any type,
1605 * including a dcmpg/dcmpl semantic for doubles.
1606 *
1607 * @param cond the condition to test
1608 * @param isCmpG is this a dcmpg for numbers, false if it's a dcmpl
1609 * @param trueLabel the destination label if condition is true
1610 */
1611 void conditionalJump(final Condition cond, final boolean isCmpG, final Label trueLabel) {
1612 if (peekType().isCategory2()) {
1613 debug("[ld]cmp isCmpG=", isCmpG);
1614 pushType(get2n().cmp(method, isCmpG));
2200 debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
2201 final String signature = getDynamicSignature(returnType, request.getArity());
2202 debug(" signature", signature);
2203 method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
2204 pushType(returnType);
2205
2206 return this;
2207 }
2208
2209 /**
2210 * Generate dynamic getter. Pop scope from stack. Push result
2211 *
2212 * @param valueType type of the value to set
2213 * @param name name of property
2214 * @param flags call site flags
2215 * @param isMethod should it prefer retrieving methods
2216 *
2217 * @return the method emitter
2218 */
2219 MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
2220 debug("dynamic_get", name, valueType, getProgramPoint(flags));
2221
2222 Type type = valueType;
2223 if (type.isObject() || type.isBoolean()) {
2224 type = Type.OBJECT; //promote e.g strings to object generic setter
2225 }
2226
2227 popType(Type.SCOPE);
2228 method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
2229 NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
2230
2231 pushType(type);
2232 convert(valueType); //most probably a nop
2233
2234 return this;
2235 }
2236
2237 /**
2238 * Generate dynamic setter. Pop receiver and property from stack.
2239 *
2240 * @param name name of property
2241 * @param flags call site flags
2242 */
2243 void dynamicSet(final String name, final int flags) {
2244 assert !isOptimistic(flags);
2245 debug("dynamic_set", name, peekType());
2246
2247 Type type = peekType();
2248 if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
2249 type = Type.OBJECT;
2250 convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
2251 }
2252 popType(type);
2253 popType(Type.SCOPE);
2254
2255 method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
2256 }
2257
2258 /**
2259 * Dynamic getter for indexed structures. Pop index and receiver from stack,
2260 * generate appropriate signatures based on types
2261 *
2262 * @param result result type for getter
2263 * @param flags call site flags for getter
|
1574 * @param table label table
1575 */
1576 void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) {
1577 debug("tableswitch", peekType());
1578 adjustStackForSwitch(defaultLabel, table);
1579 method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table));
1580 doesNotContinueSequentially();
1581 }
1582
1583 private void adjustStackForSwitch(final Label defaultLabel, final Label... table) {
1584 popType(Type.INT);
1585 joinTo(defaultLabel);
1586 for(final Label label: table) {
1587 joinTo(label);
1588 }
1589 }
1590
1591 /**
1592 * Abstraction for performing a conditional jump of any type
1593 *
1594 * @see Condition
1595 *
1596 * @param cond the condition to test
1597 * @param trueLabel the destination label is condition is true
1598 */
1599 void conditionalJump(final Condition cond, final Label trueLabel) {
1600 conditionalJump(cond, cond != Condition.GT && cond != Condition.GE, trueLabel);
1601 }
1602
1603 /**
1604 * Abstraction for performing a conditional jump of any type,
1605 * including a dcmpg/dcmpl semantic for doubles.
1606 *
1607 * @param cond the condition to test
1608 * @param isCmpG is this a dcmpg for numbers, false if it's a dcmpl
1609 * @param trueLabel the destination label if condition is true
1610 */
1611 void conditionalJump(final Condition cond, final boolean isCmpG, final Label trueLabel) {
1612 if (peekType().isCategory2()) {
1613 debug("[ld]cmp isCmpG=", isCmpG);
1614 pushType(get2n().cmp(method, isCmpG));
2200 debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
2201 final String signature = getDynamicSignature(returnType, request.getArity());
2202 debug(" signature", signature);
2203 method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
2204 pushType(returnType);
2205
2206 return this;
2207 }
2208
2209 /**
2210 * Generate dynamic getter. Pop scope from stack. Push result
2211 *
2212 * @param valueType type of the value to set
2213 * @param name name of property
2214 * @param flags call site flags
2215 * @param isMethod should it prefer retrieving methods
2216 *
2217 * @return the method emitter
2218 */
2219 MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
2220 if (name.length() > LARGE_STRING_THRESHOLD) { // use getIndex for extremely long names
2221 return load(name).dynamicGetIndex(valueType, flags, isMethod);
2222 }
2223
2224 debug("dynamic_get", name, valueType, getProgramPoint(flags));
2225
2226 Type type = valueType;
2227 if (type.isObject() || type.isBoolean()) {
2228 type = Type.OBJECT; //promote e.g strings to object generic setter
2229 }
2230
2231 popType(Type.SCOPE);
2232 method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
2233 NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
2234
2235 pushType(type);
2236 convert(valueType); //most probably a nop
2237
2238 return this;
2239 }
2240
2241 /**
2242 * Generate dynamic setter. Pop receiver and property from stack.
2243 *
2244 * @param name name of property
2245 * @param flags call site flags
2246 */
2247 void dynamicSet(final String name, final int flags) {
2248 if (name.length() > LARGE_STRING_THRESHOLD) { // use setIndex for extremely long names
2249 load(name).swap().dynamicSetIndex(flags);
2250 return;
2251 }
2252
2253 assert !isOptimistic(flags);
2254 debug("dynamic_set", name, peekType());
2255
2256 Type type = peekType();
2257 if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
2258 type = Type.OBJECT;
2259 convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
2260 }
2261 popType(type);
2262 popType(Type.SCOPE);
2263
2264 method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
2265 }
2266
2267 /**
2268 * Dynamic getter for indexed structures. Pop index and receiver from stack,
2269 * generate appropriate signatures based on types
2270 *
2271 * @param result result type for getter
2272 * @param flags call site flags for getter
|