1 /*
  2  * Copyright (c) 2000, 2020, 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.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 package sun.jvm.hotspot.oops;
 26 
 27 import java.util.*;
 28 import sun.jvm.hotspot.debugger.*;
 29 import sun.jvm.hotspot.memory.*;
 30 import sun.jvm.hotspot.runtime.*;
 31 import sun.jvm.hotspot.types.*;
 32 import sun.jvm.hotspot.utilities.Observable;
 33 import sun.jvm.hotspot.utilities.Observer;
 34 
 35 // Array is an abstract superclass for TypeArray and ObjArray
 36 
 37 public class Array extends Oop {
 38   static {
 39     VM.registerVMInitializedObserver(new Observer() {
 40         public void update(Observable o, Object data) {
 41           initialize(VM.getVM().getTypeDataBase());
 42         }
 43       });
 44   }
 45 
 46   Array(OopHandle handle, ObjectHeap heap) {
 47     super(handle, heap);
 48   }
 49 
 50   private static void initialize(TypeDataBase db) throws WrongTypeException {
 51     Type type   = db.lookupType("arrayOopDesc");
 52     typeSize    = (int)type.getSize();
 53   }
 54 
 55   // Size of the arrayOopDesc
 56   private static long headerSize=0;
 57   private static long lengthOffsetInBytes=0;
 58   private static long typeSize;
 59 
 60   // Check whether an element of a typeArrayOop with the given type must be
 61   // aligned 0 mod 8.  The typeArrayOop itself must be aligned at least this
 62   // strongly.
 63   private static boolean elementTypeShouldBeAligned(BasicType type) {
 64     if (VM.getVM().isLP64()) {
 65       if (type == BasicType.T_OBJECT || type == BasicType.T_ARRAY) {
 66         return !VM.getVM().isCompressedOopsEnabled();
 67       }
 68     }
 69     return type == BasicType.T_DOUBLE || type == BasicType.T_LONG;
 70   }
 71 
 72   private static long headerSizeInBytes() {
 73     if (headerSize != 0) {
 74       return headerSize;
 75     }
 76     if (VM.getVM().isCompactObjectHeadersEnabled()) {
 77       headerSize = lengthOffsetInBytes() + VM.getVM().getIntSize();
 78     } else if (VM.getVM().isCompressedKlassPointersEnabled()) {
 79       headerSize = typeSize;
 80     } else {
 81       headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(),
 82                                       VM.getVM().getHeapWordSize());
 83     }
 84     return headerSize;
 85   }
 86 
 87   private static long lengthOffsetInBytes() {
 88     if (lengthOffsetInBytes != 0) {
 89       return lengthOffsetInBytes;
 90     }
 91     if (VM.getVM().isCompactObjectHeadersEnabled()) {
 92       lengthOffsetInBytes = Oop.getHeaderSize();
 93     } else if (VM.getVM().isCompressedKlassPointersEnabled()) {
 94       lengthOffsetInBytes = typeSize - VM.getVM().getIntSize();
 95     } else {
 96       lengthOffsetInBytes = typeSize;
 97     }
 98     return lengthOffsetInBytes;
 99   }
100 
101   // Accessors for declared fields
102   public long getLength() {
103     boolean isUnsigned = true;
104     return this.getHandle().getCIntegerAt(lengthOffsetInBytes(), VM.getVM().getIntSize(), isUnsigned);
105   }
106 
107   public long getObjectSize() {
108     ArrayKlass klass = (ArrayKlass) getKlass();
109     // We have to fetch the length of the array, shift (multiply) it
110     // appropriately, up to wordSize, add the header, and align to
111     // object size.
112     long s = getLength() << klass.getLog2ElementSize();
113     s += klass.getArrayHeaderInBytes();
114     s = Oop.alignObjectSize(s);
115     return s;
116   }
117 
118   public static long baseOffsetInBytes(BasicType type) {
119     long typeSizeInBytes = headerSizeInBytes();
120     if (elementTypeShouldBeAligned(type)) {
121       VM vm = VM.getVM();
122       return vm.alignUp(typeSizeInBytes, vm.getVM().getHeapWordSize());
123     } else {
124       return typeSizeInBytes;
125     }
126   }
127 
128   public boolean isArray()             { return true; }
129 
130   public void iterateFields(OopVisitor visitor, boolean doVMFields) {
131     super.iterateFields(visitor, doVMFields);
132   }
133 }