From ILGenerator and emit to fixed? [modified + solution]
-
Hi, Recently I'm working on small compiler for fun (or actually still thinking about it's main features and implementing basic syntax) and I've ran into strange problem. Something that I thought would be easy seem not to be that easy :). What is troubling my mind, is that construction:
int[] b = new int [100];
fixed (int* p = b)
{
int* z = p;
for (int i = 0; i < 100; ++i)
{
*z = i;
z++;
}
}Such code when compiled and disassembled produces such code:
.locals init ([0] int32[] b,
[1] int32 i,
[2] int32& pinned p,
[3] int32* z,
[4] bool CS$4$0000,
[5] int32[] CS$0$0001)
[...]
IL_0031: ldloc.s CS$0$0001
IL_0033: ldc.i4.0
IL_0034: ldelema [mscorlib]System.Int32
IL_0039: stloc.2This code, from what I understand after searching information in MSDN and few other articles, pins table b (table [5] is the same as b) by pointing to it's first element with p pointer. I've tried to produce such code using ILGenerator, but I have no idea how to declare local variable of type int& (managed pointer), I guess I can declare only int* pointers, now the main question is, will above code work if I change
[2] int32& pinned p
to[2] int* pinned p
. If yes, why compiler uses this type, not just int* pointers, if no - how I can generate such code using code emit? I've made small test, disassembled code compiled with csc, changed pointer from int& to int* and yes, it works, but I can't prove anything with that, because GC had no reason to move the table in memory and I can't force him to try that, so that answered nothing except that I know such construction would be legal. [Solution] For future use hehe, I'll post solution I've come by accident, and it does seem to work: ilGen.DeclareLocal(Type.GetType("System.Int32&"), true); Although it's impossible to "do" anything with this type in code, it seems that it is possible to emit it to assembly (after all :) ).modified on Wednesday, December 10, 2008 12:23 PM
-
Hi, Recently I'm working on small compiler for fun (or actually still thinking about it's main features and implementing basic syntax) and I've ran into strange problem. Something that I thought would be easy seem not to be that easy :). What is troubling my mind, is that construction:
int[] b = new int [100];
fixed (int* p = b)
{
int* z = p;
for (int i = 0; i < 100; ++i)
{
*z = i;
z++;
}
}Such code when compiled and disassembled produces such code:
.locals init ([0] int32[] b,
[1] int32 i,
[2] int32& pinned p,
[3] int32* z,
[4] bool CS$4$0000,
[5] int32[] CS$0$0001)
[...]
IL_0031: ldloc.s CS$0$0001
IL_0033: ldc.i4.0
IL_0034: ldelema [mscorlib]System.Int32
IL_0039: stloc.2This code, from what I understand after searching information in MSDN and few other articles, pins table b (table [5] is the same as b) by pointing to it's first element with p pointer. I've tried to produce such code using ILGenerator, but I have no idea how to declare local variable of type int& (managed pointer), I guess I can declare only int* pointers, now the main question is, will above code work if I change
[2] int32& pinned p
to[2] int* pinned p
. If yes, why compiler uses this type, not just int* pointers, if no - how I can generate such code using code emit? I've made small test, disassembled code compiled with csc, changed pointer from int& to int* and yes, it works, but I can't prove anything with that, because GC had no reason to move the table in memory and I can't force him to try that, so that answered nothing except that I know such construction would be legal. [Solution] For future use hehe, I'll post solution I've come by accident, and it does seem to work: ilGen.DeclareLocal(Type.GetType("System.Int32&"), true); Although it's impossible to "do" anything with this type in code, it seems that it is possible to emit it to assembly (after all :) ).modified on Wednesday, December 10, 2008 12:23 PM
Hi, could it be the "int32& pinned p" line is actually a mistake in the disassembly process, and "int32* pinned p" is what is meant from the start? What does the disassembly show for your own code? IMO you can force the GC to move things using a scenario like this one: - create a class A that takes a lot of memory, say 50KB, but well below the "huge object" threshold (which is around 75KB IIRC). - create a second class B that takes slightly more memory. - instantiate a lot of objects A, keeping their references somewhere, say in a List, until allocating a few more would make you run out of memory. - remove half (i.e.every second) of those objects - now start instantiating the same number of objects from class B. Such scenario is bound to call the GC, which will have to compact (i.e. move most of the A objects) to fill the order. You can fix your class A objects, or alternatively you can replace class A by an array of appropriate size. :)
Luc Pattyn [Forum Guidelines] [My Articles]
Fixturized forever. :confused:
-
Hi, Recently I'm working on small compiler for fun (or actually still thinking about it's main features and implementing basic syntax) and I've ran into strange problem. Something that I thought would be easy seem not to be that easy :). What is troubling my mind, is that construction:
int[] b = new int [100];
fixed (int* p = b)
{
int* z = p;
for (int i = 0; i < 100; ++i)
{
*z = i;
z++;
}
}Such code when compiled and disassembled produces such code:
.locals init ([0] int32[] b,
[1] int32 i,
[2] int32& pinned p,
[3] int32* z,
[4] bool CS$4$0000,
[5] int32[] CS$0$0001)
[...]
IL_0031: ldloc.s CS$0$0001
IL_0033: ldc.i4.0
IL_0034: ldelema [mscorlib]System.Int32
IL_0039: stloc.2This code, from what I understand after searching information in MSDN and few other articles, pins table b (table [5] is the same as b) by pointing to it's first element with p pointer. I've tried to produce such code using ILGenerator, but I have no idea how to declare local variable of type int& (managed pointer), I guess I can declare only int* pointers, now the main question is, will above code work if I change
[2] int32& pinned p
to[2] int* pinned p
. If yes, why compiler uses this type, not just int* pointers, if no - how I can generate such code using code emit? I've made small test, disassembled code compiled with csc, changed pointer from int& to int* and yes, it works, but I can't prove anything with that, because GC had no reason to move the table in memory and I can't force him to try that, so that answered nothing except that I know such construction would be legal. [Solution] For future use hehe, I'll post solution I've come by accident, and it does seem to work: ilGen.DeclareLocal(Type.GetType("System.Int32&"), true); Although it's impossible to "do" anything with this type in code, it seems that it is possible to emit it to assembly (after all :) ).modified on Wednesday, December 10, 2008 12:23 PM
Sorry, I can't answer your question. That's the kind of question that you are only likely to get a proper answer from someone who worked at MS, and wrote portions of the CLR/C# compiler. (Do you have an MSDN license, try the MS managed forums) All I can do is point out a reflector plugin I came across the other day: http://www.codeplex.com/reflectoraddins/Wiki/View.aspx?title=ReflectionEmitLanguage&referringTitle=Home[^] Basically, it displays the C# code that you would need to write to output the same IL for the method. Maybe it will help you figure out how to do what you are trying. Good luck. :)
Simon
-
Sorry, I can't answer your question. That's the kind of question that you are only likely to get a proper answer from someone who worked at MS, and wrote portions of the CLR/C# compiler. (Do you have an MSDN license, try the MS managed forums) All I can do is point out a reflector plugin I came across the other day: http://www.codeplex.com/reflectoraddins/Wiki/View.aspx?title=ReflectionEmitLanguage&referringTitle=Home[^] Basically, it displays the C# code that you would need to write to output the same IL for the method. Maybe it will help you figure out how to do what you are trying. Good luck. :)
Simon
Well, I was hoping someone had similiar problem, that's why I asked here in first place :). I've tried this plugin that you've recommened, but unfortunately without any success. This plugin just copy&paste type from exe, which produces line like that: LocalBuilder p = gen.DeclareLocal(typeof(Int32&)); This isn't even proper c# statement hehe :). So I guess, this path leads to the dead end.
-
Hi, could it be the "int32& pinned p" line is actually a mistake in the disassembly process, and "int32* pinned p" is what is meant from the start? What does the disassembly show for your own code? IMO you can force the GC to move things using a scenario like this one: - create a class A that takes a lot of memory, say 50KB, but well below the "huge object" threshold (which is around 75KB IIRC). - create a second class B that takes slightly more memory. - instantiate a lot of objects A, keeping their references somewhere, say in a List, until allocating a few more would make you run out of memory. - remove half (i.e.every second) of those objects - now start instantiating the same number of objects from class B. Such scenario is bound to call the GC, which will have to compact (i.e. move most of the A objects) to fill the order. You can fix your class A objects, or alternatively you can replace class A by an array of appropriate size. :)
Luc Pattyn [Forum Guidelines] [My Articles]
Fixturized forever. :confused:
Hi, I'm afraid it's not a mistake of a compiler. Based on this article for example: http://www.codeproject.com/KB/msil/ilassembly.aspx It looks like it's just a type, now the question is, does it has some special meaning, especially when pinning objects in memory. Your method looks like it should work, I'll try it and do some tests as soon as I have few free minutes, which means now :).
-
Well, I was hoping someone had similiar problem, that's why I asked here in first place :). I've tried this plugin that you've recommened, but unfortunately without any success. This plugin just copy&paste type from exe, which produces line like that: LocalBuilder p = gen.DeclareLocal(typeof(Int32&)); This isn't even proper c# statement hehe :). So I guess, this path leads to the dead end.
Ravadre wrote:
This isn't even proper c# statement hehe Smile. So I guess, this path leads to the dead end.
Oh well. I've not used it myself, I just remember seeing it and thinking it looked interesting while looking for a different plug-in. Sorry. Good luck. ;)
Simon
-
Ravadre wrote:
This isn't even proper c# statement hehe Smile. So I guess, this path leads to the dead end.
Oh well. I've not used it myself, I just remember seeing it and thinking it looked interesting while looking for a different plug-in. Sorry. Good luck. ;)
Simon