view graal/com.oracle.max.asmdis/src/com/sun/max/asm/InlineDataDecoder.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) 2007, 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;

import java.io.*;
import java.util.*;

import com.sun.max.asm.InlineDataDescriptor.*;
import com.sun.max.io.*;
import com.sun.max.program.*;

/**
 * A decoder for a sequence of {@linkplain InlineDataDescriptor inline data descriptors} associated with an
 * instruction stream. The decoder is initialized either from an encoded or inflated sequence of descriptors.
 *
 * Once initialized, a inline data decoder can be {@linkplain #decode(int, BufferedInputStream) queried} for the
 * inline data descriptor describing the inline data at a given position in an instruction stream.
 */
public class InlineDataDecoder {

    protected final Map<Integer, InlineDataDescriptor> positionToDescriptorMap;

    /**
     * Creates a decoder from an encoded sequence of inline data descriptors.
     *
     * @param encodedDescriptors a sequence of descriptors encoded in a byte array whose format complies with that used
     *            by {@link InlineDataRecorder#encodedDescriptors()}. This value can be null.
     * @return null if {@code encodedDescriptors} is null
     */
    public static InlineDataDecoder createFrom(byte[] encodedDescriptors) {
        if (encodedDescriptors != null) {
            return new InlineDataDecoder(encodedDescriptors);
        }
        return null;
    }

    /**
     * Creates a decoder based on the descriptors in a given recorder.
     *
     * @param inlineDataRecorder
     * @return null if {@code inlineDataRecorder} does not contain any entries
     */
    public static InlineDataDecoder createFrom(InlineDataRecorder inlineDataRecorder) {
        final List<InlineDataDescriptor> descriptors = inlineDataRecorder.descriptors();
        if (descriptors != null) {
            return new InlineDataDecoder(descriptors);
        }
        return null;
    }

    public InlineDataDecoder(List<InlineDataDescriptor> descriptors) {
        positionToDescriptorMap = new TreeMap<>();
        for (InlineDataDescriptor descriptor : descriptors) {
            positionToDescriptorMap.put(descriptor.startPosition(), descriptor);
        }
    }

    /**
     * Creates a decoder from an encoded sequence of inline data descriptors.
     *
     * @param encodedDescriptors a sequence of descriptors encoded in a byte array whose format complies with that used
     *            by {@link InlineDataRecorder#encodedDescriptors()}
     */
    public InlineDataDecoder(byte[] encodedDescriptors) {
        try {
            final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(encodedDescriptors);
            final DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream);
            final int numberOfEntries = dataInputStream.readInt();
            positionToDescriptorMap = new TreeMap<>();
            for (int i = 0; i < numberOfEntries; ++i) {
                final Tag tag = InlineDataDescriptor.Tag.VALUES.get(dataInputStream.readByte());
                final InlineDataDescriptor inlineDataDescriptor = tag.decode(dataInputStream);
                positionToDescriptorMap.put(inlineDataDescriptor.startPosition(), inlineDataDescriptor);
            }
            assert byteArrayInputStream.available() == 0;
        } catch (IOException ioException) {
            throw ProgramError.unexpected(ioException);
        }
    }

    /**
     * Decodes the data (if any) from the current read position of a given stream.
     *
     * @param currentPosition the stream's current read position with respect to the start of the stream
     * @param stream the instruction stream being disassembled
     * @return the inline data decoded from the stream or null if there is no inline data at {@code currentPosition}
     */
    public InlineData decode(int currentPosition, BufferedInputStream stream) throws IOException {
        final InlineDataDescriptor inlineDataDescriptor = positionToDescriptorMap.get(currentPosition);
        if (inlineDataDescriptor != null) {
            final int size = inlineDataDescriptor.size();
            final byte[] data = new byte[size];
            Streams.readFully(stream, data);
            return new InlineData(inlineDataDescriptor, data);
        }
        return null;
    }
}