1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.implementation.bytecode;
17
18 import net.bytebuddy.description.type.TypeDefinition;
19 import net.bytebuddy.implementation.Implementation;
20 import net.bytebuddy.jar.asm.MethodVisitor;
21 import net.bytebuddy.jar.asm.Opcodes;
22
23 /**
24  * Removes a value from the operand stack.
25  */

26 public enum Removal implements StackManipulation {
27
28     /**
29      * A removal of no value. This corresponds a no-op instruction.
30      */

31     ZERO(StackSize.ZERO, Opcodes.NOP) {
32         /** {@inheritDoc} */
33         public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
34             return new Size(0, 0);
35         }
36     },
37
38     /**
39      * A removal of a single-sized value.
40      */

41     SINGLE(StackSize.SINGLE, Opcodes.POP),
42
43     /**
44      * A removal of a double-sized value.
45      */

46     DOUBLE(StackSize.DOUBLE, Opcodes.POP2);
47
48     /**
49      * The size impact of the removal onto the operand stack.
50      */

51     private final Size size;
52
53     /**
54      * The opcode to execute for the removal.
55      */

56     private final int opcode;
57
58     /**
59      * Creates a new removal stack manipulation.
60      *
61      * @param stackSize The size impact of the removal onto the operand stack.
62      * @param opcode    The opcode to execute for the removal.
63      */

64     Removal(StackSize stackSize, int opcode) {
65         size = stackSize.toDecreasingSize();
66         this.opcode = opcode;
67     }
68
69     /**
70      * Removes a value from the operand stack dependant of its size.
71      *
72      * @param typeDefinition The type to remove from the stack.
73      * @return A stack manipulation that represents the removal.
74      */

75     public static StackManipulation of(TypeDefinition typeDefinition) {
76         switch (typeDefinition.getStackSize()) {
77             case SINGLE:
78                 return SINGLE;
79             case DOUBLE:
80                 return DOUBLE;
81             case ZERO:
82                 return ZERO;
83             default:
84                 throw new AssertionError();
85         }
86     }
87
88     /**
89      * {@inheritDoc}
90      */

91     public boolean isValid() {
92         return true;
93     }
94
95     /**
96      * {@inheritDoc}
97      */

98     public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
99         methodVisitor.visitInsn(opcode);
100         return size;
101     }
102 }
103
104