1/*
2 * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.codegen.types;
27
28import static jdk.internal.org.objectweb.asm.Opcodes.BIPUSH;
29import static jdk.internal.org.objectweb.asm.Opcodes.I2D;
30import static jdk.internal.org.objectweb.asm.Opcodes.I2L;
31import static jdk.internal.org.objectweb.asm.Opcodes.IADD;
32import static jdk.internal.org.objectweb.asm.Opcodes.IAND;
33import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
34import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
35import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_2;
36import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_3;
37import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_4;
38import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_5;
39import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_M1;
40import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
41import static jdk.internal.org.objectweb.asm.Opcodes.IMUL;
42import static jdk.internal.org.objectweb.asm.Opcodes.INEG;
43import static jdk.internal.org.objectweb.asm.Opcodes.IOR;
44import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
45import static jdk.internal.org.objectweb.asm.Opcodes.ISHL;
46import static jdk.internal.org.objectweb.asm.Opcodes.ISHR;
47import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
48import static jdk.internal.org.objectweb.asm.Opcodes.ISUB;
49import static jdk.internal.org.objectweb.asm.Opcodes.IUSHR;
50import static jdk.internal.org.objectweb.asm.Opcodes.IXOR;
51import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
52import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
53import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
54import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
55
56import jdk.internal.org.objectweb.asm.MethodVisitor;
57import jdk.nashorn.internal.codegen.CompilerConstants;
58import jdk.nashorn.internal.runtime.JSType;
59
60/**
61 * Type class: INT
62 */
63class IntType extends BitwiseType {
64    private static final long serialVersionUID = 1L;
65
66    private static final CompilerConstants.Call TO_STRING = staticCallNoLookup(Integer.class, "toString", String.class, int.class);
67    private static final CompilerConstants.Call VALUE_OF  = staticCallNoLookup(Integer.class, "valueOf", Integer.class, int.class);
68
69    protected IntType() {
70        super("int", int.class, 2, 1);
71    }
72
73    @Override
74    public Type nextWider() {
75        return NUMBER;
76    }
77
78    @Override
79    public Class<?> getBoxedType() {
80        return Integer.class;
81    }
82
83    @Override
84    public char getBytecodeStackType() {
85        return 'I';
86    }
87
88    @Override
89    public Type ldc(final MethodVisitor method, final Object c) {
90        assert c instanceof Integer;
91
92        final int value = ((Integer) c);
93
94        switch (value) {
95        case -1:
96            method.visitInsn(ICONST_M1);
97            break;
98        case 0:
99            method.visitInsn(ICONST_0);
100            break;
101        case 1:
102            method.visitInsn(ICONST_1);
103            break;
104        case 2:
105            method.visitInsn(ICONST_2);
106            break;
107        case 3:
108            method.visitInsn(ICONST_3);
109            break;
110        case 4:
111            method.visitInsn(ICONST_4);
112            break;
113        case 5:
114            method.visitInsn(ICONST_5);
115            break;
116        default:
117            if (value == (byte) value) {
118                method.visitIntInsn(BIPUSH, value);
119            } else if (value == (short) value) {
120                method.visitIntInsn(SIPUSH, value);
121            } else {
122                method.visitLdcInsn(c);
123            }
124            break;
125        }
126
127        return Type.INT;
128    }
129
130    @Override
131    public Type convert(final MethodVisitor method, final Type to) {
132        if (to.isEquivalentTo(this)) {
133            return to;
134        }
135
136        if (to.isNumber()) {
137            method.visitInsn(I2D);
138        } else if (to.isLong()) {
139            method.visitInsn(I2L);
140        } else if (to.isBoolean()) {
141            //nop
142        } else if (to.isString()) {
143            invokestatic(method, TO_STRING);
144        } else if (to.isObject()) {
145            invokestatic(method, VALUE_OF);
146        } else {
147            throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
148        }
149
150        return to;
151    }
152
153    @Override
154    public Type add(final MethodVisitor method, final int programPoint) {
155        if(programPoint == INVALID_PROGRAM_POINT) {
156            method.visitInsn(IADD);
157        } else {
158            ldc(method, programPoint);
159            JSType.ADD_EXACT.invoke(method);
160        }
161        return INT;
162    }
163
164    @Override
165    public Type shr(final MethodVisitor method) {
166        method.visitInsn(IUSHR);
167        return INT;
168    }
169
170    @Override
171    public Type sar(final MethodVisitor method) {
172        method.visitInsn(ISHR);
173        return INT;
174    }
175
176    @Override
177    public Type shl(final MethodVisitor method) {
178        method.visitInsn(ISHL);
179        return INT;
180    }
181
182    @Override
183    public Type and(final MethodVisitor method) {
184        method.visitInsn(IAND);
185        return INT;
186    }
187
188    @Override
189    public Type or(final MethodVisitor method) {
190        method.visitInsn(IOR);
191        return INT;
192    }
193
194    @Override
195    public Type xor(final MethodVisitor method) {
196        method.visitInsn(IXOR);
197        return INT;
198    }
199
200    @Override
201    public Type load(final MethodVisitor method, final int slot) {
202        assert slot != -1;
203        method.visitVarInsn(ILOAD, slot);
204        return INT;
205    }
206
207    @Override
208    public void store(final MethodVisitor method, final int slot) {
209        assert slot != -1;
210        method.visitVarInsn(ISTORE, slot);
211    }
212
213    @Override
214    public Type sub(final MethodVisitor method, final int programPoint) {
215        if(programPoint == INVALID_PROGRAM_POINT) {
216            method.visitInsn(ISUB);
217        } else {
218            ldc(method, programPoint);
219            JSType.SUB_EXACT.invoke(method);
220        }
221        return INT;
222    }
223
224    @Override
225    public Type mul(final MethodVisitor method, final int programPoint) {
226        if(programPoint == INVALID_PROGRAM_POINT) {
227            method.visitInsn(IMUL);
228        } else {
229            ldc(method, programPoint);
230            JSType.MUL_EXACT.invoke(method);
231        }
232        return INT;
233    }
234
235    @Override
236    public Type div(final MethodVisitor method, final int programPoint) {
237        if (programPoint == INVALID_PROGRAM_POINT) {
238            JSType.DIV_ZERO.invoke(method);
239        } else {
240            ldc(method, programPoint);
241            JSType.DIV_EXACT.invoke(method);
242        }
243        return INT;
244    }
245
246    @Override
247    public Type rem(final MethodVisitor method, final int programPoint) {
248        if (programPoint == INVALID_PROGRAM_POINT) {
249            JSType.REM_ZERO.invoke(method);
250        } else {
251            ldc(method, programPoint);
252            JSType.REM_EXACT.invoke(method);
253        }
254        return INT;
255    }
256
257    @Override
258    public Type neg(final MethodVisitor method, final int programPoint) {
259        if(programPoint == INVALID_PROGRAM_POINT) {
260            method.visitInsn(INEG);
261        } else {
262            ldc(method, programPoint);
263            JSType.NEGATE_EXACT.invoke(method);
264        }
265        return INT;
266    }
267
268    @Override
269    public void _return(final MethodVisitor method) {
270        method.visitInsn(IRETURN);
271    }
272
273    @Override
274    public Type loadUndefined(final MethodVisitor method) {
275        method.visitLdcInsn(UNDEFINED_INT);
276        return INT;
277    }
278
279    @Override
280    public Type loadForcedInitializer(final MethodVisitor method) {
281        method.visitInsn(ICONST_0);
282        return INT;
283    }
284
285    @Override
286    public Type cmp(final MethodVisitor method, final boolean isCmpG) {
287        throw new UnsupportedOperationException("cmp" + (isCmpG ? 'g' : 'l'));
288    }
289
290    @Override
291    public Type cmp(final MethodVisitor method) {
292        throw new UnsupportedOperationException("cmp");
293    }
294
295}
296