Exemple #1
0
        private static bool System_arraycopy(DynamicTypeWrapper.FinishContext context, CodeEmitter ilgen, MethodWrapper method, MethodAnalyzer ma, int opcodeIndex, MethodWrapper caller, ClassFile classFile, Instruction[] code, InstructionFlags[] flags)
        {
            // if the array arguments on the stack are of a known array type, we can redirect to an optimized version of arraycopy.
            // Note that we also have to handle VMSystem.arraycopy, because on GNU Classpath StringBuffer directly calls
            // this method to avoid prematurely initialising System.
            TypeWrapper dst_type = ma.GetStackTypeWrapper(opcodeIndex, 2);
            TypeWrapper src_type = ma.GetStackTypeWrapper(opcodeIndex, 4);

            if (!dst_type.IsUnloadable && dst_type.IsArray && dst_type == src_type)
            {
                switch (dst_type.Name[1])
                {
                case 'J':
                case 'D':
                    ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_8);
                    break;

                case 'I':
                case 'F':
                    ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_4);
                    break;

                case 'S':
                case 'C':
                    ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_2);
                    break;

                case 'B':
                case 'Z':
                    ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_primitive_1);
                    break;

                default:
                    // TODO once the verifier tracks actual types (i.e. it knows that
                    // a particular reference is the result of a "new" opcode) we can
                    // use the fast version if the exact destination type is known
                    // (in that case the "dst_type == src_type" above should
                    // be changed to "src_type.IsAssignableTo(dst_type)".
                    TypeWrapper elemtw = dst_type.ElementTypeWrapper;
                    // note that IsFinal returns true for array types, so we have to be careful!
                    if (!elemtw.IsArray && elemtw.IsFinal)
                    {
                        ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy_fast);
                    }
                    else
                    {
                        ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.arraycopy);
                    }
                    break;
                }
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #2
0
 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);
 }
			internal override void EmitNewobj(CodeEmitter ilgen, MethodAnalyzer ma, int opcodeIndex)
			{
				TypeWrapper targetType = ma == null ? null : ma.GetStackTypeWrapper(opcodeIndex, 0);
				if (targetType == null || targetType.IsInterface)
				{
					MethodInfo createDelegate = Types.Delegate.GetMethod("CreateDelegate", new Type[] { Types.Type, Types.Object, Types.String });
					LocalBuilder targetObj = ilgen.DeclareLocal(Types.Object);
					ilgen.Emit(OpCodes.Stloc, targetObj);
					ilgen.Emit(OpCodes.Ldtoken, delegateConstructor.DeclaringType);
					ilgen.Emit(OpCodes.Call, Types.Type.GetMethod("GetTypeFromHandle", new Type[] { Types.RuntimeTypeHandle }));
					ilgen.Emit(OpCodes.Ldloc, targetObj);
					ilgen.Emit(OpCodes.Ldstr, "Invoke");
					ilgen.Emit(OpCodes.Call, createDelegate);
					ilgen.Emit(OpCodes.Castclass, delegateConstructor.DeclaringType);
				}
				else
				{
					ilgen.Emit(OpCodes.Dup);
					// we know that a DelegateInnerClassTypeWrapper has only one method
					Debug.Assert(iface.GetMethods().Length == 1);
					MethodWrapper mw = targetType.GetMethodWrapper("Invoke", iface.GetMethods()[0].Signature, true);
					// TODO linking here is not safe
					mw.Link();
					ilgen.Emit(OpCodes.Ldvirtftn, (MethodInfo)mw.GetMethod());
					ilgen.Emit(OpCodes.Newobj, delegateConstructor);
				}
			}