summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/backend/jvm/opt/InstructionResultSize.scala
blob: 8d744f6d1308031861a5ca3f44b503dd531c61ea (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
package scala.tools.nsc.backend.jvm.opt

import scala.annotation.switch
import scala.tools.asm.{Handle, Type, Opcodes}
import scala.tools.asm.tree._

object InstructionResultSize {
  import Opcodes._
  def apply(instruction: AbstractInsnNode): Int = (instruction.getOpcode: @switch) match {
    // The order of opcodes is (almost) the same as in Opcodes.java
    case ACONST_NULL => 1

    case ICONST_M1 |
         ICONST_0 |
         ICONST_1 |
         ICONST_2 |
         ICONST_3 |
         ICONST_4 |
         ICONST_5 => 1

    case LCONST_0 |
         LCONST_1 => 2

    case FCONST_0 |
         FCONST_1 |
         FCONST_2 => 1

    case DCONST_0 |
         DCONST_1 => 2

    case BIPUSH |
         SIPUSH => 1

    case LDC =>
      instruction.asInstanceOf[LdcInsnNode].cst match {
        case _: java.lang.Integer |
             _: java.lang.Float |
             _: String |
             _: Type |
             _: Handle => 1

        case _: java.lang.Long |
             _: java.lang.Double => 2
      }

    case ILOAD |
         FLOAD |
         ALOAD => 1

    case LLOAD |
         DLOAD => 2

    case IALOAD |
         FALOAD |
         AALOAD |
         BALOAD |
         CALOAD |
         SALOAD => 1

    case LALOAD |
         DALOAD => 2

    case ISTORE |
         LSTORE |
         FSTORE |
         DSTORE |
         ASTORE => 0

    case IASTORE |
         LASTORE |
         FASTORE |
         DASTORE |
         AASTORE |
         BASTORE |
         CASTORE |
         SASTORE => 0

    case POP |
         POP2 => 0

    case DUP |
         DUP_X1 |
         DUP_X2 |
         DUP2 |
         DUP2_X1 |
         DUP2_X2 |
         SWAP => throw new IllegalArgumentException("Can't compute the size of DUP/SWAP without knowing what's on stack top")

    case IADD |
         FADD => 1

    case LADD |
         DADD => 2

    case ISUB |
         FSUB => 1

    case LSUB |
         DSUB => 2

    case IMUL |
         FMUL => 1

    case LMUL |
         DMUL => 2

    case IDIV |
         FDIV => 1

    case LDIV |
         DDIV => 2

    case IREM |
         FREM => 1

    case LREM |
         DREM => 2

    case INEG |
         FNEG => 1

    case LNEG |
         DNEG => 2

    case ISHL |
         ISHR => 1

    case LSHL |
         LSHR => 2

    case IUSHR => 1

    case LUSHR => 2

    case IAND |
         IOR |
         IXOR => 1

    case LAND |
         LOR |
         LXOR => 2

    case IINC => 1

    case I2F |
         L2I |
         L2F |
         F2I |
         D2I |
         D2F |
         I2B |
         I2C |
         I2S => 1

    case I2L |
         I2D |
         L2D |
         F2L |
         F2D |
         D2L => 2

    case LCMP |
         FCMPL |
         FCMPG |
         DCMPL |
         DCMPG => 1

    case IFEQ |
         IFNE |
         IFLT |
         IFGE |
         IFGT |
         IFLE => 0

    case IF_ICMPEQ |
         IF_ICMPNE |
         IF_ICMPLT |
         IF_ICMPGE |
         IF_ICMPGT |
         IF_ICMPLE |
         IF_ACMPEQ |
         IF_ACMPNE => 0

    case GOTO => 0

    case JSR => throw new IllegalArgumentException("Subroutines are not supported.")

    case RET => 0

    case TABLESWITCH |
         LOOKUPSWITCH => 0

    case IRETURN |
         FRETURN |
         ARETURN => 1

    case LRETURN |
         DRETURN => 2

    case RETURN => 0

    case GETSTATIC => Type.getType(instruction.asInstanceOf[FieldInsnNode].desc).getSize

    case PUTSTATIC => 0

    case GETFIELD => Type.getType(instruction.asInstanceOf[FieldInsnNode].desc).getSize

    case PUTFIELD => 0

    case INVOKEVIRTUAL |
         INVOKESPECIAL |
         INVOKESTATIC |
         INVOKEINTERFACE =>
      val desc = instruction.asInstanceOf[MethodInsnNode].desc
      Type.getReturnType(desc).getSize

    case INVOKEDYNAMIC =>
      val desc = instruction.asInstanceOf[InvokeDynamicInsnNode].desc
      Type.getReturnType(desc).getSize

    case NEW => 1

    case NEWARRAY |
         ANEWARRAY |
         ARRAYLENGTH => 1

    case ATHROW => 0

    case CHECKCAST |
         INSTANCEOF => 1

    case MONITORENTER |
         MONITOREXIT => 0

    case MULTIANEWARRAY => 1

    case IFNULL |
         IFNONNULL => 0
  }
}