Difference between revisions of "Compiler-generated data and data structures"

From Lazarus wiki
Jump to navigationJump to search
 
(8 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
{{Compiler-generated_data_and_data_structures}}
 +
 +
back to contents [[FPC internals]]
 +
 
== Introduction ==
 
== Introduction ==
 
The compiler generates several data when compiling a program, this article describes its layout.
 
The compiler generates several data when compiling a program, this article describes its layout.
  
=== Classes layout ===
+
== Classes layout ==
One of the most important data in an object pascal program are classes. A class is a pointer to the actucal data of a given instance. The first entry in the data of an object is a pointer to its virtual method table (VMT). This name is historic because this table contains nowadays more information than only the pointers to the virtual methods. It contains information about the
+
One of the most important data in an object pascal program are classes. A class is a pointer to the actucal data of a given instance. The first entry in the data of an object is a pointer to its virtual method table (VMT).  
  
 
==== VMT layout ====
 
==== VMT layout ====
The layout of the VMT generated by FPC (Aug. 2006) is shown in the following table.
+
This name is historic because this table contains nowadays more information than only the pointers to the virtual methods. The layout of the VMT generated by FPC (Aug. 2006) is shown in the following table.
{|
+
{| class="wikitable"
|+ entry
+
! Entry !! Offset !! Explanation
| offset
 
| explanation
 
 
|-
 
|-
 
| vmtInstanceSize
 
| vmtInstanceSize
 
| 0
 
| 0
|
+
|  
 +
|-
 +
|
 +
| sizeof(sizeint)
 +
| This field contains the negative instance size so by adding this field to the field before and checking the result allows to validate a vmt.
 
|-
 
|-
 
| vmtParent
 
| vmtParent
| sizeof(ptrint)*2;
+
| sizeof(sizeint)*2
|
+
| Pointer to the vmt of the parent. nil in case of TObject.
 
|-
 
|-
|}
+
| vmtClassName
 
+
| vmtParent+sizeof(pointer)
      vmtClassName            = vmtParent+sizeof(pointer);
+
| Pointer to a zero terminated string containing the name of the class.
 
|-
 
|-
      vmtDynamicTable         = vmtParent+sizeof(pointer)*2;
+
| vmtDynamicTable
 +
| vmtParent+sizeof(pointer)*2
 +
|
 
|-
 
|-
      vmtMethodTable         = vmtParent+sizeof(pointer)*3;
+
| vmtMethodTable
 +
| vmtParent+sizeof(pointer)*3
 +
|
 
|-
 
|-
      vmtFieldTable           = vmtParent+sizeof(pointer)*4;
+
| vmtFieldTable  
 +
| vmtParent+sizeof(pointer)*4
 +
|
 
|-
 
|-
      vmtTypeInfo             = vmtParent+sizeof(pointer)*5;
+
| vmtTypeInfo
 +
| vmtParent+sizeof(pointer)*5
 +
|
 
|-
 
|-
      vmtInitTable           = vmtParent+sizeof(pointer)*6;
+
| vmtInitTable
 +
| vmtParent+sizeof(pointer)*6
 +
|
 
|-
 
|-
      vmtAutoTable           = vmtParent+sizeof(pointer)*7;
+
| vmtAutoTable
 +
| vmtParent+sizeof(pointer)*7
 +
|
 
|-
 
|-
      vmtIntfTable           = vmtParent+sizeof(pointer)*8;
+
| vmtIntfTable
 +
| vmtParent+sizeof(pointer)*8
 +
|
 
|-
 
|-
      vmtMsgStrPtr           = vmtParent+sizeof(pointer)*9;
+
| vmtMsgStrPtr
 +
| vmtParent+sizeof(pointer)*9
 +
|
 
|-
 
|-
      { methods }
+
| vmtMethodStart
      vmtMethodStart          = vmtParent+sizeof(pointer)*10;
+
| vmtParent+sizeof(pointer)*10
 +
| At this offset, the real vmt starts, this is the offset of the first virtual method.
 
|-
 
|-
      vmtDestroy              = vmtMethodStart;
+
|
 +
| last field
 +
| The last field has the value zero so the vmt size can be determined.
 
|-
 
|-
      vmtNewInstance          = vmtMethodStart+sizeof(pointer);
+
|}
|-
+
 
      vmtFreeInstance        = vmtMethodStart+sizeof(pointer)*2;
+
=== Instance data layout ===
|-
+
After the pointer to the vmt, the fields of the class follow. Furthermore, the vmts of the implemented interfaces are stored in the instance data. If an interface to a class instance is queried, the pointer to the vmt of this interface is returned. Later, when a method of the interface is invoked, the class instance can be determined from the vmt because it's part of the instance data simply by subtracting a fixed offset from the interface's vmt address.
      vmtSafeCallException    = vmtMethodStart+sizeof(pointer)*3;
+
 
|-
+
<!--[[Category:FPC internals]]-->
      vmtDefaultHandler      = vmtMethodStart+sizeof(pointer)*4;
 
|-
 
      vmtAfterConstruction    = vmtMethodStart+sizeof(pointer)*5;
 
|-
 
      vmtBeforeDestruction    = vmtMethodStart+sizeof(pointer)*6;
 
|-
 
      vmtDefaultHandlerStr    = vmtMethodStart+sizeof(pointer)*7;
 

Latest revision as of 12:11, 28 December 2020

English (en)

back to contents FPC internals

Introduction

The compiler generates several data when compiling a program, this article describes its layout.

Classes layout

One of the most important data in an object pascal program are classes. A class is a pointer to the actucal data of a given instance. The first entry in the data of an object is a pointer to its virtual method table (VMT).

VMT layout

This name is historic because this table contains nowadays more information than only the pointers to the virtual methods. The layout of the VMT generated by FPC (Aug. 2006) is shown in the following table.

Entry Offset Explanation
vmtInstanceSize 0
sizeof(sizeint) This field contains the negative instance size so by adding this field to the field before and checking the result allows to validate a vmt.
vmtParent sizeof(sizeint)*2 Pointer to the vmt of the parent. nil in case of TObject.
vmtClassName vmtParent+sizeof(pointer) Pointer to a zero terminated string containing the name of the class.
vmtDynamicTable vmtParent+sizeof(pointer)*2
vmtMethodTable vmtParent+sizeof(pointer)*3
vmtFieldTable vmtParent+sizeof(pointer)*4
vmtTypeInfo vmtParent+sizeof(pointer)*5
vmtInitTable vmtParent+sizeof(pointer)*6
vmtAutoTable vmtParent+sizeof(pointer)*7
vmtIntfTable vmtParent+sizeof(pointer)*8
vmtMsgStrPtr vmtParent+sizeof(pointer)*9
vmtMethodStart vmtParent+sizeof(pointer)*10 At this offset, the real vmt starts, this is the offset of the first virtual method.
last field The last field has the value zero so the vmt size can be determined.

Instance data layout

After the pointer to the vmt, the fields of the class follow. Furthermore, the vmts of the implemented interfaces are stored in the instance data. If an interface to a class instance is queried, the pointer to the vmt of this interface is returned. Later, when a method of the interface is invoked, the class instance can be determined from the vmt because it's part of the instance data simply by subtracting a fixed offset from the interface's vmt address.