List of usage examples for org.objectweb.asm Opcodes ALOAD
int ALOAD
To view the source code for org.objectweb.asm Opcodes ALOAD.
Click Source Link
From source file:com.android.tools.layoutlib.create.DelegateMethodAdapter.java
License:Apache License
/** * Generates the new code for the method. * <p/>//from w w w .ja v a2 s.co m * For native methods, this must be invoked directly by {@link DelegateClassAdapter} * (since they have no code to visit). * <p/> * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then * this method will be invoked from {@link MethodVisitor#visitEnd()}. */ public void generateCode() { /* * The goal is to generate a call to a static delegate method. * If this method is non-static, the first parameter will be 'this'. * All the parameters must be passed and then the eventual return type returned. * * Example, let's say we have a method such as * public void method_1(int a, Object b, ArrayList<String> c) { ... } * * We'll want to create a body that calls a delegate method like this: * TheClass_Delegate.method_1(this, a, b, c); * * If the method is non-static and the class name is an inner class (e.g. has $ in its * last segment), we want to push the 'this' of the outer class first: * OuterClass_InnerClass_Delegate.method_1( * OuterClass.this, * OuterClass$InnerClass.this, * a, b, c); * * Only one level of inner class is supported right now, for simplicity and because * we don't need more. * * The generated class name is the current class name with "_Delegate" appended to it. * One thing to realize is that we don't care about generics -- since generic types * are erased at runtime, they have no influence on the method name being called. */ // Add our annotation AnnotationVisitor aw = mParentVisitor.visitAnnotation( Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), true); // visible at runtime aw.visitEnd(); if (!mVisitCodeCalled) { // If this is a direct call to generateCode() as done by DelegateClassAdapter // for natives, visitCode() hasn't been called yet. mParentVisitor.visitCode(); mVisitCodeCalled = true; } ArrayList<Type> paramTypes = new ArrayList<Type>(); String delegateClassName = mClassName + DELEGATE_SUFFIX; boolean pushedArg0 = false; int maxStack = 0; // For an instance method (e.g. non-static), push the 'this' preceded // by the 'this' of any outer class, if any. if (!mIsStatic) { // Check if the last segment of the class name has inner an class. // Right now we only support one level of inner classes. int slash = mClassName.lastIndexOf('/'); int dol = mClassName.lastIndexOf('$'); if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) { String outerClass = mClassName.substring(0, dol); Type outerType = Type.getObjectType(outerClass); // Change a delegate class name to "com/foo/Outer_Inner_Delegate" delegateClassName = delegateClassName.replace('$', '_'); // The first-level inner class has a package-protected member called 'this$0' // that points to the outer class. // Push this.getField("this$0") on the call stack. mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this mParentVisitor.visitFieldInsn(Opcodes.GETFIELD, mClassName, // class where the field is defined "this$0", // field name outerType.getDescriptor()); // type of the field maxStack++; paramTypes.add(outerType); } // Push "this" for the instance method, which is always ALOAD 0 mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); maxStack++; pushedArg0 = true; paramTypes.add(Type.getObjectType(mClassName)); } // Push all other arguments. Start at arg 1 if we already pushed 'this' above. Type[] argTypes = Type.getArgumentTypes(mDesc); int maxLocals = pushedArg0 ? 1 : 0; for (Type t : argTypes) { int size = t.getSize(); mParentVisitor.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals); maxLocals += size; maxStack += size; paramTypes.add(t); } // Construct the descriptor of the delegate based on the parameters // we pushed on the call stack. The return type remains unchanged. String desc = Type.getMethodDescriptor(Type.getReturnType(mDesc), paramTypes.toArray(new Type[paramTypes.size()])); // Invoke the static delegate mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, delegateClassName, mMethodName, desc); Type returnType = Type.getReturnType(mDesc); mParentVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); mParentVisitor.visitMaxs(maxStack, maxLocals); mParentVisitor.visitEnd(); // For debugging now. Maybe we should collect these and store them in // a text file for helping create the delegates. We could also compare // the text file to a golden and break the build on unsupported changes // or regressions. Even better we could fancy-print something that looks // like the expected Java method declaration. mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc); }
From source file:com.android.tools.layoutlib.create.DelegateMethodAdapter2.java
License:Apache License
/** * Generates the new code for the method. * <p/>/*from w w w .j a v a2 s .c om*/ * For native methods, this must be invoked directly by {@link DelegateClassAdapter} * (since they have no code to visit). * <p/> * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then * this method will be invoked from {@link MethodVisitor#visitEnd()}. */ public void generateDelegateCode() { /* * The goal is to generate a call to a static delegate method. * If this method is non-static, the first parameter will be 'this'. * All the parameters must be passed and then the eventual return type returned. * * Example, let's say we have a method such as * public void myMethod(int a, Object b, ArrayList<String> c) { ... } * * We'll want to create a body that calls a delegate method like this: * TheClass_Delegate.myMethod(this, a, b, c); * * If the method is non-static and the class name is an inner class (e.g. has $ in its * last segment), we want to push the 'this' of the outer class first: * OuterClass_InnerClass_Delegate.myMethod( * OuterClass.this, * OuterClass$InnerClass.this, * a, b, c); * * Only one level of inner class is supported right now, for simplicity and because * we don't need more. * * The generated class name is the current class name with "_Delegate" appended to it. * One thing to realize is that we don't care about generics -- since generic types * are erased at build time, they have no influence on the method name being called. */ // Add our annotation AnnotationVisitor aw = mDelWriter.visitAnnotation( Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), true); // visible at runtime if (aw != null) { aw.visitEnd(); } mDelWriter.visitCode(); if (mDelegateLineNumber != null) { Object[] p = mDelegateLineNumber; mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]); } ArrayList<Type> paramTypes = new ArrayList<Type>(); String delegateClassName = mClassName + DELEGATE_SUFFIX; boolean pushedArg0 = false; int maxStack = 0; // Check if the last segment of the class name has inner an class. // Right now we only support one level of inner classes. Type outerType = null; int slash = mClassName.lastIndexOf('/'); int dol = mClassName.lastIndexOf('$'); if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) { String outerClass = mClassName.substring(0, dol); outerType = Type.getObjectType(outerClass); // Change a delegate class name to "com/foo/Outer_Inner_Delegate" delegateClassName = delegateClassName.replace('$', '_'); } // For an instance method (e.g. non-static), push the 'this' preceded // by the 'this' of any outer class, if any. if (!mIsStatic) { if (outerType != null) { // The first-level inner class has a package-protected member called 'this$0' // that points to the outer class. // Push this.getField("this$0") on the call stack. mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this mDelWriter.visitFieldInsn(Opcodes.GETFIELD, mClassName, // class where the field is defined "this$0", // field name outerType.getDescriptor()); // type of the field maxStack++; paramTypes.add(outerType); } // Push "this" for the instance method, which is always ALOAD 0 mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); maxStack++; pushedArg0 = true; paramTypes.add(Type.getObjectType(mClassName)); } // Push all other arguments. Start at arg 1 if we already pushed 'this' above. Type[] argTypes = Type.getArgumentTypes(mDesc); int maxLocals = pushedArg0 ? 1 : 0; for (Type t : argTypes) { int size = t.getSize(); mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals); maxLocals += size; maxStack += size; paramTypes.add(t); } // Construct the descriptor of the delegate based on the parameters // we pushed on the call stack. The return type remains unchanged. String desc = Type.getMethodDescriptor(Type.getReturnType(mDesc), paramTypes.toArray(new Type[paramTypes.size()])); // Invoke the static delegate mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC, delegateClassName, mMethodName, desc); Type returnType = Type.getReturnType(mDesc); mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN)); mDelWriter.visitMaxs(maxStack, maxLocals); mDelWriter.visitEnd(); // For debugging now. Maybe we should collect these and store them in // a text file for helping create the delegates. We could also compare // the text file to a golden and break the build on unsupported changes // or regressions. Even better we could fancy-print something that looks // like the expected Java method declaration. mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc); }
From source file:com.android.tools.layoutlib.create.StubMethodAdapter.java
License:Apache License
private void generateInvoke() { /* Generates the code: * OverrideMethod.invoke("signature", mIsNative ? true : false, null or this); *///www .j av a 2 s. co m mParentVisitor.visitLdcInsn(mInvokeSignature); // push true or false mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0); // push null or this if (mIsStatic) { mParentVisitor.visitInsn(Opcodes.ACONST_NULL); } else { mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); } int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID; switch (sort) { case Type.VOID: mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/android/tools/layoutlib/create/OverrideMethod", "invokeV", "(Ljava/lang/String;ZLjava/lang/Object;)V"); mParentVisitor.visitInsn(Opcodes.RETURN); break; case Type.BOOLEAN: case Type.CHAR: case Type.BYTE: case Type.SHORT: case Type.INT: mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/android/tools/layoutlib/create/OverrideMethod", "invokeI", "(Ljava/lang/String;ZLjava/lang/Object;)I"); switch (sort) { case Type.BOOLEAN: Label l1 = new Label(); mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1); mParentVisitor.visitInsn(Opcodes.ICONST_1); mParentVisitor.visitInsn(Opcodes.IRETURN); mParentVisitor.visitLabel(l1); mParentVisitor.visitInsn(Opcodes.ICONST_0); break; case Type.CHAR: mParentVisitor.visitInsn(Opcodes.I2C); break; case Type.BYTE: mParentVisitor.visitInsn(Opcodes.I2B); break; case Type.SHORT: mParentVisitor.visitInsn(Opcodes.I2S); break; } mParentVisitor.visitInsn(Opcodes.IRETURN); break; case Type.LONG: mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/android/tools/layoutlib/create/OverrideMethod", "invokeL", "(Ljava/lang/String;ZLjava/lang/Object;)J"); mParentVisitor.visitInsn(Opcodes.LRETURN); break; case Type.FLOAT: mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/android/tools/layoutlib/create/OverrideMethod", "invokeF", "(Ljava/lang/String;ZLjava/lang/Object;)F"); mParentVisitor.visitInsn(Opcodes.FRETURN); break; case Type.DOUBLE: mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/android/tools/layoutlib/create/OverrideMethod", "invokeD", "(Ljava/lang/String;ZLjava/lang/Object;)D"); mParentVisitor.visitInsn(Opcodes.DRETURN); break; case Type.ARRAY: case Type.OBJECT: mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, "com/android/tools/layoutlib/create/OverrideMethod", "invokeA", "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;"); mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName()); mParentVisitor.visitInsn(Opcodes.ARETURN); break; } }
From source file:com.android.tools.lint.checks.FieldGetterDetector.java
License:Apache License
@Override public void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method, @NonNull AbstractInsnNode instruction) { // As of Gingerbread/API 9, Dalvik performs this optimization automatically if (context.getProject().getMinSdk() >= 9) { return;/*from ww w . j av a2s .c o m*/ } if ((method.access & Opcodes.ACC_STATIC) != 0) { // Not an instance method return; } if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) { return; } MethodInsnNode node = (MethodInsnNode) instruction; String name = node.name; String owner = node.owner; AbstractInsnNode prev = LintUtils.getPrevInstruction(instruction); if (prev == null || prev.getOpcode() != Opcodes.ALOAD) { return; } VarInsnNode prevVar = (VarInsnNode) prev; if (prevVar.var != 0) { // Not on "this", variable 0 in instance methods? return; } if (((name.startsWith("get") && name.length() > 3 //$NON-NLS-1$ && Character.isUpperCase(name.charAt(3))) || (name.startsWith("is") && name.length() > 2 //$NON-NLS-1$ && Character.isUpperCase(name.charAt(2)))) && owner.equals(classNode.name)) { // Calling a potential getter method on self. We now need to // investigate the method body of the getter call and make sure // it's really a plain getter, not just a method which happens // to have a method name like a getter, or a method which not // only returns a field but possibly computes it or performs // other initialization or side effects. This is done in a // second pass over the bytecode, initiated by the finish() // method. if (mPendingCalls == null) { mPendingCalls = new ArrayList<Entry>(); } mPendingCalls.add(new Entry(name, node, method)); } super.checkInstruction(context, classNode, method, instruction); }
From source file:com.android.tools.lint.checks.FieldGetterDetector.java
License:Apache License
private static Map<String, String> checkMethods(ClassNode classNode, Set<String> names) { Map<String, String> validGetters = Maps.newHashMap(); @SuppressWarnings("rawtypes") List methods = classNode.methods; String fieldName = null;//from w ww . j a v a 2 s.c o m checkMethod: for (Object methodObject : methods) { MethodNode method = (MethodNode) methodObject; if (names.contains(method.name) && method.desc.startsWith("()")) { //$NON-NLS-1$ // (): No arguments InsnList instructions = method.instructions; int mState = 1; for (AbstractInsnNode curr = instructions.getFirst(); curr != null; curr = curr.getNext()) { switch (curr.getOpcode()) { case -1: // Skip label and line number nodes continue; case Opcodes.ALOAD: if (mState == 1) { fieldName = null; mState = 2; } else { continue checkMethod; } break; case Opcodes.GETFIELD: if (mState == 2) { FieldInsnNode field = (FieldInsnNode) curr; fieldName = field.name; mState = 3; } else { continue checkMethod; } break; case Opcodes.ARETURN: case Opcodes.FRETURN: case Opcodes.IRETURN: case Opcodes.DRETURN: case Opcodes.LRETURN: case Opcodes.RETURN: if (mState == 3) { validGetters.put(method.name, fieldName); } continue checkMethod; default: continue checkMethod; } } } } return validGetters; }
From source file:com.android.tools.lint.checks.UnsafeBroadcastReceiverDetector.java
License:Apache License
@SuppressWarnings("rawtypes") public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) { // If class isn't in mReceiversWithIntentFilter (set below by // XmlScanner), skip it. if (!mReceiversWithProtectedBroadcastIntentFilter.contains(classNode.name)) { return;//from w w w . ja v a 2s. c o m } // Search for "void onReceive(android.content.Context, android.content.Intent)" method List methodList = classNode.methods; for (Object m : methodList) { MethodNode method = (MethodNode) m; if (!"onReceive".equals(method.name) || !"(Landroid/content/Context;Landroid/content/Intent;)V".equals(method.desc)) { continue; } // Search for call to getAction but also search for references to aload_2, // which indicates that the method is making use of the received intent in // some way. // // If the onReceive method doesn't call getAction but does make use of // the received intent, it is possible that it is passing it to another // method that might be performing the getAction check, so we warn that the // finding may be a false positive. (An alternative option would be to not // report a finding at all in this case.) boolean getActionEncountered = false; boolean intentParameterEncountered = false; InsnList nodes = method.instructions; for (int i = 0, n = nodes.size(); i < n; i++) { AbstractInsnNode instruction = nodes.get(i); int type = instruction.getType(); if (type == AbstractInsnNode.VAR_INSN) { VarInsnNode node = (VarInsnNode) instruction; if (node.getOpcode() == Opcodes.ALOAD) { if (node.var == 2) { intentParameterEncountered = true; } } } else if (type == AbstractInsnNode.METHOD_INSN) { MethodInsnNode node = (MethodInsnNode) instruction; if ("android/content/Intent".equals(node.owner) && "getAction".equals(node.name)) { getActionEncountered = true; break; } } } if (!getActionEncountered) { Location location = context.getLocation(method, classNode); String report; if (!intentParameterEncountered) { report = "This broadcast receiver declares an intent-filter for a protected " + "broadcast action string, which can only be sent by the system, " + "not third-party applications. However, the receiver's onReceive " + "method does not appear to call getAction to ensure that the " + "received Intent's action string matches the expected value, " + "potentially making it possible for another actor to send a " + "spoofed intent with no action string or a different action " + "string and cause undesired behavior."; } else { // An alternative implementation option is to not report a finding at all in // this case, if we are worried about false positives causing confusion or // resulting in developers ignoring other lint warnings. report = "This broadcast receiver declares an intent-filter for a protected " + "broadcast action string, which can only be sent by the system, " + "not third-party applications. However, the receiver's onReceive " + "method does not appear to call getAction to ensure that the " + "received Intent's action string matches the expected value, " + "potentially making it possible for another actor to send a " + "spoofed intent with no action string or a different action " + "string and cause undesired behavior. In this case, it is " + "possible that the onReceive method passed the received Intent " + "to another method that checked the action string. If so, this " + "finding can safely be ignored."; } context.report(ACTION_STRING, method, null, location, report); } } }
From source file:com.asakusafw.dag.compiler.builtin.ConvertOperatorGenerator.java
License:Apache License
private static ClassData generateClass(Context context, UserOperator operator, ClassDescription target) { OperatorInput input = operator.getInput(0); OperatorOutput output = operator.getOutput(Convert.ID_OUTPUT_CONVERTED); OperatorOutput copy = operator.getOutput(Convert.ID_OUTPUT_ORIGINAL); ClassWriter writer = newWriter(target, Object.class, Result.class); FieldRef impl = defineOperatorField(writer, operator, target); Map<OperatorProperty, FieldRef> map = defineConstructor(context, operator, target, writer, method -> { setOperatorField(method, operator, impl); });/*w w w.j a v a2 s . c o m*/ defineResultAdd(writer, method -> { LocalVarRef self = new LocalVarRef(Opcodes.ALOAD, 0); LocalVarRef data = cast(method, 1, input.getDataType()); self.load(method); getField(method, map.get(output)); List<ValueRef> arguments = new ArrayList<>(); arguments.add(impl); arguments.add(data); appendSecondaryInputs(arguments::add, operator, map::get); appendArguments(arguments::add, operator, map::get); invoke(method, context, operator, arguments); invokeResultAdd(method); // must invoke about "original" after "converted" was processed self.load(method); getField(method, map.get(copy)); data.load(method); invokeResultAdd(method); }); return new ClassData(target, writer::toByteArray); }
From source file:com.asakusafw.dag.compiler.builtin.ExtractOperatorGenerator.java
License:Apache License
private static ClassData generateClass(Context context, UserOperator operator, ClassDescription target) { OperatorInput input = operator.getInput(Extract.ID_INPUT); ClassWriter writer = newWriter(target, Object.class, Result.class); FieldRef impl = defineOperatorField(writer, operator, target); Map<OperatorProperty, FieldRef> map = defineConstructor(context, operator, target, writer, method -> { setOperatorField(method, operator, impl); });// w w w. j a v a 2 s . co m defineResultAdd(writer, method -> { cast(method, 1, input.getDataType()); List<ValueRef> arguments = new ArrayList<>(); arguments.add(impl); arguments.add(new LocalVarRef(Opcodes.ALOAD, 1)); appendSecondaryInputs(arguments::add, operator, map::get); appendOutputs(arguments::add, operator, map::get); appendArguments(arguments::add, operator, map::get); invoke(method, context, operator, arguments); }); return new ClassData(target, writer::toByteArray); }
From source file:com.asakusafw.dag.compiler.builtin.FoldOperatorGenerator.java
License:Apache License
private ClassData generateClass(Context context, UserOperator operator, ClassDescription target) { ClassDescription combinerClass = generateCombinerClass(context, operator, target); ClassWriter writer = newWriter(target, CombineResult.class); writer.visitInnerClass(combinerClass.getInternalName(), target.getInternalName(), combinerClass.getSimpleName(), Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC); OperatorInput input = operator.getInput(Fold.ID_INPUT); defineDependenciesConstructor(context, operator.getOutputs(), target, writer, method -> { method.visitVarInsn(Opcodes.ALOAD, 0); getNew(method, combinerClass);//w ww .j a va 2 s . c o m getNew(method, input.getDataType()); method.visitVarInsn(Opcodes.ALOAD, 1); method.visitMethodInsn(Opcodes.INVOKESPECIAL, typeOf(CombineResult.class).getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, typeOf(ObjectCombiner.class), typeOf(DataModel.class), typeOf(Result.class)), false); }, Lang.discard()); writer.visitEnd(); return new ClassData(target, writer::toByteArray); }
From source file:com.asakusafw.dag.compiler.builtin.FoldOperatorGenerator.java
License:Apache License
private ClassDescription generateCombinerClass(Context context, UserOperator operator, ClassDescription outer) { ClassDescription target = getCombinerName(outer); OperatorInput input = operator.getInput(0); ClassWriter writer = newWriter(target, Object.class, ObjectCombiner.class); writer.visitOuterClass(outer.getInternalName(), target.getInternalName(), null); FieldRef impl = defineOperatorField(writer, operator, target); defineEmptyConstructor(writer, Object.class, method -> { setOperatorField(method, operator, impl); });/*w ww.j a v a2 s . co m*/ defineBuildKey(context, writer, input.getDataType(), input.getGroup()); MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC, "combine", Type.getMethodDescriptor(Type.VOID_TYPE, typeOf(Object.class), typeOf(Object.class)), null, null); List<ValueRef> arguments = new ArrayList<>(); arguments.add(impl); arguments.add(m -> { m.visitVarInsn(Opcodes.ALOAD, 1); m.visitTypeInsn(Opcodes.CHECKCAST, typeOf(input.getDataType()).getInternalName()); }); arguments.add(m -> { m.visitVarInsn(Opcodes.ALOAD, 2); m.visitTypeInsn(Opcodes.CHECKCAST, typeOf(input.getDataType()).getInternalName()); }); for (VertexElement dep : context.getDependencies(operator.getArguments())) { Invariants.require(dep.getElementKind() == ElementKind.VALUE); ValueDescription value = ((ValueElement) dep).getValue(); arguments.add(m -> { getConst(method, Invariants.safe(() -> value.resolve(context.getClassLoader()))); }); } invoke(method, context, operator, arguments); method.visitInsn(Opcodes.RETURN); method.visitMaxs(0, 0); method.visitEnd(); return context.addClassFile(new ClassData(target, writer::toByteArray)); }