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 }