public NMethod ncall(int index, int opcode)
{
if (m_ncalls == null) m_ncalls = new NMethod[m_methodRefs.size()];
NMethod x = m_ncalls[index];
if (x == null || opcode == FConst.CallNonVirtual) // don't use cache on nonvirt (see below)
{
int[] m = methodRef(index).val;
string type = nname(m[0]);
string mName = name(m[1]);
// if the type signature is java/lang then we route
// to static methods on FanObj, FanFloat, etc
string impl = FanUtil.toDotnetImplTypeName(type);
bool explicitSelf = false;
bool isStatic = false;
if (type != impl)
{
explicitSelf = opcode == FConst.CallVirtual;
isStatic = explicitSelf;
}
else
{
// if no object method than ok to use cache
if (x != null) return x;
}
// equals => Equals
if (!explicitSelf)
mName = FanUtil.toDotnetMethodName(mName);
string[] pars;
if (explicitSelf)
{
pars = new string[m.Length-2];
pars[0] = type;
for (int i=1; i<pars.Length; i++) pars[i] = nname(m[i+2]);
}
else
{
pars = new string[m.Length-3];
for (int i=0; i<pars.Length; i++) pars[i] = nname(m[i+3]);
}
string ret = nname(m[2]);
if (opcode == FConst.CallNew) ret = type; // factory
// Handle static mixin calls
if (opcode == FConst.CallMixinStatic) impl += "_";
x = new NMethod();
x.parentType = impl;
x.methodName = mName;
x.returnType = ret;
x.paramTypes = pars;
x.isStatic = isStatic;
// we don't cache nonvirtuals on Obj b/c of conflicting signatures:
// - CallVirtual: Obj.toStr => static FanObj.toStr(Object)
// - CallNonVirtual: Obj.toStr => FanObj.toStr()
if (type == impl || opcode != FConst.CallNonVirtual)
m_ncalls[index] = x;
}
return x;
}