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.constant;
17
18 import net.bytebuddy.build.HashCodeAndEqualsPlugin;
19 import net.bytebuddy.implementation.Implementation;
20 import net.bytebuddy.implementation.bytecode.StackManipulation;
21 import net.bytebuddy.implementation.bytecode.StackSize;
22 import net.bytebuddy.jar.asm.MethodVisitor;
23 import net.bytebuddy.jar.asm.Opcodes;
24
25 /**
26  * This class is responsible for loading any {@code long} constant onto the operand stack.
27  */

28 public enum LongConstant implements StackManipulation {
29
30     /**
31      * A {@code long} constant of value {@code 0L}.
32      */

33     ZERO(Opcodes.LCONST_0),
34
35     /**
36      * A {@code long} constant of value {@code 1L}.
37      */

38     ONE(Opcodes.LCONST_1);
39
40     /**
41      * The size impact of loading a {@code double} constant onto the operand stack.
42      */

43     private static final Size SIZE = StackSize.DOUBLE.toIncreasingSize();
44
45     /**
46      * The shortcut opcode for loading a {@code long} constant.
47      */

48     private final int opcode;
49
50     /**
51      * Creates a new shortcut operation for loading a common {@code long} onto the operand stack.
52      *
53      * @param opcode The shortcut opcode for loading a {@code long} constant.
54      */

55     LongConstant(int opcode) {
56         this.opcode = opcode;
57     }
58
59     /**
60      * Creates a stack manipulation for loading a {@code long} value onto the operand stack.
61      * <p>&nbsp;</p>
62      * This is achieved either by invoking a specific opcode, if any, or by creating a constant pool entry.
63      *
64      * @param value The {@code long} value to load onto the stack.
65      * @return A stack manipulation for loading the given {@code long} value.
66      */

67     public static StackManipulation forValue(long value) {
68         if (value == 0L) {
69             return ZERO;
70         } else if (value == 1L) {
71             return ONE;
72         } else {
73             return new ConstantPool(value);
74         }
75     }
76
77     /**
78      * {@inheritDoc}
79      */

80     public boolean isValid() {
81         return true;
82     }
83
84     /**
85      * {@inheritDoc}
86      */

87     public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
88         methodVisitor.visitInsn(opcode);
89         return SIZE;
90     }
91
92     /**
93      * A stack manipulation for loading a {@code long} value from a class's constant pool onto the operand stack.
94      */

95     @HashCodeAndEqualsPlugin.Enhance
96     protected static class ConstantPool implements StackManipulation {
97
98         /**
99          * The {@code long} value to be loaded onto the operand stack.
100          */

101         private final long value;
102
103         /**
104          * Creates a new constant pool load operation.
105          *
106          * @param value The {@code long} value to be loaded onto the operand stack.
107          */

108         protected ConstantPool(long value) {
109             this.value = value;
110         }
111
112         /**
113          * {@inheritDoc}
114          */

115         public boolean isValid() {
116             return true;
117         }
118
119         /**
120          * {@inheritDoc}
121          */

122         public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
123             methodVisitor.visitLdcInsn(value);
124             return SIZE;
125         }
126     }
127 }
128