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 
  26 package jdk.nashorn.internal.codegen.types;
  27 
  28 import static jdk.internal.org.objectweb.asm.Opcodes.BIPUSH;
  29 import static jdk.internal.org.objectweb.asm.Opcodes.I2D;
  30 import static jdk.internal.org.objectweb.asm.Opcodes.I2L;
  31 import static jdk.internal.org.objectweb.asm.Opcodes.IADD;
  32 import static jdk.internal.org.objectweb.asm.Opcodes.IAND;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
  34 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
  35 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_2;
  36 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_3;
  37 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_4;
  38 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_5;
  39 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_M1;
  40 import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
  41 import static jdk.internal.org.objectweb.asm.Opcodes.IMUL;
  42 import static jdk.internal.org.objectweb.asm.Opcodes.INEG;
  43 import static jdk.internal.org.objectweb.asm.Opcodes.IOR;
  44 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
  45 import static jdk.internal.org.objectweb.asm.Opcodes.ISHL;
  46 import static jdk.internal.org.objectweb.asm.Opcodes.ISHR;
  47 import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
  48 import static jdk.internal.org.objectweb.asm.Opcodes.ISUB;
  49 import static jdk.internal.org.objectweb.asm.Opcodes.IUSHR;
  50 import static jdk.internal.org.objectweb.asm.Opcodes.IXOR;
  51 import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
  52 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  53 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
  54 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  55 
  56 import jdk.internal.org.objectweb.asm.MethodVisitor;
  57 import jdk.nashorn.internal.codegen.CompilerConstants;
  58 import jdk.nashorn.internal.runtime.JSType;
  59 
  60 /**
  61  * Type class: INT
  62  */
  63 class 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             invokestatic(method, JSType.TO_BOOLEAN_I);
 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 }