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.LCONST_0;
  32 import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
  34 import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN;
  35 import static jdk.internal.org.objectweb.asm.Opcodes.LSTORE;
  36 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  37 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
  38 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  39 
  40 import jdk.internal.org.objectweb.asm.MethodVisitor;
  41 import jdk.nashorn.internal.codegen.CompilerConstants;
  42 import jdk.nashorn.internal.runtime.JSType;
  43 
  44 /**
  45  * Type class: LONG
  46  */
  47 class LongType extends Type {
  48     private static final long serialVersionUID = 1L;
  49 
  50     private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class);
  51 
  52     protected LongType(final String name) {
  53         super(name, long.class, 3, 2);
  54     }
  55 
  56     protected LongType() {
  57         this("long");
  58     }
  59 
  60     @Override
  61     public Type nextWider() {
  62         return NUMBER;
  63     }
  64 
  65     @Override
  66     public Class<?> getBoxedType() {
  67         return Long.class;
  68     }
  69 
  70     @Override
  71     public char getBytecodeStackType() {
  72         return 'J';
  73     }
  74 
  75     @Override
  76     public Type load(final MethodVisitor method, final int slot) {
  77         assert slot != -1;
  78         method.visitVarInsn(LLOAD, slot);
  79         return LONG;
  80     }
  81 
  82     @Override
  83     public void store(final MethodVisitor method, final int slot) {
  84         assert slot != -1;
  85         method.visitVarInsn(LSTORE, slot);
  86     }
  87 
  88     @Override
  89     public Type ldc(final MethodVisitor method, final Object c) {
  90         assert c instanceof Long;
  91 
  92         final long value = (Long) c;
  93 
  94         if (value == 0L) {
  95             method.visitInsn(LCONST_0);
  96         } else if (value == 1L) {
  97             method.visitInsn(LCONST_1);
  98         } else {
  99             method.visitLdcInsn(c);
 100         }
 101 
 102         return Type.LONG;
 103     }
 104 
 105     @Override
 106     public Type convert(final MethodVisitor method, final Type to) {
 107         if (isEquivalentTo(to)) {
 108             return to;
 109         }
 110 
 111         if (to.isNumber()) {
 112             method.visitInsn(L2D);
 113         } else if (to.isInteger()) {
 114             invokestatic(method, JSType.TO_INT32_L);
 115         } else if (to.isBoolean()) {
 116             method.visitInsn(L2I);
 117         } else if (to.isObject()) {
 118             invokestatic(method, VALUE_OF);
 119         } else {
 120             assert false : "Illegal conversion " + this + " -> " + to;
 121         }
 122 
 123         return to;
 124     }
 125 
 126     @Override
 127     public Type add(final MethodVisitor method, final int programPoint) {
 128         if(programPoint == INVALID_PROGRAM_POINT) {
 129             method.visitInsn(LADD);
 130         } else {
 131             method.visitInvokeDynamicInsn("ladd", "(JJ)J", MATHBOOTSTRAP, programPoint);
 132         }
 133         return LONG;
 134     }
 135 
 136     @Override
 137     public void _return(final MethodVisitor method) {
 138         method.visitInsn(LRETURN);
 139     }
 140 
 141     @Override
 142     public Type loadUndefined(final MethodVisitor method) {
 143         method.visitLdcInsn(UNDEFINED_LONG);
 144         return LONG;
 145     }
 146 
 147     @Override
 148     public Type loadForcedInitializer(final MethodVisitor method) {
 149         method.visitInsn(LCONST_0);
 150         return LONG;
 151     }
 152 }