private void count(File f) throws FileNotFoundException, IOException { ProgramTokenizer tokenizer = new ProgramTokenizer(new FileReader(f)); AgillaAssembler.getAssembler().expandMode(tokenizer); while (tokenizer.hasMoreInstructions()) { Instruction instr = tokenizer.nextInstruction(); Integer count = (Integer) table.remove(instr); if (count == null) table.put(instr.opcode(), new Integer(1)); else table.put(instr.opcode(), new Integer(count.intValue() + 1)); } }
protected String replace(String key, Link link) { if (link != null && link.contains(key)) return "${infinite:" + link.toString() + "}"; if (key != null) { key = key.trim(); if (key.length() > 0) { Processor source = domain; String value = null; if (key.indexOf(';') < 0) { Instruction ins = new Instruction(key); if (!ins.isLiteral()) { SortedList<String> sortedList = SortedList.fromIterator(domain.iterator()); StringBuilder sb = new StringBuilder(); String del = ""; for (String k : sortedList) { if (ins.matches(k)) { String v = replace(k, new Link(source, link, key)); if (v != null) { sb.append(del); del = ","; sb.append(v); } } } return sb.toString(); } } while (value == null && source != null) { value = source.getProperties().getProperty(key); source = source.getParent(); } if (value != null) return process(value, new Link(source, link, key)); value = doCommands(key, link); if (value != null) return process(value, new Link(source, link, key)); if (key != null && key.trim().length() > 0) { value = System.getProperty(key); if (value != null) return value; } if (!flattening && !key.equals("@")) domain.warning("No translation found for macro: " + key); } else { domain.warning("Found empty macro key"); } } else { domain.warning("Found null macro key"); } return "${" + key + "}"; }
/** * Set the last {@link Instruction} for which this local is in scope. The instruction must already * be a part of the method. WARNING: if this instruction is deleted, the results are undefined. */ public void setEnd(Instruction end) { if (end.getCode() != getCode()) throw new IllegalArgumentException( "Instruction pointers and " + "targets must be part of the same code block."); _end = end; _length = -1; }
private void assemble() { if (sourceFile == null) { printError("-i : No source file specified"); } if (assembler == null) { printError("-f : No format specified"); } print("...Assembling " + sourceFile.getName()); assembler.assemble(sourceFile); print("..." + assembler.getErrors().length + " error(s) found"); try { PrintWriter output = null; if (!assembler.hasErrors()) { if (!machineCode) { print("...saving .pco file"); output = new PrintWriter(new FileWriter(baseFileName + ".pco")); for (Instruction instruction : assembler.getInstructions()) { output.print(instruction.getInstruction()); output.println(" ;" + instruction.getSourceCode()); } } else { print("Machine code file varified"); } } else { print("...saving .err file"); output = new PrintWriter(new FileWriter(baseFileName + ".err")); for (AssemblyError error : assembler.getErrors()) { output.println(error.toString()); } } if (output != null) { output.close(); } } catch (IOException e) { printError(e.getMessage()); } }
/** * Read an instruction from (byte code) input stream and return the appropiate object. * * @param file file to read from * @return instruction object being read */ public static final Instruction readInstruction(ByteSequence bytes) throws IOException { boolean wide = false; short opcode = (short) bytes.readUnsignedByte(); Instruction obj = null; if (opcode == Constants.WIDE) { // Read next opcode after wide byte wide = true; opcode = (short) bytes.readUnsignedByte(); } if (InstructionConstants.INSTRUCTIONS[opcode] != null) return InstructionConstants.INSTRUCTIONS[ opcode]; // Used predefined immutable object, if available /* Find appropiate class, instantiate an (empty) instruction object * and initialize it by hand. */ Class clazz; try { clazz = Class.forName(className(opcode)); } catch (ClassNotFoundException cnfe) { // If a class by that name does not exist, the opcode is illegal. // Note that IMPDEP1, IMPDEP2, BREAKPOINT are also illegal in a sense. throw new ClassGenException("Illegal opcode detected."); } try { obj = (Instruction) clazz.newInstance(); if (wide && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) throw new Exception("Illegal opcode after wide: " + opcode); obj.setOpcode(opcode); obj.initFromFile(bytes, wide); // Do further initializations, if any // Byte code offset set in InstructionList } catch (Exception e) { throw new ClassGenException(e.toString()); } return obj; }
public void paint(Graphics g) { super.paint(g); if (screen.equalsIgnoreCase("title")) { MyPanel.score = 0; hs = new Highscore(); c.removeAll(); c.add(ts); panel = null; ts.revalidate(); } else if (screen.equalsIgnoreCase("instructions")) { c.removeAll(); c.add(instructions); instructions.revalidate(); } else if (screen.equalsIgnoreCase("mode")) { c.removeAll(); c.add(mode); mode.revalidate(); } else if (screen.equalsIgnoreCase("difficulty")) { c.removeAll(); c.add(dif); dif.revalidate(); } else if (screen.equalsIgnoreCase("highscore")) { if (hs.returnCount() == 0) { c.removeAll(); c.add(hs); c.validate(); } } else if (screen.equalsIgnoreCase("gameover")) { if (!once) { c.removeAll(); c.add(gg); once = true; c.validate(); } } else { if (once) { c.removeAll(); panel = new MyPanel(THA.WIDTH, THA.HEIGHT, ai, diff); c.setLayout(new BorderLayout()); c.add(panel.returnNs(), BorderLayout.WEST); c.add(panel, BorderLayout.CENTER); c.add(btns, BorderLayout.SOUTH); c.add(panel.returnAmmo(), BorderLayout.EAST); c.validate(); once = false; } } repaint(); }
/** * Transforms invoke instructions that match the specified list for this class to call the * specified static call instead. */ private InstructionList xform_inst(MethodGen mg, Instruction inst) { switch (inst.getOpcode()) { case Constants.INVOKESTATIC: { InstructionList il = new InstructionList(); INVOKESTATIC is = (INVOKESTATIC) inst; String cname = is.getClassName(pgen); String mname = is.getMethodName(pgen); Type[] args = is.getArgumentTypes(pgen); MethodDef orig = new MethodDef(cname + "." + mname, args); MethodInfo call = method_map.get(orig); if (call != null) { call.cnt++; String classname = call.method_class; String methodname = mname; debug_map.log( "%s.%s: Replacing method %s.%s (%s) with %s.%s%n", mg.getClassName(), mg.getName(), cname, mname, UtilMDE.join(args, ", "), classname, methodname); il.append( ifact.createInvoke( classname, methodname, is.getReturnType(pgen), args, Constants.INVOKESTATIC)); } return (il); } case Constants.INVOKEVIRTUAL: { InstructionList il = new InstructionList(); INVOKEVIRTUAL iv = (INVOKEVIRTUAL) inst; String cname = iv.getClassName(pgen); String mname = iv.getMethodName(pgen); Type[] args = iv.getArgumentTypes(pgen); Type instance_type = iv.getReferenceType(pgen); Type[] new_args = BCELUtil.insert_type(instance_type, args); MethodDef orig = new MethodDef(cname + "." + mname, args); if (debug_class) System.out.printf("looking for %s in map %s%n", orig, method_map); MethodInfo call = method_map.get(orig); if (call != null) { call.cnt++; String classname = call.method_class; String methodname = mname; debug_map.log( "Replacing method %s.%s (%s) with %s.%s%n", cname, mname, ArraysMDE.toString(args), classname, methodname); il.append( ifact.createInvoke( classname, methodname, iv.getReturnType(pgen), new_args, Constants.INVOKESTATIC)); } return (il); } default: return (null); } }
public void generate(String inputFileName) throws Exception { List<MetaClass> metaClasses = new ArrayList<>(); List<LifeLine> lifeLines = new ArrayList<>(); List<MethodInvocation> rootMessages = new ArrayList<>(); MethodInvocation parentMessage = new MethodInvocation(); GsonBuilder builder = new GsonBuilder(); List<MethodInvocation> methodInvocations = new ArrayList<>(); Package mainPackage = new Package(); List<Guard> listOfGuards = new ArrayList<>(); Map<Guard, Instruction> guardToCFMap = new HashMap<>(); List<Instruction> combinedFragments = new ArrayList<Instruction>(); List<Operation> operationsList = new ArrayList<>(); builder.registerTypeAdapter(RefObject.class, new RefObjectJsonDeSerializer()); Gson gson = builder.create(); Element myTypes = gson.fromJson(new FileReader(inputFileName), Element.class); if (myTypes._type.equals("Project")) { List<Element> umlElements = myTypes .ownedElements .stream() .filter(f -> f._type.equals("UMLModel")) .collect(Collectors.toList()); if (umlElements.size() > 0) { // There has be to atleast one UMLModel package Element element = umlElements.get(0); // package that the classes are supposed to be in mainPackage.setName(element.name); List<Element> umlPackages = element .ownedElements .stream() .filter(g -> g._type.equals("UMLPackage")) .collect(Collectors.toList()); if (umlPackages.size() > 1) { // There has to be two packages- one for class one for behaviour Element classes = umlPackages.get(0); Element behaviour = umlPackages.get(1); // *--------------------------CLASSES-------------------------------*// // in the first pass, get all classes that are defined in the diagram // get details that can be directly inferred from the json like, fields and operations, // which do not refer to other classes for (Element umlClass : classes.getOwnedElements()) { MetaClass metaClass = new MetaClass(umlClass.name, umlClass._id); // check if class is interface or not because there is no distinction in json if (umlClass._type.equals("UMLClass")) { metaClass.setInterface(false); } else { metaClass.setInterface(true); } if (umlClass.operations != null) { metaClass.setOperations(umlClass.operations); operationsList.addAll(metaClass.operations); } if (umlClass.attributes != null) { metaClass.setFields(umlClass.attributes); } metaClasses.add(metaClass); } // in second pass, define associations and generalizations for these classes for (Element umlClass : classes.getOwnedElements()) { if (umlClass.ownedElements != null) { // find corresponding metaclass, then populate the secondary inferences List<MetaClass> correspondingMetaClassList = metaClasses .stream() .filter(f -> f._id.equals(umlClass._id)) .collect(Collectors.toList()); MetaClass correspondingMetaClass = correspondingMetaClassList.get(0); List<Element> umlAssociations = umlClass .ownedElements .stream() .filter(f -> f._type.equals("UMLAssociation")) .collect(Collectors.toList()); if (umlAssociations.size() > 0) { correspondingMetaClass.setAssociations(metaClasses, umlAssociations); } List<Element> umlGeneralization = umlClass .ownedElements .stream() .filter(f -> f._type.equals("UMLGeneralization")) .collect(Collectors.toList()); if (umlGeneralization.size() > 0) { correspondingMetaClass.setGeneralizations(metaClasses, umlGeneralization); } List<Element> umlRealization = umlClass .ownedElements .stream() .filter(f -> f._type.equals("UMLInterfaceRealization")) .collect(Collectors.toList()); if (umlRealization.size() > 0) { correspondingMetaClass.setInterfaceRealization(metaClasses, umlRealization); } } } // *--------------------------CLASSES-------------------------------*// // *----------------------- BEHAVIOUR---------------------------------*// for (Element umlCollaboration : behaviour.getOwnedElements()) { // Role to Class mapping ArrayList<Element> attributes = umlCollaboration.attributes; HashMap<String, MetaClass> roleToClassMap = new HashMap<>(); if (attributes != null) { for (Element attribute : attributes) { List<MetaClass> roleClass = metaClasses .stream() .filter(f -> f._id.equals(attribute.type.$ref)) .collect(Collectors.toList()); roleToClassMap.put(attribute._id, roleClass.get(0)); } } for (Element umlInteraction : umlCollaboration.ownedElements) { // mapping lifelines to the classes they correspond ArrayList<Element> participants = umlInteraction.participants; if (participants != null && participants.size() > 0) { for (Element participant : participants) { MetaClass participantClass = roleToClassMap.get(participant.represent.$ref); LifeLine lifeLine = new LifeLine(); lifeLine.setName(participant.name); lifeLine.setId(participant._id); lifeLine.setMetaClass(participantClass); lifeLines.add(lifeLine); } } // first parse all the combined fragments and get ready if (umlInteraction.fragments != null) { for (Element fragment : umlInteraction.fragments) { // depending on the fragment set the class Instruction instruction = null; if (fragment.interactionOperator.equals("loop")) { Loop loop = new Loop(); loop.setId(fragment._id); loop.setWeight(0); Guard guard = new Guard(fragment.operands.get(0)._id); // loop can have only one condition--- one condition-- condition is made up of // AND or OR's guard.setCondition(fragment.operands.get(0).guard); loop.setGuard(guard); instruction = loop; combinedFragments.add(loop); listOfGuards.add(guard); guardToCFMap.put(guard, loop); } if (fragment.interactionOperator.equals("alt")) { Conditional c = new Conditional(); c.setId(fragment._id); c.setWeight(0); instruction = c; combinedFragments.add(c); Guard consequence = new Guard(fragment.operands.get(0)._id); consequence.setCondition(fragment.operands.get(0).guard); c.setCons(consequence); listOfGuards.add(consequence); guardToCFMap.put(consequence, c); consequence.setConsequence(true); if (fragment.operands.size() > 1) { Guard alternate = new Guard(fragment.operands.get(1)._id); alternate.setCondition(fragment.operands.get(1).guard); c.setAlt(alternate); listOfGuards.add(alternate); guardToCFMap.put(alternate, c); alternate.setAlternative(true); } } if (fragment.tags != null) { for (Element tag : fragment.tags) { if (tag.name.equals("parent")) { List<Instruction> instructionList = combinedFragments .stream() .filter(e -> e.getId().equals(tag.reference.$ref)) .collect(Collectors.toList()); if (instructionList.size() > 0) { instructionList.get(0).getBlock().add(instruction); instruction.setParent(instructionList.get(0)); } } } } } } // parsing the messages and make nodes out them to later build a tree from the // lifelines ArrayList<Element> messages = umlInteraction.messages; Element startMessage = messages.get(0); String sourceRef = startMessage.source.$ref; String targetRef = startMessage.target.$ref; Element endMessage = null; LifeLine sourceLifeLine = getLifeLine(lifeLines, sourceRef); LifeLine targetLifeLine = getLifeLine(lifeLines, targetRef); // First message processing parentMessage = new MethodInvocation(); parentMessage.setAssignmentTarget(startMessage.assignmentTarget); parentMessage.setMessageSort(startMessage.messageSort); parentMessage.setSource(sourceLifeLine.getMetaClass()); parentMessage.setTarget(targetLifeLine.getMetaClass()); parentMessage.setName(startMessage.name); parentMessage.setId(startMessage._id); if (sourceLifeLine.getId().equals(targetLifeLine.getId())) { parentMessage.setCallerObject("this"); } else { parentMessage.setCallerObject(targetLifeLine.getName()); } int weight = 0; parentMessage.setWeight(weight++); if (startMessage.signature != null) { parentMessage.setSignature(startMessage.signature.$ref); } if (startMessage.tags != null) { for (Element tag : startMessage.tags) { // if (tag.name.equals("CF")) { // parentMessage.setInCF(true); // // parentMessage.setCfID(tag.reference.$ref); // } if (tag.name.equals("operand")) { parentMessage.setOperandId(tag.reference.$ref); } } } MethodInvocation rootMessage = parentMessage; methodInvocations.add(rootMessage); rootMessages.add(rootMessage); Iterator<Element> iter = messages.iterator(); while (iter.hasNext()) { if (iter.next() == endMessage) { continue; } iter.remove(); List<Element> childMessages = getChildMessages(messages, targetRef); for (Element child : childMessages) { LifeLine childSource = getLifeLine(lifeLines, child.source.$ref); LifeLine childTarget = getLifeLine(lifeLines, child.target.$ref); MethodInvocation childMessage = new MethodInvocation(); childMessage.setMessageSort(child.messageSort); childMessage.setSource(childSource.getMetaClass()); childMessage.setTarget(childTarget.getMetaClass()); childMessage.setAssignmentTarget(child.assignmentTarget); childMessage.setName(child.name); childMessage.setId(child._id); childMessage.setWeight(weight++); childMessage.setArguments(child.arguments); if (childSource.getId().equals(childTarget.getId())) { childMessage.setCallerObject("this"); } else { childMessage.setCallerObject(childTarget.getName()); } if (child.signature != null) { childMessage.setSignature(child.signature.$ref); } if (child.tags != null) { for (Element tag : child.tags) { // if (tag.name.equals("CF")) { // childMessage.setInCF(true); // // childMessage.setCfID(tag.reference.$ref); // } if (tag.name.equals("operand")) { childMessage.setOperandId(tag.reference.$ref); } } } parentMessage.childNodes.add(childMessage); methodInvocations.add(childMessage); } if (childMessages.size() > 0) { List<MethodInvocation> nextMessage = parentMessage .childNodes .stream() .filter(f -> !f.source.equals(f.target)) .collect(Collectors.toList()); List<Element> startMessageNext = childMessages .stream() .filter(f -> !f.source.$ref.equals(f.target.$ref)) .collect(Collectors.toList()); startMessage = startMessageNext.get(0); targetRef = startMessage.target.$ref; sourceRef = startMessage.source.$ref; parentMessage = nextMessage.get(0); if (childMessages.size() > 1) { endMessage = childMessages.get(childMessages.size() - 1); } } } } for (MethodInvocation methodInvocation : methodInvocations) { List<Operation> matchingOperation = operationsList .stream() .filter(f -> f._id.equals(methodInvocation.getSignature())) .collect(Collectors.toList()); if (matchingOperation.size() > 0) { operationMap.put(methodInvocation, matchingOperation.get(0)._id); methodInvocation.setOperation(matchingOperation.get(0)); } } Stack stack = new Stack(); for (MethodInvocation root : methodInvocations) { stack.push(root); while (!stack.empty()) { MethodInvocation methodInvocation = (MethodInvocation) stack.pop(); Operation currentOperation = methodInvocation.getOperation(); if (currentOperation != null) { // all child nodes of this node make up its body List<MethodInvocation> childNodes = methodInvocation.childNodes; for (MethodInvocation child : childNodes) { stack.push(child); } for (MethodInvocation childNode : childNodes) { if (childNode.getOperandId() != null) { List<Instruction> combinedFragmentsList = combinedFragments .stream() .filter(f -> f.getId().equals(childNode.getCfID())) .collect(Collectors.toList()); List<Guard> guardList = listOfGuards .stream() .filter(f -> f.id.equals(childNode.getOperandId())) .collect(Collectors.toList()); if (guardList.size() > 0) { Guard currentGuard = guardList.get(0); Instruction instruction = guardToCFMap.get(guardList.get(0)); // get the topmost CF if it is in a tree Instruction parent = instruction.getParent(); while (instruction.getParent() != null) { instruction = instruction.getParent(); } if (currentGuard.isConsequence) { Conditional conditional = (Conditional) instruction; if (!conditional.getConsequence().contains(childNode)) { conditional.getConsequence().add(childNode); } } if (currentGuard.isAlternative) { Conditional conditional = (Conditional) instruction; if (!conditional.getAlternative().contains(childNode)) { conditional.getAlternative().add(childNode); } } if (!currentGuard.isAlternative && !currentGuard.isConsequence) { Loop loop = (Loop) instruction; loop.getBlock().add(childNode); } else { if (!currentOperation.getBlock().contains(instruction)) { currentOperation.getBlock().add(instruction); } } } } else { if (!currentOperation.getBlock().contains(childNode)) { currentOperation.getBlock().add(childNode); } } } } } } } } } } // //// printAllData(metaClasses); // while (parentMessage.childNodes != null || parentMessage.childNodes.size() > 0) { // System.out.println("parent " + parentMessage.name); // for (com.cbpro.main.MethodInvocation child : parentMessage.childNodes) { // System.out.println("child " + child.name); // } // if (parentMessage.childNodes.size() > 0) { // parentMessage = parentMessage.childNodes.get(0); // } else { // break; // } // } mainPackage.print(); File dir = new File("/home/ramyashenoy/Desktop/DemoFolder/" + mainPackage.getName()); boolean successful = dir.mkdir(); if (successful) { System.out.println("directory was created successfully"); for (MetaClass metaClass : metaClasses) { if (metaClass.name.equals("Main")) { continue; } else { String data = metaClass.print(); BufferedWriter out = null; try { FileWriter fstream = new FileWriter( dir.getPath() + "/" + metaClass.name + ".java", true); // true tells to append data. out = new BufferedWriter(fstream); out.write(data); } catch (IOException e) { System.err.println("Error: " + e.getMessage()); } finally { if (out != null) { out.close(); } } } } } else { // creating the directory failed System.out.println("failed trying to create the directory"); } mainPackage.setClasses(metaClasses); }
public static void main(String args[]) throws IOException { List<Instruction> insns = Instructions.getInstructions(); Collections.sort(insns); List<Character> startLetters = new java.util.ArrayList<Character>(); char last = 0; for (int i = 0; i < insns.size(); i++) { Instruction insn = (Instruction) insns.get(i); char leadChar = insn.getName().charAt(0); if (last != leadChar) { startLetters.add(leadChar); last = leadChar; } } File docdir = new File("SquawkBytecodeSpec"); Build.mkdir(docdir); PrintWriter out = null; out = new PrintWriter(new FileWriter(new File(docdir, "Instructions.doc.html"))); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); out.println("<html>"); out.println("<head>"); out.println("<title>Squawk Bytecode Instruction Set</title>"); out.println("</head>"); out.println("<body BGCOLOR=#eeeeff text=#000000 LINK=#0000ff VLINK=#000077 ALINK=#ff0000>"); out.println("<table width=100%><tr>"); out.print( "<td>Prev | <a href=\"Instructions2.doc1.html\">Next</a> | <a href=\"Instructions2.index.html\">Index</a> </td>"); out.println("<td align=right><i><i>Squawk Bytecode Instruction Set</i></i></td>"); out.println("</tr></table>"); out.println(); out.println("<hr><br>"); out.println(); for (int i = 0; i < startLetters.size(); i++) { Character c = (Character) startLetters.get(i); out.println( "<a href=\"Instructions2.doc" + (i + 1) + ".html\">" + Character.toUpperCase(c.charValue()) + "</a>"); } out.println(); out.println("<hr><br>"); out.println(); out.println("<h1>Squawk Bytecode Instruction Set</h1>"); out.println("<hr><p>"); out.println("A Squawk bytecode instruction consists of an opcode specifying the operation"); out.println( "to be performed, followed by zero or more operands embodying values to be operated"); out.println("upon. This chapter gives details about the format of each Squawk bytecode"); out.println("instruction and the operation it performs.</p>"); out.println("<hr>"); out.println("<p>Prev | <a href=\"Instructions2.doc1.html\">Next</a></p>"); out.println("</body></html>"); out.close(); PrintWriter indexPage = new PrintWriter(new FileWriter(new File(docdir, "Instructions2.index.html"))); indexPage.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); indexPage.println("<html>"); indexPage.println("<head>"); indexPage.println("<title>Squawk Bytecode Instruction Set</title>"); indexPage.println("</head>"); indexPage.println( "<body BGCOLOR=#eeeeff text=#000000 LINK=#0000ff VLINK=#000077 ALINK=#ff0000>"); indexPage.println("<table width=100%><tr>"); indexPage.println("<td><a href=\"Instructions.doc.html\">Contents</a></td>"); indexPage.println("<td align=right><i><i>Squawk Bytecode Instruction Set</i></i></td>"); indexPage.println("</tr></table>"); indexPage.println(); indexPage.println("<hr><br>"); indexPage.println(); Iterator<Instruction> iter = insns.iterator(); Instruction insn = (iter.hasNext()) ? iter.next() : null; for (int i = 0; i < startLetters.size(); i++) { String thisPage = "Instructions2.doc" + (i + 1) + ".html"; String prevPage = "Instructions2.doc" + i + ".html"; String nextPage = "Instructions2.doc" + (i + 2) + ".html"; out = new PrintWriter(new FileWriter(new File(docdir, thisPage))); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">"); out.println("<html>"); out.println("<head>"); out.println("<title>Squawk Bytecode Instruction Descriptions</title>"); out.println("</head>"); out.println("<body BGCOLOR=#eeeeff text=#000000 LINK=#0000ff VLINK=#000077 ALINK=#ff0000>"); out.println("<table width=100%><tr>"); out.print("<td>"); out.print(" <a href=\"Instructions.doc.html\">Contents</a> | "); if (i > 0) out.print("<a href=\"" + prevPage + "\">Prev</a>"); else out.print("<a href=\"Instructions.doc.html\">Prev</a>"); out.print(" | "); if (i < startLetters.size() - 1) out.print("<a href=\"" + nextPage + "\">Next</a>"); else out.print("Next"); out.println(" | <a href=\"Instructions2.index.html\">Index</a> </td>"); out.println("<td align=right><i><i>Squawk Bytecode Instruction Set</i></i></td>"); out.println("</tr></table>"); out.println(); out.println("<hr><br>"); out.println(); for (int j = 0; j < startLetters.size(); j++) { Character c = (Character) startLetters.get(j); out.println( "<a href=\"Instructions2.doc" + (j + 1) + ".html\">" + Character.toUpperCase(c.charValue()) + "</a>"); } out.println(); while (insn != null && Character.toUpperCase(insn.getName().charAt(0)) == Character.toUpperCase(((Character) startLetters.get(i)).charValue())) { String name = insn.getName(); indexPage.println("<a href=\"" + thisPage + "#" + name + "\">" + name + "</a><br>"); out.println("<hr><a name=\"" + name + "\"><h2>" + name + "</h2>"); out.println("<p><b>Operation</b></p>"); out.println("<blockquote>"); insn.printOperation(out); out.println("</blockquote>"); out.println("<p><b>Format</b></p>"); out.println("<blockquote>"); insn.printFormat(out); out.println("</blockquote>"); out.println("<p><b>Forms</b></p>"); out.println("<blockquote>"); insn.printForms(out); out.println("</blockquote>"); out.println("<p><b>Operand Stack</b></p>"); out.println("<blockquote>"); insn.printOperandStack(out); out.println("</blockquote>"); out.println("<p><b>Description</b></p>"); out.println("<blockquote>"); insn.printDescription(out); out.println("</blockquote>"); if (insn.hasNotes()) { out.println("<p><b>Notes</b></p>"); out.println("<blockquote>"); insn.printNotes(out); out.println("</blockquote>"); } insn = (iter.hasNext()) ? (Instruction) iter.next() : null; } out.println("<hr>"); if (i > 0) out.print("<a href=\"Instructions2.doc" + i + ".html\">Prev</a>"); else out.print("<a href=\"Instructions.doc.html\">Prev</a>"); out.print(" | "); if (i < startLetters.size() - 1) out.print("<a href=\"Instructions2.doc" + (i + 2) + ".html\">Next</a>"); else out.print("Next"); out.println(); out.println("</body></html>"); out.flush(); out.close(); } indexPage.println("</body></html>"); indexPage.close(); for (int i = 0; i < 256; i++) if (!opcodes.contains(new Integer(i))) System.out.println("missing opcode: " + i); }
/** * Creates a new instruction. address is the target of the operation, if one is needed. Otherwise * it is not used. * * @pre 0 <= opcode <= GO. */ public Instruction(String opcode, int address) { this(Instruction.toInt(opcode), address); }
/** * Inserts residency/update/swizzle checks into a method. Iterates over the bytecodes in the * method and inserts the appropriate residency opcode. * * @param method The method to which to add checks. * @see MethodEditor#code */ private static void transform(final MethodEditor method) { if (Main.VERBOSE > 1) { System.out.println("Decorating method " + method); } // Optimize initialization of arrays to speed things up. CompactArrayInitializer.transform(method); final ListIterator iter = method.code().listIterator(); // Go through the code (Instructions and Labels) in the method INST: while (iter.hasNext()) { final Object ce = iter.next(); if (Main.VERBOSE > 2) { System.out.println("Examining " + ce); } if (ce instanceof Instruction) { final Instruction inst = (Instruction) ce; int uctype = Main.NONE; // Type of update check (POINTER or // SCALAR) boolean insert_sc = false; // Insert swizzle check (aaload // only)? final int opc = inst.opcodeClass(); int depth; switch (opc) { case opcx_arraylength: case opcx_athrow: case opcx_getfield: case opcx_instanceof: { depth = 0; break; } case opcx_iaload: case opcx_laload: case opcx_faload: case opcx_daload: case opcx_baload: case opcx_caload: case opcx_saload: { depth = 1; break; } case opcx_aaload: { depth = 1; insert_sc = true; break; } case opcx_iastore: case opcx_fastore: case opcx_aastore: case opcx_bastore: case opcx_castore: case opcx_sastore: { depth = 2; break; } case opcx_lastore: case opcx_dastore: { depth = 3; break; } case opcx_putfield: { final MemberRef ref = (MemberRef) inst.operand(); depth = ref.type().stackHeight(); if (ref.type().isReference()) { uctype = Main.POINTER; } else { uctype = Main.SCALAR; } break; } case opcx_invokevirtual: case opcx_invokespecial: case opcx_invokeinterface: { final MemberRef ref = (MemberRef) inst.operand(); depth = ref.type().stackHeight(); break; } case opcx_rc: { // Skip any existing residency checks. iter.remove(); continue INST; } case opcx_aupdate: { // Skip any existing update checks. iter.remove(); continue INST; } case opcx_supdate: { // Skip any existing update checks. iter.remove(); continue INST; } default: { continue INST; } } Instruction addInst; // Insert a residency check... if (Main.RC) { Object t; // ////////////////////////////////// // Before... // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next // // After... // +-----+----+------+-----------+ // | ... | RC | inst | afterInst | // +-----+----+------+-----------+ // ^prev ^next // ////////////////////////////////// // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == inst, t + " != " + inst); // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next addInst = new Instruction(Opcode.opcx_rc, new Integer(depth)); iter.add(addInst); // +-----+----+------+-----------+ // | ... | RC | inst | afterInst | // +-----+----+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+----+------+-----------+ // | ... | RC | inst | afterInst | // +-----+----+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+----+------+-----------+ // | ... | RC | inst | afterInst | // +-----+----+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == inst, t + " != " + inst); // +-----+----+------+-----------+ // | ... | RC | inst | afterInst | // +-----+----+------+-----------+ // ^prev ^next if (Main.VERBOSE > 2) { System.out.println("Inserting " + addInst + " before " + inst); } } else { if (Main.VERBOSE > 2) { System.out.println("Not inserting rc before " + inst); } } // Insert a swizzle check... if (insert_sc) { if (Main.SC) { Object t; // //////////////////////////////////////////// // Before... // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next // // After... // +-----+------+----------+------+-----------+ // | ... | dup2 | aswizzle | inst | afterInst | // +-----+------+----------+------+-----------+ // ^prev ^next // ///////////////////////////////////////////// // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == inst, t + " != " + inst); // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next addInst = new Instruction(Opcode.opcx_dup2); iter.add(addInst); // +-----+------+------+-----------+ // | ... | dup2 | inst | afterInst | // +-----+------+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+------+------+-----------+ // | ... | dup2 | inst | afterInst | // +-----+------+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+------+------+-----------+ // | ... | dup2 | inst | afterInst | // +-----+------+------+-----------+ // ^prev ^next addInst = new Instruction(Opcode.opcx_aswizzle); iter.add(addInst); // +-----+------+----------+------+-----------+ // | ... | dup2 | aswizzle | inst | afterInst | // +-----+------+----------+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+------+----------+------+-----------+ // | ... | dup2 | aswizzle | inst | afterInst | // +-----+------+----------+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+------+----------+------+-----------+ // | ... | dup2 | aswizzle | inst | afterInst | // +-----+------+----------+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == inst, t + " != " + inst); // +-----+------+----------+------+-----------+ // | ... | dup2 | aswizzle | inst | afterInst | // +-----+------+----------+------+-----------+ // ^prev ^next if (Main.VERBOSE > 2) { System.out.println("Inserting dup2,aswizzle before " + inst); } } else { if (Main.VERBOSE > 2) { System.out.println("Not inserting aswizzle before " + inst); } } } // Insert an update check... if (uctype != Main.NONE) { if (Main.UC) { Object t; // //////////////////////////////////////////// // Before... // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next // // After... // +-----+---------+------+-----------+ // | ... | aupdate | inst | afterInst | // +-----+---------+------+-----------+ // ^prev ^next // ///////////////////////////////////////////// // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == inst, t + " != " + inst); // +-----+------+-----------+ // | ... | inst | afterInst | // +-----+------+-----------+ // ^prev ^next addInst = new Instruction(Opcode.opcx_aupdate, new Integer(depth)); /* * if (uctype == POINTER) { addInst = new * Instruction(opcx_aupdate, new Integer(depth)); } else { * addInst = new Instruction(opcx_supdate, new * Integer(depth)); } */ iter.add(addInst); // +-----+---------+------+-----------+ // | ... | aupdate | inst | afterInst | // +-----+---------+------+-----------+ // ^prev ^next t = iter.previous(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+---------+------+-----------+ // | ... | aupdate | inst | afterInst | // +-----+---------+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == addInst, t + " != " + addInst); // +-----+---------+------+-----------+ // | ... | aupdate | inst | afterInst | // +-----+---------+------+-----------+ // ^prev ^next t = iter.next(); Assert.isTrue(t == inst, t + " != " + inst); // +-----+---------+------+-----------+ // | ... | aupdate | inst | afterInst | // +-----+---------+------+-----------+ // ^prev ^next if (Main.VERBOSE > 2) { System.out.println("Inserting " + addInst + " before " + inst); } } else if (Main.VERBOSE > 2) { System.out.println("Not inserting uc before " + inst); } } } } }
/** Dump instruction as short code to stream out. */ public void dump(DataOutputStream out) throws IOException { super.dump(out); out.writeShort(b); }
static private void oneInstruction(Instruction instr) { int raw; int nextLoadReg = 0; int nextLoadValue = 0; // record delayed load operation, to apply // in the future // Fetch instruction try { instr.value = readMem(registers[PCReg], 4); } catch (MachineException e) { return; // exception occurred } instr.decode(); String str = Instruction.opStrings[instr.opCode]; byte args[] = Instruction.opRegs[instr.opCode]; Debug.ASSERT(instr.opCode <= Instruction.MaxOpcode); if (Debug.isEnabled('m')) { Debug.printf('m', "At PC = 0x%x: ", new Integer(registers[PCReg])); Debug.printf('m', str + "\n", new Integer(instr.typeToReg(args[0])), new Integer(instr.typeToReg(args[1])), new Integer(instr.typeToReg(args[2]))); } // Compute next pc, but don't install in case there's an error or branch. int pcAfter = registers[NextPCReg] + 4; int sum, diff, tmp, value; long rs, rt, imm; // Execute the instruction (cf. Kane's book) switch (instr.opCode) { case Instruction.OP_ADD: sum = registers[instr.rs] + registers[instr.rt]; if (((registers[instr.rs] ^ registers[instr.rt]) & SIGN_BIT) == 0 && ((registers[instr.rs] ^ sum) & SIGN_BIT) != 0) { raiseException(OverflowException, 0); return; } registers[instr.rd] = sum; break; case Instruction.OP_ADDI: sum = registers[instr.rs] + instr.extra; if (((registers[instr.rs] ^ instr.extra) & SIGN_BIT) == 0 && ((instr.extra ^ sum) & SIGN_BIT) != 0) { raiseException(OverflowException, 0); return; } registers[instr.rt] = sum; break; case Instruction.OP_ADDIU: // the registers are int, so we have to do them unsigned. // Now, precisely *WHY* didn't java give us unsigned types, again? rs = registers[instr.rs] & LOW32BITS; imm = instr.extra & LOW32BITS; rt = rs + imm; registers[instr.rt] = (int)rt; break; case Instruction.OP_ADDU: rs = registers[instr.rs] & LOW32BITS; rt = registers[instr.rt] & LOW32BITS; registers[instr.rd] = (int)(rs + rt); break; case Instruction.OP_AND: registers[instr.rd] = registers[instr.rs] & registers[instr.rt]; break; case Instruction.OP_ANDI: registers[instr.rt] = registers[instr.rs] & (instr.extra & 0xffff); break; case Instruction.OP_BEQ: if (registers[instr.rs] == registers[instr.rt]) pcAfter = registers[NextPCReg] + (instr.extra << 2); break; case Instruction.OP_BGEZAL: registers[R31] = registers[NextPCReg] + 4; case Instruction.OP_BGEZ: if ((registers[instr.rs] & SIGN_BIT) == 0) pcAfter = registers[NextPCReg] + (instr.extra << 2); break; case Instruction.OP_BGTZ: if (registers[instr.rs] > 0) pcAfter = registers[NextPCReg] + (instr.extra << 2); break; case Instruction.OP_BLEZ: if (registers[instr.rs] <= 0) pcAfter = registers[NextPCReg] + (instr.extra << 2); break; case Instruction.OP_BLTZAL: registers[R31] = registers[NextPCReg] + 4; case Instruction.OP_BLTZ: if ((registers[instr.rs] & SIGN_BIT) != 0) pcAfter = registers[NextPCReg] + (instr.extra << 2); break; case Instruction.OP_BNE: if (registers[instr.rs] != registers[instr.rt]) pcAfter = registers[NextPCReg] + (instr.extra << 2); break; case Instruction.OP_DIV: if (registers[instr.rt] == 0) { registers[LoReg] = 0; registers[HiReg] = 0; } else { registers[LoReg] = registers[instr.rs] / registers[instr.rt]; registers[HiReg] = registers[instr.rs] % registers[instr.rt]; } break; case Instruction.OP_DIVU: // don't sign extend rs = (registers[instr.rs] & LOW32BITS); rt = (registers[instr.rt] & LOW32BITS); if (rt == 0) { registers[LoReg] = 0; registers[HiReg] = 0; } else { tmp = (int) (rs / rt); registers[LoReg] = tmp; tmp = (int) (rs % rt); registers[HiReg] = tmp; } break; case Instruction.OP_JAL: registers[R31] = registers[NextPCReg] + 4; case Instruction.OP_J: pcAfter = (pcAfter & 0xf0000000) | instr.extra << 2; break; case Instruction.OP_JALR: registers[instr.rd] = registers[NextPCReg] + 4; case Instruction.OP_JR: pcAfter = registers[instr.rs]; break; case Instruction.OP_LB: case Instruction.OP_LBU: tmp = registers[instr.rs] + instr.extra; try { value = readMem(tmp, 1); } catch (MachineException e) { return; // exception occurred } if ((value & 0x80) != 0 && (instr.opCode == Instruction.OP_LB)) value |= 0xffffff00; else value &= 0xff; nextLoadReg = instr.rt; nextLoadValue = value; break; case Instruction.OP_LH: case Instruction.OP_LHU: tmp = registers[instr.rs] + instr.extra; if ((tmp & 0x1) != 0) { raiseException(AddressErrorException, tmp); return; } try { value = readMem(tmp, 2); } catch (MachineException e) { return; // exception occurred } if ((value & 0x8000) != 0 && (instr.opCode == Instruction.OP_LH)) value |= 0xffff0000; else value &= 0xffff; nextLoadReg = instr.rt; nextLoadValue = value; break; case Instruction.OP_LUI: if (Debug.isEnabled('m')) Debug.printf('m', "Executing: LUI r%d,%d\n", new Integer(instr.rt), new Integer(instr.extra)); registers[instr.rt] = instr.extra << 16; break; case Instruction.OP_LW: tmp = registers[instr.rs] + instr.extra; if ((tmp & 0x3) != 0) { raiseException(AddressErrorException, tmp); return; } try { value = readMem(tmp, 4); } catch (MachineException e) { return; // exception occurred } nextLoadReg = instr.rt; nextLoadValue = value; break; case Instruction.OP_LWL: tmp = registers[instr.rs] + instr.extra; // ReadMem assumes all 4 byte requests are aligned on an even // word boundary. Also, the little endian/big endian swap code would // fail (I think) if the other cases are ever exercised. Debug.ASSERT((tmp & 0x3) == 0); try { value = readMem(tmp, 4); } catch (MachineException e) { return; // exception occurred } if (registers[LoadReg] == instr.rt) nextLoadValue = registers[LoadValueReg]; else nextLoadValue = registers[instr.rt]; switch (tmp & 0x3) { case 0: nextLoadValue = value; break; case 1: nextLoadValue = (nextLoadValue & 0xff) | (value << 8); break; case 2: nextLoadValue = (nextLoadValue & 0xffff) | (value << 16); break; case 3: nextLoadValue = (nextLoadValue & 0xffffff) | (value << 24); break; } nextLoadReg = instr.rt; break; case Instruction.OP_LWR: tmp = registers[instr.rs] + instr.extra; // ReadMem assumes all 4 byte requests are aligned on an even // word boundary. Also, the little endian/big endian swap code would // fail (I think) if the other cases are ever exercised. Debug.ASSERT((tmp & 0x3) == 0); try { value = readMem(tmp, 4); } catch (MachineException e) { return; // exception occurred } if (registers[LoadReg] == instr.rt) nextLoadValue = registers[LoadValueReg]; else nextLoadValue = registers[instr.rt]; switch (tmp & 0x3) { case 0: nextLoadValue = (nextLoadValue & 0xffffff00) | ((value >> 24) & 0xff); break; case 1: nextLoadValue = (nextLoadValue & 0xffff0000) | ((value >> 16) & 0xffff); break; case 2: nextLoadValue = (nextLoadValue & 0xff000000) | ((value >> 8) & 0xffffff); break; case 3: nextLoadValue = value; break; } nextLoadReg = instr.rt; break; case Instruction.OP_MFHI: registers[instr.rd] = registers[HiReg]; break; case Instruction.OP_MFLO: registers[instr.rd] = registers[LoReg]; break; case Instruction.OP_MTHI: registers[HiReg] = registers[instr.rs]; break; case Instruction.OP_MTLO: registers[LoReg] = registers[instr.rs]; break; case Instruction.OP_MULT: mult(registers[instr.rs], registers[instr.rt], true, mresult); registers[HiReg] = mresult[0]; registers[LoReg] = mresult[1]; break; case Instruction.OP_MULTU: mult(registers[instr.rs], registers[instr.rt], false, mresult); registers[HiReg] = mresult[0]; registers[LoReg] = mresult[1]; break; case Instruction.OP_NOR: registers[instr.rd] = ~(registers[instr.rs] | registers[instr.rt]); break; case Instruction.OP_OR: registers[instr.rd] = registers[instr.rs] | registers[instr.rt]; break; case Instruction.OP_ORI: registers[instr.rt] = registers[instr.rs] | (instr.extra & 0xffff); break; case Instruction.OP_SB: if (!writeMem( (registers[instr.rs] + instr.extra), 1, registers[instr.rt])) return; break; case Instruction.OP_SH: if (!writeMem( (registers[instr.rs] + instr.extra), 2, registers[instr.rt])) return; break; case Instruction.OP_SLL: registers[instr.rd] = registers[instr.rt] << instr.extra; break; case Instruction.OP_SLLV: registers[instr.rd] = registers[instr.rt] << (registers[instr.rs] & 0x1f); break; case Instruction.OP_SLT: if (registers[instr.rs] < registers[instr.rt]) registers[instr.rd] = 1; else registers[instr.rd] = 0; break; case Instruction.OP_SLTI: if (registers[instr.rs] < instr.extra) registers[instr.rt] = 1; else registers[instr.rt] = 0; break; case Instruction.OP_SLTIU: rs = (registers[instr.rs] & LOW32BITS); imm = (instr.extra & LOW32BITS); if (rs < imm) registers[instr.rt] = 1; else registers[instr.rt] = 0; break; case Instruction.OP_SLTU: rs = registers[instr.rs] & LOW32BITS; rt = registers[instr.rt] & LOW32BITS; if (rs < rt) registers[instr.rd] = 1; else registers[instr.rd] = 0; break; case Instruction.OP_SRA: registers[instr.rd] = registers[instr.rt] >> instr.extra; break; case Instruction.OP_SRAV: registers[instr.rd] = registers[instr.rt] >> (registers[instr.rs] & 0x1f); break; case Instruction.OP_SRL: tmp = registers[instr.rt]; tmp >>= instr.extra; registers[instr.rd] = tmp; break; case Instruction.OP_SRLV: tmp = registers[instr.rt]; tmp >>= (registers[instr.rs] & 0x1f); registers[instr.rd] = tmp; break; case Instruction.OP_SUB: diff = registers[instr.rs] - registers[instr.rt]; if (((registers[instr.rs] ^ registers[instr.rt]) & SIGN_BIT) != 0 && ((registers[instr.rs] ^ diff) & SIGN_BIT) != 0) { raiseException(OverflowException, 0); return; } registers[instr.rd] = diff; break; case Instruction.OP_SUBU: rs = (registers[instr.rs] & LOW32BITS); rt = (registers[instr.rt] & LOW32BITS); registers[instr.rd] = (int)(rs - rt); break; case Instruction.OP_SW: if (!writeMem( (registers[instr.rs] + instr.extra), 4, registers[instr.rt])) return; break; case Instruction.OP_SWL: tmp = registers[instr.rs] + instr.extra; // The little endian/big endian swap code would // fail (I think) if the other cases are ever exercised. Debug.ASSERT((tmp & 0x3) == 0); try { value = readMem((tmp & ~0x3), 4); } catch (MachineException e) { return; // exception occurred } switch (tmp & 0x3) { case 0: value = registers[instr.rt]; break; case 1: value = (value & 0xff000000) | ((registers[instr.rt] >> 8) & 0xffffff); break; case 2: value = (value & 0xffff0000) | ((registers[instr.rt] >> 16) & 0xffff); break; case 3: value = (value & 0xffffff00) | ((registers[instr.rt] >> 24) & 0xff); break; } if (!writeMem((tmp & ~0x3), 4, value)) return; break; case Instruction.OP_SWR: tmp = registers[instr.rs] + instr.extra; // The little endian/big endian swap code would // fail (I think) if the other cases are ever exercised. Debug.ASSERT((tmp & 0x3) == 0); try { value = readMem((tmp & ~0x3), 4); } catch (MachineException e) { return; // exception occurred } switch (tmp & 0x3) { case 0: value = (value & 0xffffff) | (registers[instr.rt] << 24); break; case 1: value = (value & 0xffff) | (registers[instr.rt] << 16); break; case 2: value = (value & 0xff) | (registers[instr.rt] << 8); break; case 3: value = registers[instr.rt]; break; } if (!writeMem((tmp & ~0x3), 4, value)) return; break; case Instruction.OP_SYSCALL: raiseException(SyscallException, 0); return; case Instruction.OP_XOR: registers[instr.rd] = registers[instr.rs] ^ registers[instr.rt]; break; case Instruction.OP_XORI: registers[instr.rt] = registers[instr.rs] ^ (instr.extra & 0xffff); break; case Instruction.OP_RES: case Instruction.OP_UNIMP: raiseException(IllegalInstrException, 0); return; default: System.out.println("Bogus opcode, should not happen"); return; } // Now we have successfully executed the instruction. // Do any delayed load operation delayedLoad(nextLoadReg, nextLoadValue); // Advance program counters. registers[PrevPCReg] = registers[PCReg]; // for debugging, in case we // are jumping into lala-land registers[PCReg] = registers[NextPCReg]; registers[NextPCReg] = pcAfter; }
/** Get the number of bytes for which this local has a value in the code byte array. */ public int getLength() { if (_end != null) return _end.getByteIndex() + _end.getLength() - _target.getByteIndex(); return _length; }
/** * Adds all the constants found in the given class into the given ConstantSet, and returns it. * * @see #getConstants(String) */ public static ConstantSet getConstants(String classname, ConstantSet result) { ClassParser cp; JavaClass jc; try { String classfileBase = classname.replace('.', '/'); InputStream is = ClassPath.SYSTEM_CLASS_PATH.getInputStream(classfileBase, ".class"); cp = new ClassParser(is, classname); jc = cp.parse(); } catch (java.io.IOException e) { throw new Error("IOException while reading '" + classname + "': " + e.getMessage()); } result.classname = jc.getClassName(); // Get all of the constants from the pool ConstantPool constant_pool = jc.getConstantPool(); for (Constant c : constant_pool.getConstantPool()) { // System.out.printf ("*Constant = %s%n", c); if (c == null || c instanceof ConstantClass || c instanceof ConstantFieldref || c instanceof ConstantInterfaceMethodref || c instanceof ConstantMethodref || c instanceof ConstantNameAndType || c instanceof ConstantUtf8) { continue; } if (c instanceof ConstantString) { result.strings.add((String) ((ConstantString) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantDouble) { result.doubles.add((Double) ((ConstantDouble) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantFloat) { result.floats.add((Float) ((ConstantFloat) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantInteger) { result.ints.add((Integer) ((ConstantInteger) c).getConstantValue(constant_pool)); } else if (c instanceof ConstantLong) { result.longs.add((Long) ((ConstantLong) c).getConstantValue(constant_pool)); } else { throw new RuntimeException("Unrecognized constant of type " + c.getClass() + ": " + c); } } ClassGen gen = new ClassGen(jc); ConstantPoolGen pool = gen.getConstantPool(); // Process the code in each method looking for literals for (Method m : jc.getMethods()) { MethodGen mg = new MethodGen(m, jc.getClassName(), pool); InstructionList il = mg.getInstructionList(); if (il == null) { // System.out.println("No instructions for " + mg); } else { for (Instruction inst : il.getInstructions()) { switch (inst.getOpcode()) { // Compare two objects, no literals case Constants.IF_ACMPEQ: case Constants.IF_ACMPNE: break; // These instructions compare the integer on the top of the stack // to zero. There are no literals here (except 0) case Constants.IFEQ: case Constants.IFNE: case Constants.IFLT: case Constants.IFGE: case Constants.IFGT: case Constants.IFLE: { break; } // Instanceof pushes either 0 or 1 on the stack depending on whether // the object on top of stack is of the specified type. // If were interested in class literals, this would be interesting case Constants.INSTANCEOF: break; // Duplicates the item on the top of stack. No literal. case Constants.DUP: { break; } // Duplicates the item on the top of the stack and inserts it 2 // values down in the stack. No literals case Constants.DUP_X1: { break; } // Duplicates either the top 2 category 1 values or a single // category 2 value and inserts it 2 or 3 values down on the // stack. case Constants.DUP2_X1: { break; } // Duplicate either one category 2 value or two category 1 values. case Constants.DUP2: { break; } // Dup the category 1 value on the top of the stack and insert it either // two or three values down on the stack. case Constants.DUP_X2: { break; } case Constants.DUP2_X2: { break; } // Pop instructions discard the top of the stack. case Constants.POP: { break; } // Pops either the top 2 category 1 values or a single category 2 value // from the top of the stack. case Constants.POP2: { break; } // Swaps the two category 1 types on the top of the stack. case Constants.SWAP: { break; } // Compares two integers on the stack case Constants.IF_ICMPEQ: case Constants.IF_ICMPGE: case Constants.IF_ICMPGT: case Constants.IF_ICMPLE: case Constants.IF_ICMPLT: case Constants.IF_ICMPNE: { break; } // Get the value of a field case Constants.GETFIELD: { break; } // stores the top of stack into a field case Constants.PUTFIELD: { break; } // Pushes the value of a static field on the stack case Constants.GETSTATIC: { break; } // Pops a value off of the stack into a static field case Constants.PUTSTATIC: { break; } // pushes a local onto the stack case Constants.DLOAD: case Constants.DLOAD_0: case Constants.DLOAD_1: case Constants.DLOAD_2: case Constants.DLOAD_3: case Constants.FLOAD: case Constants.FLOAD_0: case Constants.FLOAD_1: case Constants.FLOAD_2: case Constants.FLOAD_3: case Constants.ILOAD: case Constants.ILOAD_0: case Constants.ILOAD_1: case Constants.ILOAD_2: case Constants.ILOAD_3: case Constants.LLOAD: case Constants.LLOAD_0: case Constants.LLOAD_1: case Constants.LLOAD_2: case Constants.LLOAD_3: { break; } // Pops a value off of the stack into a local case Constants.DSTORE: case Constants.DSTORE_0: case Constants.DSTORE_1: case Constants.DSTORE_2: case Constants.DSTORE_3: case Constants.FSTORE: case Constants.FSTORE_0: case Constants.FSTORE_1: case Constants.FSTORE_2: case Constants.FSTORE_3: case Constants.ISTORE: case Constants.ISTORE_0: case Constants.ISTORE_1: case Constants.ISTORE_2: case Constants.ISTORE_3: case Constants.LSTORE: case Constants.LSTORE_0: case Constants.LSTORE_1: case Constants.LSTORE_2: case Constants.LSTORE_3: { break; } // Push a value from the runtime constant pool. We'll get these // values when processing the constant pool itself case Constants.LDC: case Constants.LDC_W: case Constants.LDC2_W: { break; } // Push the length of an array on the stack case Constants.ARRAYLENGTH: { break; } // Push small constants (-1..5) on the stack. These literals are // too common to bother mentioning case Constants.DCONST_0: case Constants.DCONST_1: case Constants.FCONST_0: case Constants.FCONST_1: case Constants.FCONST_2: case Constants.ICONST_0: case Constants.ICONST_1: case Constants.ICONST_2: case Constants.ICONST_3: case Constants.ICONST_4: case Constants.ICONST_5: case Constants.ICONST_M1: case Constants.LCONST_0: case Constants.LCONST_1: { break; } case Constants.BIPUSH: case Constants.SIPUSH: { ConstantPushInstruction cpi = (ConstantPushInstruction) inst; result.ints.add((Integer) cpi.getValue()); break; } // Primitive Binary operators. case Constants.DADD: case Constants.DCMPG: case Constants.DCMPL: case Constants.DDIV: case Constants.DMUL: case Constants.DREM: case Constants.DSUB: case Constants.FADD: case Constants.FCMPG: case Constants.FCMPL: case Constants.FDIV: case Constants.FMUL: case Constants.FREM: case Constants.FSUB: case Constants.IADD: case Constants.IAND: case Constants.IDIV: case Constants.IMUL: case Constants.IOR: case Constants.IREM: case Constants.ISHL: case Constants.ISHR: case Constants.ISUB: case Constants.IUSHR: case Constants.IXOR: case Constants.LADD: case Constants.LAND: case Constants.LCMP: case Constants.LDIV: case Constants.LMUL: case Constants.LOR: case Constants.LREM: case Constants.LSHL: case Constants.LSHR: case Constants.LSUB: case Constants.LUSHR: case Constants.LXOR: break; case Constants.LOOKUPSWITCH: case Constants.TABLESWITCH: break; case Constants.ANEWARRAY: case Constants.NEWARRAY: { break; } case Constants.MULTIANEWARRAY: { break; } // push the value at an index in an array case Constants.AALOAD: case Constants.BALOAD: case Constants.CALOAD: case Constants.DALOAD: case Constants.FALOAD: case Constants.IALOAD: case Constants.LALOAD: case Constants.SALOAD: { break; } // Pop the top of stack into an array location case Constants.AASTORE: case Constants.BASTORE: case Constants.CASTORE: case Constants.DASTORE: case Constants.FASTORE: case Constants.IASTORE: case Constants.LASTORE: case Constants.SASTORE: break; case Constants.ARETURN: case Constants.DRETURN: case Constants.FRETURN: case Constants.IRETURN: case Constants.LRETURN: case Constants.RETURN: { break; } // subroutine calls. case Constants.INVOKESTATIC: case Constants.INVOKEVIRTUAL: case Constants.INVOKESPECIAL: case Constants.INVOKEINTERFACE: break; // Throws an exception. case Constants.ATHROW: break; // Opcodes that don't need any modifications. Here for reference case Constants.ACONST_NULL: case Constants.ALOAD: case Constants.ALOAD_0: case Constants.ALOAD_1: case Constants.ALOAD_2: case Constants.ALOAD_3: case Constants.ASTORE: case Constants.ASTORE_0: case Constants.ASTORE_1: case Constants.ASTORE_2: case Constants.ASTORE_3: case Constants.CHECKCAST: case Constants.D2F: // double to float case Constants.D2I: // double to integer case Constants.D2L: // double to long case Constants.DNEG: // Negate double on top of stack case Constants.F2D: // float to double case Constants.F2I: // float to integer case Constants.F2L: // float to long case Constants.FNEG: // Negate float on top of stack case Constants.GOTO: case Constants.GOTO_W: case Constants.I2B: // integer to byte case Constants.I2C: // integer to char case Constants.I2D: // integer to double case Constants.I2F: // integer to float case Constants.I2L: // integer to long case Constants.I2S: // integer to short case Constants.IFNONNULL: case Constants.IFNULL: case Constants.IINC: // increment local variable by a constant case Constants.INEG: // negate integer on top of stack case Constants.JSR: // pushes return address on the stack, case Constants.JSR_W: case Constants.L2D: // long to double case Constants.L2F: // long to float case Constants.L2I: // long to int case Constants.LNEG: // negate long on top of stack case Constants.MONITORENTER: case Constants.MONITOREXIT: case Constants.NEW: case Constants.NOP: case Constants.RET: // this is the internal JSR return break; // Make sure we didn't miss anything default: throw new Error("instruction " + inst + " unsupported"); } } } } return result; }