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 26package jdk.nashorn.internal.codegen.types; 27 28import static jdk.internal.org.objectweb.asm.Opcodes.DADD; 29import static jdk.internal.org.objectweb.asm.Opcodes.DCMPG; 30import static jdk.internal.org.objectweb.asm.Opcodes.DCMPL; 31import static jdk.internal.org.objectweb.asm.Opcodes.DCONST_0; 32import static jdk.internal.org.objectweb.asm.Opcodes.DCONST_1; 33import static jdk.internal.org.objectweb.asm.Opcodes.DDIV; 34import static jdk.internal.org.objectweb.asm.Opcodes.DLOAD; 35import static jdk.internal.org.objectweb.asm.Opcodes.DMUL; 36import static jdk.internal.org.objectweb.asm.Opcodes.DNEG; 37import static jdk.internal.org.objectweb.asm.Opcodes.DREM; 38import static jdk.internal.org.objectweb.asm.Opcodes.DRETURN; 39import static jdk.internal.org.objectweb.asm.Opcodes.DSTORE; 40import static jdk.internal.org.objectweb.asm.Opcodes.DSUB; 41import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; 42import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE; 43 44import jdk.internal.org.objectweb.asm.MethodVisitor; 45import jdk.nashorn.internal.codegen.CompilerConstants; 46import jdk.nashorn.internal.runtime.JSType; 47 48class NumberType extends NumericType { 49 private static final long serialVersionUID = 1L; 50 51 private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Double.class, "valueOf", Double.class, double.class); 52 53 protected NumberType() { 54 super("double", double.class, 4, 2); 55 } 56 57 @Override 58 public Type nextWider() { 59 return OBJECT; 60 } 61 62 @Override 63 public Class<?> getBoxedType() { 64 return Double.class; 65 } 66 67 @Override 68 public char getBytecodeStackType() { 69 return 'D'; 70 } 71 72 @Override 73 public Type cmp(final MethodVisitor method, final boolean isCmpG) { 74 method.visitInsn(isCmpG ? DCMPG : DCMPL); 75 return INT; 76 } 77 78 @Override 79 public Type load(final MethodVisitor method, final int slot) { 80 assert slot != -1; 81 method.visitVarInsn(DLOAD, slot); 82 return NUMBER; 83 } 84 85 @Override 86 public void store(final MethodVisitor method, final int slot) { 87 assert slot != -1; 88 method.visitVarInsn(DSTORE, slot); 89 } 90 91 @Override 92 public Type loadUndefined(final MethodVisitor method) { 93 method.visitLdcInsn(UNDEFINED_DOUBLE); 94 return NUMBER; 95 } 96 97 @Override 98 public Type loadForcedInitializer(final MethodVisitor method) { 99 method.visitInsn(DCONST_0); 100 return NUMBER; 101 } 102 103 @Override 104 public Type ldc(final MethodVisitor method, final Object c) { 105 assert c instanceof Double; 106 107 final double value = (Double) c; 108 109 if (Double.doubleToLongBits(value) == 0L) { // guard against -0.0 110 method.visitInsn(DCONST_0); 111 } else if (value == 1.0) { 112 method.visitInsn(DCONST_1); 113 } else { 114 method.visitLdcInsn(value); 115 } 116 117 return NUMBER; 118 } 119 120 @Override 121 public Type convert(final MethodVisitor method, final Type to) { 122 if (isEquivalentTo(to)) { 123 return null; 124 } 125 126 if (to.isInteger()) { 127 invokestatic(method, JSType.TO_INT32_D); 128 } else if (to.isLong()) { 129 invokestatic(method, JSType.TO_LONG_D); 130 } else if (to.isBoolean()) { 131 invokestatic(method, JSType.TO_BOOLEAN_D); 132 } else if (to.isString()) { 133 invokestatic(method, JSType.TO_STRING_D); 134 } else if (to.isObject()) { 135 invokestatic(method, VALUE_OF); 136 } else { 137 throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to); 138 } 139 140 return to; 141 } 142 143 @Override 144 public Type add(final MethodVisitor method, final int programPoint) { 145 method.visitInsn(DADD); 146 return NUMBER; 147 } 148 149 @Override 150 public Type sub(final MethodVisitor method, final int programPoint) { 151 method.visitInsn(DSUB); 152 return NUMBER; 153 } 154 155 @Override 156 public Type mul(final MethodVisitor method, final int programPoint) { 157 method.visitInsn(DMUL); 158 return NUMBER; 159 } 160 161 @Override 162 public Type div(final MethodVisitor method, final int programPoint) { 163 method.visitInsn(DDIV); 164 return NUMBER; 165 } 166 167 @Override 168 public Type rem(final MethodVisitor method, final int programPoint) { 169 method.visitInsn(DREM); 170 return NUMBER; 171 } 172 173 @Override 174 public Type neg(final MethodVisitor method, final int programPoint) { 175 method.visitInsn(DNEG); 176 return NUMBER; 177 } 178 179 @Override 180 public void _return(final MethodVisitor method) { 181 method.visitInsn(DRETURN); 182 } 183} 184