1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * @LastModified: Oct 2017 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xalan.internal.xsltc.compiler.util; 23 24 import com.sun.org.apache.bcel.internal.generic.ALOAD; 25 import com.sun.org.apache.bcel.internal.generic.ASTORE; 26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 27 import com.sun.org.apache.bcel.internal.generic.IFEQ; 28 import com.sun.org.apache.bcel.internal.generic.ILOAD; 29 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 30 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 31 import com.sun.org.apache.bcel.internal.generic.Instruction; 32 import com.sun.org.apache.bcel.internal.generic.InstructionList; 33 import com.sun.org.apache.bcel.internal.generic.PUSH; 34 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 35 import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 36 import com.sun.org.apache.xml.internal.dtm.DTM; 37 38 /** 39 * @author Jacek Ambroziak 40 * @author Santiago Pericas-Geertsen 41 * @author Erwin Bolwidt <ejb@klomp.org> 42 */ 43 public final class ReferenceType extends Type { 44 protected ReferenceType() {} 45 46 public String toString() { 47 return "reference"; 48 } 49 50 public boolean identicalTo(Type other) { 51 return this == other; 52 } 53 54 public String toSignature() { 55 return "Ljava/lang/Object;"; 56 } 57 58 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 59 return com.sun.org.apache.bcel.internal.generic.Type.OBJECT; 60 } 61 62 /** 63 * Translates a reference to an object of internal type <code>type</code>. 64 * The translation to int is undefined since references 65 * are always converted to reals in arithmetic expressions. 66 * 67 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 68 */ 69 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 70 Type type) { 71 if (type == Type.String) { 72 translateTo(classGen, methodGen, (StringType) type); 73 } 74 else if (type == Type.Real) { 75 translateTo(classGen, methodGen, (RealType) type); 76 } 77 else if (type == Type.Boolean) { 78 translateTo(classGen, methodGen, (BooleanType) type); 79 } 80 else if (type == Type.NodeSet) { 81 translateTo(classGen, methodGen, (NodeSetType) type); 82 } 83 else if (type == Type.Node) { 84 translateTo(classGen, methodGen, (NodeType) type); 85 } 86 else if (type == Type.ResultTree) { 87 translateTo(classGen, methodGen, (ResultTreeType) type); 88 } 89 else if (type == Type.Object) { 90 translateTo(classGen, methodGen, (ObjectType) type); 91 } 92 else if (type == Type.Reference ) { 93 } 94 else { 95 ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR, type.toString()); 96 classGen.getParser().reportError(Constants.FATAL, err); 97 } 98 } 99 100 /** 101 * Translates reference into object of internal type <code>type</code>. 102 * 103 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 104 */ 105 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 106 StringType type) { 107 final int current = methodGen.getLocalIndex("current"); 108 ConstantPoolGen cpg = classGen.getConstantPool(); 109 InstructionList il = methodGen.getInstructionList(); 110 111 // If no current, conversion is a top-level 112 if (current < 0) { 113 il.append(new PUSH(cpg, DTM.ROOT_NODE)); // push root node 114 } 115 else { 116 il.append(new ILOAD(current)); 117 } 118 il.append(methodGen.loadDOM()); 119 final int stringF = cpg.addMethodref(BASIS_LIBRARY_CLASS, 120 "stringF", 121 "(" 122 + OBJECT_SIG 123 + NODE_SIG 124 + DOM_INTF_SIG 125 + ")" + STRING_SIG); 126 il.append(new INVOKESTATIC(stringF)); 127 } 128 129 /** 130 * Translates a reference into an object of internal type <code>type</code>. 131 * 132 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 133 */ 134 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 135 RealType type) { 136 final ConstantPoolGen cpg = classGen.getConstantPool(); 137 final InstructionList il = methodGen.getInstructionList(); 138 139 il.append(methodGen.loadDOM()); 140 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "numberF", 141 "(" 142 + OBJECT_SIG 143 + DOM_INTF_SIG 144 + ")D"); 145 il.append(new INVOKESTATIC(index)); 146 } 147 148 /** 149 * Translates a reference to an object of internal type <code>type</code>. 150 * 151 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 152 */ 153 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 154 BooleanType type) { 155 final ConstantPoolGen cpg = classGen.getConstantPool(); 156 final InstructionList il = methodGen.getInstructionList(); 157 158 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "booleanF", 159 "(" 160 + OBJECT_SIG 161 + ")Z"); 162 il.append(new INVOKESTATIC(index)); 163 } 164 165 /** 166 * Casts a reference into a NodeIterator. 167 * 168 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 169 */ 170 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 171 NodeSetType type) { 172 final ConstantPoolGen cpg = classGen.getConstantPool(); 173 final InstructionList il = methodGen.getInstructionList(); 174 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToNodeSet", 175 "(" 176 + OBJECT_SIG 177 + ")" 178 + NODE_ITERATOR_SIG); 179 il.append(new INVOKESTATIC(index)); 180 181 // Reset this iterator 182 index = cpg.addInterfaceMethodref(NODE_ITERATOR, RESET, RESET_SIG); 183 il.append(new INVOKEINTERFACE(index, 1)); 184 } 185 186 /** 187 * Casts a reference into a Node. 188 * 189 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 190 */ 191 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 192 NodeType type) { 193 translateTo(classGen, methodGen, Type.NodeSet); 194 Type.NodeSet.translateTo(classGen, methodGen, type); 195 } 196 197 /** 198 * Casts a reference into a ResultTree. 199 * 200 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 201 */ 202 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 203 ResultTreeType type) { 204 final ConstantPoolGen cpg = classGen.getConstantPool(); 205 final InstructionList il = methodGen.getInstructionList(); 206 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToResultTree", 207 "(" + OBJECT_SIG + ")" + DOM_INTF_SIG); 208 il.append(new INVOKESTATIC(index)); 209 } 210 211 /** 212 * Subsume reference into ObjectType. 213 * 214 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 215 */ 216 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 217 ObjectType type) { 218 methodGen.getInstructionList().append(NOP); 219 } 220 221 /** 222 * Translates a reference into the Java type denoted by <code>clazz</code>. 223 */ 224 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 225 Class<?> clazz) { 226 final ConstantPoolGen cpg = classGen.getConstantPool(); 227 final InstructionList il = methodGen.getInstructionList(); 228 229 int referenceToLong = cpg.addMethodref(BASIS_LIBRARY_CLASS, 230 "referenceToLong", 231 "(" + OBJECT_SIG + ")J"); 232 int referenceToDouble = cpg.addMethodref(BASIS_LIBRARY_CLASS, 233 "referenceToDouble", 234 "(" + OBJECT_SIG + ")D"); 235 int referenceToBoolean = cpg.addMethodref(BASIS_LIBRARY_CLASS, 236 "referenceToBoolean", 237 "(" + OBJECT_SIG + ")Z"); 238 239 if (clazz.getName().equals("java.lang.Object")) { 240 il.append(NOP); 241 } 242 else if (clazz == Double.TYPE) { 243 il.append(new INVOKESTATIC(referenceToDouble)); 244 } 245 else if (clazz.getName().equals("java.lang.Double")) { 246 il.append(new INVOKESTATIC(referenceToDouble)); 247 Type.Real.translateTo(classGen, methodGen, Type.Reference); 248 } 249 else if (clazz == Float.TYPE) { 250 il.append(new INVOKESTATIC(referenceToDouble)); 251 il.append(D2F); 252 } 253 else if (clazz.getName().equals("java.lang.String")) { 254 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToString", 255 "(" 256 + OBJECT_SIG 257 + DOM_INTF_SIG 258 + ")" 259 + "Ljava/lang/String;"); 260 il.append(methodGen.loadDOM()); 261 il.append(new INVOKESTATIC(index)); 262 } 263 else if (clazz.getName().equals("org.w3c.dom.Node")) { 264 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToNode", 265 "(" 266 + OBJECT_SIG 267 + DOM_INTF_SIG 268 + ")" 269 + "Lorg/w3c/dom/Node;"); 270 il.append(methodGen.loadDOM()); 271 il.append(new INVOKESTATIC(index)); 272 } 273 else if (clazz.getName().equals("org.w3c.dom.NodeList")) { 274 int index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "referenceToNodeList", 275 "(" 276 + OBJECT_SIG 277 + DOM_INTF_SIG 278 + ")" 279 + "Lorg/w3c/dom/NodeList;"); 280 il.append(methodGen.loadDOM()); 281 il.append(new INVOKESTATIC(index)); 282 } 283 else if (clazz.getName().equals("com.sun.org.apache.xalan.internal.xsltc.DOM")) { 284 translateTo(classGen, methodGen, Type.ResultTree); 285 } 286 else if (clazz == Long.TYPE) { 287 il.append(new INVOKESTATIC(referenceToLong)); 288 } 289 else if (clazz == Integer.TYPE) { 290 il.append(new INVOKESTATIC(referenceToLong)); 291 il.append(L2I); 292 } 293 else if (clazz == Short.TYPE) { 294 il.append(new INVOKESTATIC(referenceToLong)); 295 il.append(L2I); 296 il.append(I2S); 297 } 298 else if (clazz == Byte.TYPE) { 299 il.append(new INVOKESTATIC(referenceToLong)); 300 il.append(L2I); 301 il.append(I2B); 302 } 303 else if (clazz == Character.TYPE) { 304 il.append(new INVOKESTATIC(referenceToLong)); 305 il.append(L2I); 306 il.append(I2C); 307 } 308 else if (clazz == java.lang.Boolean.TYPE) { 309 il.append(new INVOKESTATIC(referenceToBoolean)); 310 } 311 else if (clazz.getName().equals("java.lang.Boolean")) { 312 il.append(new INVOKESTATIC(referenceToBoolean)); 313 Type.Boolean.translateTo(classGen, methodGen, Type.Reference); 314 } 315 else { 316 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 317 toString(), clazz.getName()); 318 classGen.getParser().reportError(Constants.FATAL, err); 319 } 320 } 321 322 /** 323 * Translates an external Java type into a reference. Only conversion 324 * allowed is from java.lang.Object. 325 */ 326 public void translateFrom(ClassGenerator classGen, MethodGenerator methodGen, 327 Class<?> clazz) { 328 if (clazz.getName().equals("java.lang.Object")) { 329 methodGen.getInstructionList().append(NOP); 330 } 331 else { 332 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 333 toString(), clazz.getName()); 334 classGen.getParser().reportError(Constants.FATAL, err); 335 } 336 } 337 338 /** 339 * Expects a reference on the stack and translates it to a non-synthesized 340 * boolean. It does not push a 0 or a 1 but instead returns branchhandle 341 * list to be appended to the false list. 342 * 343 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 344 */ 345 public FlowList translateToDesynthesized(ClassGenerator classGen, 346 MethodGenerator methodGen, 347 BooleanType type) { 348 InstructionList il = methodGen.getInstructionList(); 349 translateTo(classGen, methodGen, type); 350 return new FlowList(il.append(new IFEQ(null))); 351 } 352 353 /** 354 * Translates an object of this type to its boxed representation. 355 */ 356 public void translateBox(ClassGenerator classGen, 357 MethodGenerator methodGen) { 358 } 359 360 /** 361 * Translates an object of this type to its unboxed representation. 362 */ 363 public void translateUnBox(ClassGenerator classGen, 364 MethodGenerator methodGen) { 365 } 366 367 368 public Instruction LOAD(int slot) { 369 return new ALOAD(slot); 370 } 371 372 public Instruction STORE(int slot) { 373 return new ASTORE(slot); 374 } 375 }