List of usage examples for org.objectweb.asm Opcodes ASTORE
int ASTORE
To view the source code for org.objectweb.asm Opcodes ASTORE.
Click Source Link
From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.Inlining.java
License:Open Source License
public static List<Insn> convertInsns(MethodInsn mi, List<Insn> insns, int[] args, int _index, Label end) { List<Insn> result = new ArrayList<Insn>(); HashMap labels = new HashMap(); int index = _index; for (Insn i : insns) { if (i.isExpanded()) { MethodInsn expanded = (MethodInsn) i; // This use of end should be OK because all returns should have been removed when inlined before. // What could go wrong? result.addAll(convertInsns(expanded, expanded.inlineExpansionInsns, args, _index, end)); } else if (i instanceof SingleInsn) { SingleInsn si = (SingleInsn) i; switch (si.opcode) { case Opcodes.IRETURN: case Opcodes.LRETURN: case Opcodes.FRETURN: case Opcodes.DRETURN: case Opcodes.ARETURN: case Opcodes.RETURN: result.add(new JumpInsn("RETURN->GOTO", Opcodes.GOTO, end, newIndex(mi, index++))); break; default: result.add(i.copy(newIndex(mi, index++))); }//from w w w . jav a2s .c o m } else if (i instanceof VarInsn) { VarInsn vi = (VarInsn) i; switch (vi.opcode) { case Opcodes.ILOAD: case Opcodes.LLOAD: case Opcodes.FLOAD: case Opcodes.DLOAD: case Opcodes.ALOAD: case Opcodes.ISTORE: case Opcodes.LSTORE: case Opcodes.FSTORE: case Opcodes.DSTORE: case Opcodes.ASTORE: VarInsn newVarInsn = new VarInsn(vi.name, vi.opcode, args[vi.var], newIndex(mi, index++)); result.add(newVarInsn); break; default: result.add(i.copy(newIndex(mi, index++))); } } else if (i instanceof VisitMaxs) { } else if (i instanceof VisitEnd) { } else if (i instanceof VisitCode) { } else if (i instanceof VisitFrame) { } else if (i instanceof LabelInsn) { LabelInsn li = (LabelInsn) i; if (labels.containsKey(li.label)) result.add(new LabelInsn(li.name, (Label) labels.get(li.label), newIndex(mi, index++))); else { Label l = new Label(); labels.put(li.label, l); result.add(new LabelInsn(li.name, l, newIndex(mi, index++))); } } else if (i instanceof JumpInsn) { JumpInsn ji = (JumpInsn) i; if (labels.containsKey(ji.label)) result.add( new JumpInsn(ji.name, ji.opcode, (Label) labels.get(ji.label), newIndex(mi, index++))); else { Label l = new Label(); labels.put(ji.label, l); result.add(new JumpInsn(ji.name, ji.opcode, l, newIndex(mi, index++))); } } else if (i instanceof VisitLineNumberInsn) { VisitLineNumberInsn vlni = (VisitLineNumberInsn) i; if (labels.containsKey(vlni.start)) result.add(new VisitLineNumberInsn(vlni.name, vlni.line, (Label) labels.get(vlni.start), newIndex(mi, index++))); else { Label l = new Label(); labels.put(vlni.start, l); result.add(new VisitLineNumberInsn(vlni.name, vlni.line, l, newIndex(mi, index++))); } } else if (i instanceof LocalVariableInsn) { LocalVariableInsn lvi = (LocalVariableInsn) i; if (labels.containsKey(lvi.start) && labels.containsKey(lvi.end)) { result.add(new LocalVariableInsn(lvi.name, lvi._name, lvi.desc, lvi.sig, (Label) labels.get(lvi.start), (Label) labels.get(lvi.end), args[lvi._index], newIndex(mi, index++))); } else throw new RuntimeException("NYI"); } else if (i instanceof TryCatchBlock) { TryCatchBlock tcb = (TryCatchBlock) i; if (labels.containsKey(tcb.start) && labels.containsKey(tcb.end) && labels.containsKey(tcb.handler)) { result.add( new TryCatchBlock(tcb.name, (Label) labels.get(tcb.start), (Label) labels.get(tcb.end), (Label) labels.get(tcb.handler), tcb.type, newIndex(mi, index++))); } else if (!labels.containsKey(tcb.start) && !labels.containsKey(tcb.end) && !labels.containsKey(tcb.handler)) { Label s = new Label(); Label e = new Label(); Label h = new Label(); labels.put(tcb.start, s); labels.put(tcb.end, e); labels.put(tcb.handler, h); result.add(new TryCatchBlock(tcb.name, s, e, h, tcb.type, newIndex(mi, index++))); } else throw new RuntimeException("NYI"); // Need to add TableSwitch, LookupSwitch } else { result.add(i.copy(newIndex(mi, index++))); } } return result; }
From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.Inlining.java
License:Open Source License
public static void inlineMethodCall(String className, ByteCodeMethodVisitor method, MethodInsn mi, ByteCodeMethodVisitor methodToInline, Boolean staticMethod) { List<Insn> insns = new ArrayList<Insn>(); Label start = new Label(); Label end = new Label(); int argsStart = methodToInline.args.size(); int localsStart = methodToInline.maxLocals; int index = 0; insns.add(new LabelInsn("start_" + mi._name, start, newIndex(mi, index++))); int[] offsets = new int[methodToInline.maxLocals + 1]; // Static Method start at args.size() - 1, NonStatic Methods start at args.size() if (staticMethod) argsStart = argsStart - 1;/*from w ww .j a v a 2s . co m*/ for (int i = argsStart; i >= 0; i--) { insns.add(new VarInsn("ASTORE", Opcodes.ASTORE, method.maxLocals + i, newIndex(mi, index++))); offsets[i] = method.maxLocals + i; } for (int i = localsStart - 1; i > argsStart; i--) offsets[i] = method.maxLocals + i; method.maxStack = method.maxStack + methodToInline.maxStack; method.maxLocals = method.maxLocals + methodToInline.args.size() + methodToInline.maxLocals; insns.addAll(convertInsns(mi, methodToInline.insns, offsets, index, end)); insns.add(new LabelInsn("end_" + mi._name, end, newIndex(mi, insns.size()))); for (Insn insn : insns) { insn.setParentInsn(mi); } mi.inlineExpansionInsns.addAll(insns); }
From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.RemoveLiteralCoercions.java
License:Open Source License
public static Substitution removeFloatLiterals2(ByteCodeMethodVisitor bcmv) { String floatLiteral = "com/sun/fortress/compiler/runtimeValues/FFloatLiteral"; String RR64 = "com/sun/fortress/compiler/runtimeValues/FRR64"; ArrayList<Insn> matches = new ArrayList<Insn>(); matches.add(new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC, floatLiteral, "make", "(D)L" + floatLiteral + ";", "targetedForRemoval")); matches.add(new VarInsn("ASTORE", Opcodes.ASTORE, 0, "targetedForRemoval")); matches.add(new LabelInsn("LabelInsn", new Label(), "targetedForRemoval")); matches.add(new VisitLineNumberInsn("visitlinenumber", 0, new Label(), "targetedForRemoval")); matches.add(new VarInsn("ALOAD", Opcodes.ALOAD, 0, "targetedForRemoval")); matches.add(new LabelInsn("LabelInsn", new Label(), "targetedForRemoval")); matches.add(new VisitLineNumberInsn("visitlinenumber", 0, new Label(), "targetedForRemoval")); matches.add(new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC, "fortress/CompilerBuiltin", "coerce_RR64", "(Lfortress/CompilerBuiltin$FloatLiteral;)L" + RR64 + ";", "targetedForRemoval")); ArrayList<Insn> replacements = new ArrayList<Insn>(); replacements.add(new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC, RR64, "make", "(D)L" + RR64 + ";", "ReplacementInsn")); return new Substitution(matches, replacements); }
From source file:com.sun.fortress.compiler.OverloadSet.java
License:Open Source License
public void generateCall(MethodVisitor mv, int firstArgIndex, int one_if_method_closure) { if (!splitDone) { throw new CompilerError("Must split overload set before generating call(s)"); }/*from w w w .j a va 2 s . c om*/ int l = specificDispatchOrder.length; TaggedFunctionName[] functionsToCall = new TaggedFunctionName[l]; for (int i = 0; i < l; i++) { functionsToCall[i] = getFunctionToCall(specificDispatchOrder[i]); } // create type structures for parameter types. TypeStructure[][] type_structures = new TypeStructure[l][]; MultiMap[] spmaps = new MultiMap[l]; TypeStructure[] return_type_structures = new TypeStructure[l]; for (int i = 0; i < l; i++) { TaggedFunctionName f = functionsToCall[i]; Functional eff = f.getF(); List<Param> parameters = f.getParameters(); MultiMap<String, TypeStructure> spmap = new MultiMap<String, TypeStructure>(); spmaps[i] = spmap; List<StaticParam> staticParams = staticParametersOf(f.getF()); Type rt = oa.getRangeType(eff); return_type_structures[i] = makeTypeStructure(rt, null, 1, 0, staticParams, eff); // skip parameters -- no 'this' for ordinary functions if (parameters.size() == 1 && oa.getDomainType(eff) instanceof TupleType) { TupleType tt = (TupleType) oa.getDomainType(eff); List<Type> tl = tt.getElements(); int storeAtIndex = tl.size(); // DRC back this out + firstArgIndex; // little dubious here, not sure we are getting the // right type structures for generic methods. what about 'self' TypeStructure[] f_type_structures = new TypeStructure[tl.size()]; type_structures[i] = f_type_structures; for (int j = 0; j < tl.size(); j++) { Type t = STypesUtil.insertStaticParams(tl.get(j), tt.getInfo().getStaticParams()); TypeStructure type_structure = makeTypeStructure(t, spmap, 1, storeAtIndex, staticParams, eff); f_type_structures[j] = type_structure; storeAtIndex = type_structure.successorIndex; } } else { int storeAtIndex = parameters.size(); // DRC back this out + firstArgIndex; TypeStructure[] f_type_structures = new TypeStructure[parameters.size()]; type_structures[i] = f_type_structures; for (int j = 0; j < parameters.size(); j++) { if (j != selfIndex()) { Type t = oa.getParamType(eff, j); TypeStructure type_structure = makeTypeStructure(t, spmap, 1, storeAtIndex, staticParams, eff); f_type_structures[j] = type_structure; storeAtIndex = type_structure.successorIndex; } } } } for (int i = 0; i < l; i++) { TaggedFunctionName f = functionsToCall[i]; TypeStructure[] f_type_structures = type_structures[i]; Label lookahead = null; boolean infer = false; List<StaticParam> staticParams = staticParametersOf(f.getF()); boolean last_case = i == l - 1; /* Trust the static checker; no need to verify * applicability of the last one. * Also, static parameters will be provided by static checker for the last one */ // Will need lookahead for the next one. lookahead = new Label(); // if this was a generic method that needs inference, we need to include the receiver argument // in the inference even if the firstArgIndex is 1 so that we can include it in inference // and dispatch //KBN-WIP is there a cleaner way to do this? int offset = (f_type_structures.length == specificDispatchOrder[i].getParameters().size()) ? firstArgIndex : 0; for (int j = 0; j < f_type_structures.length; j++) { if (j != selfIndex()) { //inference needed if the type structure contains generics TODO: do generics not appearing in the parameters make sense? probably not, but might need to deal with them. if (f_type_structures[j].containsTypeVariables) infer = true; } } if (infer || !last_case) for (int j = 0; j < f_type_structures.length; j++) { // Load actual parameter if (j != selfIndex()) { mv.visitVarInsn(Opcodes.ALOAD, j + offset); f_type_structures[j].emitInstanceOf(mv, lookahead, true); } } //Runtime inference for some cases if (infer) { @SuppressWarnings("unchecked") MultiMap<String, TypeStructure> staticTss = spmaps[i]; int localCount = f_type_structures[f_type_structures.length - 1].successorIndex; //counter for use storing stuff such as lower bounds //create type structures for lower bounds Map<StaticParam, TypeStructure> lowerBounds = new HashMap<StaticParam, TypeStructure>(); for (StaticParam sp : staticParams) lowerBounds.put(sp, makeParamTypeStructure(sp, localCount++, TypeStructure.COVARIANT)); //gather different types of bounds into Multimaps for use later MultiMap<StaticParam, StaticParam> relativeLowerBounds = new MultiMap<StaticParam, StaticParam>(); //form X :> Y MultiMap<StaticParam, Type> genericUpperBounds = new MultiMap<StaticParam, Type>(); //form X <: GenericStem[\ ... \] where Y appears in ... MultiMap<StaticParam, Type> concreteUpperBounds = new MultiMap<StaticParam, Type>(); //form X <: T where T contains no type variables for (int outer = 0; outer < staticParams.size(); outer++) { StaticParam outerSP = staticParams.get(outer); for (BaseType bt : outerSP.getExtendsClause()) { if (bt instanceof VarType) { // outerSP <: bt so outerSP will provide a lower bound on BT String varName = ((VarType) bt).getName().getText(); boolean found = false; for (int inner = 0; inner < outer && !found; inner++) { StaticParam innerSP = staticParams.get(inner); if (varName.equals(innerSP.getName().getText())) { relativeLowerBounds.putItem(innerSP, outerSP); // outerSP provides a lower bound on innerSP found = true; } } if (!found) throw new CompilerError( "Bad Scoping of static parameters found during runtime inference codegen:" + varName + " not declared before used in a bound"); } else if (bt instanceof AnyType) { //figure out if concrete or generic //do nothing - no need to add meaningless upper bound } else if (bt instanceof NamedType) { if (isGeneric(bt)) genericUpperBounds.putItem(outerSP, bt); else concreteUpperBounds.putItem(outerSP, bt); } } } //infer and load RTTIs for (int j = 0; j < staticParams.size(); j++) { StaticParam sp = staticParams.get(staticParams.size() - 1 - j); //reverse order due to left to right scoping Set<TypeStructure> instances = staticTss.get(sp.getName().getText()); //sort static parameters by their variance and put into //arrays using their local variable number List<Integer> invariantInstances = new ArrayList<Integer>(); List<Integer> covariantInstances = new ArrayList<Integer>(); List<Integer> contravariantInstances = new ArrayList<Integer>(); if (instances != null) for (TypeStructure ts : instances) { switch (ts.variance) { case TypeStructure.INVARIANT: invariantInstances.add(ts.localIndex); break; case TypeStructure.CONTRAVARIANT: contravariantInstances.add(ts.localIndex); break; case TypeStructure.COVARIANT: covariantInstances.add(ts.localIndex); break; default: throw new CompilerError("Unexpected Variance on TypeStructure during " + "generic instantiation analysis for overload dispatch"); } } // if any invariant instances, we must use that RTTI and check that //1) any other invariant instances are the same type (each subtypes the other) //2) any covariant instances are subtypes of the invariant instance //3) any contravariant instances are supertypes of the invariant instance if (invariantInstances.size() > 0) { //a valid instantiation must use the runtime type //of all invariant instances (which must all be the same) //thus, wlog, we can use the first invariant instance int RTTItoUse = invariantInstances.get(0); //1) for each other invariant instance, they must be the same //which we test by checking that each subtypes the other for (int k = 1; k < invariantInstances.size(); k++) { int RTTIcompare = invariantInstances.get(k); //RTTItoUse.runtimeSupertypeOf(RTTIcompare) mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail //RTTIcompare.runtimeSupertypeOf(RTTItoUse) mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //2) for each covariant instance, the runtime type (RTTIcompare) must be a // subtype of the instantiated type (RTTItoUse) for (int RTTIcompare : covariantInstances) { //RTTItoUse.runtimeSupertypeOf(RTTIcompare) mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //3) for each contravariant instance, the instantiated type (RTTItoUse) must be a // subtype of the runtime type (RTTIcompare) for (int RTTIcompare : contravariantInstances) { //RTTIcompare.runtimeSupertypeOf(RTTItoUse) mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //check lower bounds given by other variables Set<StaticParam> relativeLB = relativeLowerBounds.get(sp); if (relativeLB != null) for (StaticParam lb : relativeLB) { //RTTItoUse.runtimeSupertypeOf(otherLB) int otherOffset = lowerBounds.get(lb).localIndex; mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitVarInsn(Opcodes.ALOAD, otherOffset); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //verify meets upper bounds Set<Type> concreteUB = concreteUpperBounds.get(sp); if (concreteUB != null) for (Type cub : concreteUB) { //transform into RTTI generateRTTIfromStaticType(mv, cub); mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //generate more bounds for generic upper bounds Set<Type> genericUB = genericUpperBounds.get(sp); if (genericUB != null) for (Type gub : genericUB) { TypeStructure newTS = makeTypeStructure(gub, staticTss, TypeStructure.COVARIANT, localCount, staticParams, null); localCount = newTS.successorIndex; mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); newTS.emitInstanceOf(mv, lookahead, false); //fail if RTTItoUse doesn't have this structure } //checks out, so store the RTTI we will use into the lower bound for this parameter mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); int index = lowerBounds.get(sp).localIndex; mv.visitVarInsn(Opcodes.ASTORE, index); } else if (contravariantInstances.size() == 0) { //we can do inference for covariant-only occurrences boolean started = false; if (covariantInstances.size() > 0) { started = true; mv.visitVarInsn(Opcodes.ALOAD, covariantInstances.get(0)); for (int k = 1; k < covariantInstances.size(); k++) { mv.visitVarInsn(Opcodes.ALOAD, covariantInstances.get(k)); //TODO: allow unions joinStackNoUnion(mv, lookahead); //fails if cannot join w/o union } } //incorporate lower bounds Set<StaticParam> relativeLB = relativeLowerBounds.get(sp); if (relativeLB != null) for (StaticParam lb : relativeLB) { mv.visitVarInsn(Opcodes.ALOAD, lowerBounds.get(lb).localIndex); if (started) { //join it in //TODO: allow unions joinStackNoUnion(mv, lookahead); } else { //start with this lower bound started = true; } } if (started) { //verify meets upper bounds Set<Type> concreteUB = concreteUpperBounds.get(sp); if (concreteUB != null) for (Type cub : concreteUB) { Label cleanup = new Label(); Label next = new Label(); mv.visitInsn(Opcodes.DUP); generateRTTIfromStaticType(mv, cub); //transform concrete bound into RTTI mv.visitInsn(Opcodes.SWAP); // LB <: CUB mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, cleanup); mv.visitJumpInsn(Opcodes.GOTO, next); mv.visitLabel(cleanup); mv.visitInsn(Opcodes.POP); mv.visitJumpInsn(Opcodes.GOTO, lookahead); mv.visitLabel(next); } //checks out, so store to lower bound of sp int index = lowerBounds.get(sp).localIndex; mv.visitVarInsn(Opcodes.ASTORE, index); //generate more bounds for generic upper bounds Set<Type> genericUB = genericUpperBounds.get(sp); if (genericUB != null) for (Type gub : genericUB) { TypeStructure newTS = makeTypeStructure(gub, staticTss, TypeStructure.COVARIANT, localCount, staticParams, null); localCount = newTS.successorIndex; mv.visitVarInsn(Opcodes.ALOAD, index); newTS.emitInstanceOf(mv, lookahead, false); //fail if candidate doesn't have this structure } } else { //Bottom is ok - no need to check upper bounds //or generate lower bounds mv.visitFieldInsn(Opcodes.GETSTATIC, Naming.RT_VALUES_PKG + "VoidRTTI", Naming.RTTI_SINGLETON, Naming.RTTI_CONTAINER_DESC); int index = lowerBounds.get(sp).localIndex; mv.visitVarInsn(Opcodes.ASTORE, index); } } else { //otherwise, we might need to do inference which is not implemented yet throw new CompilerError("non-invariant inference with contravariance not implemented"); } } //load instance cache table to avoid classloader when possible String tableName = this.generateClosureTableName(specificDispatchOrder[i]); //use original function for table name String tableOwner = this.generateClosureTableOwner(f); mv.visitFieldInsn(Opcodes.GETSTATIC, tableOwner, tableName, Naming.CACHE_TABLE_DESC); //load template class name String arrow = this.instanceArrowSchema(f); //NamingCzar.makeArrowDescriptor(f.getParameters(), f.getReturnType(),f.tagA); String functionName = this.functionName(f); String templateClass = Naming.genericFunctionPkgClass(Naming.dotToSep(f.tagA.getText()), functionName, Naming.LEFT_OXFORD + Naming.RIGHT_OXFORD, arrow); if (otherOverloadKeys.contains(templateClass)) { templateClass = Naming.genericFunctionPkgClass(Naming.dotToSep(f.tagA.getText()), NamingCzar.mangleAwayFromOverload(functionName), Naming.LEFT_OXFORD + Naming.RIGHT_OXFORD, arrow); //templateClass = NamingCzar.mangleAwayFromOverload(templateClass); } mv.visitLdcInsn(templateClass); String ic_sig; if (staticParams.size() > 6) { //use an array //load the function: RThelpers.loadClosureClass:(BAlongTree,String,RTTI[]) String paramList = Naming.CACHE_TABLE_DESC + NamingCzar.descString + Naming.RTTI_CONTAINER_ARRAY_DESC; ic_sig = Naming.makeMethodDesc(paramList, Naming.internalToDesc(NamingCzar.internalObject)); mv.visitLdcInsn(staticParams.size()); mv.visitTypeInsn(Opcodes.ANEWARRAY, Naming.RTTI_CONTAINER_TYPE); //dup array enough times to store RTTIs into it //know need at least 6 more mv.visitInsn(Opcodes.DUP); //first one to get arrays as top two elts on stack for (int numDups = staticParams.size() - 1; numDups > 0; numDups = numDups / 2) mv.visitInsn(Opcodes.DUP2); if (staticParams.size() % 2 == 0) mv.visitInsn(Opcodes.DUP); //if even, started halving with an odd number, so needs one last //store parameters into array for (int k = 0; k < staticParams.size(); k++) { int index = lowerBounds.get(staticParams.get(k)).localIndex; mv.visitLdcInsn(k); //index is the static param number mv.visitVarInsn(Opcodes.ALOAD, index); mv.visitInsn(Opcodes.AASTORE); } //array left on stack } else { //load the function: RTHelpers.loadClosureClass:(BAlongTree,(String,RTTI)^n)Object ic_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes( Naming.CACHE_TABLE_TYPE + ";L" + NamingCzar.internalString, staticParams.size(), Naming.RTTI_CONTAINER_TYPE, Naming.internalToDesc(NamingCzar.internalObject)); //load parameter RTTIs for (int k = 0; k < staticParams.size(); k++) { int index = lowerBounds.get(staticParams.get(k)).localIndex; mv.visitVarInsn(Opcodes.ALOAD, index); } } mv.visitMethodInsn(Opcodes.INVOKESTATIC, Naming.RT_HELPERS, "loadClosureClass", ic_sig); //cast to object arrow int numParams = f.getParameters().size(); String objectAbstractArrow = NamingCzar.objectAbstractArrowTypeForNParams(numParams); InstantiatingClassloader.generalizedCastTo(mv, objectAbstractArrow); //if a method parameters converted //loadThisForMethods(mv); //load parameters for (int j = 0; j < f_type_structures.length; j++) { // Load actual parameter if (j != selfIndex()) { mv.visitVarInsn(Opcodes.ALOAD, j); // DRC back this out+ one_if_method_closure); // + firstArgIndex); KBN if a method, parameters already converted //no cast needed here - done by apply method } } //call apply method String objectArrow = NamingCzar.objectArrowTypeForNParams(numParams); String applySig = InstantiatingClassloader.jvmSignatureForNTypes(numParams, NamingCzar.internalObject, Naming.internalToDesc(NamingCzar.internalObject)); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, objectArrow, Naming.APPLY_METHOD, applySig); //cast to correct return type Type f_return = f.getReturnType(); if (f_return instanceof BottomType) { CodeGen.castToBottom(mv); } else { String returnType = NamingCzar.makeBoxedTypeName(f_return, f.tagA); InstantiatingClassloader.generalizedCastTo(mv, returnType); } } else { //no inferences needed loadThisForMethods(mv); for (int j = 0; j < f_type_structures.length; j++) { // Load actual parameter if (j != selfIndex()) { mv.visitVarInsn(Opcodes.ALOAD, j + firstArgIndex); InstantiatingClassloader.generalizedCastTo(mv, f_type_structures[j].fullname); } } String sig = jvmSignatureFor(f); invokeParticularMethod(mv, f, sig); Type f_return = f.getReturnType(); if (f_return instanceof BottomType) { CodeGen.castToBottom(mv); } } mv.visitInsn(Opcodes.ARETURN); if (lookahead != null) mv.visitLabel(lookahead); } }
From source file:com.sun.fortress.runtimeSystem.InstantiatingClassloader.java
License:Open Source License
private byte[] instantiateAbstractArrow(String name, List<String> parameters) { ManglingClassWriter cw = new ManglingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); /*// w w w . j ava2 s. c o m * Special case extensions to plumb tuples * correctly in the face of generics instantiated * with tuple types. * * Except, recall that Arrow parameters are domain...;range * * if > 1 param then * unwrap = params * wrap = tuple params * else 1 param * if tuple * wrap = param * unwrap = untuple params * else * unwrap = param * wrap = null * * Use unwrapped parameters to generate the all-Objects case * for casting; check the generated signature against the input * to see if we are them. * */ Triple<List<String>, List<String>, String> stuff = normalizeArrowParameters(parameters); List<String> flat_params_and_ret = stuff.getA(); List<String> tupled_params_and_ret = stuff.getB(); String tupleType = stuff.getC(); List<String> flat_obj_params_and_ret = Useful.applyToAll(flat_params_and_ret, toJLO); List<String> norm_obj_params_and_ret = normalizeArrowParametersAndReturn(flat_obj_params_and_ret); List<String> norm_params_and_ret = normalizeArrowParametersAndReturn(flat_params_and_ret); String obj_sig = stringListToGeneric(ABSTRACT_ARROW, norm_obj_params_and_ret); String obj_intf_sig = stringListToGeneric(Naming.ARROW_TAG, norm_obj_params_and_ret); String wrapped_sig = stringListToGeneric(WRAPPED_ARROW, norm_params_and_ret); String typed_intf_sig = stringListToGeneric(Naming.ARROW_TAG, norm_params_and_ret); String unwrapped_apply_sig; if (parameters.size() == 2 && parameters.get(0).equals(Naming.INTERNAL_SNOWMAN)) unwrapped_apply_sig = arrowParamsToJVMsig(parameters.subList(1, 2)); else unwrapped_apply_sig = arrowParamsToJVMsig(flat_params_and_ret); String obj_apply_sig = arrowParamsToJVMsig(flat_obj_params_and_ret); String[] interfaces = new String[] { stringListToArrow(norm_params_and_ret) }; /* * Note that in the case of foo -> bar, * normalized = flattened, and tupled does not exist (is null). */ String typed_tupled_intf_sig = tupled_params_and_ret == null ? null : stringListToGeneric(Naming.ARROW_TAG, tupled_params_and_ret); String objectified_tupled_intf_sig = tupled_params_and_ret == null ? null : stringListToGeneric(Naming.ARROW_TAG, Useful.applyToAll(tupled_params_and_ret, toJLO)); boolean is_all_objects = norm_obj_params_and_ret.equals(norm_params_and_ret); String _super = is_all_objects ? "java/lang/Object" : obj_sig; cw.visit(JVM_BYTECODE_VERSION, ACC_PUBLIC + ACC_SUPER + ACC_ABSTRACT, name, null, _super, interfaces); simpleInitMethod(cw, _super); /* */ if (!is_all_objects) { // implement method for the object version. // cast parameters, invoke this.apply on cast parameters, ARETURN // note cut and paste from apply below, work in progress. MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, obj_apply_sig, null, null); mv.visitVarInsn(Opcodes.ALOAD, 0); // this int unwrapped_l = flat_params_and_ret.size(); for (int i = 0; i < unwrapped_l - 1; i++) { String t = flat_params_and_ret.get(i); if (!t.equals(Naming.INTERNAL_SNOWMAN) || unwrapped_l > 2) { mv.visitVarInsn(Opcodes.ALOAD, i + 1); // element // mv.visitTypeInsn(CHECKCAST, t); generalizedCastTo(mv, Naming.internalToType(t)); } } mv.visitMethodInsn(INVOKEVIRTUAL, name, Naming.APPLY_METHOD, unwrapped_apply_sig); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } // is instance method -- takes an Object { String sig = "(Ljava/lang/Object;)Z"; MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, IS_A, sig, null, null); Label fail = new Label(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.INSTANCEOF, Naming.ANY_TYPE_CLASS); mv.visitJumpInsn(Opcodes.IFEQ, fail); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.CHECKCAST, Naming.ANY_TYPE_CLASS); mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, IS_A, "(" + Naming.internalToDesc(Naming.ANY_TYPE_CLASS) + ")Z"); mv.visitInsn(Opcodes.IRETURN); mv.visitLabel(fail); mv.visitIntInsn(BIPUSH, 0); mv.visitInsn(Opcodes.IRETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } // is instance method -- takes an Any { String sig = "(" + Naming.internalToDesc(Naming.ANY_TYPE_CLASS) + ")Z"; MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, IS_A, sig, null, null); Label fail = new Label(); //get RTTI to compare to mv.visitFieldInsn(GETSTATIC, name, Naming.RTTI_FIELD, Naming.RTTI_CONTAINER_DESC); //get RTTI of object mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(INVOKEINTERFACE, Naming.ANY_TYPE_CLASS, Naming.RTTI_GETTER, "()" + Naming.RTTI_CONTAINER_DESC); // mv.visitJumpInsn(IFNONNULL, fail); mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); //mv.visitIntInsn(BIPUSH, 0); mv.visitJumpInsn(Opcodes.IFEQ, fail); mv.visitIntInsn(BIPUSH, 1); mv.visitInsn(Opcodes.IRETURN); mv.visitLabel(fail); mv.visitIntInsn(BIPUSH, 0); mv.visitInsn(Opcodes.IRETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } // castTo { /* * If arg0 instanceof typed_intf_sig * return arg0 * arg0 = arg0.getWrappee() * if arg0 instanceof typed_intf_sig * return arg0 * new WrappedArrow * dup * push argo * init * return tos */ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CAST_TO, "(" + // Naming.internalToDesc(obj_intf_sig) "Ljava/lang/Object;" + ")" + Naming.internalToDesc(typed_intf_sig), null, null); Label not_instance1 = new Label(); Label not_instance2 = new Label(); // try bare instanceof mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig); mv.visitJumpInsn(Opcodes.IFEQ, not_instance1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.CHECKCAST, typed_intf_sig); mv.visitInsn(Opcodes.ARETURN); // unwrap mv.visitLabel(not_instance1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.CHECKCAST, obj_intf_sig); mv.visitMethodInsn(INVOKEINTERFACE, obj_intf_sig, getWrappee, "()" + Naming.internalToDesc(obj_intf_sig)); mv.visitVarInsn(Opcodes.ASTORE, 0); // try instanceof on unwrapped mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig); mv.visitJumpInsn(Opcodes.IFEQ, not_instance2); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.CHECKCAST, typed_intf_sig); mv.visitInsn(Opcodes.ARETURN); // wrap and return mv.visitLabel(not_instance2); mv.visitTypeInsn(NEW, wrapped_sig); mv.visitInsn(DUP); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, wrapped_sig, "<init>", "(" + Naming.internalToDesc(obj_intf_sig) + ")V"); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } if (typed_tupled_intf_sig != null) { /* * If arg0 instanceof typed_intf_sig * return arg0 * arg0 = arg0.getWrappee() * if arg0 instanceof typed_intf_sig * return arg0 * new WrappedArrow * dup * push argo * init * return tos */ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CAST_TO, "(" + Naming.internalToDesc(objectified_tupled_intf_sig) + ")" + Naming.internalToDesc(typed_intf_sig), null, null); Label not_instance1 = new Label(); Label not_instance2 = new Label(); // try bare instanceof mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig); mv.visitJumpInsn(Opcodes.IFEQ, not_instance1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitInsn(Opcodes.ARETURN); // unwrap mv.visitLabel(not_instance1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(INVOKEINTERFACE, objectified_tupled_intf_sig, getWrappee, "()" + Naming.internalToDesc(objectified_tupled_intf_sig)); mv.visitVarInsn(Opcodes.ASTORE, 0); // try instanceof on unwrapped mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig); mv.visitJumpInsn(Opcodes.IFEQ, not_instance2); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitInsn(Opcodes.ARETURN); // wrap and return - untupled should be okay here, since it subtypes mv.visitLabel(not_instance2); mv.visitTypeInsn(NEW, wrapped_sig); mv.visitInsn(DUP); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, wrapped_sig, "<init>", "(" + Naming.internalToDesc(obj_intf_sig) + ")V"); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } // getWrappee { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, getWrappee, "()" + Naming.internalToDesc(obj_intf_sig), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); mv.visitEnd(); // return this } if (tupled_params_and_ret == null) { /* Single abstract method */ if (LOG_LOADS) System.err.println(name + ".apply" + unwrapped_apply_sig + " abstract for abstract"); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, Naming.APPLY_METHOD, unwrapped_apply_sig, null, null); mv.visitEnd(); } else { /* * Establish two circular forwarding methods; * the eventual implementer will break the cycle. * */ String tupled_apply_sig = arrowParamsToJVMsig(tupled_params_and_ret); { /* Given tupled args, extract, and invoke apply. */ if (LOG_LOADS) System.err.println(name + ".apply" + tupled_apply_sig + " abstract for abstract"); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, tupled_apply_sig, null, null); mv.visitVarInsn(Opcodes.ALOAD, 0); // closure int unwrapped_l = flat_params_and_ret.size(); for (int i = 0; i < unwrapped_l - 1; i++) { String param = flat_params_and_ret.get(i); mv.visitVarInsn(Opcodes.ALOAD, 1); // tuple mv.visitMethodInsn(INVOKEINTERFACE, tupleType, TUPLE_TYPED_ELT_PFX + (Naming.TUPLE_ORIGIN + i), "()" + Naming.internalToDesc(param)); } mv.visitMethodInsn(INVOKEVIRTUAL, name, Naming.APPLY_METHOD, unwrapped_apply_sig); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } { /* Given untupled args, load, make a tuple, invoke apply. */ if (LOG_LOADS) System.err.println(name + ".apply" + unwrapped_apply_sig + " abstract for abstract"); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, unwrapped_apply_sig, null, null); mv.visitVarInsn(Opcodes.ALOAD, 0); // closure int unwrapped_l = flat_params_and_ret.size(); for (int i = 0; i < unwrapped_l - 1; i++) { mv.visitVarInsn(Opcodes.ALOAD, i + 1); // element } List<String> tuple_elements = flat_params_and_ret.subList(0, unwrapped_l - 1); String make_sig = toJvmSig(tuple_elements, Naming.javaDescForTaggedFortressType(tupleType)); mv.visitMethodInsn(INVOKESTATIC, stringListToGeneric(CONCRETE_TUPLE, tuple_elements), "make", make_sig); mv.visitMethodInsn(INVOKEVIRTUAL, name, Naming.APPLY_METHOD, tupled_apply_sig); mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); } } //RTTI comparison field final String final_name = name; ArrayList<InitializedStaticField> isf_list = new ArrayList<InitializedStaticField>(); if (!parameters.contains("java/lang/Object")) { isf_list.add(new InitializedStaticField.StaticForUsualRttiField(final_name, this)); } else { isf_list.add(new InitializedStaticField.StaticForJLOParameterizedRttiField(final_name)); } cw.visitEnd(); // //RTTI getter { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.RTTI_GETTER, "()" + Naming.RTTI_CONTAINER_DESC, null, null); mv.visitCode(); mv.visitFieldInsn(GETSTATIC, name, Naming.RTTI_FIELD, Naming.RTTI_CONTAINER_DESC); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } optionalStaticsAndClassInitForTO(isf_list, cw); return cw.toByteArray(); }
From source file:com.sun.fortress.runtimeSystem.InstantiatingClassloader.java
License:Open Source License
/** * @param rttiClassName/*from w w w . j ava 2s. c o m*/ * @param sparams_size */ static public void emitDictionaryAndFactoryForGenericRTTIclass(ManglingClassWriter cw, String rttiClassName, int sparams_size, final Naming.XlationData xldata) { // Push nulls for opr parameters in the factory call. List<Boolean> spks; int type_sparams_size = sparams_size; if (xldata != null) { spks = xldata.isOprKind(); sparams_size = spks.size(); } else { spks = new InfiniteList<Boolean>(false); } // FIELD // static, initialized to Map-like thing cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL, "DICTIONARY", Naming.RTTI_MAP_DESC, null, null); // CLINIT // factory, consulting map, optionally invoking constructor. MethodVisitor mv = cw.visitNoMangleMethod(ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode(); // new mv.visitTypeInsn(NEW, Naming.RTTI_MAP_TYPE); // init mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, Naming.RTTI_MAP_TYPE, "<init>", "()V"); // store mv.visitFieldInsn(PUTSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC); mv.visitInsn(RETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); // FACTORY boolean useSparamsArray = sparams_size > 6; int sparamsArrayIndex = sparams_size; String fact_sig = Naming.rttiFactorySig(type_sparams_size); String init_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes("java/lang/Class", type_sparams_size, Naming.RTTI_CONTAINER_TYPE, "V"); String get_sig; String put_sig; String getClass_sig; if (useSparamsArray) { get_sig = Naming.makeMethodDesc(Naming.RTTI_CONTAINER_ARRAY_DESC, Naming.RTTI_CONTAINER_DESC); put_sig = Naming.makeMethodDesc(Naming.RTTI_CONTAINER_ARRAY_DESC + Naming.RTTI_CONTAINER_DESC, Naming.RTTI_CONTAINER_DESC); getClass_sig = Naming.makeMethodDesc(NamingCzar.descString + Naming.RTTI_CONTAINER_ARRAY_DESC, NamingCzar.descClass); } else { get_sig = InstantiatingClassloader.jvmSignatureForNTypes(sparams_size, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_CONTAINER_DESC); put_sig = InstantiatingClassloader.jvmSignatureForNTypes(sparams_size + 1, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_CONTAINER_DESC); getClass_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes(NamingCzar.internalString, sparams_size, Naming.RTTI_CONTAINER_TYPE, NamingCzar.descClass); } mv = cw.visitNoMangleMethod(ACC_PUBLIC + ACC_STATIC, Naming.RTTI_FACTORY, fact_sig, null, null); mv.visitCode(); /* * First arg is java class, necessary for creation of type. * * rCN x = DICTIONARY.get(args) * if x == null then * x = new rCN(args) * x = DICTIONARY.put(args, x) * end * return x */ // object mv.visitFieldInsn(GETSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC); // push args int l = sparams_size; if (useSparamsArray) { mv.visitLdcInsn(sparams_size); mv.visitTypeInsn(Opcodes.ANEWARRAY, Naming.RTTI_CONTAINER_TYPE); mv.visitVarInsn(Opcodes.ASTORE, sparamsArrayIndex); InstantiatingClassloader.pushArgsIntoArray(mv, 0, l, sparamsArrayIndex, spks); } else { InstantiatingClassloader.pushArgs(mv, 0, l, spks); } // invoke Dictionary.get mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_MAP_TYPE, "get", get_sig); Label not_null = new Label(); mv.visitInsn(DUP); mv.visitJumpInsn(IFNONNULL, not_null); mv.visitInsn(POP); // discard dup'd null // doing it all on the stack -- (unless too many static params, then use an array for human coded stuff) // 1) first push the dictionary and args (array if used) // 2) create new RTTI object // 3) push args again (array if used) and create the class for this object // 4) push the args again (never array) to init RTTI object // 5) add to dictionary //1) mv.visitFieldInsn(GETSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC); if (useSparamsArray) { mv.visitVarInsn(ALOAD, sparamsArrayIndex); } else { InstantiatingClassloader.pushArgs(mv, 0, l, spks); } // 2) invoke constructor mv.visitTypeInsn(NEW, rttiClassName); mv.visitInsn(DUP); // 3) create class for this object String stem = Naming.rttiClassToBaseClass(rttiClassName); if (true || xldata == null) { // NOT symbolic (and a problem if we pretend that it is) mv.visitLdcInsn(stem); } else { RTHelpers.symbolicLdc(mv, stem); } if (useSparamsArray) { mv.visitVarInsn(ALOAD, sparamsArrayIndex); } else { InstantiatingClassloader.pushArgs(mv, 0, l, spks); } //(mv, "before getRTTIclass"); mv.visitMethodInsn(Opcodes.INVOKESTATIC, Naming.RT_HELPERS, "getRTTIclass", getClass_sig); //eep(mv, "after getRTTIclass"); // 4) init RTTI object (do not use array) // NOTE only pushing type_sparams here. InstantiatingClassloader.pushArgs(mv, 0, type_sparams_size); mv.visitMethodInsn(INVOKESPECIAL, rttiClassName, "<init>", init_sig); // 5) add to dictionary mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_MAP_TYPE, "putIfNew", put_sig); mv.visitLabel(not_null); mv.visitInsn(ARETURN); mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter); mv.visitEnd(); }
From source file:com.tencent.tinker.build.auxiliaryclass.AuxiliaryClassInjectAdapter.java
License:Open Source License
@Override public void visitEnd() { // If method <clinit> and <init> are not found, we should generate a <clinit>. if (!this.isClInitExists && !this.isInitExists) { MethodVisitor mv = super.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null); mv.visitCode();/*from w w w . j a v a 2 s . c o m*/ mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "lineSeparator", "()Ljava/lang/String;", false); Label lblSkipInvalidInsn = new Label(); mv.visitJumpInsn(Opcodes.IFNONNULL, lblSkipInvalidInsn); mv.visitLdcInsn(Type.getType(this.auxiliaryClassDesc)); mv.visitVarInsn(Opcodes.ASTORE, 0); mv.visitLabel(lblSkipInvalidInsn); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } super.visitEnd(); }
From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java
public void testReplacingThisWithOtherVariable() throws Exception { final String FIELDPROXYWORKED = "FIELDPROXYWORKED"; //set up the proxy object. this is the object that will receive //the proxied calls TestSubClass tcc = new TestSubClass(); tcc.setBaseString(FIELDPROXYWORKED); TestBaseClassHolder.setTestBase(tcc); //get the dynamic source that has the donor body in it ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF); MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout"); System.out.println("Donor"); printMethodNode(donorMethod);/*from ww w.ja v a2s .c o m*/ //alright here's the strategy: (1) inject a new local variable that points // to our remote instance, // (2) inject code that sets this local to the value of a method call, // (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1 InsnList instructionsToInject = donorMethod.instructions; //make a new local variable LabelNode begin = new LabelNode(); LabelNode end = new LabelNode(); instructionsToInject.insertBefore(instructionsToInject.getFirst(), begin); instructionsToInject.add(end); Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass"); int variableIndex = donorMethod.maxLocals; donorMethod.maxLocals += type.getSize(); donorMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(), variableIndex); //set the value of the local variable with a new instruction at the top //fetch a reference to our proxy object MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC, "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase", "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;"); //insert after begin label instructionsToInject.insert(begin, getTestBase); //store reference VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex); //insert store after fetch instructionsToInject.insert(getTestBase, setRef); //replace all references to 'this' with the new variable for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) { AbstractInsnNode node = instructionsToInject.get(currentIndex); if (node.getOpcode() == Opcodes.ALOAD) { VarInsnNode vin = (VarInsnNode) node; //'this' is var index 0. ours is var index varindex if (vin.var == 0) { vin.var = variableIndex; } } } System.out.println(">>>>>>>>>Finished Modifying<<<<<<<<"); printMethodNode(donorMethod); String NEWCLASSNAME = "ScriptTestClass"; //write a class Class c = createClassFromClassNode(donorSource, NEWCLASSNAME); Object o = c.newInstance(); Method m = o.getClass().getDeclaredMethod("before_whatDoIThinkAbout", String.class); //should return HAHAHA not baseStringValue String result = (String) m.invoke(o, new Object[] { "AAAA" }); System.out.println("TestDonorClass.whatDoIThinkAbout Result: " + result); assertTrue(result.equals(FIELDPROXYWORKED + "AAAA")); }
From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java
@Test public void testInjectingIntoMethodWithLotsOfParameters() throws Exception { final String FIELDPROXYWORKED = "FIELDPROXYWORKED"; //set up the proxy object. this is the object that will receive //the proxied calls TestSubClass tcc = new TestSubClass(); tcc.setBaseString(FIELDPROXYWORKED); TestBaseClassHolder.setTestBase(tcc); //get the dynamic source that has the donor body in it ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF2); MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout"); System.out.println("Donor Method Before Modifications:"); printMethodNode(donorMethod);//w w w. j av a2 s . com String TARGETCLASSNAME = "com.triage.bytecodemaster.fortesting.Concatenator"; ClassNode targetSource = loadLocalClass(TARGETCLASSNAME); ClassNode exampleSource = loadLocalClass("com.triage.bytecodemaster.fortesting.JustLikeGroovyClass"); MethodNode exampleMethod = findMethod(exampleSource, "before_whatDoIThinkAbout"); System.out.println("Example Method-- Should be just like the Donor Source"); printMethodNode(exampleMethod); MethodNode targetMethod = findMethod(targetSource, "concat"); System.out.println("Target Method <Before Mods>"); printMethodNode(targetMethod); //alright here's the strategy: (1) inject a new local variable that points // to our remote instance, // (2) inject code that sets this local to the value of a method call, // (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1 InsnList instructionsToInject = donorMethod.instructions; InsnList targetInstructions = targetMethod.instructions; //make a new local variable in the donor method. //this variable needs to have a slot high enough that it doesnt //conflict with either the target or the source method //it will hold references to the objects we replace with 'this' LabelNode begin = new LabelNode(); LabelNode end = new LabelNode(); targetInstructions.insertBefore(targetInstructions.getFirst(), begin); targetInstructions.add(end); Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass"); int variableIndex = targetMethod.maxLocals; targetMethod.maxLocals += type.getSize(); targetMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(), variableIndex); //set the value of the local variable with a new instruction at the top //fetch a reference to our proxy object MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC, "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase", "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;"); //insert after begin label targetInstructions.insert(begin, getTestBase); //store reference VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex); //insert store after fetch targetInstructions.insert(getTestBase, setRef); //replace all references to 'this' in the DONOR method with the new variable //in the TARGET code for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) { AbstractInsnNode node = instructionsToInject.get(currentIndex); if (node.getOpcode() == Opcodes.ALOAD) { VarInsnNode vin = (VarInsnNode) node; //'this' is var index 0. ours is var index varindex if (vin.var == 0) { vin.var = variableIndex; } } //remove return methods. this will prevent a return. it should cause the donor //method to have parameters that overlap with the target, which has more parameters if (node.getOpcode() == Opcodes.RETURN || node.getOpcode() == Opcodes.ARETURN) { instructionsToInject.remove(node); } } System.out.println(">>>>>>>>>Finished Modifying Donor Method <<<<<<<<"); printMethodNode(donorMethod); String NEWCLASSNAME = "ScriptTestClass"; //stash instructions at the beginning of the original method, //but after populating the new variable targetInstructions.insert(setRef, instructionsToInject); System.out.println("Modified Target:"); printMethodNode(targetMethod); //write a class Class c = createClassFromClassNode(targetSource, TARGETCLASSNAME); Object o = c.newInstance(); Method m = o.getClass().getDeclaredMethod("concat", String.class, String.class, String.class, String.class); //should return HAHAHA not baseStringValue String result = (String) m.invoke(o, new Object[] { "A", "B", "C", "D" }); System.out.println("Concatenator.concat Result: " + result); assertTrue(result.equals("ABCD")); }
From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java
public void testMergedInReplacingThisWithOtherVariable() throws Exception { final String FIELDPROXYWORKED = "FIELDPROXYWORKED"; //set up the proxy object. this is the object that will receive //the proxied calls TestSubClass tcc = new TestSubClass(); tcc.setBaseString(FIELDPROXYWORKED); TestBaseClassHolder.setTestBase(tcc); //get the dynamic source that has the donor body in it ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF); MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout"); //load the target class String TARGETCLASSNAME = "com.triage.bytecodemaster.fortesting.TestFriend"; ClassNode targetSource = loadLocalClass(TARGETCLASSNAME); MethodNode targetMethod = findMethod(targetSource, "whatDoIThinkAbout"); System.out.println("Target"); printMethodNode(targetMethod);/*from w w w . ja v a2s .c o m*/ System.out.println("Donor"); printMethodNode(donorMethod); //alright here's the strategy: (1) inject a new local variable that points // to our remote instance, // (2) inject code that sets this local to the value of a method call, // (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1 InsnList instructionsToInject = donorMethod.instructions; //make a new local variable LabelNode begin = new LabelNode(); LabelNode end = new LabelNode(); instructionsToInject.insertBefore(instructionsToInject.getFirst(), begin); instructionsToInject.add(end); Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass"); int variableIndex = donorMethod.maxLocals; donorMethod.maxLocals += type.getSize(); donorMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(), variableIndex); //set the value of the local variable with a new instruction at the top //fetch a reference to our proxy object MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC, "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase", "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;"); //insert after begin label instructionsToInject.insert(begin, getTestBase); //store reference VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex); //insert store after fetch instructionsToInject.insert(getTestBase, setRef); //replace all references to 'this' with the new variable for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) { AbstractInsnNode node = instructionsToInject.get(currentIndex); if (node.getOpcode() == Opcodes.ALOAD) { VarInsnNode vin = (VarInsnNode) node; //'this' is var index 0. ours is var index varindex if (vin.var == 0) { vin.var = variableIndex; } } } System.out.println(">>>>>>>>>Finished Modifying<<<<<<<<"); printMethodNode(donorMethod); //insert the donorMethod targetMethod.instructions.insert(instructionsToInject); System.out.println(">>>>>>>>>Final Method<<<<<<<<"); printMethodNode(targetMethod); //write a class Class c = createClassFromClassNode(targetSource, TARGETCLASSNAME); Object o = c.newInstance(); Method m = o.getClass().getDeclaredMethod("whatDoIThinkAbout", TestPerson.class); TestPerson testPerson = new TestPerson(); testPerson.setName("AAAA"); //should return HAHAHA not baseStringValue String result = (String) m.invoke(o, new Object[] { testPerson }); System.out.println("TestFriend.whatDoIThinkAbout Result: " + result); assertTrue(result.equals(FIELDPROXYWORKED + "AAAA")); }