private static bool Object_getClass(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags)
{
// this is the null-check idiom that javac uses (both in its own source and in the code it generates)
if (code[opcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__pop)
{
ilgen.Emit(OpCodes.Dup);
ilgen.EmitNullCheck();
return(true);
}
// this optimizes obj1.getClass() ==/!= obj2.getClass()
else if (opcodeIndex + 3 < code.Length &&
(flags[opcodeIndex + 1] & InstructionFlags.BranchTarget) == 0 &&
(flags[opcodeIndex + 2] & InstructionFlags.BranchTarget) == 0 &&
(flags[opcodeIndex + 3] & InstructionFlags.BranchTarget) == 0 &&
code[opcodeIndex + 1].NormalizedOpCode == NormalizedByteCode.__aload &&
code[opcodeIndex + 2].NormalizedOpCode == NormalizedByteCode.__invokevirtual &&
(code[opcodeIndex + 3].NormalizedOpCode == NormalizedByteCode.__if_acmpeq || code[opcodeIndex + 3].NormalizedOpCode == NormalizedByteCode.__if_acmpne) &&
(IsSafeForGetClassOptimization(ma.GetStackTypeWrapper(opcodeIndex, 0)) || IsSafeForGetClassOptimization(ma.GetStackTypeWrapper(opcodeIndex + 2, 0))))
{
ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(code[opcodeIndex + 2].Arg1);
if (cpi.Class == "java.lang.Object" && cpi.Name == "getClass" && cpi.Signature == "()Ljava.lang.Class;")
{
// we can't patch the current opcode, so we have to emit the first call to GetTypeHandle here
ilgen.Emit(OpCodes.Callvirt, Compiler.getTypeMethod);
code[opcodeIndex + 2].PatchOpCode(NormalizedByteCode.__intrinsic_gettype);
return(true);
}
}
return(false);
}