All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.wala.ipa.summaries.XMLMethodSummaryReader Maven / Gradle / Ivy

/*
 * Copyright (c) 2002 - 2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.ipa.summaries;

import static com.ibm.wala.types.TypeName.ArrayMask;
import static com.ibm.wala.types.TypeName.ElementBits;
import static com.ibm.wala.types.TypeName.PrimitiveMask;

import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.Language;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.core.util.strings.Atom;
import com.ibm.wala.core.util.warnings.Warning;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.shrike.shrikeBT.BytecodeConstants;
import com.ibm.wala.shrike.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.ConstantValue;
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.ssa.SSANewInstruction;
import com.ibm.wala.ssa.SSAPutInstruction;
import com.ibm.wala.ssa.SSAReturnInstruction;
import com.ibm.wala.ssa.SSAThrowInstruction;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/** This class reads method summaries from an XML Stream. */
public class XMLMethodSummaryReader implements BytecodeConstants {

  static final boolean DEBUG = false;

  /** Governing analysis scope */
  private final AnalysisScope scope;

  /** Method summaries collected for methods */
  private final HashMap summaries = HashMapFactory.make();

  /** Set of TypeReferences that are marked as "allocatable" */
  private final HashSet allocatable = HashSetFactory.make();

  /** Set of Atoms that represent packages that can be ignored */
  private final HashSet ignoredPackages = HashSetFactory.make();

  //
  // Define XML element names
  //
  private static final int E_CLASSLOADER = 0;

  private static final int E_METHOD = 1;

  private static final int E_CLASS = 2;

  private static final int E_PACKAGE = 3;

  private static final int E_CALL = 4;

  private static final int E_NEW = 5;

  private static final int E_POISON = 6;

  private static final int E_SUMMARY_SPEC = 7;

  private static final int E_RETURN = 8;

  private static final int E_PUTSTATIC = 9;

  private static final int E_AASTORE = 10;

  private static final int E_PUTFIELD = 11;

  private static final int E_GETFIELD = 12;

  private static final int E_ATHROW = 13;

  private static final int E_CONSTANT = 14;

  private static final int E_AALOAD = 15;

  private static final Map elementMap = HashMapFactory.make(14);

  static {
    elementMap.put("classloader", E_CLASSLOADER);
    elementMap.put("method", E_METHOD);
    elementMap.put("class", E_CLASS);
    elementMap.put("package", E_PACKAGE);
    elementMap.put("call", E_CALL);
    elementMap.put("new", E_NEW);
    elementMap.put("poison", E_POISON);
    elementMap.put("summary-spec", E_SUMMARY_SPEC);
    elementMap.put("return", E_RETURN);
    elementMap.put("putstatic", E_PUTSTATIC);
    elementMap.put("aastore", E_AASTORE);
    elementMap.put("putfield", E_PUTFIELD);
    elementMap.put("getfield", E_GETFIELD);
    elementMap.put("throw", E_ATHROW);
    elementMap.put("constant", E_CONSTANT);
    elementMap.put("aaload", E_AALOAD);
  }

  //
  // Define XML attribute names
  //
  private static final String A_NAME = "name";

  private static final String A_TYPE = "type";

  private static final String A_CLASS = "class";

  private static final String A_SIZE = "size";

  private static final String A_DESCRIPTOR = "descriptor";

  private static final String A_REASON = "reason";

  private static final String A_LEVEL = "level";

  private static final String A_WILDCARD = "*";

  private static final String A_DEF = "def";

  private static final String A_STATIC = "static";

  private static final String A_VALUE = "value";

  private static final String A_FIELD = "field";

  private static final String A_FIELD_TYPE = "fieldType";

  private static final String A_ARG = "arg";

  private static final String A_ALLOCATABLE = "allocatable";

  private static final String A_REF = "ref";

  private static final String A_INDEX = "index";

  private static final String A_IGNORE = "ignore";

  private static final String A_FACTORY = "factory";

  private static final String A_NUM_ARGS = "numArgs";

  private static final String A_PARAM_NAMES = "paramNames";

  private static final String V_NULL = "null";

  private static final String V_TRUE = "true";

  public XMLMethodSummaryReader(InputStream xmlFile, AnalysisScope scope) {
    super();
    if (xmlFile == null) {
      throw new IllegalArgumentException("null xmlFile");
    }
    if (scope == null) {
      throw new IllegalArgumentException("null scope");
    }
    this.scope = scope;
    try {
      readXML(xmlFile);
    } catch (Exception e) {
      throw new Error("bad xml file", e);
    }
  }

  private void readXML(InputStream xml)
      throws SAXException, IOException, ParserConfigurationException {
    SAXHandler handler = new SAXHandler();

    assert xml != null : "Null xml stream";
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser parser = factory.newSAXParser();
    parser.parse(new InputSource(xml), handler);
  }

  /**
   * @return Method summaries collected for methods. Mapping Object -> MethodSummary where Object
   *     is either a
   *     
    *
  • MethodReference *
  • TypeReference *
  • Atom (package name) *
*/ public Map getSummaries() { return summaries; } /** * @return Set of TypeReferences marked "allocatable" */ public Set getAllocatableClasses() { return allocatable; } /** * @return Set of Atoms representing ignorable packages */ public Set getIgnoredPackages() { return ignoredPackages; } /** * @author sfink *

SAX parser logic for XML method summaries */ private class SAXHandler extends DefaultHandler { /** The class loader reference for the element being processed */ private ClassLoaderReference governingLoader = null; /** The method summary for the element being processed */ private MethodSummary governingMethod = null; /** The declaring class for the element begin processed */ private TypeReference governingClass = null; /** The package for the element being processed */ private Atom governingPackage = null; /** The next available local number for the method being processed */ private int nextLocal = -1; /** A mapping from String (variable name) -> Integer (local number) */ private Map symbolTable = null; /** * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, * java.lang.String, org.xml.sax.Attributes) */ @Override public void startElement(String uri, String name, String qName, Attributes atts) { Integer element = elementMap.get(qName); if (element == null) { Assertions.UNREACHABLE("Invalid element: " + qName); } switch (element) { case E_CLASSLOADER: { String clName = atts.getValue(A_NAME); governingLoader = classLoaderName2Ref(clName); } break; case E_METHOD: String mname = atts.getValue(A_NAME); if (mname.equals(A_WILDCARD)) { Assertions.UNREACHABLE("Wildcards not currently implemented."); } else { startMethod(atts); } break; case E_CLASS: String cname = atts.getValue(A_NAME); if (cname.equals(A_WILDCARD)) { Assertions.UNREACHABLE("Wildcards not currently implemented"); } else { startClass(cname, atts); } break; case E_PACKAGE: governingPackage = Atom.findOrCreateUnicodeAtom(atts.getValue(A_NAME)); String ignore = atts.getValue(A_IGNORE); if (ignore != null && ignore.equals(V_TRUE)) { ignoredPackages.add(governingPackage); } break; case E_CALL: processCallSite(atts); break; case E_NEW: processAllocation(atts); break; case E_PUTSTATIC: processPutStatic(atts); break; case E_PUTFIELD: processPutField(atts); break; case E_GETFIELD: processGetField(atts); break; case E_ATHROW: processAthrow(atts); break; case E_AASTORE: processAastore(atts); break; case E_AALOAD: processAaload(atts); break; case E_RETURN: processReturn(atts); break; case E_POISON: processPoison(atts); break; case E_CONSTANT: processConstant(atts); break; case E_SUMMARY_SPEC: break; default: Assertions.UNREACHABLE("Unexpected element: " + name); break; } } private void startClass(String cname, Attributes atts) { String clName = governingPackage == null ? 'L' + cname : "L" + governingPackage + '/' + cname; governingClass = className2Ref(clName); String allocString = atts.getValue(A_ALLOCATABLE); if (allocString != null) { Assertions.productionAssertion(allocString.equals("true")); allocatable.add(governingClass); } } /** * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, * java.lang.String) */ @Override public void endElement(String uri, String name, String qName) { Integer element = elementMap.get(qName); if (element == null) { Assertions.UNREACHABLE("Invalid element: " + name); } switch (element) { case E_CLASSLOADER: governingLoader = null; break; case E_METHOD: if (governingMethod != null) { checkReturnValue(governingMethod); } governingMethod = null; symbolTable = null; break; case E_CLASS: governingClass = null; break; case E_PACKAGE: governingPackage = null; break; case E_CALL: case E_GETFIELD: case E_NEW: case E_POISON: case E_PUTSTATIC: case E_PUTFIELD: case E_AALOAD: case E_AASTORE: case E_ATHROW: case E_SUMMARY_SPEC: case E_RETURN: case E_CONSTANT: break; default: Assertions.UNREACHABLE("Unexpected element: " + name); break; } } /** * If a method is declared to return a value, be sure the method summary includes a return * statement. Throw an assertion if not. */ private void checkReturnValue(MethodSummary governingMethod) { Assertions.productionAssertion(governingMethod != null); Assertions.productionAssertion(governingMethod.getReturnType() != null); if (governingMethod.getReturnType().isReferenceType()) { SSAInstruction[] statements = governingMethod.getStatements(); for (SSAInstruction statement : statements) { if (statement instanceof SSAReturnInstruction) { return; } } Assertions.UNREACHABLE( "Method summary " + governingMethod + " must have a return statement."); } } /** Process an element indicating a call instruction */ private void processCallSite(Attributes atts) { String typeString = atts.getValue(A_TYPE); String nameString = atts.getValue(A_NAME); String classString = atts.getValue(A_CLASS); String descString = atts.getValue(A_DESCRIPTOR); TypeReference type = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(classString)); Atom nm = Atom.findOrCreateAsciiAtom(nameString); Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); Descriptor D = Descriptor.findOrCreateUTF8(lang, descString); MethodReference ref = MethodReference.findOrCreate(type, nm, D); CallSiteReference site = null; int nParams = ref.getNumberOfParameters(); switch (typeString) { case "virtual": site = CallSiteReference.make( governingMethod.getNumberOfStatements(), ref, IInvokeInstruction.Dispatch.VIRTUAL); nParams++; break; case "special": site = CallSiteReference.make( governingMethod.getNumberOfStatements(), ref, IInvokeInstruction.Dispatch.SPECIAL); nParams++; break; case "interface": site = CallSiteReference.make( governingMethod.getNumberOfStatements(), ref, IInvokeInstruction.Dispatch.INTERFACE); nParams++; break; case "static": site = CallSiteReference.make( governingMethod.getNumberOfStatements(), ref, IInvokeInstruction.Dispatch.STATIC); break; default: Assertions.UNREACHABLE("Invalid call type " + typeString); break; } String paramCount = atts.getValue(A_NUM_ARGS); if (paramCount != null) { nParams = Integer.parseInt(paramCount); } int[] params = new int[nParams]; for (int i = 0; i < params.length; i++) { String argString = atts.getValue(A_ARG + i); Assertions.productionAssertion( argString != null, "unspecified arg in method " + governingMethod + ' ' + site); Integer valueNumber = symbolTable.get(argString); if (valueNumber == null) { if (argString.equals(V_NULL)) { valueNumber = getValueNumberForNull(); } else { valueNumber = Integer.parseInt(argString); } } params[i] = valueNumber; } // allocate local for exceptions int exceptionValue = nextLocal++; // register the local variable defined by this call, if appropriate String defVar = atts.getValue(A_DEF); if (defVar != null) { if (symbolTable.containsKey(defVar)) { Assertions.UNREACHABLE("Cannot def variable twice: " + defVar + " in " + governingMethod); } int defNum = nextLocal; symbolTable.put(defVar, nextLocal++); governingMethod.addStatement( insts.InvokeInstruction( governingMethod.getNumberOfStatements(), defNum, params, exceptionValue, site, null)); } else { // ignore return value, if any governingMethod.addStatement( insts.InvokeInstruction( governingMethod.getNumberOfStatements(), params, exceptionValue, site, null)); } } /** Process an element indicating a new allocation site. */ private void processAllocation(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); // deduce the concrete type allocated String classString = atts.getValue(A_CLASS); final TypeReference type = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(classString)); // register the local variable defined by this allocation String defVar = atts.getValue(A_DEF); if (symbolTable.containsKey(defVar)) { Assertions.UNREACHABLE("Cannot def variable twice: " + defVar + " in " + governingMethod); } if (defVar == null) { // the method summary ignores the def'ed variable. // just allocate a temporary defVar = "L" + nextLocal; } int defNum = nextLocal; symbolTable.put(defVar, nextLocal++); // create the allocation statement and add it to the method summary NewSiteReference ref = NewSiteReference.make(governingMethod.getNumberOfStatements(), type); final SSANewInstruction a; if (type.isArrayType()) { String size = atts.getValue(A_SIZE); Assertions.productionAssertion(size != null); Integer sNumber = symbolTable.get(size); Assertions.productionAssertion(sNumber != null); Assertions.productionAssertion( // array of objects type.getDerivedMask() == ArrayMask || // array of primitives type.getDerivedMask() == ((ArrayMask << ElementBits) | PrimitiveMask)); a = insts.NewInstruction( governingMethod.getNumberOfStatements(), defNum, ref, new int[] {sNumber}); } else { a = insts.NewInstruction(governingMethod.getNumberOfStatements(), defNum, ref); } governingMethod.addStatement(a); } /** Process an element indicating an Athrow */ private void processAthrow(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); // get the value thrown String V = atts.getValue(A_VALUE); if (V == null) { Assertions.UNREACHABLE("Must specify value for putfield " + governingMethod); } Integer valueNumber = symbolTable.get(V); if (valueNumber == null) { Assertions.UNREACHABLE("Cannot lookup value: " + V); } SSAThrowInstruction T = insts.ThrowInstruction(governingMethod.getNumberOfStatements(), valueNumber); governingMethod.addStatement(T); } /** Process an element indicating a putfield. */ private void processGetField(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); // deduce the field written String classString = atts.getValue(A_CLASS); TypeReference type = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(classString)); String fieldString = atts.getValue(A_FIELD); Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString); String ftString = atts.getValue(A_FIELD_TYPE); TypeReference fieldType = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(ftString)); FieldReference field = FieldReference.findOrCreate(type, fieldName, fieldType); // get the value def'fed String defVar = atts.getValue(A_DEF); if (symbolTable.containsKey(defVar)) { Assertions.UNREACHABLE("Cannot def variable twice: " + defVar + " in " + governingMethod); } if (defVar == null) { Assertions.UNREACHABLE("Must specify def for getfield " + governingMethod); } int defNum = nextLocal; symbolTable.put(defVar, nextLocal++); // get the ref read from String R = atts.getValue(A_REF); if (R == null) { Assertions.UNREACHABLE("Must specify ref for getfield " + governingMethod); } Integer refNumber = symbolTable.get(R); if (refNumber == null) { Assertions.UNREACHABLE("Cannot lookup ref: " + R); } SSAGetInstruction G = insts.GetInstruction(governingMethod.getNumberOfStatements(), defNum, refNumber, field); governingMethod.addStatement(G); } /** Process an element indicating a putfield. */ private void processPutField(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); // deduce the field written String classString = atts.getValue(A_CLASS); TypeReference type = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(classString)); String fieldString = atts.getValue(A_FIELD); Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString); String ftString = atts.getValue(A_FIELD_TYPE); TypeReference fieldType = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(ftString)); FieldReference field = FieldReference.findOrCreate(type, fieldName, fieldType); // get the value stored String V = atts.getValue(A_VALUE); if (V == null) { Assertions.UNREACHABLE("Must specify value for putfield " + governingMethod); } Integer valueNumber = symbolTable.containsKey(V) ? symbolTable.get(V) : Integer.parseInt(V); // get the ref stored to String R = atts.getValue(A_REF); if (R == null) { Assertions.UNREACHABLE("Must specify ref for putfield " + governingMethod); } Integer refNumber = symbolTable.get(R); if (refNumber == null) { Assertions.UNREACHABLE("Cannot lookup ref: " + R); } SSAPutInstruction P = insts.PutInstruction( governingMethod.getNumberOfStatements(), refNumber, valueNumber, field); governingMethod.addStatement(P); } /** Process an element indicating a putstatic. */ private void processPutStatic(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); // deduce the field written String classString = atts.getValue(A_CLASS); TypeReference type = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(classString)); String fieldString = atts.getValue(A_FIELD); Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString); String ftString = atts.getValue(A_FIELD_TYPE); TypeReference fieldType = TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(ftString)); FieldReference field = FieldReference.findOrCreate(type, fieldName, fieldType); // get the value stored String V = atts.getValue(A_VALUE); if (V == null) { Assertions.UNREACHABLE("Must specify value for putstatic " + governingMethod); } Integer valueNumber = symbolTable.get(V); if (valueNumber == null) { Assertions.UNREACHABLE("Cannot lookup value: " + V); } SSAPutInstruction P = insts.PutInstruction(governingMethod.getNumberOfStatements(), valueNumber, field); governingMethod.addStatement(P); } /** Process an element indicating an Aastore */ private void processAastore(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); String R = atts.getValue(A_REF); if (R == null) { Assertions.UNREACHABLE("Must specify ref for aastore " + governingMethod); } Integer refNumber = symbolTable.get(R); if (refNumber == null) { Assertions.UNREACHABLE("Cannot lookup value: " + R); } // N.B: we currently ignore the index String I = atts.getValue(A_INDEX); if (I == null) { Assertions.UNREACHABLE("Must specify index for aastore " + governingMethod); } String V = atts.getValue(A_VALUE); if (V == null) { Assertions.UNREACHABLE("Must specify value for aastore " + governingMethod); } /* BEGIN Custom change: expect type information in array-store instructions */ String strType = atts.getValue(A_TYPE); TypeReference type; if (strType == null) { type = TypeReference.JavaLangObject; } else { type = TypeReference.findOrCreate(governingLoader, strType); } /* END Custom change: get type information in array-store instructions */ Integer valueNumber = symbolTable.get(V); if (valueNumber == null) { Assertions.UNREACHABLE("Cannot lookup value: " + V); } /* BEGIN Custom change: expect type information in array-store instructions */ SSAArrayStoreInstruction S = insts.ArrayStoreInstruction( governingMethod.getNumberOfStatements(), refNumber, 0, valueNumber, type); /* END Custom change: get type information in array-store instructions */ governingMethod.addStatement(S); } /** Process an element indicating an Aaload */ private void processAaload(Attributes atts) { // Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); String R = atts.getValue(A_REF); if (R == null) { Assertions.UNREACHABLE("Must specify ref for aaload " + governingMethod); } Integer refNumber = symbolTable.get(R); if (refNumber == null) { Assertions.UNREACHABLE("Cannot lookup value: " + R); } String I = atts.getValue(A_INDEX); if (I == null) { Assertions.UNREACHABLE("Must specify index for aaload " + governingMethod); } Integer idxNumber = symbolTable.get(I); if (idxNumber == null) { Assertions.UNREACHABLE("Cannot lookup value: " + I); } String strType = atts.getValue(A_TYPE); TypeReference type; if (strType == null) { type = TypeReference.JavaLangObject; } else { type = TypeReference.findOrCreate(governingLoader, strType); } // get the value def'fed String defVar = atts.getValue(A_DEF); if (symbolTable.containsKey(defVar)) { Assertions.UNREACHABLE("Cannot def variable twice: " + defVar + " in " + governingMethod); } if (defVar == null) { Assertions.UNREACHABLE("Must specify def for getfield " + governingMethod); } int defNum = nextLocal; symbolTable.put(defVar, nextLocal++); SSAArrayLoadInstruction S = insts.ArrayLoadInstruction( governingMethod.getNumberOfStatements(), defNum, refNumber, idxNumber, type); governingMethod.addStatement(S); } /** Process an element indicating a return statement. */ private void processReturn(Attributes atts) { Language lang = scope.getLanguage(governingLoader.getLanguage()); SSAInstructionFactory insts = lang.instructionFactory(); if (governingMethod.getReturnType() != null) { String retV = atts.getValue(A_VALUE); if (retV == null) { SSAReturnInstruction R = insts.ReturnInstruction(governingMethod.getNumberOfStatements()); governingMethod.addStatement(R); } else { Integer valueNumber = symbolTable.get(retV); if (valueNumber == null) { if (!retV.equals(V_NULL)) { Assertions.UNREACHABLE("Cannot return value with no def: " + retV); } else { valueNumber = getValueNumberForNull(); } } boolean isPrimitive = governingMethod.getReturnType().isPrimitiveType(); SSAReturnInstruction R = insts.ReturnInstruction( governingMethod.getNumberOfStatements(), valueNumber, isPrimitive); governingMethod.addStatement(R); } } } private Integer getValueNumberForNull() { Integer valueNumber; valueNumber = symbolTable.get(V_NULL); if (valueNumber == null) { valueNumber = nextLocal++; symbolTable.put(V_NULL, valueNumber); } return valueNumber; } private void processConstant(Attributes atts) { String var = atts.getValue(A_NAME); if (var == null) Assertions.UNREACHABLE("Must give name for constant"); Integer valueNumber = nextLocal++; symbolTable.put(var, valueNumber); String typeString = atts.getValue(A_TYPE); String valueString = atts.getValue(A_VALUE); governingMethod.addConstant( valueNumber, typeString.equals("int") ? new ConstantValue(Integer.valueOf(valueString)) : typeString.equals("long") ? new ConstantValue(Long.valueOf(valueString)) : typeString.equals("short") ? new ConstantValue(Short.valueOf(valueString)) : typeString.equals("float") ? new ConstantValue(Float.valueOf(valueString)) : typeString.equals("double") ? new ConstantValue(Double.valueOf(valueString)) : null); } /** Process an element which indicates this method is "poison" */ private void processPoison(Attributes atts) { String reason = atts.getValue(A_REASON); governingMethod.addPoison(reason); String level = atts.getValue(A_LEVEL); switch (level) { case "severe": governingMethod.setPoisonLevel(Warning.SEVERE); break; case "moderate": governingMethod.setPoisonLevel(Warning.MODERATE); break; case "mild": governingMethod.setPoisonLevel(Warning.MILD); break; default: Assertions.UNREACHABLE("Unexpected level: " + level); break; } } /** * Begin processing of a method. 1. Set the governing method. 2. Initialize the nextLocal * variable */ private void startMethod(Attributes atts) { String methodName = atts.getValue(A_NAME); Atom mName = Atom.findOrCreateUnicodeAtom(methodName); String descString = atts.getValue(A_DESCRIPTOR); Language lang = scope.getLanguage(governingLoader.getLanguage()); Descriptor D = Descriptor.findOrCreateUTF8(lang, descString); MethodReference ref = MethodReference.findOrCreate(governingClass, mName, D); boolean isStatic = false; String staticString = atts.getValue(A_STATIC); if (staticString != null) { switch (staticString) { case "true": isStatic = true; break; case "false": isStatic = false; break; default: Assertions.UNREACHABLE("Invalid attribute value " + A_STATIC + ": " + staticString); break; } } // This is somewhat gross, but it is to deal with the fact that // some non-Java languages have notions of arguments that do not // map nicely to descriptors. int nParams; String specifiedArgs = atts.getValue(A_NUM_ARGS); if (specifiedArgs == null) { nParams = ref.getNumberOfParameters(); if (!isStatic) { nParams += 1; } } else { nParams = Integer.parseInt(specifiedArgs); } governingMethod = new MethodSummary(ref, nParams); governingMethod.setStatic(isStatic); if (DEBUG) { System.err.println(("Register method summary: " + ref)); } summaries.put(ref, governingMethod); String factoryString = atts.getValue(A_FACTORY); if (factoryString != null) { switch (factoryString) { case "true": governingMethod.setFactory(true); break; case "false": governingMethod.setFactory(false); break; default: Assertions.UNREACHABLE("Invalid attribute value " + A_FACTORY + ": " + factoryString); break; } } // note that symbol tables reserve v0 for "unknown", so v1 gets assigned // to the first parameter "arg0", and so forth. nextLocal = nParams + 1; symbolTable = HashMapFactory.make(5); // create symbols for the parameters for (int i = 0; i < nParams; i++) { symbolTable.put("arg" + i, i + 1); } int pn = 1; String paramDescString = atts.getValue(A_PARAM_NAMES); if (paramDescString != null) { StringTokenizer paramNames = new StringTokenizer(paramDescString); while (paramNames.hasMoreTokens()) { symbolTable.put(paramNames.nextToken(), pn++); } } Map nameTable = HashMapFactory.make(); for (Map.Entry x : symbolTable.entrySet()) { if (!x.getKey().startsWith("arg")) { nameTable.put(x.getValue(), Atom.findOrCreateUnicodeAtom(x.getKey())); } } governingMethod.setValueNames(nameTable); } /** * Method classLoaderName2Ref. * * @return ClassLoaderReference */ private ClassLoaderReference classLoaderName2Ref(String clName) { return scope.getLoader(Atom.findOrCreateUnicodeAtom(clName)); } /** * Method classLoaderName2Ref. * * @return ClassLoaderReference */ private TypeReference className2Ref(String clName) { return TypeReference.findOrCreate(governingLoader, TypeName.string2TypeName(clName)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy