Доступ к другой переменной с содержимым каждого цикла

Для выполнения этого типа селектора нет выделенной инструкции по байт-коду, поэтому, если вы хотите загрузить локальную переменную на основе содержимого другой переменной, вы должны сами выполнить эту операцию, например

// pick #1 or #2 based on #0 in [0..1]
 0: iload_0
 1: ifne          8
 4: aload_1
 5: goto          9
 8: aload_2
 9: // value is now on the stack, ready for use

или

// pick #1, #2, or #3 based on #0 in [0..2]
 0: iload_0
 1: ifne          8
 4: aload_1
 5: goto          18
 8: iload_0
 9: iconst_1
10: if_icmpne     17
13: aload_2
14: goto          18
17: aload_3
18:  // value is now on the stack, ready for use

или, чтобы иметь вариант, который масштабируется с большим числом переменных:

// pick #1, #2, or #3 based on #0 in [0..2]
 0: iload_0
 1: tableswitch   { // 0 to 2
               0: 28
               1: 32
               2: 36
         default: 36
    }
28: aload_1
29: goto          37
32: aload_2
33: goto          37
36: aload_3
37: // value is now on the stack, ready for use

Последний вариант был сгенерирован с помощью библиотеки ASM и следующего helper method, называя его как loadDynamic(…, 0, 1, 3);

/**
 * Load variable #(firstChoice + value(#selector))
 */
public static void loadDynamic(
              MethodVisitor target, int selector, int firstChoice, int numChoices) {
    Label[] labels = new Label[numChoices];
    for(int ix = 0; ix < numChoices; ix++) labels[ix] = new Label();
    Label end = new Label();
    target.visitVarInsn(Opcodes.ILOAD, selector);
    target.visitTableSwitchInsn(0, numChoices - 1, labels[numChoices - 1], labels);
    target.visitLabel(labels[0]);
    target.visitVarInsn(Opcodes.ALOAD, firstChoice);
    for(int ix = 1; ix < numChoices; ix++) {
        target.visitJumpInsn(Opcodes.GOTO, end);
        target.visitLabel(labels[ix]);
        target.visitVarInsn(Opcodes.ALOAD, firstChoice + ix);
    }
    target.visitLabel(end); // choosen value is now on the stack
}

Очевидно, что в большинстве случаев код на основе массива с использованием инструкций доступа на основе индексов намного проще и эффективнее.

0
задан user82395214 19 January 2019 в 03:55
поделиться

1 ответ

Другие вопросы по тегам:

Похожие вопросы: