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 */
013package org.jikesrvm.compilers.opt.ir.operand;
014
015import org.jikesrvm.VM;
016import org.jikesrvm.classloader.Atom;
017import org.jikesrvm.classloader.BootstrapClassLoader;
018import org.jikesrvm.classloader.TypeReference;
019import org.vmmagic.unboxed.Offset;
020import 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 */
028public class ObjectConstantOperand extends ConstantOperand {
029
030  /**
031   * The non-{@code 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  @Override
061  public Operand copy() {
062    return new ObjectConstantOperand(value, offset);
063  }
064
065  @Override
066  public TypeReference getType() {
067    if (VM.runningVM) {
068      return java.lang.JikesRVMSupport.getTypeForClass(value.getClass()).getTypeRef();
069    } else {
070      Class<?> rc = value.getClass();
071      String className = rc.getName();
072      Atom classAtom = Atom.findOrCreateAsciiAtom(className.replace('.', '/'));
073      if (className.startsWith("[")) {
074        // an array
075        return TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classAtom);
076      } else {
077        // a class
078        Atom classDescriptor = classAtom.descriptorFromClassName();
079        return TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor);
080      }
081    }
082  }
083
084  @Override
085  public final boolean isRef() {
086    return true;
087  }
088
089  /**
090   * @return {@link #movable}
091   */
092  @Override
093  public boolean isMovableObjectConstant() {
094    return movable;
095  }
096
097
098  @Override
099  public boolean similar(Operand op) {
100    return (op instanceof ObjectConstantOperand) && value.equals(((ObjectConstantOperand) op).value);
101  }
102
103  /**
104   * Returns the string representation of this operand.
105   *
106   * @return a string representation of this operand.
107   */
108  @Override
109  public String toString() {
110    return "object \"" + value + "\"";
111  }
112}