view graal/com.oracle.max.asmdis/src/com/sun/max/asm/dis/AddressMapper.java @ 4142:bc8527f3071c

Adjust code base to new level of warnings.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 18 Dec 2011 05:24:06 +0100
parents e233f5660da4
children
line wrap: on
line source

/*
 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. 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.
 *
 * 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.sun.max.asm.dis;

import java.util.*;

import com.sun.max.asm.gen.*;

/**
 * A facility for mapping addresses to {@linkplain DisassembledLabel labels} and {@linkplain DisassembledObject
 * disassembled objects}. Labels are only used to identify addresses that are a) explicitly targeted by an operand of a
 * disassembled object {@linkplain #add(DisassembledObject) added} to the map or b) explicitly
 * {@linkplain #add(ImmediateArgument, String) added}.
 */
public class AddressMapper {

    private int serial;
    private int unnamedLabels;
    private final Map<ImmediateArgument, DisassembledObject> objectMap = new HashMap<>();
    private final Map<ImmediateArgument, DisassembledLabel> labelMap = new TreeMap<>(new Comparator<ImmediateArgument>() {
        public int compare(ImmediateArgument o1, ImmediateArgument o2) {
            final long l1 = o1.asLong();
            final long l2 = o2.asLong();
            if (l1 < l2) {
                return -1;
            } else if (l1 > l2) {
                return 1;
            }
            return 0;
        }
    });

    /**
     * Gets the label for a given address.
     *
     * @param address the address for which a label is requested
     * @return the label for {@code address} or null if no label exists for that address
     */
    public synchronized DisassembledLabel labelAt(ImmediateArgument address) {
        fixupUnnamedLabels();
        return labelMap.get(address);
    }

    /**
     * Gets the label for a given disassembled object.
     *
     * @param disassembledObject the disassembled object for which a label is requested
     * @return the label corresponding to {@code disassembledObject}'s start address or null if no label exists for that address
     */
    public synchronized DisassembledLabel labelAt(DisassembledObject disassembledObject) {
        fixupUnnamedLabels();
        return labelAt(disassembledObject.startAddress());
    }

    /**
     * Adds a mapping from a given address to a given name.
     *
     * @return the previous mapping (if any) for {@code address}
     */
    public synchronized DisassembledLabel add(ImmediateArgument address, String name) {
        return labelMap.put(address, new DisassembledLabel(address, name));
    }

    /**
     * Adds a mapping for the address {@linkplain DisassembledObject#targetAddress() targeted} by a given disassembled object.
     * If {@code disassembledObject} does not target another object, then no update is made to this mapping.
     *
     * @param disassembledObject the disassembled object to consider
     */
    public void add(DisassembledObject disassembledObject) {
        add(Arrays.asList(new DisassembledObject[] {disassembledObject}));
    }

    /**
     * Adds a mapping for the addresses {@linkplain DisassembledObject#targetAddress() targeted} by a given sequence of
     * disassembled objects. If none of {@code disassembledObjects} target other objects, then no update is made to
     * this mapping.
     *
     * @param disassembledObjects the disassembled objects to consider
     */
    public synchronized void add(List<DisassembledObject> disassembledObjects) {
        for (DisassembledObject disassembledObject : disassembledObjects) {
            final ImmediateArgument address = disassembledObject.startAddress();
            objectMap.put(address, disassembledObject);
        }
        for (DisassembledObject disassembledObject : disassembledObjects) {
            final ImmediateArgument targetAddress = disassembledObject.targetAddress();
            if (targetAddress != null) {
                final DisassembledObject targetDisassembledObject = objectMap.get(targetAddress);
                if (targetDisassembledObject == null) {
                    labelMap.remove(targetAddress);
                } else {
                    DisassembledLabel label = labelMap.get(targetAddress);
                    if (label == null || label.target() != targetDisassembledObject) {
                        label = new UnnamedLabel(targetDisassembledObject);
                        final DisassembledLabel oldValue = labelMap.put(targetAddress, label);
                        if (!(oldValue instanceof UnnamedLabel)) {
                            unnamedLabels++;
                        }
                    }
                }
            }
        }
    }

    private static class UnnamedLabel extends DisassembledLabel {
        UnnamedLabel(DisassembledObject targetDisassembledObject) {
            super(targetDisassembledObject, "L?");
        }
    }

    private void fixupUnnamedLabels() {
        while (unnamedLabels != 0) {
            for (Map.Entry<ImmediateArgument, DisassembledLabel> entry : labelMap.entrySet()) {
                final DisassembledLabel label = entry.getValue();
                if (label instanceof UnnamedLabel) {
                    entry.setValue(new DisassembledLabel(label.target(), "L" + (++serial)));
                    unnamedLabels--;
                }
            }
        }
    }

    /**
     * Computes the maximum length of any label name in this mapping.
     */
    public synchronized int maximumLabelNameLength() {
        fixupUnnamedLabels();
        int max = 0;
        for (DisassembledLabel label : labelMap.values()) {
            final String name = label.name();
            if (name.length() > max) {
                max = name.length();
            }
        }
        return max;
    }
}