Eliot Moss wrote:
>
> IIRC, Zvi, the header offset would indeed not give you the minimum size.
> To
> accomodate arrays and treat them similarly to scalars, and to have element
> 0 of an array be where the object pointer points (which is more
> efficient),
> the object header begins THREE words before the fields/elements. However,
> in a scalar, the length field does not exsit (it's used only for arrays),
> so the first scalar field is at offset -4, the second at 0, etc. (assuming
> 32-bit fileds). The smallest object is 2 words. I expect there's a
> suitable
> constant to use in one of the object model files.
>
> -- Eliot
>
So, since scalars have one less field than arrays, do they still start at 3
words before the object pointer? Or do they start two words before the
object pointer?
~Zvi
--
View this message in context: http://www.nabble.com/Determine-minimum-object-size-tf4144796.html#a11792230
Sent from the jikesrvm-researchers mailing list archive at Nabble.com.

IIRC, Zvi, the header offset would indeed not give you the minimum size. To
accomodate arrays and treat them similarly to scalars, and to have element
0 of an array be where the object pointer points (which is more efficient),
the object header begins THREE words before the fields/elements. However,
in a scalar, the length field does not exsit (it's used only for arrays),
so the first scalar field is at offset -4, the second at 0, etc. (assuming
32-bit fileds). The smallest object is 2 words. I expect there's a suitable
constant to use in one of the object model files.
-- Eliot

A wondering, Jian: Is some routine on this call path supposed to be
checking for a null pointer, but it is not doing it, and thus calls a
tracing routine that expects an object pointer but receives a null,
accessses through it and causes the fault?
-- Eliot

Since I use a simple free list for my allocation, it would be useful to not
keep any free blocks that are too small to allocate objects to. I've been
using the object header size (as determined from
VM.objectModel.GC_HEADER_OFFSET()) as my minimum size, but when debugging my
code, I found an object smaller than that. I also verified that there is,
in fact, an allocation request for at least one object that is smaller than
the apparent size of the object header. Below is the code and output that
lead me to my discovery:
-----Start Code-----
public ObjectReference traceObject(TraceLocal trace,
ObjectReference object) {
if (testAndMark(object, markState)) {
// This is the first time we've seen the object so remove it from the
// free list and add it to the trace queue
int size = VM.objectModel.getCurrentSize(object);
Address start =
object.toAddress().plus(VM.objectModel.GC_HEADER_OFFSET());
Address trueStart = VM.objectModel.objectStartRef(object);
Address end = VM.objectModel.getObjectEndAddress(object).minus(1);
Address calcEnd = start.plus(VM.objectModel.getCurrentSize(object) - 1);
Assertion._assert(end.EQ(calcEnd), "The reported end is not the true end
of the object");
Assertion._assert(trueStart.EQ(start), "The reported start is not the
true start");
Assertion._assert(end.toWord().minus(start.toWord()).plus(Word.one()).toInt()
== size, "The reported size is not the correct size");
if (DEBUG && DEBUG_TRACING) {
Log.write("Object: ");
Log.writeln(object);
Log.write("\tStart: ");
Log.write(start);
Log.write("\tEnd: ");
Log.writeln(end);
if (intervalTree.findInterval(start, false) == null)
intervalTree.findInterval(start, true);
}
Assertion._assert(intervalTree.findInterval(start, false) != null, "The
interval for the address does not exist");
//Assertion._assert((intervalTree.findInterval(start, false) != null) ||
(size < Math.abs(VM.objectModel.GC_HEADER_OFFSET().toInt())), "The interval
for the address does not exist, and the object is not too small to keep");
intervalTree.split(start, end);
Assertion._assert(intervalTree.findInterval(start, false) == null, "The
interval for the address exists");
trace.enqueue(object);
}
return object;
}
-----End Code-----
Just as a note, the Assertion._assert() function is a function that I wrote
for my own assertions that simply takes in a boolean value and a string, and
displays the string followed by a call to System.exit(1) if the boolean is
false. The interval.split() method modifies a tree that is stored in
immortal space, so it is not relevant to the issue here, since I am not
attempting to garbage collect the immortal space.
-----Start Output-----
Object: 0x7643a2ac
Start: 0x7643a2a0 End: 0x7643a2c7
Object: 0x76a779d0
Start: 0x76a779c4 End: 0x76a779db
Object: 0x76a779f8
Start: 0x76a779ec End: 0x76a779ff
Object: 0x7640d600
Start: 0x7640d5f4 End: 0x7640d5fb
-----End Output-----
This leads me to a couple questions:
1) How can an object smaller than the object header make its way onto the
heap?
2) Is the absolute value of the offset returned by GC_HEADER_OFFSET() (after
it's been converted to an int, of course) actually the size of the header?
Or is it based on some more complex formula?
3) How can I determine the minimum object size, since I can no longer rely
on objects being at least as big as what appears to be the size of the
header?
~Zvi
--
View this message in context: http://www.nabble.com/Determine-minimum-object-size-tf4144796.html#a11789111
Sent from the jikesrvm-researchers mailing list archive at Nabble.com.

Dear folks,
After the opt-compiled code get running, there are a GC exception that's
hard to trace down. Do you think it is because there are some potential
error in the compiled gcmap to cause this exception? Or any suggestion on
narrow down this exception? Thank you.
Regards,
Jian
Exception in thread "VM_CollectorThread": java.lang.NullPointerException
at com.ibm.JikesRVM.VM_JavaHeader.readAvailableBitsWord(VM_JavaHeader.java:609)
at com.ibm.JikesRVM.VM_ObjectModel.readAvailableBitsWord(VM_ObjectModel.java:525)
at com.ibm.JikesRVM.mm.mmtk.ObjectModel.readAvailableBitsWord(ObjectModel.java:343)
at org.mmtk.policy.LargeObjectSpace.isInNursery(LargeObjectSpace.java:314)
at org.mmtk.policy.LargeObjectSpace.traceObject(LargeObjectSpace.java:222)
at org.mmtk.plan.generational.GenNurseryTraceLocal.traceObject(GenNurseryTraceLocal.java:94)
at org.mmtk.plan.TraceLocal.traceObject(TraceLocal.java:286)
at org.mmtk.plan.TraceLocal.traceObjectLocation(TraceLocal.java:91)
at org.mmtk.plan.generational.GenNurseryTraceLocal.processRememberedSets(GenNurseryTraceLocal.java:114)
at org.mmtk.plan.TraceLocal.completeTrace(TraceLocal.java:474)
at org.mmtk.plan.TraceLocal.startTrace(TraceLocal.java:458)
at org.mmtk.plan.generational.GenCollector.collectionPhase(GenCollector.java:109)
at org.mmtk.plan.generational.marksweep.GenMSCollector.collectionPhase(GenMSCollector.java:155)
at org.mmtk.plan.SimplePhase.delegatePhase(SimplePhase.java:127)
at org.mmtk.plan.Phase.delegatePhase(Phase.java:159)
at org.mmtk.plan.Phase.delegatePhase(Phase.java:145)
at org.mmtk.plan.ComplexPhase.delegatePhase(ComplexPhase.java:100)
at org.mmtk.plan.Phase.delegatePhase(Phase.java:159)
at org.mmtk.plan.Phase.delegatePhase(Phase.java:145)
at org.mmtk.plan.ComplexPhase.delegatePhase(ComplexPhase.java:100)
at org.mmtk.plan.Phase.delegatePhase(Phase.java:159)
at org.mmtk.plan.StopTheWorldCollector.collect(StopTheWorldCollector.java:59)
at com.ibm.JikesRVM.memoryManagers.mmInterface.VM_CollectorThread.run(VM_CollectorThread.java:346)
vm internal error at:
-- Stack --
Lcom/ibm/JikesRVM/VM; sysFail(Ljava/lang/String;)V at line 1095
Lcom/ibm/JikesRVM/VM; _assertionFailure(Ljava/lang/String;Ljava/lang/String;)V at line 593
Lcom/ibm/JikesRVM/VM; _assert(ZLjava/lang/String;Ljava/lang/String;)V at line 574
Lcom/ibm/JikesRVM/VM; _assert(Z)V at line 554
Lcom/ibm/JikesRVM/VM_Thread; terminate()V at line 908
Lcom/ibm/JikesRVM/VM_Runtime; deliverException(Ljava/lang/Throwable;Lcom/ibm/JikesRVM/VM_Registers;)V at line 999
Lcom/ibm/JikesRVM/VM_Runtime; deliverHardwareException(II)V at line 756
<hardware trap>
Lcom/ibm/JikesRVM/VM_JavaHeader; readAvailableBitsWord(Ljava/lang/Object;)Lorg/vmmagic/unboxed/Word; at line 609
Lcom/ibm/JikesRVM/VM_ObjectModel; readAvailableBitsWord(Ljava/lang/Object;)Lorg/vmmagic/unboxed/Word; at line 525
Lcom/ibm/JikesRVM/mm/mmtk/ObjectModel; readAvailableBitsWord(Lorg/vmmagic/unboxed/ObjectReference;)Lorg/vmmagic/unboxed/Word; at line 343
Lorg/mmtk/policy/LargeObjectSpace; isInNursery(Lorg/vmmagic/unboxed/ObjectReference;)Z at line 314
Lorg/mmtk/policy/LargeObjectSpace; traceObject(Lorg/mmtk/plan/TraceLocal;Lorg/vmmagic/unboxed/ObjectReference;)Lorg/vmmagic/unboxed/ObjectReference;
at line 222
Lorg/mmtk/plan/generational/GenNurseryTraceLocal; traceObject(Lorg/vmmagic/unboxed/ObjectReference;)Lorg/vmmagic/unboxed/ObjectReference; at line 94
Lorg/mmtk/plan/TraceLocal; traceObject(Lorg/vmmagic/unboxed/ObjectReference;Z)Lorg/vmmagic/unboxed/ObjectReference; at line 286
Lorg/mmtk/plan/TraceLocal; traceObjectLocation(Lorg/vmmagic/unboxed/Address;Z)V at line 91
Lorg/mmtk/plan/generational/GenNurseryTraceLocal; processRememberedSets()V at line 114
Lorg/mmtk/plan/TraceLocal; completeTrace()V at line 474
Lorg/mmtk/plan/TraceLocal; startTrace()V at line 458
Lorg/mmtk/plan/generational/GenCollector; collectionPhase(IZ)V at line 109
Lorg/mmtk/plan/generational/marksweep/GenMSCollector; collectionPhase(IZ)V at line 155
Lorg/mmtk/plan/SimplePhase; delegatePhase()V at line 127
Lorg/mmtk/plan/Phase; delegatePhase(Lorg/mmtk/plan/Phase;)V at line 159
Lorg/mmtk/plan/Phase; delegatePhase(I)V at line 145
Lorg/mmtk/plan/ComplexPhase; delegatePhase()V at line 100
Lorg/mmtk/plan/Phase; delegatePhase(Lorg/mmtk/plan/Phase;)V at line 159
Lorg/mmtk/plan/Phase; delegatePhase(I)V at line 145
Lorg/mmtk/plan/ComplexPhase; delegatePhase()V at line 100
Lorg/mmtk/plan/Phase; delegatePhase(Lorg/mmtk/plan/Phase;)V at line 159
Lorg/mmtk/plan/StopTheWorldCollector; collect()V at line 59
Lcom/ibm/JikesRVM/memoryManagers/mmInterface/VM_CollectorThread; run()V at line 346
Lcom/ibm/JikesRVM/VM_Thread; startoff()V at line 786