Check-in [b3ceace762]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Implement String.intern() using an internal LinkedList<WeakReference<String>> table.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:b3ceace762546be17b56f8aca5c0f103064d9cca
User & Date: stephanie.gawroriski 2019-05-24 14:28:55
Context
2019-05-24
14:37
Remove the string BasicSequence stuff since it is no longer used and this greatly simplifies `String`. check-in: db5936fbd9 user: stephanie.gawroriski tags: trunk
14:28
Implement String.intern() using an internal LinkedList<WeakReference<String>> table. check-in: b3ceace762 user: stephanie.gawroriski tags: trunk
14:09
Change String to use character arrays instead of sequences (faster). check-in: 8b68b756c8 user: stephanie.gawroriski tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to runt/apis/cldc-compact/java/lang/String.java.

24
25
26
27
28
29
30

31
32


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
64
65
66
67
68
69
70




71
72
73
74
75
76
77
...
847
848
849
850
851
852
853







854
855
856
857
858
859
860
861































862
863
864
865
866
867
868
import cc.squirreljme.runtime.cldc.string.SubBasicSequenceSequence;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Arrays;

import java.util.Comparator;
import java.util.Formatter;


import java.util.Map;
import java.util.WeakHashMap;

/**
 * A {@link String} represents a sequence of characters which make up a group
 * of alphanumeric or other symbols and represents text.
 *
 * Note that only {@link #toLowerCase()} and {@link #toUpperCase()} take
 * locale into considering during their conversion.
 *
 * @since 2018/09/16
 */
@ImplementationNote("The internal representation of characters in this " +
	"class is not a concrete character array, instead the strings are " +
	"handled by classes which represent sequences and such. This allows " +
	"for potential compression or representation of different strings " +
	"without needing to up the complexity of this class greatly. There " +
	"is slight overhead, but it will allow for Strings to be for the most " +
	"part be directly mapped into memory which will be the case when " +
	"stuff from the string table is to be used.")
public final class String
	implements Comparable<String>, CharSequence
{
	/** The minumum trim character. */
	private static final char _MIN_TRIM_CHAR =
		' ';
	
................................................................................
	/** Is this string already uppercased? */
	private static final short _QUICK_ISUPPER =
		0b0000_0000__0000_0010;
	
	/** String is already interned? */
	private static final short _QUICK_INTERN =
		0b0000_0000__0000_0100;




	
	/** String character data. */
	private final char[] _chars;
	
	/** Quick determination flags for speedy operations. */
	private volatile short _quickflags;
	
................................................................................
	 *
	 * Although this may be used for {@code ==} to work, it is not recommended
	 * to use this method for such things.
	 *
	 * @return The unique string instance.
	 * @since 2016/04/01
	 */







	public String intern()
	{
		// If this string is already interned then use this one instead
		// of searching through the map
		if ((this._quickflags & _QUICK_INTERN) != 0)
			return this;
		
		throw new todo.TODO();































	}
	
	/**
	 * Returns {@code true} if this string is empty.
	 *
	 * @return {@code true} if this string is empty.
	 * @since 2017/08/15







>


>
>












<
<
<
<
<
<
<
<







 







>
>
>
>







 







>
>
>
>
>
>
>







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47








48
49
50
51
52
53
54
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
import cc.squirreljme.runtime.cldc.string.SubBasicSequenceSequence;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Formatter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.WeakHashMap;

/**
 * A {@link String} represents a sequence of characters which make up a group
 * of alphanumeric or other symbols and represents text.
 *
 * Note that only {@link #toLowerCase()} and {@link #toUpperCase()} take
 * locale into considering during their conversion.
 *
 * @since 2018/09/16
 */








public final class String
	implements Comparable<String>, CharSequence
{
	/** The minumum trim character. */
	private static final char _MIN_TRIM_CHAR =
		' ';
	
................................................................................
	/** Is this string already uppercased? */
	private static final short _QUICK_ISUPPER =
		0b0000_0000__0000_0010;
	
	/** String is already interned? */
	private static final short _QUICK_INTERN =
		0b0000_0000__0000_0100;
	
	/** Intern string table, weakly cached to reduce memory use. */
	private static final Collection<Reference<String>> _INTERNS =
		new LinkedList<>();
	
	/** String character data. */
	private final char[] _chars;
	
	/** Quick determination flags for speedy operations. */
	private volatile short _quickflags;
	
................................................................................
	 *
	 * Although this may be used for {@code ==} to work, it is not recommended
	 * to use this method for such things.
	 *
	 * @return The unique string instance.
	 * @since 2016/04/01
	 */
	@ImplementationNote("This method is a bit slow in SquirrelJME as it " +
		"will search a list of weak reference to string. So despite this " +
		"being a O(n) search it will allow any strings to be garbage " +
		"collected when no longer used. Also the collection is a LinkedList " +
		"since the __BucketMap__ is a complicated class. But do note that " +
		"String.equals() checks the hashCode() so in-depth searches will " +
		"only be performed for strings with the same hashCode().")
	public String intern()
	{
		// If this string is already interned then use this one instead
		// of searching through the map
		if ((this._quickflags & _QUICK_INTERN) != 0)
			return this;
		
		// Search for string in the collection
		Collection<Reference<String>> interns = _INTERNS;
		synchronized (interns)
		{
			// Same string that was internalized?
			Iterator<Reference<String>> it = interns.iterator();
			while (it.hasNext())
			{
				Reference<String> ref = it.next();
				
				// If the reference has been cleared, then delete it
				String oth = ref.get();
				if (oth == null)
				{
					it.remove();
					continue;
				}
				
				// If this matches the string, use that one
				if (this.equals(oth))
					return oth;
			}
			
			// Not in the table, so add it
			interns.add(new WeakReference<>(this));
			
			// Also flag that this has been interned
			this._quickflags |= _QUICK_INTERN;
			
			// This will be the intern string
			return this;
		}
	}
	
	/**
	 * Returns {@code true} if this string is empty.
	 *
	 * @return {@code true} if this string is empty.
	 * @since 2017/08/15

Changes to runt/libs/springcoat-vm/cc/squirreljme/vm/springcoat/SpringThreadWorker.java.

438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
...
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
			SpringClass strclass = this.loadClass(
				new ClassName("java/lang/String"));
				
			// Setup an array of characters to represent the string data,
			// this is the simplest thing to do right now
			SpringObject array = (SpringObject)this.asVMObject(
				s.toString().toCharArray());
				
			// Setup character array sequence which wraps our array
			SpringObject cas = this.newInstance(new ClassName(
				"cc/squirreljme/runtime/cldc/string/" +
					"ClassConstantCharArraySequence"),
				new MethodDescriptor("([C)V"), array);
			
			// Setup string which uses this sequence
			SpringObject rv = this.newInstance(
				new ClassName("java/lang/String"),
				new MethodDescriptor(
				"(Lcc/squirreljme/runtime/cldc/string/BasicSequence;)V"),
				cas);
			
			return rv;
		}
		
		// Constant string from the constant pool, which shared a global pool
		// of string objects! This must be made so that "aaa" == "aaa" is true
		// even across different classes!
................................................................................
					return rv;
				
				// Setup an array of characters to represent the string data,
				// this is the simplest thing to do right now
				SpringObject array = (SpringObject)this.asVMObject(
					cvs.toString().toCharArray());
				
				// Setup character array sequence which wraps our array
				SpringObject cas = this.newInstance(new ClassName(
					"cc/squirreljme/runtime/cldc/string/" +
						"ClassConstantCharArraySequence"),
					new MethodDescriptor("([C)V"), array);
				
				// Setup string which uses this sequence
				rv = this.newInstance(new ClassName("java/lang/String"),
					new MethodDescriptor(
					"(Lcc/squirreljme/runtime/cldc/string/BasicSequence;)V"),
					cas);
				
				// Cache
				stringmap.put(cvs, rv);
				
				// Use it
				return rv;
			}







<
<
<
<
<
<




|
|
<







 







|
|
|
|
|
|
|
<
<
<
<







438
439
440
441
442
443
444






445
446
447
448
449
450

451
452
453
454
455
456
457
...
474
475
476
477
478
479
480
481
482
483
484
485
486
487




488
489
490
491
492
493
494
			SpringClass strclass = this.loadClass(
				new ClassName("java/lang/String"));
				
			// Setup an array of characters to represent the string data,
			// this is the simplest thing to do right now
			SpringObject array = (SpringObject)this.asVMObject(
				s.toString().toCharArray());






			
			// Setup string which uses this sequence
			SpringObject rv = this.newInstance(
				new ClassName("java/lang/String"),
				new MethodDescriptor("([CS)V"),
				array, 0);

			
			return rv;
		}
		
		// Constant string from the constant pool, which shared a global pool
		// of string objects! This must be made so that "aaa" == "aaa" is true
		// even across different classes!
................................................................................
					return rv;
				
				// Setup an array of characters to represent the string data,
				// this is the simplest thing to do right now
				SpringObject array = (SpringObject)this.asVMObject(
					cvs.toString().toCharArray());
				
				// Setup string which uses this sequence, but it also needs
				// to be interned!
				ClassName strclass = new ClassName("java/lang/String");
				rv = (SpringObject)this.invokeMethod(false, strclass,
					new MethodNameAndType("intern", "()Ljava/lang/String;"),
					this.newInstance(strclass, new MethodDescriptor("([CS)V"),
						array, 0));




				
				// Cache
				stringmap.put(cvs, rv);
				
				// Use it
				return rv;
			}