-
Bug
-
Resolution: Fixed
-
P2
-
1.1
-
1.1.1
-
generic
-
windows_95
-
Not verified
I'd like to report an apparent problem in gc.c with the latest sources. A
spurious out of memory error is reported when the heap can in fact be
grown. The scenario look something like this. We need a block of size N
and none is available. manageAllocFailure triggers a compaction which
results in a free block large enough to accomodate the allocation.
However in the test at the end of manageAllocFailure we decide that this
is not good enough because it would leave us with too little free space
(that is, "FreeObjectCtr-n >- minFree" does not result true). We continue
with overflow actions FINALIZE and REFS and get to EXPAND.
When we enter expandObjectSpace we test last_free, note that it is set
(by the previous compaction) and that the size of the last_free block is
large enough. Thus at the comment "We must be expanding to
preallocate" we set incr to zero even though the variable preallocIncr
was computed to a negative value. Thus max(incr, preallocincr) leaves
incr at 0 which ultimately causes the VirtuallAlloc in sysCommitMem to fail
and gc to conculde the heap cannot be grown.
Here are some numbers :
Ultimately, the problem is that expandObject space returns 0 because sysCommitMem has been passed a request (incr) of size 0. Incr is 0 because it is set to zero at the comment "We must be expanding to preallocate" and because
preallocIncr is negative. We set incr to 0 because last_free is not null and
obj_len(last_free) is 329400 which is greater than the requested amount
(65544). An noted in the eralier mail the large last_free block results from
a compaction. Lastly, preallocIncr is negative because "FreeAllocCtr-n" is
larger than "TotalObjectCrtr*preallocFactor.:
TotalObjectCtr = 838856
preallocFactor = 0.25
FreeAllocCtr = 329400
n = 65544
so preallocIncr is set to -72188.
spurious out of memory error is reported when the heap can in fact be
grown. The scenario look something like this. We need a block of size N
and none is available. manageAllocFailure triggers a compaction which
results in a free block large enough to accomodate the allocation.
However in the test at the end of manageAllocFailure we decide that this
is not good enough because it would leave us with too little free space
(that is, "FreeObjectCtr-n >- minFree" does not result true). We continue
with overflow actions FINALIZE and REFS and get to EXPAND.
When we enter expandObjectSpace we test last_free, note that it is set
(by the previous compaction) and that the size of the last_free block is
large enough. Thus at the comment "We must be expanding to
preallocate" we set incr to zero even though the variable preallocIncr
was computed to a negative value. Thus max(incr, preallocincr) leaves
incr at 0 which ultimately causes the VirtuallAlloc in sysCommitMem to fail
and gc to conculde the heap cannot be grown.
Here are some numbers :
Ultimately, the problem is that expandObject space returns 0 because sysCommitMem has been passed a request (incr) of size 0. Incr is 0 because it is set to zero at the comment "We must be expanding to preallocate" and because
preallocIncr is negative. We set incr to 0 because last_free is not null and
obj_len(last_free) is 329400 which is greater than the requested amount
(65544). An noted in the eralier mail the large last_free block results from
a compaction. Lastly, preallocIncr is negative because "FreeAllocCtr-n" is
larger than "TotalObjectCrtr*preallocFactor.:
TotalObjectCtr = 838856
preallocFactor = 0.25
FreeAllocCtr = 329400
n = 65544
so preallocIncr is set to -72188.