Göran Andersson said:
No, I'm not at all confused about what scope is.
I don't understand how you could have quoted me in this context without
you being mistaken.
It's a bit surprising
how much the GC knows about it, though.
The GC doesn't know anything about scope. That's what I've been trying
to explain to you. The scope information is *LOST* after compile time.
The thing that the GC knows about IS NOT SCOPE.
it seems to know the "utilized"
scope, or the active lifetime of the variables (which may be shorter
than the physical lifetime).
Like I said in the other messages, the JIT needs this info (variable
lifetime - not scope) for enregistering and stack reuse, and so it
calculates it, and the GC needs this data for adjusting pointers after a
collection.
Is there any information that supports the theory that the GC knows when
a reference is no longer reachable?
The JIT can only detect the last use of a given variable definition (in
the Single Static Assignment (SSA) model of "variable definition"). It's
the JIT compiler that is doing the analysis, not the GC.
I recommend that you Google up on:
* Use-Definition chain, Definition-Use chain (ud-chain, du-chain)
* Single Static Assignment (SSA - this is a more modern approach)
Alternatively, you can look up use-def / def-use chains in the Dragon
book (Compilers: Principles, Techniques and Tools, by Aho, Sethi &
Ullman).
Can we trust that it will always be
able to collect objects that won't be used?
No, it can only collect objects which aren't used. For example:
---8<---
object x = new object();
Halting_Problem(); // might not return
Console.WriteLine(x);
--->8---
The JIT clearly can't determine that x is dead at the point of calling
Halting_Problem(), so the GC can't collect x.
THE SCOPE DOESN'T EXIST IN IL. The scope is GONE, GONE, GONE, ALL GONE,
after the C# compiler has produced IL. Use ILDASM to decompile an
assembly some time. You will notice that THERE IS NO SCOPE INFORMATION
in the dump. There is only a list of local variables per method.
Will there be a difference between:
for (int i=0; i<1000; i++) {
byte[] buffer = new byte[10000];
}
and:
byte[] buffer;
for (int i=0; i<1000; i++) {
buffer = new byte[10000];
}
Will it with certainty always be able to collect the previous buffer?
Will it never differ from this?
It's entirely implementation defined, based on how smart the JIT is at
recognizing that variables are no longer needed. It's a function of the
sophistication of the compiler. It's in the JIT's interest to discover
when variables are no longer needed, because that creates room for other
variables to be enregistered, or stack space minimized.
-- Barry