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.L2D;
  29 import static jdk.internal.org.objectweb.asm.Opcodes.L2I;
  30 import static jdk.internal.org.objectweb.asm.Opcodes.LADD;
  31 import static jdk.internal.org.objectweb.asm.Opcodes.LAND;
  32 import static jdk.internal.org.objectweb.asm.Opcodes.LCMP;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0;
  34 import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1;
  35 import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
  36 import static jdk.internal.org.objectweb.asm.Opcodes.LMUL;
  37 import static jdk.internal.org.objectweb.asm.Opcodes.LOR;
  38 import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN;
  39 import static jdk.internal.org.objectweb.asm.Opcodes.LSHL;
  40 import static jdk.internal.org.objectweb.asm.Opcodes.LSHR;
  41 import static jdk.internal.org.objectweb.asm.Opcodes.LSTORE;
  42 import static jdk.internal.org.objectweb.asm.Opcodes.LSUB;
  43 import static jdk.internal.org.objectweb.asm.Opcodes.LUSHR;
  44 import static jdk.internal.org.objectweb.asm.Opcodes.LXOR;
  45 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  46 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
  47 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  48 
  49 import jdk.internal.org.objectweb.asm.MethodVisitor;
  50 import jdk.nashorn.internal.codegen.CompilerConstants;
  51 import jdk.nashorn.internal.runtime.JSType;
  52 
  53 /**
  54  * Type class: LONG
  55  */
  56 class LongType extends BitwiseType {
  57     private static final long serialVersionUID = 1L;
  58 
  59     private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class);
  60 
  61     protected LongType(final String name) {
  62         super(name, long.class, 3, 2);
  63     }
  64 
  65     protected LongType() {
  66         this("long");
  67     }
  68 
  69     @Override
  70     public Type nextWider() {
  71         return NUMBER;
  72     }
  73 
  74     @Override
  75     public Class<?> getBoxedType() {
  76         return Long.class;
  77     }
  78 
  79     @Override
  80     public char getBytecodeStackType() {
  81         return 'J';
  82     }
  83 
  84     @Override
  85     public Type cmp(final MethodVisitor method) {
  86         method.visitInsn(LCMP);
  87         return INT;
  88     }
  89 
  90     @Override
  91     public Type load(final MethodVisitor method, final int slot) {
  92         assert slot != -1;
  93         method.visitVarInsn(LLOAD, slot);
  94         return LONG;
  95     }
  96 
  97     @Override
  98     public void store(final MethodVisitor method, final int slot) {
  99         assert slot != -1;
 100         method.visitVarInsn(LSTORE, slot);
 101     }
 102 
 103     @Override
 104     public Type ldc(final MethodVisitor method, final Object c) {
 105         assert c instanceof Long;
 106 
 107         final long value = (Long) c;
 108 
 109         if (value == 0L) {
 110             method.visitInsn(LCONST_0);
 111         } else if (value == 1L) {
 112             method.visitInsn(LCONST_1);
 113         } else {
 114             method.visitLdcInsn(c);
 115         }
 116 
 117         return Type.LONG;
 118     }
 119 
 120     @Override
 121     public Type convert(final MethodVisitor method, final Type to) {
 122         if (isEquivalentTo(to)) {
 123             return to;
 124         }
 125 
 126         if (to.isNumber()) {
 127             method.visitInsn(L2D);
 128         } else if (to.isInteger()) {
 129             invokestatic(method, JSType.TO_INT32_L);
 130         } else if (to.isBoolean()) {
 131             method.visitInsn(L2I);
 132         } else if (to.isObject()) {
 133             invokestatic(method, VALUE_OF);
 134         } else {
 135             assert false : "Illegal conversion " + this + " -> " + to;
 136         }
 137 
 138         return to;
 139     }
 140 
 141     @Override
 142     public Type add(final MethodVisitor method, final int programPoint) {
 143         if(programPoint == INVALID_PROGRAM_POINT) {
 144             method.visitInsn(LADD);
 145         } else {
 146             method.visitInvokeDynamicInsn("ladd", "(JJ)J", MATHBOOTSTRAP, programPoint);
 147         }
 148         return LONG;
 149     }
 150 
 151     @Override
 152     public Type sub(final MethodVisitor method, final int programPoint) {
 153         if(programPoint == INVALID_PROGRAM_POINT) {
 154             method.visitInsn(LSUB);
 155         } else {
 156             method.visitInvokeDynamicInsn("lsub", "(JJ)J", MATHBOOTSTRAP, programPoint);
 157         }
 158         return LONG;
 159     }
 160 
 161     @Override
 162     public Type mul(final MethodVisitor method, final int programPoint) {
 163         if(programPoint == INVALID_PROGRAM_POINT) {
 164             method.visitInsn(LMUL);
 165         } else {
 166             method.visitInvokeDynamicInsn("lmul", "(JJ)J", MATHBOOTSTRAP, programPoint);
 167         }
 168         return LONG;
 169     }
 170 
 171     @Override
 172     public Type div(final MethodVisitor method, final int programPoint) {
 173         if (programPoint == INVALID_PROGRAM_POINT) {
 174             JSType.DIV_ZERO_LONG.invoke(method);
 175         } else {
 176             method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint);
 177         }
 178         return LONG;
 179     }
 180 
 181     @Override
 182     public Type rem(final MethodVisitor method, final int programPoint) {
 183         if (programPoint == INVALID_PROGRAM_POINT) {
 184             JSType.REM_ZERO_LONG.invoke(method);
 185         } else {
 186             method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
 187         }
 188         return LONG;
 189     }
 190 
 191     @Override
 192     public Type shr(final MethodVisitor method) {
 193         method.visitInsn(LUSHR);
 194         return LONG;
 195     }
 196 
 197     @Override
 198     public Type sar(final MethodVisitor method) {
 199         method.visitInsn(LSHR);
 200         return LONG;
 201     }
 202 
 203     @Override
 204     public Type shl(final MethodVisitor method) {
 205         method.visitInsn(LSHL);
 206         return LONG;
 207     }
 208 
 209     @Override
 210     public Type and(final MethodVisitor method) {
 211         method.visitInsn(LAND);
 212         return LONG;
 213     }
 214 
 215     @Override
 216     public Type or(final MethodVisitor method) {
 217         method.visitInsn(LOR);
 218         return LONG;
 219     }
 220 
 221     @Override
 222     public Type xor(final MethodVisitor method) {
 223         method.visitInsn(LXOR);
 224         return LONG;
 225     }
 226 
 227     @Override
 228     public Type neg(final MethodVisitor method, final int programPoint) {
 229         method.visitInvokeDynamicInsn("lneg", "(J)J", MATHBOOTSTRAP, programPoint);
 230         return LONG;
 231     }
 232 
 233     @Override
 234     public void _return(final MethodVisitor method) {
 235         method.visitInsn(LRETURN);
 236     }
 237 
 238     @Override
 239     public Type loadUndefined(final MethodVisitor method) {
 240         method.visitLdcInsn(UNDEFINED_LONG);
 241         return LONG;
 242     }
 243 
 244     @Override
 245     public Type loadForcedInitializer(final MethodVisitor method) {
 246         method.visitInsn(LCONST_0);
 247         return LONG;
 248     }
 249 
 250     @Override
 251     public Type cmp(final MethodVisitor method, final boolean isCmpG) {
 252         return cmp(method);
 253     }
 254 }