blob: d88416f54ac2f4c77ad628077f6cfcd58b073c8b [file] [log] [blame]
//===-- VMClass.cpp - Compiler representation of a Java class ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declaration of the Class class that represents a
// compile time representation of a Java class (java.lang.Class). This unlike
// a classfile representation, it resolves the constant pool, creates global
// variables for the static members of this class and also creates the class
// record (vtable) of this class.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "javaclass"
#include "VMClass.h"
#include "Resolver.h"
#include <llvm/DerivedTypes.h>
#include <llvm/Constants.h>
#include <llvm/Java/ClassFile.h>
#include <llvm/Support/Debug.h>
using namespace llvm;
using namespace llvm::Java;
// On initialization we create a placeholder global for the class
// record that will be patched later when the class record is
// computed.
void VMClass::init()
{
classRecord_ = new GlobalVariable(
OpaqueType::get(),
false,
GlobalVariable::ExternalLinkage,
NULL,
getName() + "<class_record>",
resolver_->getModule());
}
VMClass::VMClass(Resolver* resolver, const std::string& className)
: name_(className),
descriptor_(Resolver::canonicalizeClassName(className)),
resolver_(resolver),
classFile_(ClassFile::get(className)),
componentClass_(NULL),
layoutType_(OpaqueType::get()),
type_(PointerType::get(layoutType_)),
interfaceIndex_(INVALID_INTERFACE_INDEX),
resolvedConstantPool_(classFile_->getNumConstants())
{
init();
}
VMClass::VMClass(Resolver* resolver, const VMClass* componentClass)
: name_('[' + componentClass->getDescriptor()),
descriptor_(name_),
resolver_(resolver),
classFile_(NULL),
componentClass_(componentClass),
layoutType_(OpaqueType::get()),
type_(PointerType::get(layoutType_)),
interfaceIndex_(INVALID_INTERFACE_INDEX)
{
init();
}
VMClass::VMClass(Resolver* resolver, const Type* type)
: name_(type == Type::SByteTy ? "byte" :
type == Type::UShortTy ? "char" :
type == Type::DoubleTy ? "double" :
type == Type::FloatTy ? "float" :
type == Type::IntTy ? "int" :
type == Type::LongTy ? "long" :
type == Type::ShortTy ? "short" :
type == Type::BoolTy ? "boolean" : "void"),
descriptor_(type == Type::SByteTy ? "B" :
type == Type::UShortTy ? "C" :
type == Type::DoubleTy ? "D" :
type == Type::FloatTy ? "F" :
type == Type::IntTy ? "I" :
type == Type::LongTy ? "J" :
type == Type::ShortTy ? "S" :
type == Type::BoolTy ? "Z" : "V"),
resolver_(resolver),
classFile_(NULL),
componentClass_(NULL),
layoutType_(const_cast<Type*>(type)),
type_(type),
interfaceIndex_(INVALID_INTERFACE_INDEX)
{
init();
}
const VMField* VMClass::lookupField(const std::string& name) const
{
if (const VMField* field = getField(name))
return field;
for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) {
const VMClass* interface = getInterface(i);
if (const VMField* field = interface->getField(name))
return field;
}
for (unsigned i = 0, e = getNumSuperClasses(); i != e; ++i) {
const VMClass* superClass = getSuperClass(i);
if (const VMField* field = superClass->getField(name))
return field;
}
return NULL;
}
const VMMethod* VMClass::lookupMethod(const std::string& nameAndType) const
{
if (const VMMethod* method = getMethod(nameAndType))
return method;
if (isInterface())
for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) {
const VMClass* interface = getInterface(i);
if (const VMMethod* method = interface->getMethod(nameAndType))
return method;
}
else
for (unsigned i = 0, e = getNumSuperClasses(); i != e; ++i) {
const VMClass* superClass = getSuperClass(i);
if (const VMMethod* method = superClass->getMethod(nameAndType))
return method;
}
return NULL;
}
void VMClass::computeLayout()
{
DEBUG(std::cerr << "Computing layout for: " << getName() << '\n');
// The layout of primitive classes is already computed.
if (isPrimitive()) {
DEBUG(std::cerr << "Computed layout for: " << getName() << '\n');
return;
}
std::vector<const Type*> layout;
if (isArray()) {
layout.reserve(3);
layout.push_back(resolver_->getClass("java/lang/Object")->getLayoutType());
layout.push_back(Type::UIntTy);
layout.push_back(ArrayType::get(componentClass_->getType(), 0));
}
else {
if (const VMClass* superClass = getSuperClass())
layout.push_back(superClass->getLayoutType());
else // This is java/lang/Object
layout.push_back(resolver_->getObjectBaseLayoutType());
// Now add the fields.
const Fields& fields = classFile_->getFields();
for (unsigned i = 0, e = fields.size(); i != e; ++i) {
Field* field = fields[i];
const std::string& name = field->getName()->str();
if (field->isStatic()) {
FieldMap::iterator i = fieldMap_.insert(
std::make_pair(name, VMField(this, field))).first;
staticFields_.push_back(&i->second);
}
else {
unsigned index = memberFields_.size() + 1;
FieldMap::iterator i = fieldMap_.insert(
std::make_pair(name, VMField(this, field, index))).first;
const VMField* vmf = &i->second;
memberFields_.push_back(vmf);
layout.push_back(vmf->getClass()->getType());
}
}
}
PATypeHolder holder = layoutType_;
Type* resolvedType = StructType::get(layout);
cast<OpaqueType>(layoutType_)->refineAbstractTypeTo(resolvedType);
layoutType_ = holder.get();
type_ = PointerType::get(layoutType_);
DEBUG(std::cerr << "Computed layout for: " << getName() << '\n');
}
llvm::Constant* VMClass::buildSuperClassRecords() const
{
std::vector<llvm::Constant*> init;
init.reserve(getNumSuperClasses());
for (unsigned i = getNumSuperClasses(); i--; )
init.push_back(ConstantExpr::getCast(
getSuperClass(i)->getClassRecord(),
resolver_->getClassRecordPtrType()));
const ArrayType* superClassRecordsType =
ArrayType::get(resolver_->getClassRecordPtrType(), init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
superClassRecordsType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(superClassRecordsType, init),
getName() + "<super_class_records>",
resolver_->getModule()));
}
llvm::Constant*
VMClass::buildInterfaceClassRecord(const VMClass* interface) const
{
assert(interface->isInterface() && "Must be passed an interface!");
std::vector<llvm::Constant*> init;
init.reserve(interface->getNumDynamicMethods() + 1);
// Insert a null type info for this interface.
init.push_back(llvm::Constant::getNullValue(resolver_->getTypeInfoType()));
// For each method this interface declares, find the corresponding
// method in this class and put it in its slot.
for (unsigned i = 0, e = interface->getNumDynamicMethods(); i != e; ++i) {
assert(init.size() == i+1 && "Interface method not found in class!");
const VMMethod* interfaceMethod = interface->getDynamicMethod(i);
for (unsigned j = 0, f = getNumDynamicMethods(); j != f; ++j) {
const VMMethod* method = getDynamicMethod(j);
if (method->getName() == interfaceMethod->getName() &&
method->getDescriptor() == interfaceMethod->getDescriptor()) {
init.push_back(method->getFunction());
break;
}
}
}
llvm::Constant* classRecordInit = ConstantStruct::get(init);
return ConstantExpr::getCast(
new GlobalVariable(
classRecordInit->getType(),
true,
GlobalVariable::ExternalLinkage,
classRecordInit,
getName() + '+' + interface->getName() + "<class_record>",
resolver_->getModule()),
resolver_->getClassRecordPtrType());
}
llvm::Constant* VMClass::buildInterfaceClassRecords() const
{
// This is an interface or primitive class record so it doesn't
// implement any interfaces. Thus the pointer to the array of
// implemented interfaces is null.
if (isInterface() || isPrimitive()) {
const Type* classRecordPtrPtrType =
PointerType::get(resolver_->getClassRecordPtrType());
return llvm::Constant::getNullValue(classRecordPtrPtrType);
}
// Otherwise this is a class or array class record so we have to
// fill in the array of implemented interfaces up the max interface
// index and build each individual interface class record for this
// class.
llvm::Constant* nullClassRecord =
llvm::Constant::getNullValue(resolver_->getClassRecordPtrType());
std::vector<llvm::Constant*> init(getInterfaceIndex()+1, nullClassRecord);
for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i) {
const VMClass* interface = getInterface(i);
init[interface->getInterfaceIndex()] = buildInterfaceClassRecord(interface);
}
const ArrayType* interfaceClassRecordsType =
ArrayType::get(resolver_->getClassRecordPtrType(), init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
interfaceClassRecordsType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(interfaceClassRecordsType, init),
getName() + "<interface_class_records>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildClassName() const
{
llvm::Constant* name = ConstantArray::get(getName());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
name->getType(),
true,
GlobalVariable::ExternalLinkage,
name,
getName() + "<classname>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildFieldDescriptors() const
{
std::vector<llvm::Constant*> init;
init.reserve(memberFields_.size()+1);
for (unsigned i = 0, e = memberFields_.size(); i != e; ++i) {
const VMField* field = memberFields_[i];
init.push_back(field->buildFieldDescriptor());
}
// Null terminate.
init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy)));
const ArrayType* arrayType =
ArrayType::get(init.back()->getType(), init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<field_descriptors>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildFieldOffsets() const
{
std::vector<llvm::Constant*> init;
init.reserve(memberFields_.size());
for (unsigned i = 0, e = memberFields_.size(); i != e; ++i) {
const VMField* field = memberFields_[i];
init.push_back(field->buildFieldOffset());
}
const ArrayType* arrayType = ArrayType::get(Type::UIntTy, init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<field_offsets>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildStaticFieldDescriptors() const
{
std::vector<llvm::Constant*> init;
init.reserve(staticFields_.size()+1);
for (unsigned i = 0, e = staticFields_.size(); i != e; ++i) {
const VMField* field = staticFields_[i];
init.push_back(field->buildFieldDescriptor());
}
// Null terminate.
init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy)));
const ArrayType* arrayType =
ArrayType::get(init.back()->getType(), init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<static_field_descriptors>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildStaticFieldPointers() const
{
std::vector<llvm::Constant*> init;
init.reserve(staticFields_.size());
const Type* pointerType = PointerType::get(Type::SByteTy);
for (unsigned i = 0, e = staticFields_.size(); i != e; ++i) {
const VMField* field = staticFields_[i];
init.push_back(ConstantExpr::getCast(field->getGlobal(), pointerType));
}
const ArrayType* arrayType = ArrayType::get(pointerType, init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<static_field_pointers>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildMethodDescriptors() const
{
std::vector<llvm::Constant*> init;
init.reserve(getNumStaticMethods() + 1);
for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) {
const VMMethod* method = getDynamicMethod(i);
init.push_back(method->buildMethodDescriptor());
}
// Null terminate.
init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy)));
const ArrayType* arrayType =
ArrayType::get(init.back()->getType(), init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<method_descriptors>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildMethodPointers() const
{
std::vector<llvm::Constant*> init;
init.reserve(getNumStaticMethods());
const Type* pointerType = PointerType::get(Type::SByteTy);
for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) {
const VMMethod* method = getDynamicMethod(i);
init.push_back(ConstantExpr::getCast(method->getBridgeFunction(),
pointerType));
}
const ArrayType* arrayType = ArrayType::get(pointerType, init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<method_pointers>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildStaticMethodDescriptors() const
{
std::vector<llvm::Constant*> init;
init.reserve(getNumStaticMethods() + 1);
for (unsigned i = 0, e = getNumStaticMethods(); i != e; ++i) {
const VMMethod* method = getStaticMethod(i);
init.push_back(method->buildMethodDescriptor());
}
// Null terminate.
init.push_back(llvm::Constant::getNullValue(PointerType::get(Type::SByteTy)));
const ArrayType* arrayType =
ArrayType::get(init.back()->getType(), init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<static_method_descriptors>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildStaticMethodPointers() const
{
std::vector<llvm::Constant*> init;
init.reserve(getNumStaticMethods());
const Type* pointerType = PointerType::get(Type::SByteTy);
for (unsigned i = 0, e = getNumStaticMethods(); i != e; ++i) {
const VMMethod* method = getStaticMethod(i);
init.push_back(ConstantExpr::getCast(method->getBridgeFunction(),
pointerType));
}
const ArrayType* arrayType = ArrayType::get(pointerType, init.size());
return ConstantExpr::getPtrPtrFromArrayPtr(
new GlobalVariable(
arrayType,
true,
GlobalVariable::ExternalLinkage,
ConstantArray::get(arrayType, init),
getName() + "<static_method_pointers>",
resolver_->getModule()));
}
llvm::Constant* VMClass::buildClassTypeInfo() const
{
std::vector<llvm::Constant*> init;
init.reserve(5);
init.push_back(buildClassName());
init.push_back(ConstantSInt::get(Type::IntTy, getNumSuperClasses()));
init.push_back(buildSuperClassRecords());
init.push_back(ConstantSInt::get(Type::IntTy, getInterfaceIndex()));
init.push_back(buildInterfaceClassRecords());
if (isArray())
init.push_back(ConstantExpr::getCast(getComponentClass()->getClassRecord(),
resolver_->getClassRecordPtrType()));
else
init.push_back(
llvm::Constant::getNullValue(resolver_->getClassRecordPtrType()));
if (isArray())
init.push_back(
ConstantExpr::getCast(
ConstantExpr::getSizeOf(getComponentClass()->getType()), Type::IntTy));
else if (isPrimitive())
init.push_back(ConstantSInt::get(Type::IntTy, -2));
else if (isInterface())
init.push_back(ConstantSInt::get(Type::IntTy, -1));
else // A class.
init.push_back(ConstantSInt::get(Type::IntTy, 0));
init.push_back(buildFieldDescriptors());
init.push_back(buildFieldOffsets());
init.push_back(buildStaticFieldDescriptors());
init.push_back(buildStaticFieldPointers());
init.push_back(buildMethodDescriptors());
init.push_back(buildMethodPointers());
init.push_back(buildStaticMethodDescriptors());
init.push_back(buildStaticMethodPointers());
return ConstantStruct::get(init);
}
void VMClass::computeClassRecord()
{
DEBUG(std::cerr << "Computing class record for: " << getName() << '\n');
// Find dynamically bound methods.
if (!isPrimitive()) {
if (const VMClass* superClass = getSuperClass())
dynamicMethods_ = superClass->dynamicMethods_;
if (getClassFile()) {
const Methods& methods = classFile_->getMethods();
for (unsigned i = 0, e = methods.size(); i != e; ++i) {
Method* method = methods[i];
const std::string& name = method->getName()->str();
const std::string& descriptor = method->getDescriptor()->str();
// If method is statically bound just create it.
if (method->isPrivate() || method->isStatic() || name[0] == '<') {
MethodMap::iterator i =
methodMap_.insert(
std::make_pair(name + descriptor, VMMethod(this, method))).first;
staticMethods_.push_back(&i->second);
}
// Otherwise we need to assign an index for it and update the
// dynamicMethods_ vector.
else {
const VMMethod* overridenMethod = NULL;
for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) {
const VMMethod* m = getDynamicMethod(i);
if (m->getName() == name && m->getDescriptor() == descriptor)
overridenMethod = m;
}
// If this is an overriden method reuse the method index
// with the overriding one.
if (overridenMethod) {
int index = overridenMethod->getMethodIndex();
MethodMap::iterator i = methodMap_.insert(
std::make_pair(name + descriptor,
VMMethod(this, method, index))).first;
dynamicMethods_[index] = &i->second;
}
// Otherwise assign it a new index.
else {
int index = dynamicMethods_.size();
MethodMap::iterator i = methodMap_.insert(
std::make_pair(
name + descriptor, VMMethod(this, method, index))).first;
dynamicMethods_.push_back(&i->second);
}
}
}
}
}
std::vector<llvm::Constant*> init;
init.reserve(1 + getNumDynamicMethods());
init.push_back(buildClassTypeInfo());
for (unsigned i = 0, e = getNumDynamicMethods(); i != e; ++i) {
const VMMethod* method = getDynamicMethod(i);
init.push_back(
method->isAbstract() ?
llvm::Constant::getNullValue(method->getFunction()->getType()) :
method->getFunction());
}
llvm::Constant* classRecordInit = ConstantStruct::get(init);
resolver_->getModule()->addTypeName("classRecord." + getName(),
classRecordInit->getType());
// Now resolve the opaque type of the placeholder class record.
const Type* classRecordType =
cast<PointerType>(classRecord_->getType())->getElementType();
OpaqueType* opaqueType = cast<OpaqueType>(const_cast<Type*>(classRecordType));
opaqueType->refineAbstractTypeTo(classRecordInit->getType());
// Set the initializer of the class record.
classRecord_->setInitializer(classRecordInit);
// Mark the class record as constant.
classRecord_->setConstant(true);
DEBUG(std::cerr << "Computed class record for: " << getName() << '\n');
}
void VMClass::link()
{
// Primitive classes require no linking.
if (isPrimitive())
;
else if (isArray()) {
superClasses_.reserve(1);
superClasses_.push_back(resolver_->getClass("java/lang/Object"));
interfaces_.reserve(2);
interfaces_.push_back(resolver_->getClass("java/lang/Cloneable"));
interfaces_.push_back(resolver_->getClass("java/io/Serializable"));
}
else {
// This is any class but java/lang/Object.
if (classFile_->getSuperClass()) {
// Our direct super class.
const VMClass* superClass = getClass(classFile_->getSuperClassIndex());
// Add the interfaces of our direct superclass.
for (unsigned i = 0, e = superClass->getNumInterfaces(); i != e; ++i)
interfaces_.push_back(superClass->getInterface(i));
// The first class is the direct super class of this class.
superClasses_.reserve(superClass->getNumSuperClasses() + 1);
superClasses_.push_back(superClass);
for (unsigned i = 0, e = superClass->getNumSuperClasses(); i != e; ++i)
superClasses_.push_back(superClass->getSuperClass(i));
}
// For each of the interfaces we implement, load it and add that
// interface and all the interfaces it inherits from.
for (unsigned i = 0, e = classFile_->getNumInterfaces(); i != e; ++i) {
const VMClass* interface = getClass(classFile_->getInterfaceIndex(i));
interfaces_.push_back(interface);
for (unsigned j = 0, f = interface->getNumInterfaces(); j != f; ++j)
interfaces_.push_back(interface->getInterface(j));
}
// Sort the interfaces array and remove duplicates.
std::sort(interfaces_.begin(), interfaces_.end());
interfaces_.erase(std::unique(interfaces_.begin(), interfaces_.end()),
interfaces_.end());
}
// The interface index for an interface is a unique number generated
// from the resolver.
if (isInterface())
interfaceIndex_ = resolver_->getNextInterfaceIndex();
// For a class it is the max index of all the interfaces it implements.
else {
for (unsigned i = 0, e = getNumInterfaces(); i != e; ++i)
interfaceIndex_ =
std::max(interfaceIndex_, getInterface(i)->getInterfaceIndex());
}
computeLayout();
computeClassRecord();
assert(!isa<OpaqueType>(getLayoutType()) &&"Class not initialized properly!");
}
llvm::Constant* VMClass::getConstant(unsigned index) const
{
assert(classFile_ && "No constant pool!");
assert((dynamic_cast<ConstantString*>(classFile_->getConstant(index)) ||
dynamic_cast<ConstantInteger*>(classFile_->getConstant(index)) ||
dynamic_cast<ConstantFloat*>(classFile_->getConstant(index)) ||
dynamic_cast<ConstantLong*>(classFile_->getConstant(index)) ||
dynamic_cast<ConstantDouble*>(classFile_->getConstant(index))) &&
"Not an index to a constant!");
// If we haven't resolved this constant already, do so now.
if (!resolvedConstantPool_[index]) {
Constant* jc = classFile_->getConstant(index);
if (ConstantString* s = dynamic_cast<ConstantString*>(jc)) {
const VMClass* stringClass = resolver_->getClass("java/lang/String");
const Type* stringType = stringClass->getLayoutType();
resolvedConstantPool_[index] =
new GlobalVariable(stringType,
false,
GlobalVariable::LinkOnceLinkage,
llvm::Constant::getNullValue(stringType),
s->getValue()->str() + ".java/lang/String",
resolver_->getModule());
}
else if (ConstantInteger* i = dynamic_cast<ConstantInteger*>(jc))
resolvedConstantPool_[index] =
ConstantSInt::get(Type::IntTy, i->getValue());
else if (ConstantFloat* f = dynamic_cast<ConstantFloat*>(jc))
resolvedConstantPool_[index] =
ConstantFP::get(Type::FloatTy, f->getValue());
else if (ConstantLong* l = dynamic_cast<ConstantLong*>(jc))
resolvedConstantPool_[index] =
ConstantSInt::get(Type::LongTy, l->getValue());
else if (ConstantDouble* d = dynamic_cast<ConstantDouble*>(jc))
resolvedConstantPool_[index] =
ConstantFP::get(Type::DoubleTy, d->getValue());
else
assert(0 && "Not a constant!");
}
return static_cast<llvm::Constant*>(resolvedConstantPool_[index]);
}
const VMClass* VMClass::getClass(unsigned index) const
{
assert(classFile_ && "No constant pool!");
assert((dynamic_cast<ConstantClass*>(classFile_->getConstant(index)) ||
dynamic_cast<ConstantUtf8*>(classFile_->getConstant(index))) &&
"Not an index to a class or descriptor reference!");
// If we haven't resolved this constant already, do so now.
if (!resolvedConstantPool_[index]) {
Constant* jc = classFile_->getConstant(index);
if (ConstantClass* c = dynamic_cast<ConstantClass*>(jc))
resolvedConstantPool_[index] =
const_cast<VMClass*>(resolver_->getClass(c->getName()->str()));
else if (ConstantUtf8* d = dynamic_cast<ConstantUtf8*>(jc))
resolvedConstantPool_[index] =
const_cast<VMClass*>(resolver_->getClassForDesc(d->str()));
else
assert(0 && "Not a class!");
}
return static_cast<const VMClass*>(resolvedConstantPool_[index]);
}
const VMField* VMClass::getField(unsigned index) const
{
assert(classFile_ && "No constant pool!");
assert(dynamic_cast<ConstantFieldRef*>(classFile_->getConstant(index)) &&
"Not an index to a field reference!");
// If we haven't resolved this constant already, do so now.
if (!resolvedConstantPool_[index]) {
ConstantFieldRef* jc = classFile_->getConstantFieldRef(index);
const VMClass* clazz = getClass(jc->getClassIndex());
const std::string& name = jc->getNameAndType()->getName()->str();
resolvedConstantPool_[index] =
const_cast<VMField*>(clazz->lookupField(name));
}
return static_cast<const VMField*>(resolvedConstantPool_[index]);
}
const VMMethod* VMClass::getMethod(unsigned index) const
{
assert(classFile_ && "No constant pool!");
assert((dynamic_cast<ConstantMethodRef*>(classFile_->getConstant(index)) ||
dynamic_cast<ConstantInterfaceMethodRef*>(classFile_->getConstant(index))) &&
"Not an index to a method reference!");
// If we haven't resolved this constant already, do so now.
if (!resolvedConstantPool_[index]) {
ConstantMemberRef* jc = classFile_->getConstantMemberRef(index);
const VMClass* clazz = getClass(jc->getClassIndex());
ConstantNameAndType* ntc = jc->getNameAndType();
const std::string& name = ntc->getName()->str();
const std::string& descriptor = ntc->getDescriptor()->str();
resolvedConstantPool_[index] =
const_cast<VMMethod*>(clazz->lookupMethod(name + descriptor));
}
return static_cast<const VMMethod*>(resolvedConstantPool_[index]);
}