| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.apache.flex.abc.semantics; |
| |
| import static org.apache.flex.abc.ABCConstants.*; |
| |
| /** |
| * The InstructionFactory creates implementation Instruction subclasses for |
| * particular types of Instructions, and also handles caching and pooling of |
| * shared Instructions. |
| */ |
| public abstract class InstructionFactory |
| { |
| /* |
| * Singleton instructions. Any Instruction without operands can be shared as |
| * a singleton. |
| */ |
| private static final Instruction s_add = new NoOperandsInstruction(OP_add); |
| private static final Instruction s_astypelate = new NoOperandsInstruction(OP_astypelate); |
| private static final Instruction s_bitand = new NoOperandsInstruction(OP_bitand); |
| private static final Instruction s_bitnot = new NoOperandsInstruction(OP_bitnot); |
| private static final Instruction s_bitor = new NoOperandsInstruction(OP_bitor); |
| private static final Instruction s_bitxor = new NoOperandsInstruction(OP_bitxor); |
| private static final Instruction s_checkfilter = new NoOperandsInstruction(OP_checkfilter); |
| private static final Instruction s_coerce = new NoOperandsInstruction(OP_coerce); |
| private static final Instruction s_coerce_a = new NoOperandsInstruction(OP_coerce_a); |
| private static final Instruction s_coerce_s = new NoOperandsInstruction(OP_coerce_s); |
| private static final Instruction s_convert_b = new NoOperandsInstruction(OP_convert_b); |
| private static final Instruction s_convert_d = new NoOperandsInstruction(OP_convert_d); |
| private static final Instruction s_convert_i = new NoOperandsInstruction(OP_convert_i); |
| private static final Instruction s_convert_o = new NoOperandsInstruction(OP_convert_o); |
| private static final Instruction s_convert_s = new NoOperandsInstruction(OP_convert_s); |
| private static final Instruction s_convert_u = new NoOperandsInstruction(OP_convert_u); |
| private static final Instruction s_decrement = new NoOperandsInstruction(OP_decrement); |
| private static final Instruction s_decrement_i = new NoOperandsInstruction(OP_decrement_i); |
| private static final Instruction s_divide = new NoOperandsInstruction(OP_divide); |
| private static final Instruction s_dup = new NoOperandsInstruction(OP_dup); |
| private static final Instruction s_dxnslate = new NoOperandsInstruction(OP_dxnslate); |
| private static final Instruction s_equals = new NoOperandsInstruction(OP_equals); |
| private static final Instruction s_esc_xattr = new NoOperandsInstruction(OP_esc_xattr); |
| private static final Instruction s_esc_xelem = new NoOperandsInstruction(OP_esc_xelem); |
| private static final Instruction s_getglobalscope = new NoOperandsInstruction(OP_getglobalscope); |
| private static final Instruction s_getlocal0 = new NoOperandsInstruction(OP_getlocal0); |
| private static final Instruction s_getlocal1 = new NoOperandsInstruction(OP_getlocal1); |
| private static final Instruction s_getlocal2 = new NoOperandsInstruction(OP_getlocal2); |
| private static final Instruction s_getlocal3 = new NoOperandsInstruction(OP_getlocal3); |
| private static final Instruction s_greaterequals = new NoOperandsInstruction(OP_greaterequals); |
| private static final Instruction s_greaterthan = new NoOperandsInstruction(OP_greaterthan); |
| private static final Instruction s_hasnext = new NoOperandsInstruction(OP_hasnext); |
| private static final Instruction s_in = new NoOperandsInstruction(OP_in); |
| private static final Instruction s_increment = new NoOperandsInstruction(OP_increment); |
| private static final Instruction s_increment_i = new NoOperandsInstruction(OP_increment_i); |
| private static final Instruction s_instanceof = new NoOperandsInstruction(OP_instanceof); |
| private static final Instruction s_istypelate = new NoOperandsInstruction(OP_istypelate); |
| private static final Instruction s_label = new NoOperandsInstruction(OP_label); |
| private static final Instruction s_lessequals = new NoOperandsInstruction(OP_lessequals); |
| private static final Instruction s_lessthan = new NoOperandsInstruction(OP_lessthan); |
| private static final Instruction s_lshift = new NoOperandsInstruction(OP_lshift); |
| private static final Instruction s_modulo = new NoOperandsInstruction(OP_modulo); |
| private static final Instruction s_multiply = new NoOperandsInstruction(OP_multiply); |
| private static final Instruction s_multiply_i = new NoOperandsInstruction(OP_multiply_i); |
| private static final Instruction s_negate = new NoOperandsInstruction(OP_negate); |
| private static final Instruction s_negate_i = new NoOperandsInstruction(OP_negate_i); |
| private static final Instruction s_newactivation = new NoOperandsInstruction(OP_newactivation); |
| private static final Instruction s_nextname = new NoOperandsInstruction(OP_nextname); |
| private static final Instruction s_nextvalue = new NoOperandsInstruction(OP_nextvalue); |
| private static final Instruction s_nop = new NoOperandsInstruction(OP_nop); |
| private static final Instruction s_not = new NoOperandsInstruction(OP_not); |
| private static final Instruction s_pop = new NoOperandsInstruction(OP_pop); |
| private static final Instruction s_popscope = new NoOperandsInstruction(OP_popscope); |
| private static final Instruction s_pushfalse = new NoOperandsInstruction(OP_pushfalse); |
| private static final Instruction s_pushnan = new NoOperandsInstruction(OP_pushnan); |
| private static final Instruction s_pushnull = new NoOperandsInstruction(OP_pushnull); |
| private static final Instruction s_pushscope = new NoOperandsInstruction(OP_pushscope); |
| private static final Instruction s_pushtrue = new NoOperandsInstruction(OP_pushtrue); |
| private static final Instruction s_pushundefined = new NoOperandsInstruction(OP_pushundefined); |
| private static final Instruction s_pushwith = new NoOperandsInstruction(OP_pushwith); |
| private static final Instruction s_returnvalue = new NoOperandsInstruction(OP_returnvalue); |
| private static final Instruction s_returnvoid = new NoOperandsInstruction(OP_returnvoid); |
| private static final Instruction s_rshift = new NoOperandsInstruction(OP_rshift); |
| private static final Instruction s_setlocal0 = new NoOperandsInstruction(OP_setlocal0); |
| private static final Instruction s_setlocal1 = new NoOperandsInstruction(OP_setlocal1); |
| private static final Instruction s_setlocal2 = new NoOperandsInstruction(OP_setlocal2); |
| private static final Instruction s_setlocal3 = new NoOperandsInstruction(OP_setlocal3); |
| private static final Instruction s_strictequals = new NoOperandsInstruction(OP_strictequals); |
| private static final Instruction s_subtract = new NoOperandsInstruction(OP_subtract); |
| private static final Instruction s_subtract_i = new NoOperandsInstruction(OP_subtract_i); |
| private static final Instruction s_swap = new NoOperandsInstruction(OP_swap); |
| private static final Instruction s_throw = new NoOperandsInstruction(OP_throw); |
| private static final Instruction s_typeof = new NoOperandsInstruction(OP_typeof); |
| private static final Instruction s_urshift = new NoOperandsInstruction(OP_urshift); |
| private static final Instruction s_unplus = new NoOperandsInstruction(OP_unplus); |
| |
| private static final Object[] NO_OPERANDS = new Object[0]; |
| |
| /** |
| * @return the singleton instance of an instruction with no operands, or a |
| * "blank" instruction whose operands are to be filled in. |
| */ |
| public static final Instruction getInstruction(int opcode) |
| { |
| switch (opcode) |
| { |
| case OP_add: |
| return s_add; |
| case OP_astypelate: |
| return s_astypelate; |
| case OP_bitand: |
| return s_bitand; |
| case OP_bitnot: |
| return s_bitnot; |
| case OP_bitor: |
| return s_bitor; |
| case OP_bitxor: |
| return s_bitxor; |
| case OP_checkfilter: |
| return s_checkfilter; |
| case OP_coerce: |
| return s_coerce; |
| case OP_coerce_a: |
| return s_coerce_a; |
| case OP_coerce_s: |
| return s_coerce_s; |
| case OP_convert_b: |
| return s_convert_b; |
| case OP_convert_d: |
| return s_convert_d; |
| case OP_convert_i: |
| return s_convert_i; |
| case OP_convert_o: |
| return s_convert_o; |
| case OP_convert_s: |
| return s_convert_s; |
| case OP_convert_u: |
| return s_convert_u; |
| case OP_decrement: |
| return s_decrement; |
| case OP_decrement_i: |
| return s_decrement_i; |
| case OP_divide: |
| return s_divide; |
| case OP_dup: |
| return s_dup; |
| case OP_dxnslate: |
| return s_dxnslate; |
| case OP_equals: |
| return s_equals; |
| case OP_esc_xattr: |
| return s_esc_xattr; |
| case OP_esc_xelem: |
| return s_esc_xelem; |
| case OP_getglobalscope: |
| return s_getglobalscope; |
| case OP_getlocal0: |
| return s_getlocal0; |
| case OP_getlocal1: |
| return s_getlocal1; |
| case OP_getlocal2: |
| return s_getlocal2; |
| case OP_getlocal3: |
| return s_getlocal3; |
| case OP_greaterequals: |
| return s_greaterequals; |
| case OP_greaterthan: |
| return s_greaterthan; |
| case OP_hasnext: |
| return s_hasnext; |
| case OP_in: |
| return s_in; |
| case OP_increment: |
| return s_increment; |
| case OP_increment_i: |
| return s_increment_i; |
| case OP_instanceof: |
| return s_instanceof; |
| case OP_istypelate: |
| return s_istypelate; |
| case OP_label: |
| return s_label; |
| case OP_lessequals: |
| return s_lessequals; |
| case OP_lessthan: |
| return s_lessthan; |
| case OP_lshift: |
| return s_lshift; |
| case OP_modulo: |
| return s_modulo; |
| case OP_multiply: |
| return s_multiply; |
| case OP_multiply_i: |
| return s_multiply_i; |
| case OP_negate: |
| return s_negate; |
| case OP_negate_i: |
| return s_negate_i; |
| case OP_newactivation: |
| return s_newactivation; |
| case OP_nextname: |
| return s_nextname; |
| case OP_nextvalue: |
| return s_nextvalue; |
| case OP_nop: |
| return s_nop; |
| case OP_not: |
| return s_not; |
| case OP_pop: |
| return s_pop; |
| case OP_popscope: |
| return s_popscope; |
| case OP_pushfalse: |
| return s_pushfalse; |
| case OP_pushnan: |
| return s_pushnan; |
| case OP_pushnull: |
| return s_pushnull; |
| case OP_pushscope: |
| return s_pushscope; |
| case OP_pushtrue: |
| return s_pushtrue; |
| case OP_pushundefined: |
| return s_pushundefined; |
| case OP_pushwith: |
| return s_pushwith; |
| case OP_returnvalue: |
| return s_returnvalue; |
| case OP_returnvoid: |
| return s_returnvoid; |
| case OP_rshift: |
| return s_rshift; |
| case OP_setlocal0: |
| return s_setlocal0; |
| case OP_setlocal1: |
| return s_setlocal1; |
| case OP_setlocal2: |
| return s_setlocal2; |
| case OP_setlocal3: |
| return s_setlocal3; |
| case OP_strictequals: |
| return s_strictequals; |
| case OP_subtract: |
| return s_subtract; |
| case OP_subtract_i: |
| return s_subtract_i; |
| case OP_swap: |
| return s_swap; |
| case OP_throw: |
| return s_throw; |
| case OP_typeof: |
| return s_typeof; |
| case OP_urshift: |
| return s_urshift; |
| case OP_unplus: |
| return s_unplus; |
| default: |
| // TODO: This can be tightened up by isolating the |
| // instructions that require a "blank" instruction |
| // (find/get/set/deleteproperty variants) and |
| // asserting on others. |
| return new ArbitraryOperandsInstruction(opcode, NO_OPERANDS); |
| } |
| } |
| |
| /** |
| * @return an Instruction with an immediate operand. |
| */ |
| public static final Instruction getInstruction(int opcode, int immediate) |
| { |
| return new ImmediateOperandInstruction(opcode, immediate); |
| } |
| |
| /** |
| * @return an immediate-operand instruction in cases where the immediate |
| * operand is not yet known. |
| */ |
| public static final Instruction getDeferredImmediateInstruction(int opcode) |
| { |
| return new ImmediateOperandInstruction(opcode); |
| } |
| |
| /** |
| * @return an Instruction with a single operand. |
| */ |
| public static final Instruction getInstruction(int opcode, Object singleOperand) |
| { |
| return new OneOperandInstruction(opcode, singleOperand); |
| } |
| |
| /** |
| * @return a single-operand instruction, with the operand TBA. |
| */ |
| public static final Instruction getTargetableInstruction(int opcode) |
| { |
| return new OneOperandInstruction(opcode); |
| } |
| |
| /** |
| * @return an Instruction with an arbitrary number of operands. |
| */ |
| public static final Instruction getInstruction(int opcode, Object[] operands) |
| { |
| return new ArbitraryOperandsInstruction(opcode, operands); |
| } |
| |
| /** |
| * @return a hasNext2 instruction. |
| */ |
| public static final Instruction getHasnext2Instruction() |
| { |
| return new ArbitraryOperandsInstruction(OP_hasnext2, NO_OPERANDS); |
| } |
| |
| /** |
| * Copy an instruction's operands as necessary and substitute a new opcode. |
| * |
| * @param opcode - the opcode required. |
| * @param original - the original instruction. |
| * @return an instruction with the original instruction's operands, whatever |
| * they may be, and the specified novel opcode. |
| */ |
| public static final Instruction createModifiedInstruction(int opcode, Instruction original) |
| { |
| if (original instanceof ArbitraryOperandsInstruction) |
| return new ArbitraryOperandsInstruction(opcode, (ArbitraryOperandsInstruction)original); |
| |
| else if (original instanceof OneOperandInstruction) |
| return getInstruction(opcode, original.getOperand(0)); |
| |
| else if (original instanceof ImmediateOperandInstruction) |
| return getInstruction(opcode, original.getImmediate()); |
| |
| else |
| return getInstruction(opcode); |
| } |
| } |