1 /*
2  * Copyright (c) 2018, 2021, 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.gc.z;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 import sun.jvm.hotspot.debugger.Address;
31 import sun.jvm.hotspot.debugger.OopHandle;
32 import sun.jvm.hotspot.gc.shared.LiveRegionsProvider;
33 import sun.jvm.hotspot.memory.MemRegion;
34 import sun.jvm.hotspot.oops.Oop;
35 import sun.jvm.hotspot.oops.UnknownOopException;
36 import sun.jvm.hotspot.runtime.VM;
37 import sun.jvm.hotspot.runtime.VMObject;
38 import sun.jvm.hotspot.runtime.VMObjectFactory;
39 import sun.jvm.hotspot.types.AddressField;
40 import sun.jvm.hotspot.types.CIntegerField;
41 import sun.jvm.hotspot.types.Type;
42 import sun.jvm.hotspot.types.TypeDataBase;
43 
44 public class ZPage extends VMObject implements LiveRegionsProvider {
45     private static CIntegerField typeField;
46     private static CIntegerField seqnumField;
47     private static long virtualFieldOffset;
48     private static AddressField topField;
49 
50     static {
VM.registerVMInitializedObserver(o, d) -> initialize(VM.getVM().getTypeDataBase())51         VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase()));
52     }
53 
initialize(TypeDataBase db)54     static private synchronized void initialize(TypeDataBase db) {
55         Type type = db.lookupType("ZPage");
56 
57         typeField = type.getCIntegerField("_type");
58         seqnumField = type.getCIntegerField("_seqnum");
59         virtualFieldOffset = type.getField("_virtual").getOffset();
60         topField = type.getAddressField("_top");
61     }
62 
ZPage(Address addr)63     public ZPage(Address addr) {
64         super(addr);
65     }
66 
type()67     private byte type() {
68         return typeField.getJByte(addr);
69     }
70 
seqnum()71     private int seqnum() {
72         return seqnumField.getJInt(addr);
73     }
74 
virtual()75     private ZVirtualMemory virtual() {
76         return VMObjectFactory.newObject(ZVirtualMemory.class, addr.addOffsetTo(virtualFieldOffset));
77     }
78 
top()79     private Address top() {
80         return topField.getValue(addr);
81     }
82 
is_relocatable()83     private boolean is_relocatable() {
84         return seqnum() < ZGlobals.ZGlobalSeqNum();
85     }
86 
start()87     long start() {
88         return virtual().start();
89     }
90 
size()91     long size() {
92         return virtual().end() - virtual().start();
93     }
94 
object_alignment_shift()95     long object_alignment_shift() {
96         if (type() == ZGlobals.ZPageTypeSmall) {
97             return ZGlobals.ZObjectAlignmentSmallShift();
98         } else if (type() == ZGlobals.ZPageTypeMedium) {
99             return ZGlobals.ZObjectAlignmentMediumShift;
100         } else {
101             assert(type() == ZGlobals.ZPageTypeLarge);
102             return ZGlobals.ZObjectAlignmentLargeShift;
103         }
104     }
105 
objectAlignmentSize()106     long objectAlignmentSize() {
107         return 1 << object_alignment_shift();
108     }
109 
isIn(Address addr)110     public boolean isIn(Address addr) {
111         long offset = ZAddress.offset(addr);
112         // FIXME: it does not consider the sign.
113         return (offset >= start()) && (offset < top().asLongValue());
114     }
115 
getObjectSize(Address good)116     private long getObjectSize(Address good) {
117         OopHandle handle = good.addOffsetToAsOopHandle(0);
118         Oop obj = null;
119 
120         try {
121            obj = VM.getVM().getObjectHeap().newOop(handle);
122         } catch (UnknownOopException exp) {
123           throw new RuntimeException(" UnknownOopException  " + exp);
124         }
125 
126         return VM.getVM().alignUp(obj.getObjectSize(), objectAlignmentSize());
127     }
128 
getLiveRegions()129     public List<MemRegion> getLiveRegions() {
130         Address start = ZAddress.good(ZUtils.longToAddress(start()));
131 
132         // Can't convert top() to a "good" address because it might
133         // be at the top of the "offset" range, and therefore also
134         // looks like one of the color bits. Instead use the "good"
135         // address and add the size.
136         long size = top().asLongValue() - start();
137         Address end = start.addOffsetTo(size);
138 
139         return List.of(new MemRegion(start, end));
140     }
141 }
142