null reference detection
Posted: Fri Nov 15, 2013 3:01 pm
I am writing a compiler for CIL to native code. The underlying byte-code has the notion of an object, from which you can read or write fields with special instructions. In addition, arrays are also encapsulated as objects, and there are different instructions for loading and storing array elements.
My implementation uses object references (basically pointers) to identify objects. These can either have the value null (0) or be a valid pointer into the heap pointing to the start of an object of appropriate length - this is provable as the only instructions that can assign to object references are those which load null or those which create an object. References cannot be altered (pointer arithmetic is not allowed outside of protected kernel code).
My issue is trying to efficiently detect whether the pointer is valid (i.e. not null) before a field from it is loaded. I mark the first 4 kiB of the address space 'not present' and so can detect most with a page fault. The problem is if, for example, a user declares a huge class e.g. with the last member several megabytes in. They could in theory then assign null to the reference, and use the last member to access memory beyond the first page but not within the heap, or even within another processes heap space (I use a single-address space design).
Given that most field references will actually be valid, I need a way to detect this problem with the least overhead possible. My current plan is to special-case access to fields (or array elements) that are beyond 4 kiB from the start of the object. For these, I will try a dummy read from the actual object address first and try and catch a page fault there if invalid, otherwise continue, however this introduces a unnecessary memory read. The other option is to compare the object reference with null with a CMP/TEST instruction and then jump to a null reference handler if so. This avoids the memory access but means I need two different code paths into the null reference handler (the first being from the page fault for small <4 kiB classes). Obviously I could ensure that all field references check the validity of the object first, but this really does introduce unnecessary delays.
Does anyone else have any suggestions how this could be done? Note I control the compiler so can output any opcodes required.
Regards,
John.
My implementation uses object references (basically pointers) to identify objects. These can either have the value null (0) or be a valid pointer into the heap pointing to the start of an object of appropriate length - this is provable as the only instructions that can assign to object references are those which load null or those which create an object. References cannot be altered (pointer arithmetic is not allowed outside of protected kernel code).
My issue is trying to efficiently detect whether the pointer is valid (i.e. not null) before a field from it is loaded. I mark the first 4 kiB of the address space 'not present' and so can detect most with a page fault. The problem is if, for example, a user declares a huge class e.g. with the last member several megabytes in. They could in theory then assign null to the reference, and use the last member to access memory beyond the first page but not within the heap, or even within another processes heap space (I use a single-address space design).
Given that most field references will actually be valid, I need a way to detect this problem with the least overhead possible. My current plan is to special-case access to fields (or array elements) that are beyond 4 kiB from the start of the object. For these, I will try a dummy read from the actual object address first and try and catch a page fault there if invalid, otherwise continue, however this introduces a unnecessary memory read. The other option is to compare the object reference with null with a CMP/TEST instruction and then jump to a null reference handler if so. This avoids the memory access but means I need two different code paths into the null reference handler (the first being from the page fault for small <4 kiB classes). Obviously I could ensure that all field references check the validity of the object first, but this really does introduce unnecessary delays.
Does anyone else have any suggestions how this could be done? Note I control the compiler so can output any opcodes required.
Regards,
John.