Skip to content

Add a model for String.intern #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 30, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions src/main/java/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -4271,6 +4271,18 @@ public static String valueOf(double d) {
// return Double.toString(d);
}

/**
* Pool of strings used by the {@code String}.intern model.
*/
static String[] cproverInternPool = null;

/**
* Number of elements stored in the pool for {@code String.intern} pool.
* This can be smaller than {@code cproverInternPool.length} which
* represents the capacity of the array and is fixed for each execution.
*/
static int cproverInternPoolSize = 0;

/**
* Returns a canonical representation for the string object.
* <p>
Expand All @@ -4294,11 +4306,29 @@ public static String valueOf(double d) {
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
*
* @diffblue.noSupport
* @diffblue.limitedSupport literal strings and string-valued constant
* expressions are not interned.
*/
// DIFFBLUE MODEL LIBRARY
// public native String intern();
public String intern() {
CProver.notModelled();
return CProver.nondetWithoutNullForNotModelled();
// Initialize the pool if needed
if (cproverInternPool == null) {
int capacity = CProver.nondetInt();
CProver.assume(capacity > 0);
cproverInternPool = new String[capacity];
Copy link

@antlechner antlechner Apr 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Why isn't this done as part of the initialisation of cproverInternPool? Is this to avoid the static initialiser getting too complicated? If that is not a problem, it would be good to avoid this null check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I don't expect String.intern to be used often so I prefer to keep the String static initialiser simple (which is called all the time). The null check is relatively simple compared to the loop that follows, it could also be replaced by if(cproverInternPoolSize == 0) but I don't know if there is an advantage in that.

cproverInternPool[0] = this;
return this;
}
// Look for an entry in the pool equal to `this`
for (int i = 0; i < cproverInternPoolSize; ++i) {
if (CProverString.equals(cproverInternPool[i], this)) {
return cproverInternPool[i];
}
}
// Add `this` to the pool
CProver.assume(cproverInternPool.length > cproverInternPoolSize);
cproverInternPool[cproverInternPoolSize++] = this;
return this;
}
}