001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.compilers.opt.ir.operand;
014
015 import org.jikesrvm.VM;
016 import org.jikesrvm.classloader.Atom;
017 import org.jikesrvm.classloader.BootstrapClassLoader;
018 import org.jikesrvm.classloader.TypeReference;
019 import org.vmmagic.unboxed.Offset;
020 import org.jikesrvm.mm.mminterface.MemoryManager;
021
022 /**
023 * Represents a constant object operand (for example, from an
024 * initialized static final).
025 *
026 * @see Operand
027 */
028 public class ObjectConstantOperand extends ConstantOperand {
029
030 /**
031 * The non-null object value
032 */
033 public final Object value;
034
035 /**
036 * Offset in JTOC where this object constant lives.
037 */
038 public final Offset offset;
039
040 /**
041 * Can this object be moved in memory?
042 */
043 private final boolean movable;
044
045 /**
046 * Construct a new object constant operand
047 *
048 * @param v the object constant
049 * @param i JTOC offset of the object constant
050 */
051 public ObjectConstantOperand(Object v, Offset i) {
052 if (VM.VerifyAssertions) VM._assert(v != null);
053 value = v;
054 offset = i;
055 // prior to writing the boot image we don't know where objects will reside,
056 // so we must treat them as movable when writing the boot image
057 movable = !VM.runningVM || !MemoryManager.willNeverMove(v);
058 }
059
060 /**
061 * Return a new operand that is semantically equivalent to <code>this</code>.
062 *
063 * @return a copy of <code>this</code>
064 */
065 public Operand copy() {
066 return new ObjectConstantOperand(value, offset);
067 }
068
069 /**
070 * Return the {@link TypeReference} of the value represented by the operand.
071 *
072 * @return type reference for type of object
073 */
074 public TypeReference getType() {
075 if (VM.runningVM) {
076 return java.lang.JikesRVMSupport.getTypeForClass(value.getClass()).getTypeRef();
077 } else {
078 Class<?> rc = value.getClass();
079 String className = rc.getName();
080 Atom classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/'));
081 if (className.startsWith("[")) {
082 // an array
083 return TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classAtom);
084 } else {
085 // a class
086 Atom classDescriptor = classAtom.descriptorFromClassName();
087 return TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor);
088 }
089 }
090 }
091
092 /**
093 * Does the operand represent a value of the reference data type?
094 *
095 * @return <code>true</code>
096 */
097 public final boolean isRef() {
098 return true;
099 }
100
101 /**
102 * Is the operand a movable {@link ObjectConstantOperand}?
103 *
104 * @return movable
105 */
106 public boolean isMovableObjectConstant() {
107 return movable;
108 }
109
110
111 /**
112 * Are two operands semantically equivalent?
113 *
114 * @param op other operand
115 * @return <code>true</code> if <code>this</code> and <code>op</code>
116 * are semantically equivalent or <code>false</code>
117 * if they are not.
118 */
119 public boolean similar(Operand op) {
120 return (op instanceof ObjectConstantOperand) && value.equals(((ObjectConstantOperand) op).value);
121 }
122
123 /**
124 * Returns the string representation of this operand.
125 *
126 * @return a string representation of this operand.
127 */
128 public String toString() {
129 return "object \"" + value + "\"";
130 }
131 }