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 }