/*
 * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020, 2020, Red Hat Inc. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.oracle.objectfile.debugentry;

import com.oracle.objectfile.debuginfo.DebugInfoProvider.DebugFrameSizeChange;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

track debug info associated with a Java class.
/** * track debug info associated with a Java class. */
public class ClassEntry {
the name of the associated class.
/** * the name of the associated class. */
private String className;
details of the associated file.
/** * details of the associated file. */
private FileEntry fileEntry;
a list recording details of all primary ranges included in this class sorted by ascending address range.
/** * a list recording details of all primary ranges included in this class sorted by ascending * address range. */
private LinkedList<PrimaryEntry> primaryEntries;
an index identifying primary ranges which have already been encountered.
/** * an index identifying primary ranges which have already been encountered. */
private Map<Range, PrimaryEntry> primaryIndex;
an index of all primary and secondary files referenced from this class's compilation unit.
/** * an index of all primary and secondary files referenced from this class's compilation unit. */
private Map<FileEntry, Integer> localFilesIndex;
a list of the same files.
/** * a list of the same files. */
private LinkedList<FileEntry> localFiles;
an index of all primary and secondary dirs referenced from this class's compilation unit.
/** * an index of all primary and secondary dirs referenced from this class's compilation unit. */
private HashMap<DirEntry, Integer> localDirsIndex;
a list of the same dirs.
/** * a list of the same dirs. */
private LinkedList<DirEntry> localDirs;
index of debug_info section compilation unit for this class.
/** * index of debug_info section compilation unit for this class. */
private int cuIndex;
index of debug_info section compilation unit for deopt target methods.
/** * index of debug_info section compilation unit for deopt target methods. */
private int deoptCUIndex;
index into debug_line section for associated compilation unit.
/** * index into debug_line section for associated compilation unit. */
private int lineIndex;
size of line number info prologue region for associated compilation unit.
/** * size of line number info prologue region for associated compilation unit. */
private int linePrologueSize;
total size of line number info region for associated compilation unit.
/** * total size of line number info region for associated compilation unit. */
private int totalSize;
true iff the entry includes methods that are deopt targets.
/** * true iff the entry includes methods that are deopt targets. */
private boolean includesDeoptTarget; public ClassEntry(String className, FileEntry fileEntry) { this.className = className; this.fileEntry = fileEntry; this.primaryEntries = new LinkedList<>(); this.primaryIndex = new HashMap<>(); this.localFiles = new LinkedList<>(); this.localFilesIndex = new HashMap<>(); this.localDirs = new LinkedList<>(); this.localDirsIndex = new HashMap<>(); if (fileEntry != null) { localFiles.add(fileEntry); localFilesIndex.put(fileEntry, localFiles.size()); DirEntry dirEntry = fileEntry.getDirEntry(); if (dirEntry != null) { localDirs.add(dirEntry); localDirsIndex.put(dirEntry, localDirs.size()); } } this.cuIndex = -1; this.deoptCUIndex = -1; this.lineIndex = -1; this.linePrologueSize = -1; this.totalSize = -1; this.includesDeoptTarget = false; } public void addPrimary(Range primary, List<DebugFrameSizeChange> frameSizeInfos, int frameSize) { if (primaryIndex.get(primary) == null) { PrimaryEntry primaryEntry = new PrimaryEntry(primary, frameSizeInfos, frameSize, this); primaryEntries.add(primaryEntry); primaryIndex.put(primary, primaryEntry); if (primary.isDeoptTarget()) { includesDeoptTarget = true; } else { /* deopt targets should all come after normal methods */ assert includesDeoptTarget == false; } } } public void addSubRange(Range subrange, FileEntry subFileEntry) { Range primary = subrange.getPrimary(); /* * the subrange should belong to a primary range */ assert primary != null; PrimaryEntry primaryEntry = primaryIndex.get(primary); /* * we should already have seen the primary range */ assert primaryEntry != null; assert primaryEntry.getClassEntry() == this; primaryEntry.addSubRange(subrange, subFileEntry); if (subFileEntry != null) { if (localFilesIndex.get(subFileEntry) == null) { localFiles.add(subFileEntry); localFilesIndex.put(subFileEntry, localFiles.size()); } DirEntry dirEntry = subFileEntry.getDirEntry(); if (dirEntry != null && localDirsIndex.get(dirEntry) == null) { localDirs.add(dirEntry); localDirsIndex.put(dirEntry, localDirs.size()); } } } public int localDirsIdx(DirEntry dirEntry) { if (dirEntry != null) { return localDirsIndex.get(dirEntry); } else { return 0; } } public int localFilesIdx(@SuppressWarnings("hiding") FileEntry fileEntry) { return localFilesIndex.get(fileEntry); } public String getFileName() { if (fileEntry != null) { return fileEntry.getFileName(); } else { return ""; } } @SuppressWarnings("unused") String getFullFileName() { if (fileEntry != null) { return fileEntry.getFullName(); } else { return null; } } @SuppressWarnings("unused") String getDirName() { if (fileEntry != null) { return fileEntry.getPathName(); } else { return ""; } } public void setCUIndex(int cuIndex) { // Should only get set once to a non-negative value. assert cuIndex >= 0; assert this.cuIndex == -1; this.cuIndex = cuIndex; } public int getCUIndex() { // Should have been set before being read. assert cuIndex >= 0; return cuIndex; } public void setDeoptCUIndex(int deoptCUIndex) { // Should only get set once to a non-negative value. assert deoptCUIndex >= 0; assert this.deoptCUIndex == -1; this.deoptCUIndex = deoptCUIndex; } public int getDeoptCUIndex() { // Should have been set before being read. assert deoptCUIndex >= 0; return deoptCUIndex; } public int getLineIndex() { return lineIndex; } public void setLineIndex(int lineIndex) { this.lineIndex = lineIndex; } public void setLinePrologueSize(int linePrologueSize) { this.linePrologueSize = linePrologueSize; } public int getLinePrologueSize() { return linePrologueSize; } public int getTotalSize() { return totalSize; } public void setTotalSize(int totalSize) { this.totalSize = totalSize; } public FileEntry getFileEntry() { return fileEntry; } public String getClassName() { return className; } public LinkedList<PrimaryEntry> getPrimaryEntries() { return primaryEntries; } public Object primaryIndexFor(Range primaryRange) { return primaryIndex.get(primaryRange); } public LinkedList<DirEntry> getLocalDirs() { return localDirs; } public LinkedList<FileEntry> getLocalFiles() { return localFiles; } public boolean includesDeoptTarget() { return includesDeoptTarget; } public String getCachePath() { if (fileEntry != null) { return fileEntry.getCachePath(); } else { return ""; } } }