Yet another MSIL question (ldsfld, ldarg_0 problem)
-
Hello everyone, I really hope someone can help me out as this is a major break point in my development process. I've been googling for info to no avail, and sadly my knowledge reaches a certain extent, being self-taught. I've been working with IL lately, and I came to the point where optimization was needed (since I'm working in a real-time 3d environment). The code - which was working (thanks to S. Senthil Kumar) - contained ldarg_0 instructions. Too many in my opinion, since the argument was already loaded onto the stack, as far as I know. I was passing to the dynamic method an object array (defined as params object[] in the delegate). Argument: object[] objectParams
ldarg_0 ldc.I4 0 ldelem_ref call (calling some method included in the objectParams[0] object) ldarg_0 ldc.I4 1 ldelem_ref call (calling some method included in the objectParams[1] object) ...
This code worked. As I stated above, I needed to optimize this, since I found pretty useless to reload the argument every time I switched to the subsequent array item. I decided to have a static field in my static class which contained that object array, instead of passing it to the dynamic method. m_MyField is a FieldInfo reference to this object array. I can safely obtain it, it's not null. Code:
ldsfld m_MyField ldc.I4 0 ldelem_ref
So, I should have three values in my stack, in this sequence: m_MyField (object[]), 0, m_MyField[0] If I were to pop twice, the current value in the stack should be m_MyField, right? So that this could would be right: Code:
ldsfld m_MyField ldc.I4 0 ldelem_ref call (some method contained in the referenced object) pop pop //back to m_MyField, I can load the next array item //the stack is containing the m_MyField array ldc.I4 1 ldelem_ref call (some method contained in the referenced object) pop pop
As you can see, there's only one ldsfld instruction, and then two pops, in order to get back to the object array. Sadly, this is not working. I am assuming that ldarg_0 works just like ldsfld in order to get that specific object array. Here's a ILStream excerpt:
IL_0000: /* 7e | 04000002 */ ldsfld System.Object[] m_MSILMethodTemporaryParamField/Dreams.PlugInManager IL_0005: /* 20 | 00000000 */ ldc.i4 0 IL_000a: /* 9a | */ ldelem.ref IL_000b: /* 28 | 06000003 */ call Void PreRender()/Dreams.UserInterface.UserInterface IL_0010: /* 26 | *
-
Hello everyone, I really hope someone can help me out as this is a major break point in my development process. I've been googling for info to no avail, and sadly my knowledge reaches a certain extent, being self-taught. I've been working with IL lately, and I came to the point where optimization was needed (since I'm working in a real-time 3d environment). The code - which was working (thanks to S. Senthil Kumar) - contained ldarg_0 instructions. Too many in my opinion, since the argument was already loaded onto the stack, as far as I know. I was passing to the dynamic method an object array (defined as params object[] in the delegate). Argument: object[] objectParams
ldarg_0 ldc.I4 0 ldelem_ref call (calling some method included in the objectParams[0] object) ldarg_0 ldc.I4 1 ldelem_ref call (calling some method included in the objectParams[1] object) ...
This code worked. As I stated above, I needed to optimize this, since I found pretty useless to reload the argument every time I switched to the subsequent array item. I decided to have a static field in my static class which contained that object array, instead of passing it to the dynamic method. m_MyField is a FieldInfo reference to this object array. I can safely obtain it, it's not null. Code:
ldsfld m_MyField ldc.I4 0 ldelem_ref
So, I should have three values in my stack, in this sequence: m_MyField (object[]), 0, m_MyField[0] If I were to pop twice, the current value in the stack should be m_MyField, right? So that this could would be right: Code:
ldsfld m_MyField ldc.I4 0 ldelem_ref call (some method contained in the referenced object) pop pop //back to m_MyField, I can load the next array item //the stack is containing the m_MyField array ldc.I4 1 ldelem_ref call (some method contained in the referenced object) pop pop
As you can see, there's only one ldsfld instruction, and then two pops, in order to get back to the object array. Sadly, this is not working. I am assuming that ldarg_0 works just like ldsfld in order to get that specific object array. Here's a ILStream excerpt:
IL_0000: /* 7e | 04000002 */ ldsfld System.Object[] m_MSILMethodTemporaryParamField/Dreams.PlugInManager IL_0005: /* 20 | 00000000 */ ldc.i4 0 IL_000a: /* 9a | */ ldelem.ref IL_000b: /* 28 | 06000003 */ call Void PreRender()/Dreams.UserInterface.UserInterface IL_0010: /* 26 | *
Hi, isnt the method you call popping all its args ?? If so, you could contemplate a "duplicate" before the call. if not, are you sure it is not modifying the stacked values ? At a more macroscopic level: are you sure a few loads will be noticed amongst those calls ? I expect call to be more expensive than load, and unless your called method is extremely short, the loads wouldnt matter much... Hope this helps. :)
Luc Pattyn
-
Hi, isnt the method you call popping all its args ?? If so, you could contemplate a "duplicate" before the call. if not, are you sure it is not modifying the stacked values ? At a more macroscopic level: are you sure a few loads will be noticed amongst those calls ? I expect call to be more expensive than load, and unless your called method is extremely short, the loads wouldnt matter much... Hope this helps. :)
Luc Pattyn
Hello Luc, thanks for your reply. I will consider what you wrote about the loads. Can you please extend what you mean with a "duplicate"? I don't know if other variables will remain into the stack after the calls, I'll check further into this. Thanks again!
-
Hello Luc, thanks for your reply. I will consider what you wrote about the loads. Can you please extend what you mean with a "duplicate"? I don't know if other variables will remain into the stack after the calls, I'll check further into this. Thanks again!
Hi Roberto, I dont know MSIL in detail, but some stack oriented machines have a "duplicate" or "dup" instruction that just duplicates "top of stack" (I know PostScript has it). If there is, it may be cheaper than a second load. BTW I forgot the most obvious tip of all: if the method you call is short, you should inline it (and if its long, then thats where you should optimize). Regards,
Luc Pattyn