IntType.java revision 1350:3cb11f4d617e
1/*
2 * Copyright (c) 2010, 2013, 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 LONG;
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            method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint);
159        }
160        return INT;
161    }
162
163    @Override
164    public Type shr(final MethodVisitor method) {
165        method.visitInsn(IUSHR);
166        return INT;
167    }
168
169    @Override
170    public Type sar(final MethodVisitor method) {
171        method.visitInsn(ISHR);
172        return INT;
173    }
174
175    @Override
176    public Type shl(final MethodVisitor method) {
177        method.visitInsn(ISHL);
178        return INT;
179    }
180
181    @Override
182    public Type and(final MethodVisitor method) {
183        method.visitInsn(IAND);
184        return INT;
185    }
186
187    @Override
188    public Type or(final MethodVisitor method) {
189        method.visitInsn(IOR);
190        return INT;
191    }
192
193    @Override
194    public Type xor(final MethodVisitor method) {
195        method.visitInsn(IXOR);
196        return INT;
197    }
198
199    @Override
200    public Type load(final MethodVisitor method, final int slot) {
201        assert slot != -1;
202        method.visitVarInsn(ILOAD, slot);
203        return INT;
204    }
205
206    @Override
207    public void store(final MethodVisitor method, final int slot) {
208        assert slot != -1;
209        method.visitVarInsn(ISTORE, slot);
210    }
211
212    @Override
213    public Type sub(final MethodVisitor method, final int programPoint) {
214        if(programPoint == INVALID_PROGRAM_POINT) {
215            method.visitInsn(ISUB);
216        } else {
217            method.visitInvokeDynamicInsn("isub", "(II)I", MATHBOOTSTRAP, programPoint);
218        }
219        return INT;
220    }
221
222    @Override
223    public Type mul(final MethodVisitor method, final int programPoint) {
224        if(programPoint == INVALID_PROGRAM_POINT) {
225            method.visitInsn(IMUL);
226        } else {
227            method.visitInvokeDynamicInsn("imul", "(II)I", MATHBOOTSTRAP, programPoint);
228        }
229        return INT;
230    }
231
232    @Override
233    public Type div(final MethodVisitor method, final int programPoint) {
234        if (programPoint == INVALID_PROGRAM_POINT) {
235            JSType.DIV_ZERO.invoke(method);
236        } else {
237            method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
238        }
239        return INT;
240    }
241
242    @Override
243    public Type rem(final MethodVisitor method, final int programPoint) {
244        if (programPoint == INVALID_PROGRAM_POINT) {
245            JSType.REM_ZERO.invoke(method);
246        } else {
247            method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
248        }
249        return INT;
250    }
251
252    @Override
253    public Type neg(final MethodVisitor method, final int programPoint) {
254        if(programPoint == INVALID_PROGRAM_POINT) {
255            method.visitInsn(INEG);
256        } else {
257            method.visitInvokeDynamicInsn("ineg", "(I)I", MATHBOOTSTRAP, programPoint);
258        }
259        return INT;
260    }
261
262    @Override
263    public void _return(final MethodVisitor method) {
264        method.visitInsn(IRETURN);
265    }
266
267    @Override
268    public Type loadUndefined(final MethodVisitor method) {
269        method.visitLdcInsn(UNDEFINED_INT);
270        return INT;
271    }
272
273    @Override
274    public Type loadForcedInitializer(final MethodVisitor method) {
275        method.visitInsn(ICONST_0);
276        return INT;
277    }
278
279    @Override
280    public Type cmp(final MethodVisitor method, final boolean isCmpG) {
281        throw new UnsupportedOperationException("cmp" + (isCmpG ? 'g' : 'l'));
282    }
283
284    @Override
285    public Type cmp(final MethodVisitor method) {
286        throw new UnsupportedOperationException("cmp");
287    }
288
289}
290