view graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantPool.java @ 13254:42aaf7306707

Teach Graal about Symbol and ConstantPool so we can move more logic into Java. We'll see how that ends...
author twisti
date Thu, 05 Dec 2013 18:13:04 -0800
parents ae412befde21
children b16fb0b7479b
line wrap: on
line source

/*
 * Copyright (c) 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.oracle.graal.hotspot.meta;

import static com.oracle.graal.graph.UnsafeAccess.*;
import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;

import com.oracle.graal.api.meta.*;
import com.oracle.graal.bytecode.*;
import com.oracle.graal.graph.*;
import com.oracle.graal.hotspot.*;

/**
 * Implementation of {@link ConstantPool} for HotSpot.
 */
public class HotSpotConstantPool extends CompilerObject implements ConstantPool {

    private static final long serialVersionUID = -5443206401485234850L;

    private final HotSpotResolvedObjectType type;

    public HotSpotConstantPool(HotSpotResolvedObjectType type) {
        this.type = type;
    }

    /**
     * Returns the address of this type's constant pool ({@code InstanceKlass::_constants}).
     * 
     * @return native address of this type's constant pool
     */
    private long getAddress() {
        HotSpotVMConfig config = runtime().getConfig();
        return unsafe.getAddress(type.metaspaceKlass() + config.instanceKlassConstantsOffset);
    }

    /**
     * Returns the constant pool tag at index {@code index}.
     * 
     * @param index constant pool index
     * @return constant pool tag at index
     */
    private int getTagAt(int index) {
        assertBounds(index);
        HotSpotVMConfig config = runtime().getConfig();
        long tags = unsafe.getAddress(getAddress() + config.constantPoolTagsOffset);
        return unsafe.getByteVolatile(null, tags + config.arrayU1DataOffset + index);
    }

    /**
     * Returns the constant pool entry at index {@code index}.
     * 
     * @param index constant pool index
     * @return constant pool entry at index
     */
    private long getEntryAt(int index) {
        assertBounds(index);
        HotSpotVMConfig config = runtime().getConfig();
        return unsafe.getAddress(getAddress() + config.constantPoolSize + index * runtime().getTarget().wordSize);
    }

    /**
     * Returns the integer constant pool entry at index {@code index}.
     * 
     * @param index constant pool index
     * @return integer constant pool entry at index
     */
    private int getIntAt(int index) {
        HotSpotVMConfig config = runtime().getConfig();
        assertTag(index, config.jvmConstantInteger);
        return unsafe.getInt(getAddress() + config.constantPoolSize + index * runtime().getTarget().wordSize);
    }

    /**
     * Returns the long constant pool entry at index {@code index}.
     * 
     * @param index constant pool index
     * @return long constant pool entry at index
     */
    private long getLongAt(int index) {
        HotSpotVMConfig config = runtime().getConfig();
        assertTag(index, config.jvmConstantLong);
        return unsafe.getLong(getAddress() + config.constantPoolSize + index * runtime().getTarget().wordSize);
    }

    /**
     * Returns the float constant pool entry at index {@code index}.
     * 
     * @param index constant pool index
     * @return float constant pool entry at index
     */
    private float getFloatAt(int index) {
        HotSpotVMConfig config = runtime().getConfig();
        assertTag(index, config.jvmConstantFloat);
        return unsafe.getFloat(getAddress() + config.constantPoolSize + index * runtime().getTarget().wordSize);
    }

    /**
     * Returns the double constant pool entry at index {@code index}.
     * 
     * @param index constant pool index
     * @return float constant pool entry at index
     */
    private double getDoubleAt(int index) {
        HotSpotVMConfig config = runtime().getConfig();
        assertTag(index, config.jvmConstantDouble);
        return unsafe.getDouble(getAddress() + config.constantPoolSize + index * runtime().getTarget().wordSize);
    }

    /**
     * Asserts that the constant pool index {@code index} is in the bounds of the constant pool.
     * 
     * @param index constant pool index
     */
    private void assertBounds(int index) {
        assert 0 <= index && index < length() : "index " + index + " not between 0 or " + length();
    }

    /**
     * Asserts that the constant pool tag at index {@code index} is equal to {@code tag}.
     * 
     * @param index constant pool index
     * @param tag expected tag
     */
    private void assertTag(int index, int tag) {
        assert getTagAt(index) == tag : "constant pool tag at index " + index + " is " + getTagAt(index) + " but expected " + tag;
    }

    @Override
    public int length() {
        HotSpotVMConfig config = runtime().getConfig();
        return unsafe.getInt(getAddress() + config.constantPoolLengthOffset);
    }

    @Override
    public Object lookupConstant(int cpi) {
        assert cpi != 0;

        HotSpotVMConfig config = runtime().getConfig();
        final int tag = getTagAt(cpi);

        // Handle primitive constant pool entries directly.
        if (tag == config.jvmConstantInteger) {
            return Constant.forInt(getIntAt(cpi));
        }
        if (tag == config.jvmConstantLong) {
            return Constant.forLong(getLongAt(cpi));
        }
        if (tag == config.jvmConstantFloat) {
            return Constant.forFloat(getFloatAt(cpi));
        }
        if (tag == config.jvmConstantDouble) {
            return Constant.forDouble(getDoubleAt(cpi));
        }

        // All the other constant pool entries need special attention so we call down into the VM.
        if (tag == config.jvmConstantClass || tag == config.jvmConstantUnresolvedClass || tag == config.jvmConstantUnresolvedClassInError) {
            final int opcode = -1;  // opcode is not used
            return lookupType(cpi, opcode);
        }
        if (tag == config.jvmConstantString) {
            Object string = runtime().getCompilerToVM().lookupConstantInPool(type, cpi);
            return Constant.forObject(string);
        }
        if (tag == config.jvmConstantMethodHandle || tag == config.jvmConstantMethodHandleInError || tag == config.jvmConstantMethodType || tag == config.jvmConstantMethodTypeInError) {
            Object obj = runtime().getCompilerToVM().lookupConstantInPool(type, cpi);
            return Constant.forObject(obj);
        }

        throw GraalInternalError.shouldNotReachHere("unknown constant pool tag " + tag);
    }

    @Override
    public String lookupUtf8(int cpi) {
        assertTag(cpi, runtime().getConfig().jvmConstantUtf8);
        long signature = getEntryAt(cpi);
        HotSpotSymbol symbol = new HotSpotSymbol(signature);
        return symbol.asString();
    }

    @Override
    public Signature lookupSignature(int cpi) {
        return new HotSpotSignature(lookupUtf8(cpi));
    }

    @Override
    public Object lookupAppendix(int cpi, int opcode) {
        assert Bytecodes.isInvoke(opcode);
        return runtime().getCompilerToVM().lookupAppendixInPool(type, cpi, (byte) opcode);
    }

    @Override
    public JavaMethod lookupMethod(int cpi, int opcode) {
        return runtime().getCompilerToVM().lookupMethodInPool(type, cpi, (byte) opcode);
    }

    @Override
    public JavaType lookupType(int cpi, int opcode) {
        return runtime().getCompilerToVM().lookupTypeInPool(type, cpi);
    }

    @Override
    public JavaField lookupField(int cpi, int opcode) {
        return runtime().getCompilerToVM().lookupFieldInPool(type, cpi, (byte) opcode);
    }

    @Override
    public void loadReferencedType(int cpi, int opcode) {
        runtime().getCompilerToVM().lookupReferencedTypeInPool(type, cpi, (byte) opcode);
    }
}