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 double} constant onto the operand stack.
27 */
28 public enum DoubleConstant implements StackManipulation {
29
30 /**
31 * A {@code double} constant of value {@code 0.0}.
32 */
33 ZERO(Opcodes.DCONST_0),
34
35 /**
36 * A {@code double} constant of value {@code 1.0}.
37 */
38 ONE(Opcodes.DCONST_1);
39
40 /**
41 * The size impact of loading a {@code double} constant onto the operand stack.
42 */
43 private static final StackManipulation.Size SIZE = StackSize.DOUBLE.toIncreasingSize();
44
45 /**
46 * The shortcut opcode for loading a {@code double} constant.
47 */
48 private final int opcode;
49
50 /**
51 * Creates a new shortcut operation for loading a common {@code double} onto the operand stack.
52 *
53 * @param opcode The shortcut opcode for loading a {@code double} constant.
54 */
55 DoubleConstant(int opcode) {
56 this.opcode = opcode;
57 }
58
59 /**
60 * Creates a stack manipulation for loading a {@code double} value onto the operand stack.
61 * <p> </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 double} value to load onto the stack.
65 * @return A stack manipulation for loading the given {@code double} value.
66 */
67 public static StackManipulation forValue(double value) {
68 if (value == 0d) {
69 return ZERO;
70 } else if (value == 1d) {
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 StackManipulation.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 double} 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 double} value to be loaded onto the operand stack.
100 */
101 private final double value;
102
103 /**
104 * Creates a new constant pool load operation.
105 *
106 * @param value The {@code double} value to be loaded onto the operand stack.
107 */
108 protected ConstantPool(double 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