Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Nächste Überarbeitung
Vorhergehende Überarbeitung
software:deep:dev:crosscompiler:strings [2013-12-29 16:30] – Externe Bearbeitung 127.0.0.1software:deep:dev:crosscompiler:strings [Unbekanntes Datum] (aktuell) – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1
Zeile 1: Zeile 1:
-====== Implementation of Strings ====== 
-In Java a string like 
-<code java> 
-String str = new String("abc"); 
-</code> 
-causes the allocation of two objects. Strings in Java are //immutable//. With the field //offset// it is possible to form substrings in the constant string.   
  
-[{{ .:strings1.png?450&direct | //A string in Java// }}] 
- 
-Creating two objects and managing them leads to unfavorable behaviour in terms of memory and runtime. A more elegant solution would create a single object. What to do? 
-  - Change of the class file and replacement of the class //String// (relatively  costly) 
-  - Change of code generator 
-We choose the second alternative. When a //new// is encountered we must check if a string is to be created. If this is the case a special string allocation method is to be called, see [[.:objects|Objects]]. The translation of the SSA instructions //sCloadFromArray// and //sCstoreToArray// nedd to be adapted as well. 
- 
-===== Optimized String ===== 
-Damit in Java wie gewohnt mit Strings gearbeitet werden kann, wird das Erzeugen und Verarbeiten von Strings vollständig in der Klasse //java/lang/String// gekapselt. Diese Klasse ist eine Erweiterung von //BString// (steht für BaseString). //BString// hat als einziges Feld die Länge des Strings //count//. Damit wird sichergestellt, dass //count// stets auf dem Index 0 zu liegen kommt. //String// weist ein weiteres Feld auf //value// vom Typ //char[]//. Aber statt einer Referenz auf ein Characterarray sollen nun in //value// direkt die Zeichen abgelegt werden.  
- 
-[{{ .strings2.png?300&direct | //Optimierter String// }}] 
- 
-Das Feld //size// zeigt die Anzahl Bytes des ganzen Objektes an, analog zu anderen Objekten (siehe [[heap|Heap]]). Es dient der schnelleren Sweep-Phase. 
- 
-===== Erzeugung ===== 
-Beim Erzeugen eines String steht folgender Bytecode im Classfile 
-<code> 
-new java/lang/String 
-invokespecial constructor 
-</code> 
-Das //new// darf noch nicht ausgeführt werden, weil die Grösse des Char-Arrays nicht aus dem Typdescriptor herausgelesen werden kann. Da das Array ja fix ins Objekt zu liegen kommt, variiert die Grösse des Objektes von String zu String. Im Codegenerator wird nun geprüft, ob das new ein Objekt vom Typ String erzeugt und falls ja, wird nichts unternommen. Einzig die Referenz auf den Typdescriptor von String muss in das Resultatregister von //new// geschrieben werden. \\ 
-Die nächste Bytecode-Instruktion //invokespecial// ruft nun den passenden Objektkonstruktor auf. Hier darf nun nicht dieser Konstruktor aufgerufen werden, da ja das Objekt noch gar nicht existiert. Durch den Linker wird anstelle des Objektkonstruktors eine Fabrikmethode mit den gleichen Parametern gelinkt.  
-<code java> 
-public static String allocateString(int ref, char value[]) { 
- int len = value.length; 
- String str = newstring(ref, len * 2); 
- str.count = len; 
- for (int i = 0; i < len; i++) str.value[i] = value[i]; 
- return str; 
-} 
-</code> 
-Zuerst wird die Grösse des notwendigen Arrays bestimmt und dann die Allokation auf dem Heap gemacht. Auch hier muss der Linker statt des Hilfsstubs //newstring// die entsprechende Methode //newstring// in Heap.java einsetzen. //newstring// bewirkt folgende Aktionen:  
-  * setzt setzt den Tag  des Stringsobjektes auf den Typdescriptor von //String// (wie ein newobject) 
-  * erzeugt aber auch die notwendige Anzahl Arrayfelder (wie ein newarray) 
-  * das Feld //count// wird gesetzt 
-  * der Konstruktor der Oberklasse wird aufgerufen. Dieser Aufruf muss direkt im Codegenerator eingefügt werden. 
-  * Der String wird initialisiert 
-Am Schluss muss die Referenz auf den durch die Fabrikmethode erzeugten String in das Resultatregister der //sCnew//-Instruktion geschrieben werden.   
-===== Feldzugriffe ===== 
-Sobald auf Felder des Stringarrays zugegriffen werden soll, muss das im Codegenerator speziell berücksichtigt werden. Ein solcher Zugriff hat in der SSA die Form 
-<code> 
-1: MonadicRef[sCloadFromField] {0} <value([C)> (Char-Array) 
-2: NoOpnd[sCloadLocal] (Integer) 
-3: Dyadic[sCloadFromArray] {1, 2} (Char) 
-</code> 
-Zuerst wird also das Feld //value// geladen. //value// ist eine Referenz. Anschliessend wird über die Referenz und ein Index auf das Array zugegriffen. Im Codegenerator muss bei einer Instruktion //sCloadFromField// geprüft werden, ob auf das Feld //String.value// zugegriffen wird. Falls ja, wird dieser Zugriff weggelassen und der Offset von //value// gemerkt. Bei der darauffolgenden Instruktion //sCloadFromArray// muss dieser Offset zum Index dazuaddiert werden. Ebenfalls darf als Arrayreferenz nicht das //value// dienen, sondern die Referenz auf den String. \\ 
-Analog muss auch das Schreiben auf die Stringzeichen angepasst werden. Hier gibt es aber noch eine Besonderheit. Weil Strings immutable sind, werden nur beim Initialisieren in den Fabrikmethoden die Arrayfelder geschrieben. Darum kann die Prüfung auf Arrayüberschreitung weggelassen werden. 
- 
-===== Constant String ===== 
-Constant strings are stored in the constant block of a class, see [[linker|Linker]]. The layout there must be identical to the layout on the heap as given above. 
- 
-===== Special Linking ===== 
-The type descriptor of the class //String// must have its field //nofInstPtr// set to 0. Though there is a field //char[] values// we access this field in an omtimized way as decribed above. The garbage collector must not follow this field!