/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.classloader;
import org.jikesrvm.VM;
import org.jikesrvm.VM_Constants;
import org.jikesrvm.memorymanagers.mminterface.MM_Interface;
import org.jikesrvm.runtime.VM_Magic;
import org.jikesrvm.runtime.VM_Runtime;
import org.vmmagic.pragma.Entrypoint;
/**
* Dynamic linking via indirection tables. <p>
*
* The main idea for dynamic linking is that we maintain
* arrays of member offsets indexed by the member's
* dynamic linking id. The generated code at a dynamically linked
* site will load the appropriate value from the offset table and
* check to see if the value is valid. If it is, then no dynamic linking
* is required. If the value is invalid, then resolveDynamicLink
* is invoked to perfrom any required dynamic class loading.
* After member resolution and class loading completes, we can
* store the offset value in the offset table.
* Thus when resolve method returns, execution can be restarted
* by reloading/indexing the offset table. <p>
*
* <p> NOTE: We believe that only use of invokespecial that could possibly
* require dynamic linking is that of invoking an object initializer.
*/
public class VM_TableBasedDynamicLinker implements VM_Constants {
@Entrypoint
private static int[] memberOffsets;
static {
memberOffsets = MM_Interface.newContiguousIntArray(16000);
if (NEEDS_DYNAMIC_LINK != 0) {
java.util.Arrays.fill(memberOffsets, NEEDS_DYNAMIC_LINK);
}
}
/**
* Cause dynamic linking of the VM_Member whose member reference id is given.
* Invoked directly from (baseline) compiled code.
* @param memberId the dynamicLinkingId of the method to link.
* @return returns the offset of the member.
*/
@Entrypoint
public static int resolveMember(int memberId, boolean forSubArch) throws NoClassDefFoundError {
VM_MemberReference ref = VM_MemberReference.getMemberRef(memberId);
return resolveMember(ref, forSubArch);
}
/**
* Cause dynamic linking of the argument VM_MemberReference
* @param ref reference to the member to link
* @return returns the offset of the member.
*/
public static int resolveMember(VM_MemberReference ref, boolean forSubArch) throws NoClassDefFoundError {
VM_Member resolvedMember = ref.resolveMember(forSubArch);
VM_Class declaringClass = resolvedMember.getDeclaringClass();
VM_Runtime.initializeClassForDynamicLink(declaringClass);
int offset;
if (!forSubArch) {
offset = resolvedMember.getOffset().toInt();
} else {
offset = resolvedMember.getSubArchOffset().toInt();
}
if (VM.VerifyAssertions) VM._assert(offset != NEEDS_DYNAMIC_LINK);
memberOffsets[ref.getId()] = offset;
return offset;
}
/**
* Method invoked from VM_MemberReference to
* ensure that there is space in the dynamic linking table for
* the given member reference.
*/
static synchronized void ensureCapacity(int id) {
if (id == memberOffsets.length) {
int oldLen = memberOffsets.length;
int[] tmp1 = MM_Interface.newContiguousIntArray(oldLen * 2);
System.arraycopy(memberOffsets, 0, tmp1, 0, oldLen);
if (NEEDS_DYNAMIC_LINK != 0) {
java.util.Arrays.fill(tmp1, oldLen, tmp1.length, NEEDS_DYNAMIC_LINK);
}
VM_Magic.sync(); // be sure array initialization is visible before we publish the reference!
memberOffsets = tmp1;
}
}
}