final LocalVariableGen getLocal(MethodGen m, LocalVariableInstruction curr, int pos) { int localNr = curr.getIndex(); LocalVariableGen[] lt = getLocalTable(m); for (int i = 0; i < lt.length; i++) { // Watch out. The first initialization seems not to be included in // the range given in the local variable table! if (localNr == lt[i].getIndex()) { // System.err.println("Looking for local " + localNr // + " on position " + pos); // System.err.println("found one with range " // + lt[i].getStart().getPrev().getPosition() + ", " // + lt[i].getEnd().getPosition()); if (pos >= lt[i].getStart().getPrev().getPosition() && pos < (lt[i].getEnd().getPosition())) { return lt[i]; } } } return null; }
private void getIndicesStores(InstructionHandle start, InstructionHandle end, ArrayList<LocalVariableGen> resultIndices) { for (InstructionHandle current = start.getNext() ;current != end.getNext(); current = current.getNext()) { try { LocalVariableGen l = getIndexStore(current); if (! resultIndices.contains(l)) { resultIndices.add(l); } for (LocalVariableGen ll : this.getLocalVariables()) { if (ll != l && l.getIndex() == ll.getIndex() && l.getName().equals(ll.getName())) { if (! resultIndices.contains(ll)) { resultIndices.add(ll); } } } } catch (ClassCastException e) { // no problem, just not a store } } }
private SpawnableCall getSpawnableCallWithException(InstructionHandle invokeInstruction, ArrayList<CodeExceptionGen> exceptionHandlers) { ArrayList<LocalVariableGen> resultIndices = new ArrayList<LocalVariableGen>(); for (CodeExceptionGen exceptionHandler : exceptionHandlers) { InstructionHandle start = exceptionHandler.getHandlerPC(); InstructionHandle end = getEndExceptionHandler(exceptionHandler); getIndicesStores(start, end, resultIndices); } LocalVariableGen[] dummy = new LocalVariableGen[resultIndices.size()]; return new SpawnableCall(invokeInstruction, getObjectReferenceLoadInstruction(invokeInstruction), resultIndices.toArray(dummy)); }
/** Tests whether this spawnable call stores in variables with index index. * * @param index The index which is tested. * @return true if the spawnable call stores in a variable with index * index; false otherwise. */ public boolean storesIn(int index, InstructionHandle ih) { int insNo = ih.getPosition(); for (LocalVariableGen g : indicesStores) { if (g.getIndex() == index) { InstructionHandle end = g.getEnd(); InstructionHandle start = g.getStart(); if (start.getPrev() != null) { start = start.getPrev(); } if (insNo >= start.getPosition() && insNo <= end.getPosition()) { return true; } } } return false; }
/** Returns a string representation. */ public String toString() { StringBuilder sb = new StringBuilder(); sb.append(invokeInstruction.toString()); sb.append(", resultIndices: "); if (indicesStores == null) { sb.append("(none), exceptions are not handled"); } else { for (LocalVariableGen i : indicesStores) { sb.append(i); sb.append(", "); } sb.delete(sb.length()-2, sb.length()); } return sb.toString(); }
/** Returns the end of an exception handler. * * @param codeException The codeException which end is returned. * @return The instructionHandle that is the end of the exception handler. */ public InstructionHandle getEndExceptionHandler(CodeExceptionGen codeException) { LocalVariableGen[] localVars = getLocalVariables(); InstructionHandle startHandler = codeException.getHandlerPC(); for (LocalVariableGen localVar : localVars) { InstructionHandle startScope = localVar.getStart(); InstructionHandle endScope = localVar.getEnd(); if (startScope == startHandler || startScope == startHandler.getNext() || startScope == startHandler.getNext().getNext() && localVar.getType().equals(codeException.getCatchType())) return endScope.getPrev(); } throw new Error("no end exceptionhandler..."); }
boolean noAliasesLoadWithIndexBefore(InstructionHandle ih, LocalVariableGen lg) { for (InstructionContext ic : instructions) { InstructionHandle current = ic.getInstruction(); if (current.equals(ih)) { break; } LocalVariableGen l = methodGen.findLocalVar(current, lg.getIndex(), false); if (l == lg && methodGen.instructionLoadsTo(current, lg.getIndex())) { // OK, there is a load, but maybe it does not create an alias? if (! methodGen.isUsedForArrayLoad(current) && ! methodGen.isUsedForArrayLength(current) && ! methodGen.isUsedForArrayStore(current) && ! methodGen.isUsedForPutField(current) && ! methodGen.isUsedForGetField(current)) { return false; } } } return true; }
private boolean containsLoadWithIndexAfter(InstructionHandle ih, boolean ignoreInstructions, LocalVariableGen lg) { InstructionHandle start = lg.getStart(); InstructionHandle prev = start.getPrev(); // The initial store is not included in the start/end range, so include the previous // instruction if it exists. InstructionHandle end = lg.getEnd(); int startPosition = prev != null ? prev.getPosition() : start.getPosition(); int endPosition = end.getPosition(); for (InstructionContext ic : instructions) { InstructionHandle current = ic.getInstruction(); if (ignoreInstructions) { ignoreInstructions = !current.equals(ih); } else if (current.getPosition() >= startPosition && current.getPosition() <= endPosition && methodGen.instructionLoadsTo(current, lg.getIndex())) { return true; } } return false; }
private boolean noAliasesLoadWithIndex(InstructionHandle ih, boolean ignoreInstructions, LocalVariableGen lg) { InstructionHandle start = lg.getStart(); InstructionHandle prev = start.getPrev(); // The initial store is not included in the start/end range, so include the previous // instruction if it exists. InstructionHandle end = lg.getEnd(); int startPosition = prev != null ? prev.getPosition() : start.getPosition(); int endPosition = end.getPosition(); for (InstructionContext ic : instructions) { InstructionHandle current = ic.getInstruction(); if (ignoreInstructions) { ignoreInstructions = !current.equals(ih); } else if (current.getPosition() >= startPosition && current.getPosition() <= endPosition && methodGen.instructionLoadsTo(current, lg.getIndex())) { // OK, there is a load, but maybe it does not create an alias? if (! methodGen.isUsedForArrayLoad(current) && ! methodGen.isUsedForArrayLength(current) && ! methodGen.isUsedForArrayStore(current) && ! methodGen.isUsedForPutField(current) && ! methodGen.isUsedForGetField(current)) { return false; } } } return true; }
private void fillStoreLoadPaths(ArrayList<StoreLoadPath> storeLoadPaths, Path path, SpawnableCall spawnableCall) { LocalVariableGen[] indicesStores = spawnableCall.getIndicesStores(); InstructionHandle invokeInstruction = spawnableCall.getInvokeInstruction(); if (!spawnableCall.exceptionsHandled()) { return; } else { StoreLoadPath storeLoadPath = null; try { storeLoadPath = new StoreLoadPath(invokeInstruction, path, indicesStores); } catch (NeverReadException e) { } if (storeLoadPath != null && !storeLoadPaths.contains(storeLoadPath)) { storeLoadPaths.add(storeLoadPath); } } }
private int getIndexEarliestBasicBlock(LocalVariableGen[] localVariableIndices, InstructionHandle storeInstruction) throws NeverReadException { for (int i = 0; i < size(); i++) { LoadAwareBasicBlock basicBlock = new LoadAwareBasicBlock(get(i)); if (i == 0) { if (containsLoadWithIndexAfter(basicBlock, localVariableIndices, storeInstruction)) { return i; } } else { if (containsLoadWithIndex(basicBlock, localVariableIndices)) { return i; } } } throw new NeverReadException(); }
public String toString(MethodGen method) { String[] variables = new String[method.getLocalVariables().length]; LocalVariableGen[] variablesGen = method.getLocalVariables(); for(int i=0; i<variablesGen.length ;i++) { variables[i] = variablesGen[i].getName(); } return toString(variables); }
static InstructionHandle getEndOfCatchBlock(MethodGen m, CodeExceptionGen catchBlock) { if (catchBlock.getCatchType() == null) { // finally clause, no local variable! return null; } LocalVariableGen[] lt = m.getLocalVariables(); InstructionHandle handler = catchBlock.getHandlerPC(); for (int i = 0; i < lt.length; i++) { InstructionHandle start = lt[i].getStart(); InstructionHandle end = lt[i].getEnd(); // dangerous, javac is one instruction further... if ((start == handler || start == handler.getNext() || start == handler .getNext().getNext()) && lt[i].getType().equals(catchBlock.getCatchType())) { // System.out.println("found range of catch block: " // + handler + " - " + end); return end.getPrev(); } } System.err .println("Could not find end of catch block, did you compile " + "with the '-g' option?"); System.exit(1); return null; }
private final LocalVariableGen[] getLocalTable(MethodGen m) { LocalVariableGen[] lt = m.getLocalVariables(); if (lt == null) { System.err.println("Could not get local variable table, did you " + "compile with the '-g' option?"); System.exit(1); } return lt; }
String getLocalName(MethodGen m, LocalVariableInstruction curr, int pos) { LocalVariableGen a = getLocal(m, curr, pos); if (a == null) { return null; } return a.getName(); }
Type getLocalType(MethodGen m, LocalVariableInstruction curr, int pos) { LocalVariableGen a = getLocal(m, curr, pos); if (a == null) { return null; } return a.getType(); }
private LocalVariableGen[] findIndexStore(InstructionHandle spawnableMethodInvoke) throws ResultNotStored { InstructionHandle[] stackConsumers = findInstructionConsumers(spawnableMethodInvoke); if (stackConsumers.length != 1) { /* throw new Error("Uncovered situation, invoke instruction's " + "result is consumed by multiple instructions. " + "Is there controlflow right after the spawnable invoke???"); */ throw new ResultNotStored(); // I think this is a better solution. Controlflow right after the // invoke is something that is hard to analyze and rare. Better to // just mark it as a result that isn't stored. } try { ArrayList<LocalVariableGen> resultIndices = new ArrayList<LocalVariableGen>(); LocalVariableGen l = getIndexStore(stackConsumers[0]); resultIndices.add(l); for (LocalVariableGen ll : this.getLocalVariables()) { if (ll != l && l.getIndex() == ll.getIndex() && l.getName().equals(ll.getName())) { if (! resultIndices.contains(ll)) { resultIndices.add(ll); } } } return resultIndices.toArray(new LocalVariableGen[resultIndices.size()]); } catch (ClassCastException e) { throw new ResultNotStored(); } }
SpawnableCall(InstructionHandle invokeInstruction, InstructionHandle objectReference, LocalVariableGen[] indicesStores) { this.invokeInstruction = invokeInstruction; this.objectReference = objectReference; this.indicesStores = indicesStores; this.type = Type.NORMAL; }
boolean containsLoadWithIndexBefore(InstructionHandle ih, LocalVariableGen lg) { for (InstructionContext ic : instructions) { InstructionHandle current = ic.getInstruction(); if (current.equals(ih)) { break; } LocalVariableGen l = methodGen.findLocalVar(current, lg.getIndex(), false); if (l == lg && methodGen.instructionLoadsTo(current, lg.getIndex())) { return true; } } return false; }
StoreLoadPath(InstructionHandle storeInstruction, BasicBlock block, LocalVariableGen[] localVariableIndices) { super(new Path()); add(block); this.storeInstruction = storeInstruction; this.localVariableIndices = localVariableIndices; aliasProblem = true; }
private boolean containsLoadWithIndex(LoadAwareBasicBlock basicBlock, LocalVariableGen[] localVariableIndices) { for (LocalVariableGen localVariableIndex : localVariableIndices) { if (basicBlock.containsLoadWithIndex(localVariableIndex)) { return true; } } return false; }
private boolean containsLoadWithIndexAfter(LoadAwareBasicBlock basicBlock, LocalVariableGen[] localVariableIndices, InstructionHandle instruction) { for (LocalVariableGen localVariableIndex : localVariableIndices) { if (basicBlock.containsLoadWithIndexAfter(instruction, localVariableIndex)) { return true; } } return false; }
private int findSlot( int slot, Map<Integer,Integer> map, String prefix, Type type ) { Integer islot = Integer.valueOf(slot); if ( map.containsKey(islot) ) return ((Integer)map.get(islot)).intValue(); String name = prefix+slot; LocalVariableGen local = mg.addLocalVariable(name, type, null, null); int index = local.getIndex(); map.put(islot, Integer.valueOf(index)); localVarGenBySlot.put(islot, local); return index; }
public void setVarStartEnd(int slot, int start_pc, int end_pc, String name) { Integer islot = Integer.valueOf(slot); if (localVarGenBySlot.containsKey(islot)) { name = name.replaceAll("[^a-zA-Z0-9]", "_"); LocalVariableGen l = (LocalVariableGen)localVarGenBySlot.get(islot); l.setEnd(lastInstrHandles[end_pc-1]); if (start_pc > 1) l.setStart(lastInstrHandles[start_pc-2]); l.setName(name); } }
private int findSlot( int slot, Map map, String prefix, Type type ) { Integer islot = Integer.valueOf(slot); if ( map.containsKey(islot) ) return ((Integer)map.get(islot)).intValue(); String name = prefix+slot; LocalVariableGen local = mg.addLocalVariable(name, type, null, null); int index = local.getIndex(); map.put(islot, Integer.valueOf(index)); localVarGenBySlot.put(islot, local); return index; }
protected boolean loadLocalVariable(Variable variable, InstructionList il) { if ( currentMethod == null ) throw new IllegalStateException(); for (LocalVariableGen lvg : currentMethod.getLocalVariables()) { if (lvg.getName().equals( variable.getName()) ) { il.append(new ALOAD(lvg.getIndex())); return true; } } return false; }
@Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); InstructionFactory ifact = scope.getInstructionFactory(); LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT); // Null initialization of the result il.append(InstructionConstants.ACONST_NULL); il.append(new ASTORE(lvg.getIndex())); generateWithNoVar(scope); il.append(new ASTORE(lvg.getIndex())); }
/** * A new IdcMetaclass object is created to wrap de * real metaclass providing additional functionality. * * <pre> * NEW IdcMetaclass * DUP * LDC <<model_name>> * LDC <<class_name>> * INVOKESPECIAL IdcMetaclass.<init> * ASTORE !!#variable!! * </pre> */ @Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); InstructionFactory ifact = scope.getInstructionFactory(); ConstantPoolGen cpg = scope.getConstantPool(); LocalVariableGen lvg = null; if ( getKind() == ReadMetaKind.METACLASS) { lvg = scope.newLocalVariable(this, DefaultTypes.IdcMetaclass); lvg.setStart(il.append(ifact.createNew(DefaultTypes.IdcMetaclass))); il.append(new DUP()); // il.append(new LDC(cpg.addString(getModel().getName()))); scope.generateGetTransformation(); scope.generateGetModel(getModel().getName()); // CommonGen.generateGetModel(getModel().getName(), il, ifact, scope); il.append(new LDC(cpg.addString(getClassName()))); il.append(ifact.createInvoke(DefaultTypes.IdcMetaclass.getClassName(), "<init>", Type.VOID, new Type[] { DefaultTypes.IdcTransformation, DefaultTypes.IModel, Type.STRING }, Constants.INVOKESPECIAL)); } else if ( getKind() == ReadMetaKind.THIS_TRANSFORMATION_OBJECT || getKind() == ReadMetaKind.THIS_TRANSFORMATION_METHOD_HANDLER ) { lvg = scope.newLocalVariable(this, DefaultTypes.IdcTransformation); lvg.setStart(il.append(InstructionConstants.NOP)); scope.generateGetTransformation(); } else if ( getKind() == ReadMetaKind.MODEL ){ lvg = scope.newLocalVariable(this, DefaultTypes.IModel); lvg.setStart(il.append(InstructionConstants.NOP)); scope.generateGetModel(getModel().getName()); } else { throw new IllegalArgumentException(); } il.append(new ASTORE(lvg.getIndex())); }
@Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT); // create element ModelStrategy strategy = Processor.getModelStrategy(this, scope.getTransformationContext()); strategy.genCreate(this, scope); // store result il.append(new ASTORE( lvg.getIndex() )); }
@Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); InstructionFactory ifact = scope.getInstructionFactory(); NewScopeResult closureClassScope = createClosureClass(scope); ClassGen closureClass = closureClassScope.cg; ClosureScope closureScope = (ClosureScope) closureClassScope.scope; scope.getTransformationContext().addExtraClass(closureClass.getJavaClass()); LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT); // Create the closure instance il.append(ifact.createNew(closureClass.getClassName())); il.append(new DUP()); scope.generateGetTransformation(); scope.generateGetModelManager(); il.append(ifact.createInvoke(closureClass.getClassName(), "<init>", Type.VOID, new Type[] { DefaultTypes.IdcTransformation, DefaultTypes.ModelManager }, Constants.INVOKESPECIAL)); //Type.VOID, new Type[] { DefaultTypes.ModelManager }, Constants.INVOKESPECIAL)); // This is a bit hard-wired because the OuterVariableSet // is computed as a result of creating the closureClass... OuterVariableSet outers = closureScope.getOuterVariables(); Set<Variable> o = outers.get(); for (Variable variable : o) { il.append(new DUP()); scope.loadVariable(variable, il); il.append(scope.getInstructionFactory().createPutField(closureClass.getClassName(), variable.getName(), Type.OBJECT)); } il.append(new ASTORE(lvg.getIndex())); }
@Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); InstructionFactory ifact = scope.getInstructionFactory(); ConstantPoolGen cpg = scope.getConstantPool(); String transformationName = this.getTransformationName(); String entryPointName = this.getEntryPointName(); LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT); // Probably this could be improved, but for the moment a transformation // object will provide a facility to instantiate another transformation // Create the new transformation // [This_Transformation, "TransformationName"] -> instantiateTransformation -> [Created_Transformation] scope.generateGetTransformation(); il.append(ifact.createConstant(transformationName)); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "instantiateTransformation", DefaultTypes.IdcTransformation, new Type[] { Type.STRING }, Constants.INVOKEVIRTUAL)); // There are two cases // // 1. Explicit invocation of a transformation rule if ( entryPointName != null ) { generateInvokeEntryPoint(scope, il, ifact, transformationName, entryPointName, lvg); } else { generateInvokeTransformation(scope, il, ifact, transformationName, lvg); } }
private void generateInvokeEntryPoint(GenScope scope, InstructionList il, InstructionFactory ifact, String transformationName, String entryPointName, LocalVariableGen lvg) { // Configure the transformation il.append(InstructionFactory.DUP); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "configure_", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL)); // TODO: Configure the models properly, not as I'm doing directly in instantiateTransformation directly // Put the params into the stack and invoke, but first check the type of the transformation object ObjectType transformationType = new ObjectType(transformationName); il.append(ifact.createCheckCast(transformationType)); // [Transformation, param1, ..., paramN] EList<Variable> params = this.getEntryPointParameters(); Type[] types = new Type[params.size()]; int i = 0; for (Variable variable : params) { scope.loadVariable(variable, il); types[i++] = Type.OBJECT; } il.append(ifact.createInvoke(transformationType.getClassName(), entryPointName, Type.OBJECT, types, Constants.INVOKEVIRTUAL)); il.append(new ASTORE( lvg.getIndex() )); }
private void generateInvokeTransformation(GenScope scope, InstructionList il, InstructionFactory ifact, String transformationName, LocalVariableGen lvg) { // Configure the invoked transformation: view filter if ( this.getInputViewFilter() != null ) { il.append(InstructionFactory.DUP); scope.loadVariable(this.getInputViewFilter(), il); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "configure_invocation_", Type.VOID, new Type[] { DefaultTypes.RunnableClosure }, Constants.INVOKEVIRTUAL)); } // Set the parent transformation il.append(InstructionFactory.DUP); scope.generateGetTransformation(); il.append(InstructionFactory.SWAP); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "setParentTransformation", Type.VOID, new Type[] { DefaultTypes.IdcTransformation }, Constants.INVOKEVIRTUAL)); // Configure the transformation il.append(InstructionFactory.DUP); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "configure_", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL)); // Start the transformation il.append(InstructionFactory.DUP); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "start_", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL)); il.append(InstructionFactory.ACONST_NULL); il.append(new ASTORE( lvg.getIndex() )); }
private void generateInvokeEntryPoint(GenScope scope, InstructionList il, InstructionFactory ifact, String transformationName, String entryPointName, LocalVariableGen lvg) { throw new UnsupportedOperationException(); // Not sure /* // Configure the transformation il.append(InstructionFactory.DUP); il.append(ifact.createInvoke(DefaultTypes.IdcTransformation.getClassName(), "configure_", Type.VOID, new Type[] { }, Constants.INVOKEVIRTUAL)); // TODO: Configure the models properly, not as I'm doing directly in instantiateTransformation directly // Put the params into the stack and invoke, but first check the type of the transformation object ObjectType transformationType = new ObjectType(transformationName); il.append(ifact.createCheckCast(transformationType)); // [Transformation, param1, ..., paramN] EList<Variable> params = this.getEntryPointParameters(); Type[] types = new Type[params.size()]; int i = 0; for (Variable variable : params) { scope.loadVariable(variable, il); types[i++] = Type.OBJECT; } il.append(ifact.createInvoke(transformationType.getClassName(), entryPointName, Type.OBJECT, types, Constants.INVOKEVIRTUAL)); il.append(new ASTORE( lvg.getIndex() )); */ }
@Override public void generate(GenScope scope) { InstructionList il = scope.getInstructionList(); // if (CompilerFlags.use_assign) { LocalVariableGen lvg = scope.newLocalVariable(this, Type.OBJECT); scope.loadVariable(rightVariable, il); il.append(new ASTORE(lvg.getIndex())); // } }
public LocalVariableGen findLocalVar(InstructionHandle ih, int index) { return findLocalVar(ih, index, true); }
boolean containsLoadWithIndex(LocalVariableGen lg) { return containsLoadWithIndexAfter(null, !IGNORE_FIRST_INSTRUCTIONS, lg); }
boolean noAliasesLoadWithIndex(LocalVariableGen lg) { return noAliasesLoadWithIndex(null, !IGNORE_FIRST_INSTRUCTIONS, lg); }