Beispiel #1
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);
 }
Beispiel #2
0
 internal ClassFile.ConstantPoolItemMI GetMethodref(int offset)
 {
     return(ClassFile.GetMethodref(Code[OpcodeIndex + offset].Arg1));
 }
Beispiel #3
0
    private static Dictionary <int, string>[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state)
    {
        ClassFile.Method.Instruction[] instructions = method.Instructions;
        ExceptionTableEntry[]          exceptions   = method.ExceptionTable;
        int maxLocals = method.MaxLocals;

        Dictionary <int, string>[] localStoreReaders = new Dictionary <int, string> [instructions.Length];
        bool done = false;

        while (!done)
        {
            done = true;
            for (int i = 0; i < instructions.Length; i++)
            {
                if (state[i].changed)
                {
                    done             = false;
                    state[i].changed = false;

                    FindLocalVarState curr = state[i].Copy();

                    for (int j = 0; j < exceptions.Length; j++)
                    {
                        if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex)
                        {
                            state[exceptions[j].handlerIndex].Merge(curr);
                        }
                    }

                    if (IsLoadLocal(instructions[i].NormalizedOpCode) &&
                        (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0))))
                    {
                        if (localStoreReaders[i] == null)
                        {
                            localStoreReaders[i] = new Dictionary <int, string>();
                        }
                        for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++)
                        {
                            localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = "";
                        }
                    }

                    if (IsStoreLocal(instructions[i].NormalizedOpCode) &&
                        (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0))))
                    {
                        curr.Store(i, instructions[i].NormalizedArg1);
                        // if this is a store at the end of an exception block,
                        // we need to propagate the new state to the exception handler
                        for (int j = 0; j < exceptions.Length; j++)
                        {
                            if (exceptions[j].endIndex == i + 1)
                            {
                                state[exceptions[j].handlerIndex].Merge(curr);
                            }
                        }
                    }

                    if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                    {
                        ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1);
                        if (ReferenceEquals(cpi.Name, StringConstants.INIT))
                        {
                            TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length);
                            // after we've invoked the constructor, the uninitialized references
                            // are now initialized
                            if (type == VerifierTypeWrapper.UninitializedThis ||
                                VerifierTypeWrapper.IsNew(type))
                            {
                                for (int j = 0; j < maxLocals; j++)
                                {
                                    if (codeInfo.GetLocalTypeWrapper(i, j) == type)
                                    {
                                        curr.Store(i, j);
                                    }
                                }
                            }
                        }
                    }
                    else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally)
                    {
                        int handler = instructions[i].HandlerIndex;

                        // Normally a store at the end of a try block doesn't affect the handler block,
                        // but in the case of a finally handler it does, so we need to make sure that
                        // we merge here in case the try block ended with a store.
                        state[handler].Merge(curr);

                        // Now we recursively analyse the handler and afterwards merge the endfault locations back to us
                        FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length];
                        handlerState[handler].Merge(curr);
                        curr = new FindLocalVarState();
                        FindLocalVariablesImpl(codeInfo, classFile, method, handlerState);

                        // Merge back to the target of our __goto_finally
                        for (int j = 0; j < handlerState.Length; j++)
                        {
                            if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow &&
                                codeInfo.HasState(j) &&
                                VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) &&
                                ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler)
                            {
                                curr.Merge(handlerState[j]);
                            }
                        }
                    }

                    switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode))
                    {
                    case ByteCodeFlowControl.Switch:
                    {
                        for (int j = 0; j < instructions[i].SwitchEntryCount; j++)
                        {
                            state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr);
                        }
                        state[instructions[i].DefaultTarget].Merge(curr);
                        break;
                    }

                    case ByteCodeFlowControl.Branch:
                        state[instructions[i].TargetIndex].Merge(curr);
                        break;

                    case ByteCodeFlowControl.CondBranch:
                        state[instructions[i].TargetIndex].Merge(curr);
                        state[i + 1].Merge(curr);
                        break;

                    case ByteCodeFlowControl.Return:
                    case ByteCodeFlowControl.Throw:
                        break;

                    case ByteCodeFlowControl.Next:
                        state[i + 1].Merge(curr);
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }
        return(localStoreReaders);
    }
Beispiel #4
0
	private static Dictionary<int, string>[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state)
	{
		ClassFile.Method.Instruction[] instructions = method.Instructions;
		ExceptionTableEntry[] exceptions = method.ExceptionTable;
		int maxLocals = method.MaxLocals;
		Dictionary<int, string>[] localStoreReaders = new Dictionary<int, string>[instructions.Length];
		bool done = false;

		while (!done)
		{
			done = true;
			for (int i = 0; i < instructions.Length; i++)
			{
				if (state[i].changed)
				{
					done = false;
					state[i].changed = false;

					FindLocalVarState curr = state[i].Copy();

					for (int j = 0; j < exceptions.Length; j++)
					{
						if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex)
						{
							state[exceptions[j].handlerIndex].Merge(curr);
						}
					}

					if (IsLoadLocal(instructions[i].NormalizedOpCode)
						&& (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0))))
					{
						if (localStoreReaders[i] == null)
						{
							localStoreReaders[i] = new Dictionary<int, string>();
						}
						for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++)
						{
							localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = "";
						}
					}

					if (IsStoreLocal(instructions[i].NormalizedOpCode)
						&& (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0))))
					{
						curr.Store(i, instructions[i].NormalizedArg1);
						// if this is a store at the end of an exception block,
						// we need to propagate the new state to the exception handler
						for (int j = 0; j < exceptions.Length; j++)
						{
							if (exceptions[j].endIndex == i + 1)
							{
								state[exceptions[j].handlerIndex].Merge(curr);
							}
						}
					}

					if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial)
					{
						ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1);
						if (ReferenceEquals(cpi.Name, StringConstants.INIT))
						{
							TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length);
							// after we've invoked the constructor, the uninitialized references
							// are now initialized
							if (type == VerifierTypeWrapper.UninitializedThis
								|| VerifierTypeWrapper.IsNew(type))
							{
								for (int j = 0; j < maxLocals; j++)
								{
									if (codeInfo.GetLocalTypeWrapper(i, j) == type)
									{
										curr.Store(i, j);
									}
								}
							}
						}
					}
					else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally)
					{
						int handler = instructions[i].HandlerIndex;

						// Normally a store at the end of a try block doesn't affect the handler block,
						// but in the case of a finally handler it does, so we need to make sure that
						// we merge here in case the try block ended with a store.
						state[handler].Merge(curr);

						// Now we recursively analyse the handler and afterwards merge the endfault locations back to us
						FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length];
						handlerState[handler].Merge(curr);
						curr = new FindLocalVarState();
						FindLocalVariablesImpl(codeInfo, classFile, method, handlerState);

						// Merge back to the target of our __goto_finally
						for (int j = 0; j < handlerState.Length; j++)
						{
							if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow
								&& codeInfo.HasState(j)
								&& VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0))
								&& ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler)
							{
								curr.Merge(handlerState[j]);
							}
						}
					}

					switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode))
					{
						case ByteCodeFlowControl.Switch:
							{
								for (int j = 0; j < instructions[i].SwitchEntryCount; j++)
								{
									state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr);
								}
								state[instructions[i].DefaultTarget].Merge(curr);
								break;
							}
						case ByteCodeFlowControl.Branch:
							state[instructions[i].TargetIndex].Merge(curr);
							break;
						case ByteCodeFlowControl.CondBranch:
							state[instructions[i].TargetIndex].Merge(curr);
							state[i + 1].Merge(curr);
							break;
						case ByteCodeFlowControl.Return:
						case ByteCodeFlowControl.Throw:
							break;
						case ByteCodeFlowControl.Next:
							state[i + 1].Merge(curr);
							break;
						default:
							throw new InvalidOperationException();
					}
				}
			}
		}
		return localStoreReaders;
	}