Mixed mode '__pin' internals: does '__pin' does anything at all?

G

Guest

Hi,

I am writing a mixed mode application, I have a mixed mode Assembly manipulating a managed byte[] array, to access this array in unmanaged code I '__pin' the array, As I understand, pining an object guarantee that it will not be collected by the GC ( by increasing it's refcount or so ), Taking that in mind, looking at the code generated by the compiler I can't see anything taking care of the GC refcount... following is the pinned variable with the corresponding dis-assembly section:

****************** Mixed mode C++ code line ******************
BYTE __pin *pbtArray = &btArray[0];

******************** The dis-assembly ***********************
00000019 cmp dword ptr [esi+4],0 // makes sure that NULL != &btArray[0]
0000001d ja 00000026 // if it is not NULL go three lines bellow
0000001f xor ecx,ecx
00000021 call 7227F90B // call some exception handling procedure...
00000026 lea eax,[esi+8] // get the address of &btArray[0] to eax
00000029 mov dword ptr [ebp-14h],eax // pbtArray = content of eax
********************************************************
Why there is no GC manipulation code? isn't it needed?

The original code:
********************************************************
virtual int NotArray(System::Byte btArray __gc[])
{
int i = 0;
BYTE __pin *pbtArray = &btArray[0];
for(i; i < btArray->Length; i++)
pbtArray <<= 1;
return 0;
}

Nadav
http://www.ddevel.com
 
C

Christopher Kimbell

The garbage collection is done by the runtime, not the application, therefor
there is no GC code in your application code.
If Microsoft embedded GC manipulation code in the apllication code, it would
be impossible to change GC policy in the future.

Pinning an object prevents the GC from moving the reference in memory, it
has nothing to do with reference counting. The GC periodically moves things
around so that the memory used is located together in memory.

Chris

Nadav said:
Hi,

I am writing a mixed mode application, I have a mixed mode Assembly
manipulating a managed byte[] array, to access this array in unmanaged code
I '__pin' the array, As I understand, pining an object guarantee that it
will not be collected by the GC ( by increasing it's refcount or so ),
Taking that in mind, looking at the code generated by the compiler I can't
see anything taking care of the GC refcount... following is the pinned
variable with the corresponding dis-assembly section:
****************** Mixed mode C++ code line ******************
BYTE __pin *pbtArray = &btArray[0];

******************** The dis-assembly ***********************
00000019 cmp dword ptr [esi+4],0 // makes sure that NULL != &btArray[0]
0000001d ja 00000026 // if it is not NULL go three lines bellow
0000001f xor ecx,ecx
00000021 call 7227F90B // call some exception handling procedure...
00000026 lea eax,[esi+8] // get the address of &btArray[0] to eax
00000029 mov dword ptr [ebp-14h],eax // pbtArray = content of eax
********************************************************
Why there is no GC manipulation code? isn't it needed?

The original code:
********************************************************
virtual int NotArray(System::Byte btArray __gc[])
{
int i = 0;
BYTE __pin *pbtArray = &btArray[0];
for(i; i < btArray->Length; i++)
pbtArray <<= 1;
return 0;
}

Nadav
http://www.ddevel.com
 
N

Nadav

Thanks for your immediate response, concerning the '__pin' keyword causes
the GC to prevent moving the buffer in memory ( and not manipulate any
refcount ), how does it do that? there must be some assembler code to
instruct the GC that this is a '__pined' variable so it would know not to
move it, looking at the assembler code produced by the compiler (provided at
the root query) I can't see anything as such... It seems as the '__pin'
keyword has no effect on the assembler code being generated by the compiler,
why is that? how can it be guaranteed that the memory pointed to by
'pbtArray' will stay valid for the duration it is being used...



(*)Another thing: Taking in mind what you have said concerning the way GC is
operating, Is it possible to prevent the GC from moving memory in the first
place? e.g. lets say I have a performance critical application, I allocate
(apriory) a collection of buffers to be used by the App, those buffers
should be moved as less as possible during runtime, how can I achieve that
using the .NET Framework????



Nadav.


Christopher Kimbell said:
The garbage collection is done by the runtime, not the application, therefor
there is no GC code in your application code.
If Microsoft embedded GC manipulation code in the apllication code, it would
be impossible to change GC policy in the future.

Pinning an object prevents the GC from moving the reference in memory, it
has nothing to do with reference counting. The GC periodically moves things
around so that the memory used is located together in memory.

Chris

Nadav said:
Hi,

I am writing a mixed mode application, I have a mixed mode Assembly
manipulating a managed byte[] array, to access this array in unmanaged code
I '__pin' the array, As I understand, pining an object guarantee that it
will not be collected by the GC ( by increasing it's refcount or so ),
Taking that in mind, looking at the code generated by the compiler I can't
see anything taking care of the GC refcount... following is the pinned
variable with the corresponding dis-assembly section:
****************** Mixed mode C++ code line ******************
BYTE __pin *pbtArray = &btArray[0];

******************** The dis-assembly ***********************
00000019 cmp dword ptr [esi+4],0 // makes sure that NULL != &btArray[0]
0000001d ja 00000026 // if it is not NULL go
three
lines bellow
0000001f xor ecx,ecx
00000021 call 7227F90B // call some exception handling procedure...
00000026 lea eax,[esi+8] // get the address of &btArray[0] to eax
00000029 mov dword ptr [ebp-14h],eax // pbtArray = content of eax
********************************************************
Why there is no GC manipulation code? isn't it needed?

The original code:
********************************************************
virtual int NotArray(System::Byte btArray __gc[])
{
int i = 0;
BYTE __pin *pbtArray = &btArray[0];
for(i; i < btArray->Length; i++)
pbtArray <<= 1;
return 0;
}

Nadav
http://www.ddevel.com

 
C

Christopher Kimbell

Remember that the code is JIT compiled, the compiler may generate different
code for pinned references than unpinned references.


If performance is that critical, I would consider using something else than
..NET. .NET provides a level of abstraction that comes with a cost. Just out
of interest, if you wrote this application in native C++, how would you
prevent Windows from moving the memory containing the buffers to the swap
file?

If you allocate the objects at the start of program execution, they would be
located at the start of the managed heap. Objects are allocated continuously
from the start of the managed heap, as objects become disposed the GC will
compact the heap to reduce the number of actual memory pages used. This
still wouldn't prevent Windows from paging all the memory to the swap file.

Chris

Nadav said:
Thanks for your immediate response, concerning the '__pin' keyword causes
the GC to prevent moving the buffer in memory ( and not manipulate any
refcount ), how does it do that? there must be some assembler code to
instruct the GC that this is a '__pined' variable so it would know not to
move it, looking at the assembler code produced by the compiler (provided at
the root query) I can't see anything as such... It seems as the '__pin'
keyword has no effect on the assembler code being generated by the compiler,
why is that? how can it be guaranteed that the memory pointed to by
'pbtArray' will stay valid for the duration it is being used...



(*)Another thing: Taking in mind what you have said concerning the way GC is
operating, Is it possible to prevent the GC from moving memory in the first
place? e.g. lets say I have a performance critical application, I allocate
(apriory) a collection of buffers to be used by the App, those buffers
should be moved as less as possible during runtime, how can I achieve that
using the .NET Framework????



Nadav.


Christopher Kimbell said:
The garbage collection is done by the runtime, not the application, therefor
there is no GC code in your application code.
If Microsoft embedded GC manipulation code in the apllication code, it would
be impossible to change GC policy in the future.

Pinning an object prevents the GC from moving the reference in memory, it
has nothing to do with reference counting. The GC periodically moves things
around so that the memory used is located together in memory.

Chris

Nadav said:
Hi,

I am writing a mixed mode application, I have a mixed mode Assembly
manipulating a managed byte[] array, to access this array in unmanaged code
I '__pin' the array, As I understand, pining an object guarantee that it
will not be collected by the GC ( by increasing it's refcount or so ),
Taking that in mind, looking at the code generated by the compiler I can't
see anything taking care of the GC refcount... following is the pinned
variable with the corresponding dis-assembly section:
****************** Mixed mode C++ code line ******************
BYTE __pin *pbtArray = &btArray[0];

******************** The dis-assembly ***********************
00000019 cmp dword ptr [esi+4],0 // makes sure that NULL != &btArray[0]
0000001d ja 00000026 // if it is not NULL go
three
lines bellow
0000001f xor ecx,ecx
00000021 call 7227F90B // call some exception handling procedure...
00000026 lea eax,[esi+8] // get the address of &btArray[0] to eax
00000029 mov dword ptr [ebp-14h],eax // pbtArray = content of eax
********************************************************
Why there is no GC manipulation code? isn't it needed?

The original code:
********************************************************
virtual int NotArray(System::Byte btArray __gc[])
{
int i = 0;
BYTE __pin *pbtArray = &btArray[0];
for(i; i < btArray->Length; i++)
pbtArray <<= 1;
return 0;
}

Nadav
http://www.ddevel.com


 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top