private unsafe static FuncEvalResult CallParameterizedFunctionOrNewParameterizedObject(ref long myFuncEvalId, byte *parameterBuffer, uint parameterBufferSize, bool isConstructor) { InvokeFunctionData invokeFunctionData = new InvokeFunctionData(); LowLevelNativeFormatReader reader = new LowLevelNativeFormatReader(parameterBuffer, parameterBufferSize); myFuncEvalId = s_funcEvalId = (long)reader.GetUnsignedLong(); uint parameterCount = reader.GetUnsigned(); invokeFunctionData.parameterValues = new byte[parameterCount][]; for (int i = 0; i < parameterCount; i++) { uint parameterValueSize = reader.GetUnsigned(); byte[] parameterValue = new byte[parameterValueSize]; for (int j = 0; j < parameterValueSize; j++) { uint parameterByte = reader.GetUnsigned(); parameterValue[j] = (byte)parameterByte; } invokeFunctionData.parameterValues[i] = parameterValue; } ulong[] debuggerPreparedExternalReferences; BuildDebuggerPreparedExternalReferences(reader, out debuggerPreparedExternalReferences); bool hasThis; TypeDesc[] parameters; bool[] parametersWithGenericDependentLayout; bool result = TypeSystemHelper.CallingConverterDataFromMethodSignature( reader, debuggerPreparedExternalReferences, out hasThis, out parameters, out parametersWithGenericDependentLayout ); invokeFunctionData.types = new RuntimeTypeHandle[parameters.Length]; for (int i = 0; i < invokeFunctionData.types.Length; i++) { invokeFunctionData.types[i] = parameters[i].GetRuntimeTypeHandle(); } LocalVariableType[] argumentTypes = new LocalVariableType[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { // TODO, FuncEval, what these false really means? Need to make sure our format contains those information argumentTypes[i] = new LocalVariableType(invokeFunctionData.types[i], false, false); } if (isConstructor) { // TODO, FuncEval, deal with Nullable objects invokeFunctionData.thisObj = RuntimeAugments.RawNewObject(invokeFunctionData.types[1]); } LocalVariableSet.SetupArbitraryLocalVariableSet <InvokeFunctionData>(InvokeFunction, ref invokeFunctionData, argumentTypes); return(invokeFunctionData.result); }
private unsafe static void InvokeFunction(ref InvokeFunctionData invokeFunctionData, ref LocalVariableSet arguments) { // Offset begins with 1 because we always skip setting the return value before we call the function int offset = 1; if (invokeFunctionData.thisObj != null) { // For constructors - caller does not pass the this pointer, instead, we constructed param.thisObj and pass it as the first argument arguments.SetVar <object>(offset, invokeFunctionData.thisObj); offset++; } for (int i = 0; i < invokeFunctionData.parameterValues.Length; i++) { IntPtr input = arguments.GetAddressOfVarData(i + offset); byte * pInput = (byte *)input; fixed(byte *pParam = invokeFunctionData.parameterValues[i]) { for (int j = 0; j < invokeFunctionData.parameterValues[i].Length; j++) { pInput[j] = pParam[j]; } } } // Obtain the target method address from the runtime IntPtr targetAddress = RuntimeAugments.RhpGetFuncEvalTargetAddress(); LocalVariableType[] returnAndArgumentTypes = new LocalVariableType[invokeFunctionData.types.Length]; for (int i = 0; i < returnAndArgumentTypes.Length; i++) { returnAndArgumentTypes[i] = new LocalVariableType(invokeFunctionData.types[i], false, false); } DynamicCallSignature dynamicCallSignature = new DynamicCallSignature(invokeFunctionData.callingConvention, returnAndArgumentTypes, returnAndArgumentTypes.Length); // Invoke the target method Exception ex = null; try { Internal.Runtime.CallInterceptor.CallInterceptor.MakeDynamicCall(targetAddress, dynamicCallSignature, arguments); } catch (Exception e) { ex = e; } bool isVoid = (RuntimeTypeHandle.Equals(invokeFunctionData.types[0], typeof(void).TypeHandle)); object returnValue = null; if (ex != null) { returnValue = ex; } else if (invokeFunctionData.thisObj != null) { // For constructors - the debugger would like to get 'this' back returnValue = invokeFunctionData.thisObj; } else if (!isVoid) { IntPtr input = arguments.GetAddressOfVarData(0); returnValue = RuntimeAugments.RhBoxAny(input, invokeFunctionData.types[0].Value); } // Note that the return value could be null if the target function returned null invokeFunctionData.result = new FuncEvalResult(returnValue, ex != null); }