This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
dev:crosscompiler:type_checking [2015/03/29 13:10] – ursgraf | dev:crosscompiler:type_checking [2019/07/12 13:58] – ursgraf | ||
---|---|---|---|
Line 10: | Line 10: | ||
\\ | \\ | ||
If the object is of type //[ClassA// and is checked for type //[IA// (while //ClassA// implements interface //IA//), the check must return true. This is ok because under point 6. of the last case the type check will get the type descriptor of //ClassA// which contains //IA//. Further details can be found further down in //Type Check for Interface Type//.\\ | If the object is of type //[ClassA// and is checked for type //[IA// (while //ClassA// implements interface //IA//), the check must return true. This is ok because under point 6. of the last case the type check will get the type descriptor of //ClassA// which contains //IA//. Further details can be found further down in //Type Check for Interface Type//.\\ | ||
- | The opposite case must work as well. An object is of type [IA und es wird auf [IA oder auch ein Superinterface von IA geprüft. Im Punkt 6. wird ebenfalls im TD auf den Interfacetyp geprüft. Ist das Objekt vom Typ [IA und wird auf [ClassA | + | The opposite case must work as well. An object is of type //[IA// and is checked against //[IA// or one of its superinterfaces. In 6. there is a check against the interface type. If the object is of type //[IA// and is checked against //[ClassA// then this check will be in 6. For this reason, the type descriptors of the interfaces must contain the base classes, similar to the type descriptors of the standard classes. With interfaces this is simply the class //Object//. All other entries must be empty (see below //Type Checking for Regular Class//).\\ |
- | Hinweis: Sobald ein Typtest auf ein Array von Interfaces gemacht wird, wird für dieses Interface ein Typdescriptor erstellt. Wenn das Objekt zur Laufzeit aber vom Typ Array of Std-Klasse ist, wird der Interface-Typdescriptor gar nicht verwendet. Das ist erst der Fall, wenn der Typ zur Laufzeit auch selber Array of Interfaces ist. | + | Hint: As soon as there is a type check against an array of interfaces, a type descriptor for this interface must be created. On the other hand, if the object at runtime is of type array of standard class, then the interface descriptor won't be used. It will be used solely in case when the type at runtime is itself of type array of interfaces. |
- | ==== Spezialfall | + | ==== Special Case 'Object' |
- | Wenn auf den Typ // | + | When you check against |
- | Wird auf ein Array of // | + | A check against an array of // |
- | - Zeigt die Referenz auf ein Array von normalen Klassen, liefert die Prüfung | + | - The reference points to an array of regular classes: the check returns '' |
- | - Zeigt die Referenz auf ein Array von Basistypen, liefert die Prüfung | + | - The reference points to an array of base types: the check returns '' |
==== checkcast ==== | ==== checkcast ==== | ||
- | Die obenstehende Beschreibung galt für // | + | All the explanations above were for // |
- | - Die Prüfung auf // | + | - The check against |
- Bei einer misslungenen Prüfung wird eine Trap-Instruktion ausgelöst. | - Bei einer misslungenen Prüfung wird eine Trap-Instruktion ausgelöst. | ||
- | - Eine null-Referenz liefert eine positive | + | - A '' |
==== Type Checking for Regular Class ==== | ==== Type Checking for Regular Class ==== | ||
- | Die Instruktionen | + | Both instructions |
- | - Tag von objectref | + | - read tag of objectref (contains address of actual type descriptor) |
- | - Die zu überprüfende Basisklasse muss im Typdescriptor vorkommen. Zu diesem Zweck berechnet der Compiler den Offset im Typdescriptor, | + | - the base class to check against must be present in the type descriptor. For this purpose the compiler calculates the offset of this class in the type descriptor. |
- | - Über den Tag und den berechneten Offset wird die Adresse der Basisklasse geholt. | + | - this address must be identical with the address of the type descriptor of the actual object. |
- | - Diese Adresse muss mit der Adresse des zu überprüfenden Typs übereinstimmen. | + | The type descriptor of a class is constructed as follows: the base class 0 is always |
- | Der Typdescriptor einer Klasse ist wie folgt aufgebaut. Basisklasse | + | [{{ .: |
- | Das folgende Beispiel soll den Ablauf veranschaulichen. | + | |
- | [{{ .: | + | |
- | Für den folgenden Code | + | For the java code |
<code java> | <code java> | ||
ClassA1 o = new ClassA20(); | ClassA1 o = new ClassA20(); | ||
((ClassA20)o).m1(); | ((ClassA20)o).m1(); | ||
</ | </ | ||
- | berechnet der Compiler den Offset | + | the compiler calculates the offset in the type descriptor of the class // |
<code java> | <code java> | ||
ClassA1 o = new ClassA3(); | ClassA1 o = new ClassA3(); | ||
((ClassA20)o).m1(); | ((ClassA20)o).m1(); | ||
</ | </ | ||
- | Hier berechnet der Compiler ebenfalls den Offset | + | In this case the compiler will determine the offset to be 2. The reference points to //ClassA3// at runtime. With offset |
<code java> | <code java> | ||
ClassA1 o = new ClassA21(); | ClassA1 o = new ClassA21(); | ||
((ClassA20)o).m1(); | ((ClassA20)o).m1(); | ||
</ | </ | ||
- | Auch hier berechnet der Compiler den Offset | + | Here again, the compiler calculates the offset to be 2. However, the reference points to //ClassA21//. With offset |
\\ | \\ | ||
- | Es muss sichergestellt werden, dass alle Typdecriptoren die gleiche Anzahl von Einträgen aufweisen. Das bedeutet, dass die Descriptoren der Basisklassen mit der notwendigen Anzahl von leeren Einträgen gefüllt werden müssen. Damit wird vermieden, dass ungültige Adressen gelesen werden können. Als Beispiel dazu: | + | \\ |
+ | All the type descriptors must have the same number of entries. All descriptors must be filled with empty entries up to the maximal number of entries. This ensures that non-valid addresses are read, see the following example. | ||
<code java> | <code java> | ||
ClassA1 o = new ClassA21(); | ClassA1 o = new ClassA21(); | ||
((ClassA3)o).m1(); | ((ClassA3)o).m1(); | ||
</ | </ | ||
- | Hier wird der Offset | + | The offset will be calculated to be 3. In the type descriptor of //ClassA21// the entry at offset |
\\ | \\ | ||
- | Warum müssen alle Typdescriptoren die gleiche (maximale) Anzahl von Einträgen aufweisen? Nehmen wir den Code | + | Let's consider another case: |
<code java> | <code java> | ||
Object o; | Object o; | ||
((ClassX)o).m1(); | ((ClassX)o).m1(); | ||
</ | </ | ||
- | Weil o vom Typ statischen Typ // | + | The static type of //o// is //Object//. The runtime type could be anything. Therefore, we could check against any type. For instance, |
==== Type Check for Interface Type ==== | ==== Type Check for Interface Type ==== | ||
- | Interfaceklassen dürfen nicht in der Tabelle mit den Standardklassen aufgeführt werden. Der folgende Fall zeigt warum:\\ | + | Interface classes cannot be listed |
- | [{{ .: | + | [{{ .: |
- | Je nach Vererbungshierarchie belegt das Interface einen anderen Platz in der Tabelle und der Compiler kann keinen fixen Offset berechnen mit dem in der Tabelle geprüft werden könnte. \\ Aus diesem Grund gibt es eine Tabelle im Typdescriptor mit allen Interfaces, die diese Klasse implementiert und auf die überhaupt je ein Typtest gemacht wird. \\ | + | Depending on the extension hierarchy the interface occupies different places |
- | [{{ .: | + | For this reason the type descriptor has a table with all interfaces that this class implements. The compiler will determine at compile time for which interfaces there is ever a type check. Only these will be inserted into the table. \\ |
- | Die betroffenen Interfaces werden alle nummeriert | + | [{{ .: |
- | Auch hier muss wieder wie oben ein Unterschied zwischen | + | All the affected interfaces get numbered |
+ | Here again, | ||
- | ==== Anwendungsfall: | + | ==== Complex Use Case ==== |
- | Der folgende Code | + | The following code |
<code java> | <code java> | ||
- | Object[][][] a1 = new Object[2][3][4]; | + | Object[][][] a1 = new Object[2][3][4]; |
A[] x = new AA[5]; | A[] x = new AA[5]; | ||
a1[0][0] = x; | a1[0][0] = x; | ||
Line 86: | Line 85: | ||
a1[1][1][0] = y; | a1[1][1][0] = y; | ||
</ | </ | ||
- | führt auf die folgende Abbildung\\ | + | leads to\\ |
- | [{{ .: | + | [{{ .: |
- | Dieses Beispiel befindet sich auch in den Testfällen | + | This example can be found in the test cases (//ch.ntb.inf.deep.comp.targettest.arrays.ArrayInstanceTest.testInstance4//). |