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 
  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 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).intValue();
  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 }