Example usage for org.objectweb.asm.commons TableSwitchGenerator TableSwitchGenerator

List of usage examples for org.objectweb.asm.commons TableSwitchGenerator TableSwitchGenerator

Introduction

In this page you can find the example usage for org.objectweb.asm.commons TableSwitchGenerator TableSwitchGenerator.

Prototype

TableSwitchGenerator

Source Link

Usage

From source file:com.google.template.soy.jbcsrc.DetachState.java

License:Apache License

/**
 * Returns a statement that generates the reattach jump table.
 * /* ww  w. ja  v  a  2  s  .  co m*/
 * <p>Note: This statement should be the <em>first</em> statement in any detachable method.
 */
Statement generateReattachTable() {
    final Expression readField = stateField.accessor(thisExpr);
    final Statement defaultCase = Statement
            .throwExpression(MethodRef.RUNTIME_UNEXPECTED_STATE_ERROR.invoke(readField));
    return new Statement() {
        @Override
        void doGen(final CodeBuilder adapter) {
            int[] keys = new int[reattaches.size()];
            for (int i = 0; i < keys.length; i++) {
                keys[i] = i;
            }
            readField.gen(adapter);
            // Generate a switch table.  Note, while it might be preferable to just 'goto state', Java
            // doesn't allow computable gotos (probably because it makes verification impossible).  So
            // instead we emulate that with a jump table.  And anyway we still need to execute 'restore'
            // logic to repopulate the local variable tables, so the 'case' statements are a natural
            // place for that logic to live.
            adapter.tableSwitch(keys, new TableSwitchGenerator() {
                @Override
                public void generateCase(int key, Label end) {
                    if (key == 0) {
                        // State 0 is special, it means initial state, so we just jump to the very end
                        adapter.goTo(end);
                        return;
                    }
                    ReattachState reattachState = reattaches.get(key);
                    // restore and jump!
                    reattachState.restoreStatement().gen(adapter);
                    adapter.goTo(reattachState.reattachPoint());
                }

                @Override
                public void generateDefault() {
                    defaultCase.gen(adapter);
                }
            },
                    // Use tableswitch instead of lookupswitch.  TableSwitch is appropriate because our case
                    // labels are sequential integers in the range [0, N).  This means that switch is O(1) and
                    // there are no 'holes' meaning that it is compact in the bytecode.
                    true);
        }
    };
}