deep

a Cross Development Platform for Java

User Tools

Site Tools


dev:crosscompiler:strings

This is an old revision of the document!


Implementation of Strings

In Java a string like

String str = new String("abc");

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.

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?

  1. Change of the class file and replacement of the class String (relatively costly)
  2. 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. 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.

Optimierter String

Das Feld size zeigt die Anzahl Bytes des ganzen Objektes an, analog zu anderen Objekten (siehe Heap). Es dient der schnelleren Sweep-Phase.

Erzeugung

Beim Erzeugen eines String steht folgender Bytecode im Classfile

new java/lang/String
invokespecial constructor

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.

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;
}

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

1: MonadicRef[sCloadFromField] {0} <value([C)> (Char-Array)
2: NoOpnd[sCloadLocal] (Integer)
3: Dyadic[sCloadFromArray] {1, 2} (Char)

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 Linker32. 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!

dev/crosscompiler/strings.1398928638.txt.gz · Last modified: 2016/02/25 13:33 (external edit)