12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454 |
- /*
- * Copyright 2004-2011 H2 Group.
- * Copyright 2011 James Moger.
- *
- * Licensed 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 com.iciql.bytecode;
-
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Stack;
-
- import com.iciql.IciqlException;
- import com.iciql.Token;
-
- /**
- * This class converts a method to a SQL Token by interpreting (decompiling) the
- * bytecode of the class.
- */
- public class ClassReader {
-
- private static final boolean DEBUG = false;
-
- private byte[] data;
- private int pos;
- private Constant[] constantPool;
- private int startByteCode;
- private String methodName;
-
- private String convertMethodName;
- private Token result;
- private Stack<Token> stack = new Stack<Token>();
- private ArrayList<Token> variables = new ArrayList<Token>();
- private boolean endOfMethod;
- private boolean condition;
- private int nextPc;
- private Map<String, Object> fieldMap = new HashMap<String, Object>();
-
- private static void debug(String s) {
- if (DEBUG) {
- System.out.println(s);
- }
- }
-
- public Token decompile(Object instance, Map<String, Object> fields, String method) {
- this.fieldMap = fields;
- this.convertMethodName = method;
- Class<?> clazz = instance.getClass();
- String className = clazz.getName();
- debug("class name " + className);
- ByteArrayOutputStream buff = new ByteArrayOutputStream();
- try {
- InputStream in = clazz.getClassLoader().getResource(className.replace('.', '/') + ".class").openStream();
- while (true) {
- int x = in.read();
- if (x < 0) {
- break;
- }
- buff.write(x);
- }
- } catch (IOException e) {
- throw new IciqlException("Could not read class bytecode", e);
- }
- data = buff.toByteArray();
- int header = readInt();
- debug("header: " + Integer.toHexString(header));
- int minorVersion = readShort();
- int majorVersion = readShort();
- debug("version: " + majorVersion + "." + minorVersion);
- int constantPoolCount = readShort();
- constantPool = new Constant[constantPoolCount];
- for (int i = 1; i < constantPoolCount; i++) {
- int type = readByte();
- switch (type) {
- case 1:
- constantPool[i] = ConstantString.get(readString());
- break;
- case 3: {
- int x = readInt();
- constantPool[i] = ConstantNumber.get(x);
- break;
- }
- case 4: {
- int x = readInt();
- constantPool[i] = ConstantNumber.get("" + Float.intBitsToFloat(x), x, Constant.Type.FLOAT);
- break;
- }
- case 5: {
- long x = readLong();
- constantPool[i] = ConstantNumber.get(x);
- i++;
- break;
- }
- case 6: {
- long x = readLong();
- constantPool[i] = ConstantNumber.get("" + Double.longBitsToDouble(x), x, Constant.Type.DOUBLE);
- i++;
- break;
- }
- case 7: {
- int x = readShort();
- constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.CLASS_REF);
- break;
- }
- case 8: {
- int x = readShort();
- constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.STRING_REF);
- break;
- }
- case 9: {
- int x = readInt();
- constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.FIELD_REF);
- break;
- }
- case 10: {
- int x = readInt();
- constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.METHOD_REF);
- break;
- }
- case 11: {
- int x = readInt();
- constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.INTERFACE_METHOD_REF);
- break;
- }
- case 12: {
- int x = readInt();
- constantPool[i] = ConstantNumber.get(null, x, ConstantNumber.Type.NAME_AND_TYPE);
- break;
- }
- default:
- throw new IciqlException("Unsupported constant pool tag: " + type);
- }
- }
- int accessFlags = readShort();
- debug("access flags: " + accessFlags);
- int classRef = readShort();
- debug("class: " + constantPool[constantPool[classRef].intValue()]);
- int superClassRef = readShort();
- debug(" extends " + constantPool[constantPool[superClassRef].intValue()]);
- int interfaceCount = readShort();
- for (int i = 0; i < interfaceCount; i++) {
- int interfaceRef = readShort();
- debug(" implements " + constantPool[constantPool[interfaceRef].intValue()]);
- }
- int fieldCount = readShort();
- for (int i = 0; i < fieldCount; i++) {
- readField();
- }
- int methodCount = readShort();
- for (int i = 0; i < methodCount; i++) {
- readMethod();
- }
- readAttributes();
- return result;
- }
-
- private void readField() {
- int accessFlags = readShort();
- int nameIndex = readShort();
- int descIndex = readShort();
- debug(" " + constantPool[descIndex] + " " + constantPool[nameIndex] + " " + accessFlags);
- readAttributes();
- }
-
- private void readMethod() {
- int accessFlags = readShort();
- int nameIndex = readShort();
- int descIndex = readShort();
- String desc = constantPool[descIndex].toString();
- methodName = constantPool[nameIndex].toString();
- debug(" " + desc + " " + methodName + " " + accessFlags);
- readAttributes();
- }
-
- private void readAttributes() {
- int attributeCount = readShort();
- for (int i = 0; i < attributeCount; i++) {
- int attributeNameIndex = readShort();
- String attributeName = constantPool[attributeNameIndex].toString();
- debug(" attribute " + attributeName);
- int attributeLength = readInt();
- int end = pos + attributeLength;
- if ("Code".equals(attributeName)) {
- readCode();
- }
- pos = end;
- }
- }
-
- void decompile() {
- int maxStack = readShort();
- int maxLocals = readShort();
- debug("stack: " + maxStack + " locals: " + maxLocals);
- int codeLength = readInt();
- startByteCode = pos;
- int end = pos + codeLength;
- while (pos < end) {
- readByteCode();
- }
- debug("");
- pos = startByteCode + codeLength;
- int exceptionTableLength = readShort();
- pos += 2 * exceptionTableLength;
- readAttributes();
- }
-
- private void readCode() {
- variables.clear();
- stack.clear();
- int maxStack = readShort();
- int maxLocals = readShort();
- debug("stack: " + maxStack + " locals: " + maxLocals);
- int codeLength = readInt();
- startByteCode = pos;
- if (methodName.startsWith(convertMethodName)) {
- result = getResult();
- }
- pos = startByteCode + codeLength;
- int exceptionTableLength = readShort();
- pos += 2 * exceptionTableLength;
- readAttributes();
- }
-
- private Token getResult() {
- while (true) {
- readByteCode();
- if (endOfMethod) {
- return stack.pop();
- }
- if (condition) {
- Token c = stack.pop();
- Stack<Token> currentStack = new Stack<Token>();
- currentStack.addAll(stack);
- ArrayList<Token> currentVariables = new ArrayList<Token>();
- currentVariables.addAll(variables);
- int branch = nextPc;
- Token a = getResult();
- stack = currentStack;
- variables = currentVariables;
- pos = branch + startByteCode;
- Token b = getResult();
- if (a.equals("0") && b.equals("1")) {
- return c;
- } else if (a.equals("1") && b.equals("0")) {
- return Not.get(c);
- } else if (b.equals("0")) {
- return And.get(Not.get(c), a);
- } else if (a.equals("0")) {
- return And.get(c, b);
- } else if (b.equals("1")) {
- return Or.get(c, a);
- } else if (a.equals("1")) {
- return And.get(Not.get(c), b);
- }
- return CaseWhen.get(c, b, a);
- }
- if (nextPc != 0) {
- pos = nextPc + startByteCode;
- }
- }
- }
-
- private void readByteCode() {
- int startPos = pos - startByteCode;
- int opCode = readByte();
- String op;
- endOfMethod = false;
- condition = false;
- nextPc = 0;
- switch (opCode) {
- case 0:
- op = "nop";
- break;
- case 1:
- op = "aconst_null";
- stack.push(Null.INSTANCE);
- break;
- case 2:
- op = "iconst_m1";
- stack.push(ConstantNumber.get("-1"));
- break;
- case 3:
- op = "iconst_0";
- stack.push(ConstantNumber.get("0"));
- break;
- case 4:
- op = "iconst_1";
- stack.push(ConstantNumber.get("1"));
- break;
- case 5:
- op = "iconst_2";
- stack.push(ConstantNumber.get("2"));
- break;
- case 6:
- op = "iconst_3";
- stack.push(ConstantNumber.get("3"));
- break;
- case 7:
- op = "iconst_4";
- stack.push(ConstantNumber.get("4"));
- break;
- case 8:
- op = "iconst_5";
- stack.push(ConstantNumber.get("5"));
- break;
- case 9:
- op = "lconst_0";
- stack.push(ConstantNumber.get("0"));
- break;
- case 10:
- op = "lconst_1";
- stack.push(ConstantNumber.get("1"));
- break;
- case 11:
- op = "fconst_0";
- stack.push(ConstantNumber.get("0.0"));
- break;
- case 12:
- op = "fconst_1";
- stack.push(ConstantNumber.get("1.0"));
- break;
- case 13:
- op = "fconst_2";
- stack.push(ConstantNumber.get("2.0"));
- break;
- case 14:
- op = "dconst_0";
- stack.push(ConstantNumber.get("0.0"));
- break;
- case 15:
- op = "dconst_1";
- stack.push(ConstantNumber.get("1.0"));
- break;
- case 16: {
- int x = (byte) readByte();
- op = "bipush " + x;
- stack.push(ConstantNumber.get(x));
- break;
- }
- case 17: {
- int x = (short) readShort();
- op = "sipush " + x;
- stack.push(ConstantNumber.get(x));
- break;
- }
- case 18: {
- Token s = getConstant(readByte());
- op = "ldc " + s;
- stack.push(s);
- break;
- }
- case 19: {
- Token s = getConstant(readShort());
- op = "ldc_w " + s;
- stack.push(s);
- break;
- }
- case 20: {
- Token s = getConstant(readShort());
- op = "ldc2_w " + s;
- stack.push(s);
- break;
- }
- case 21: {
- int x = readByte();
- op = "iload " + x;
- stack.push(getVariable(x));
- break;
- }
- case 22: {
- int x = readByte();
- op = "lload " + x;
- stack.push(getVariable(x));
- break;
- }
- case 23: {
- int x = readByte();
- op = "fload " + x;
- stack.push(getVariable(x));
- break;
- }
- case 24: {
- int x = readByte();
- op = "dload " + x;
- stack.push(getVariable(x));
- break;
- }
- case 25: {
- int x = readByte();
- op = "aload " + x;
- stack.push(getVariable(x));
- break;
- }
- case 26:
- op = "iload_0";
- stack.push(getVariable(0));
- break;
- case 27:
- op = "iload_1";
- stack.push(getVariable(1));
- break;
- case 28:
- op = "iload_2";
- stack.push(getVariable(2));
- break;
- case 29:
- op = "iload_3";
- stack.push(getVariable(3));
- break;
- case 30:
- op = "lload_0";
- stack.push(getVariable(0));
- break;
- case 31:
- op = "lload_1";
- stack.push(getVariable(1));
- break;
- case 32:
- op = "lload_2";
- stack.push(getVariable(2));
- break;
- case 33:
- op = "lload_3";
- stack.push(getVariable(3));
- break;
- case 34:
- op = "fload_0";
- stack.push(getVariable(0));
- break;
- case 35:
- op = "fload_1";
- stack.push(getVariable(1));
- break;
- case 36:
- op = "fload_2";
- stack.push(getVariable(2));
- break;
- case 37:
- op = "fload_3";
- stack.push(getVariable(3));
- break;
- case 38:
- op = "dload_0";
- stack.push(getVariable(0));
- break;
- case 39:
- op = "dload_1";
- stack.push(getVariable(1));
- break;
- case 40:
- op = "dload_2";
- stack.push(getVariable(2));
- break;
- case 41:
- op = "dload_3";
- stack.push(getVariable(3));
- break;
- case 42:
- op = "aload_0";
- stack.push(getVariable(0));
- break;
- case 43:
- op = "aload_1";
- stack.push(getVariable(1));
- break;
- case 44:
- op = "aload_2";
- stack.push(getVariable(2));
- break;
- case 45:
- op = "aload_3";
- stack.push(getVariable(3));
- break;
- case 46: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "iaload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 47: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "laload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 48: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "faload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 49: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "daload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 50: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "aaload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 51: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "baload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 52: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "caload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 53: {
- Token index = stack.pop();
- Token ref = stack.pop();
- op = "saload";
- stack.push(ArrayGet.get(ref, index));
- break;
- }
- case 54: {
- int var = readByte();
- op = "istore " + var;
- setVariable(var, stack.pop());
- break;
- }
- case 55: {
- int var = readByte();
- op = "lstore " + var;
- setVariable(var, stack.pop());
- break;
- }
- case 56: {
- int var = readByte();
- op = "fstore " + var;
- setVariable(var, stack.pop());
- break;
- }
- case 57: {
- int var = readByte();
- op = "dstore " + var;
- setVariable(var, stack.pop());
- break;
- }
- case 58: {
- int var = readByte();
- op = "astore " + var;
- setVariable(var, stack.pop());
- break;
- }
- case 59:
- op = "istore_0";
- setVariable(0, stack.pop());
- break;
- case 60:
- op = "istore_1";
- setVariable(1, stack.pop());
- break;
- case 61:
- op = "istore_2";
- setVariable(2, stack.pop());
- break;
- case 62:
- op = "istore_3";
- setVariable(3, stack.pop());
- break;
- case 63:
- op = "lstore_0";
- setVariable(0, stack.pop());
- break;
- case 64:
- op = "lstore_1";
- setVariable(1, stack.pop());
- break;
- case 65:
- op = "lstore_2";
- setVariable(2, stack.pop());
- break;
- case 66:
- op = "lstore_3";
- setVariable(3, stack.pop());
- break;
- case 67:
- op = "fstore_0";
- setVariable(0, stack.pop());
- break;
- case 68:
- op = "fstore_1";
- setVariable(1, stack.pop());
- break;
- case 69:
- op = "fstore_2";
- setVariable(2, stack.pop());
- break;
- case 70:
- op = "fstore_3";
- setVariable(3, stack.pop());
- break;
- case 71:
- op = "dstore_0";
- setVariable(0, stack.pop());
- break;
- case 72:
- op = "dstore_1";
- setVariable(1, stack.pop());
- break;
- case 73:
- op = "dstore_2";
- setVariable(2, stack.pop());
- break;
- case 74:
- op = "dstore_3";
- setVariable(3, stack.pop());
- break;
- case 75:
- op = "astore_0";
- setVariable(0, stack.pop());
- break;
- case 76:
- op = "astore_1";
- setVariable(1, stack.pop());
- break;
- case 77:
- op = "astore_2";
- setVariable(2, stack.pop());
- break;
- case 78:
- op = "astore_3";
- setVariable(3, stack.pop());
- break;
- case 79: {
- // String value = stack.pop();
- // String index = stack.pop();
- // String ref = stack.pop();
- op = "iastore";
- // TODO side effect - not supported
- break;
- }
- case 80:
- op = "lastore";
- // TODO side effect - not supported
- break;
- case 81:
- op = "fastore";
- // TODO side effect - not supported
- break;
- case 82:
- op = "dastore";
- // TODO side effect - not supported
- break;
- case 83:
- op = "aastore";
- // TODO side effect - not supported
- break;
- case 84:
- op = "bastore";
- // TODO side effect - not supported
- break;
- case 85:
- op = "castore";
- // TODO side effect - not supported
- break;
- case 86:
- op = "sastore";
- // TODO side effect - not supported
- break;
- case 87:
- op = "pop";
- stack.pop();
- break;
- case 88:
- op = "pop2";
- // TODO currently we don't know the stack types
- stack.pop();
- stack.pop();
- break;
- case 89: {
- op = "dup";
- Token x = stack.pop();
- stack.push(x);
- stack.push(x);
- break;
- }
- case 90: {
- op = "dup_x1";
- Token a = stack.pop();
- Token b = stack.pop();
- stack.push(a);
- stack.push(b);
- stack.push(a);
- break;
- }
- case 91: {
- // TODO currently we don't know the stack types
- op = "dup_x2";
- Token a = stack.pop();
- Token b = stack.pop();
- Token c = stack.pop();
- stack.push(a);
- stack.push(c);
- stack.push(b);
- stack.push(a);
- break;
- }
- case 92: {
- // TODO currently we don't know the stack types
- op = "dup2";
- Token a = stack.pop();
- Token b = stack.pop();
- stack.push(b);
- stack.push(a);
- stack.push(b);
- stack.push(a);
- break;
- }
- case 93: {
- // TODO currently we don't know the stack types
- op = "dup2_x1";
- Token a = stack.pop();
- Token b = stack.pop();
- Token c = stack.pop();
- stack.push(b);
- stack.push(a);
- stack.push(c);
- stack.push(b);
- stack.push(a);
- break;
- }
- case 94: {
- // TODO currently we don't know the stack types
- op = "dup2_x2";
- Token a = stack.pop();
- Token b = stack.pop();
- Token c = stack.pop();
- Token d = stack.pop();
- stack.push(b);
- stack.push(a);
- stack.push(d);
- stack.push(c);
- stack.push(b);
- stack.push(a);
- break;
- }
- case 95: {
- op = "swap";
- Token a = stack.pop();
- Token b = stack.pop();
- stack.push(a);
- stack.push(b);
- break;
- }
- case 96: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "iadd";
- stack.push(Operation.get(a, Operation.Type.ADD, b));
- break;
- }
- case 97: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "ladd";
- stack.push(Operation.get(a, Operation.Type.ADD, b));
- break;
- }
- case 98: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "fadd";
- stack.push(Operation.get(a, Operation.Type.ADD, b));
- break;
- }
- case 99: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "dadd";
- stack.push(Operation.get(a, Operation.Type.ADD, b));
- break;
- }
- case 100: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "isub";
- stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
- break;
- }
- case 101: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "lsub";
- stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
- break;
- }
- case 102: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "fsub";
- stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
- break;
- }
- case 103: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "dsub";
- stack.push(Operation.get(a, Operation.Type.SUBTRACT, b));
- break;
- }
- case 104: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "imul";
- stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
- break;
- }
- case 105: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "lmul";
- stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
- break;
- }
- case 106: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "fmul";
- stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
- break;
- }
- case 107: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "dmul";
- stack.push(Operation.get(a, Operation.Type.MULTIPLY, b));
- break;
- }
- case 108: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "idiv";
- stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
- break;
- }
- case 109: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "ldiv";
- stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
- break;
- }
- case 110: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "fdiv";
- stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
- break;
- }
- case 111: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "ddiv";
- stack.push(Operation.get(a, Operation.Type.DIVIDE, b));
- break;
- }
- case 112: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "irem";
- stack.push(Operation.get(a, Operation.Type.MOD, b));
- break;
- }
- case 113: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "lrem";
- stack.push(Operation.get(a, Operation.Type.MOD, b));
- break;
- }
- case 114: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "frem";
- stack.push(Operation.get(a, Operation.Type.MOD, b));
- break;
- }
- case 115: {
- Token b = stack.pop();
- Token a = stack.pop();
- op = "drem";
- stack.push(Operation.get(a, Operation.Type.MOD, b));
- break;
- }
- // case 116:
- // op = "ineg";
- // break;
- // case 117:
- // op = "lneg";
- // break;
- // case 118:
- // op = "fneg";
- // break;
- // case 119:
- // op = "dneg";
- // break;
- // case 120:
- // op = "ishl";
- // break;
- // case 121:
- // op = "lshl";
- // break;
- // case 122:
- // op = "ishr";
- // break;
- // case 123:
- // op = "lshr";
- // break;
- // case 124:
- // op = "iushr";
- // break;
- // case 125:
- // op = "lushr";
- // break;
- // case 126:
- // op = "iand";
- // break;
- // case 127:
- // op = "land";
- // break;
- // case 128:
- // op = "ior";
- // break;
- // case 129:
- // op = "lor";
- // break;
- // case 130:
- // op = "ixor";
- // break;
- // case 131:
- // op = "lxor";
- // break;
- // case 132: {
- // int var = readByte();
- // int off = (byte) readByte();
- // op = "iinc " + var + " " + off;
- // break;
- // }
- // case 133:
- // op = "i2l";
- // break;
- // case 134:
- // op = "i2f";
- // break;
- // case 135:
- // op = "i2d";
- // break;
- // case 136:
- // op = "l2i";
- // break;
- // case 137:
- // op = "l2f";
- // break;
- // case 138:
- // op = "l2d";
- // break;
- // case 139:
- // op = "f2i";
- // break;
- // case 140:
- // op = "f2l";
- // break;
- // case 141:
- // op = "f2d";
- // break;
- // case 142:
- // op = "d2i";
- // break;
- // case 143:
- // op = "d2l";
- // break;
- // case 144:
- // op = "d2f";
- // break;
- // case 145:
- // op = "i2b";
- // break;
- // case 146:
- // op = "i2c";
- // break;
- // case 147:
- // op = "i2s";
- // break;
- case 148: {
- Token b = stack.pop(), a = stack.pop();
- stack.push(new Function("SIGN", Operation.get(a, Operation.Type.SUBTRACT, b)));
- op = "lcmp";
- break;
- }
- // case 149:
- // op = "fcmpl";
- // break;
- // case 150:
- // op = "fcmpg";
- // break;
- // case 151:
- // op = "dcmpl";
- // break;
- // case 152:
- // op = "dcmpg";
- // break;
- case 153:
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- stack.push(Operation.get(stack.pop(), Operation.Type.EQUALS, ConstantNumber.get(0)));
- op = "ifeq " + nextPc;
- break;
- case 154:
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- stack.push(Operation.get(stack.pop(), Operation.Type.NOT_EQUALS, ConstantNumber.get(0)));
- op = "ifne " + nextPc;
- break;
- case 155:
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER, ConstantNumber.get(0)));
- op = "iflt " + nextPc;
- break;
- case 156:
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER_EQUALS, ConstantNumber.get(0)));
- op = "ifge " + nextPc;
- break;
- case 157:
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- stack.push(Operation.get(stack.pop(), Operation.Type.BIGGER, ConstantNumber.get(0)));
- op = "ifgt " + nextPc;
- break;
- case 158:
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- stack.push(Operation.get(stack.pop(), Operation.Type.SMALLER_EQUALS, ConstantNumber.get(0)));
- op = "ifle " + nextPc;
- break;
- case 159: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.EQUALS, b));
- op = "if_icmpeq " + nextPc;
- break;
- }
- case 160: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
- op = "if_icmpne " + nextPc;
- break;
- }
- case 161: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.SMALLER, b));
- op = "if_icmplt " + nextPc;
- break;
- }
- case 162: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.BIGGER_EQUALS, b));
- op = "if_icmpge " + nextPc;
- break;
- }
- case 163: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.BIGGER, b));
- op = "if_icmpgt " + nextPc;
- break;
- }
- case 164: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.SMALLER_EQUALS, b));
- op = "if_icmple " + nextPc;
- break;
- }
- case 165: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.EQUALS, b));
- op = "if_acmpeq " + nextPc;
- break;
- }
- case 166: {
- condition = true;
- nextPc = getAbsolutePos(pos, readShort());
- Token b = stack.pop(), a = stack.pop();
- stack.push(Operation.get(a, Operation.Type.NOT_EQUALS, b));
- op = "if_acmpne " + nextPc;
- break;
- }
- case 167:
- nextPc = getAbsolutePos(pos, readShort());
- op = "goto " + nextPc;
- break;
- // case 168:
- // // TODO not supported yet
- // op = "jsr " + getAbsolutePos(pos, readShort());
- // break;
- // case 169:
- // // TODO not supported yet
- // op = "ret " + readByte();
- // break;
- // case 170: {
- // int start = pos;
- // pos += 4 - ((pos - startByteCode) & 3);
- // int def = readInt();
- // int low = readInt(), high = readInt();
- // int n = high - low + 1;
- // op = "tableswitch default:" + getAbsolutePos(start, def);
- // StringBuilder buff = new StringBuilder();
- // for (int i = 0; i < n; i++) {
- // buff.append(' ').append(low++).
- // append(":").
- // append(getAbsolutePos(start, readInt()));
- // }
- // op += buff.toString();
- // // pos += n * 4;
- // break;
- // }
- // case 171: {
- // int start = pos;
- // pos += 4 - ((pos - startByteCode) & 3);
- // int def = readInt();
- // int n = readInt();
- // op = "lookupswitch default:" + getAbsolutePos(start, def);
- // StringBuilder buff = new StringBuilder();
- // for (int i = 0; i < n; i++) {
- // buff.append(' ').
- // append(readInt()).
- // append(":").
- // append(getAbsolutePos(start, readInt()));
- // }
- // op += buff.toString();
- // // pos += n * 8;
- // break;
- // }
- case 172:
- op = "ireturn";
- endOfMethod = true;
- break;
- case 173:
- op = "lreturn";
- endOfMethod = true;
- break;
- case 174:
- op = "freturn";
- endOfMethod = true;
- break;
- case 175:
- op = "dreturn";
- endOfMethod = true;
- break;
- case 176:
- op = "areturn";
- endOfMethod = true;
- break;
- case 177:
- op = "return";
- // no value returned
- stack.push(null);
- endOfMethod = true;
- break;
- // case 178:
- // op = "getstatic " + getField(readShort());
- // break;
- // case 179:
- // op = "putstatic " + getField(readShort());
- // break;
- case 180: {
- String field = getField(readShort());
- Token p = stack.pop();
- String s = p + "." + field.substring(field.lastIndexOf('.') + 1, field.indexOf(' '));
- if (s.startsWith("this.")) {
- s = s.substring(5);
- }
- stack.push(Variable.get(s, fieldMap.get(s)));
- op = "getfield " + field;
- break;
- }
- // case 181:
- // op = "putfield " + getField(readShort());
- // break;
- case 182: {
- String method = getMethod(readShort());
- op = "invokevirtual " + method;
- if (method.equals("java/lang/String.equals (Ljava/lang/Object;)Z")) {
- Token a = stack.pop();
- Token b = stack.pop();
- stack.push(Operation.get(a, Operation.Type.EQUALS, b));
- } else if (method.equals("java/lang/Integer.intValue ()I")) {
- // ignore
- } else if (method.equals("java/lang/Long.longValue ()J")) {
- // ignore
- }
- break;
- }
- case 183: {
- String method = getMethod(readShort());
- op = "invokespecial " + method;
- break;
- }
- case 184:
- op = "invokestatic " + getMethod(readShort());
- break;
- // case 185: {
- // int methodRef = readShort();
- // readByte();
- // readByte();
- // op = "invokeinterface " + getMethod(methodRef);
- // break;
- // }
- case 187: {
- String className = constantPool[constantPool[readShort()].intValue()].toString();
- op = "new " + className;
- break;
- }
- // case 188:
- // op = "newarray " + readByte();
- // break;
- // case 189:
- // op = "anewarray " + cpString[readShort()];
- // break;
- // case 190:
- // op = "arraylength";
- // break;
- // case 191:
- // op = "athrow";
- // break;
- // case 192:
- // op = "checkcast " + cpString[readShort()];
- // break;
- // case 193:
- // op = "instanceof " + cpString[readShort()];
- // break;
- // case 194:
- // op = "monitorenter";
- // break;
- // case 195:
- // op = "monitorexit";
- // break;
- // case 196: {
- // opCode = readByte();
- // switch (opCode) {
- // case 21:
- // op = "wide iload " + readShort();
- // break;
- // case 22:
- // op = "wide lload " + readShort();
- // break;
- // case 23:
- // op = "wide fload " + readShort();
- // break;
- // case 24:
- // op = "wide dload " + readShort();
- // break;
- // case 25:
- // op = "wide aload " + readShort();
- // break;
- // case 54:
- // op = "wide istore " + readShort();
- // break;
- // case 55:
- // op = "wide lstore " + readShort();
- // break;
- // case 56:
- // op = "wide fstore " + readShort();
- // break;
- // case 57:
- // op = "wide dstore " + readShort();
- // break;
- // case 58:
- // op = "wide astore " + readShort();
- // break;
- // case 132: {
- // int var = readShort();
- // int off = (short) readShort();
- // op = "wide iinc " + var + " " + off;
- // break;
- // }
- // case 169:
- // op = "wide ret " + readShort();
- // break;
- // default:
- // throw new IciqlException(
- // "Unsupported wide opCode " + opCode);
- // }
- // break;
- // }
- // case 197:
- // op = "multianewarray " + cpString[readShort()] + " " + readByte();
- // break;
- // case 198: {
- // condition = true;
- // nextPc = getAbsolutePos(pos, readShort());
- // Token a = stack.pop();
- // stack.push("(" + a + " IS NULL)");
- // op = "ifnull " + nextPc;
- // break;
- // }
- // case 199: {
- // condition = true;
- // nextPc = getAbsolutePos(pos, readShort());
- // Token a = stack.pop();
- // stack.push("(" + a + " IS NOT NULL)");
- // op = "ifnonnull " + nextPc;
- // break;
- // }
- case 200:
- op = "goto_w " + getAbsolutePos(pos, readInt());
- break;
- case 201:
- op = "jsr_w " + getAbsolutePos(pos, readInt());
- break;
- default:
- throw new IciqlException("Unsupported opCode " + opCode);
- }
- debug(" " + startPos + ": " + op);
- }
-
- private void setVariable(int x, Token value) {
- while (x >= variables.size()) {
- variables.add(Variable.get("p" + variables.size(), null));
- }
- variables.set(x, value);
- }
-
- private Token getVariable(int x) {
- if (x == 0) {
- return Variable.THIS;
- }
- while (x >= variables.size()) {
- variables.add(Variable.get("p" + variables.size(), null));
- }
- return variables.get(x);
- }
-
- private String getField(int fieldRef) {
- int field = constantPool[fieldRef].intValue();
- int classIndex = field >>> 16;
- int nameAndType = constantPool[field & 0xffff].intValue();
- String className = constantPool[constantPool[classIndex].intValue()] + "." + constantPool[nameAndType >>> 16]
- + " " + constantPool[nameAndType & 0xffff];
- return className;
- }
-
- private String getMethod(int methodRef) {
- int method = constantPool[methodRef].intValue();
- int classIndex = method >>> 16;
- int nameAndType = constantPool[method & 0xffff].intValue();
- String className = constantPool[constantPool[classIndex].intValue()] + "." + constantPool[nameAndType >>> 16]
- + " " + constantPool[nameAndType & 0xffff];
- return className;
- }
-
- private Constant getConstant(int constantRef) {
- Constant c = constantPool[constantRef];
- switch (c.getType()) {
- case INT:
- case FLOAT:
- case DOUBLE:
- case LONG:
- return c;
- case STRING_REF:
- return constantPool[c.intValue()];
- default:
- throw new IciqlException("Not a constant: " + constantRef);
- }
- }
-
- private String readString() {
- int size = readShort();
- byte[] buff = data;
- int p = pos, end = p + size;
- char[] chars = new char[size];
- int j = 0;
- for (; p < end; j++) {
- int x = buff[p++] & 0xff;
- if (x < 0x80) {
- chars[j] = (char) x;
- } else if (x >= 0xe0) {
- chars[j] = (char) (((x & 0xf) << 12) + ((buff[p++] & 0x3f) << 6) + (buff[p++] & 0x3f));
- } else {
- chars[j] = (char) (((x & 0x1f) << 6) + (buff[p++] & 0x3f));
- }
- }
- pos = p;
- return new String(chars, 0, j);
- }
-
- private int getAbsolutePos(int start, int offset) {
- return start - startByteCode - 1 + (short) offset;
- }
-
- private int readByte() {
- return data[pos++] & 0xff;
- }
-
- private int readShort() {
- byte[] buff = data;
- return ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
- }
-
- private int readInt() {
- byte[] buff = data;
- return (buff[pos++] << 24) + ((buff[pos++] & 0xff) << 16) + ((buff[pos++] & 0xff) << 8) + (buff[pos++] & 0xff);
- }
-
- private long readLong() {
- return ((long) (readInt()) << 32) + (readInt() & 0xffffffffL);
- }
-
- }
|