You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2007/06/07 15:53:35 UTC
svn commit: r545183 - in /harmony/enhanced/drlvm/trunk/vm:
tests/smoke/stress/ vmcore/include/ vmcore/src/class_support/
vmcore/src/init/
vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/
vmcore/src/kernel_classes/native/ vmcore/src/util/
Author: gshimansky
Date: Thu Jun 7 06:53:34 2007
New Revision: 545183
URL: http://svn.apache.org/viewvc?view=rev&rev=545183
Log:
Apply patch from HARMONY-1016 [drlvm][kernel] Make interned strings garbage collectable
Added:
harmony/enhanced/drlvm/trunk/vm/tests/smoke/stress/Intern.java (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/InternMap.java (with props)
Modified:
harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_strings.h
harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java
harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp
harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp
Added: harmony/enhanced/drlvm/trunk/vm/tests/smoke/stress/Intern.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/tests/smoke/stress/Intern.java?view=auto&rev=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/tests/smoke/stress/Intern.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/tests/smoke/stress/Intern.java Thu Jun 7 06:53:34 2007
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package stress;
+
+/**
+ * Tests the correctness of string interning.
+ *
+ * @keyword XXX_stress
+ */
+public class Intern {
+ public static void main(String[] args) {
+ String s = "abc";
+ for (int i = 0; i < 100000; i++) {
+ s = (s + i + s).intern();
+ if (s.length() > 65536) s = "abc" + i;
+ if (i % 1000 == 0) trace(".");
+ }
+ }
+
+ public static void trace(Object o) {
+ System.out.print(o);
+ System.out.flush();
+ }
+}
Propchange: harmony/enhanced/drlvm/trunk/vm/tests/smoke/stress/Intern.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Thu Jun 7 06:53:34 2007
@@ -157,6 +157,11 @@
String* InitCauseDescriptor_String;
/**
+ * Preloaded methods
+ */
+ Method* VM_intern;
+
+ /**
* Preloaded classes
*/
Class* Boolean_Class;
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_strings.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_strings.h?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_strings.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_strings.h Thu Jun 7 06:53:34 2007
@@ -33,20 +33,6 @@
* Exported functons.
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Interns a string.
- */
-VMEXPORT jstring
-string_intern(JNIEnv*, jobject string);
-
-#ifdef __cplusplus
-}
-#endif
-
VMEXPORT // temporary solution for interpreter unplug
Java_java_lang_String *vm_instantiate_cp_string_resolved(String*);
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/String_Pool.cpp Thu Jun 7 06:53:34 2007
@@ -19,26 +19,24 @@
* @version $Revision: 1.1.2.1.4.4 $
*/
-#include "platform_lowlevel.h"
-
-//MVM
-#include <iostream>
-using namespace std;
-
#include <assert.h>
#include <apr_atomic.h>
#include <apr_pools.h>
#include <apr_hash.h>
#include <apr_time.h>
-#include "String_Pool.h"
-#include "environment.h"
#include "open/hythread.h"
#include "open/vm_util.h"
#include "open/gc.h"
+
+#include "platform_lowlevel.h"
+#include "String_Pool.h"
+#include "environment.h"
#include "atomics.h"
#include "vm_strings.h"
#include "vm_stats.h"
+#include "ini.h"
+#include "exceptions.h"
#include "port_threadunsafe.h"
#define LOG_DOMIAN "vm.strings"
@@ -326,19 +324,30 @@
// NOTE: it is safe to call this function in multiple threads BUT
// don't iterate through interned strings while other threads do interning
ManagedObject * String_Pool::intern(String * str) {
+ jobject string = oh_allocate_local_handle();
ManagedObject* lang_string = string_create_from_utf8(str->bytes, str->len);
if (!lang_string) { // if OutOfMemory
return NULL;
}
+ string->object = lang_string;
assert(!hythread_is_suspend_enabled());
+ Global_Env* env = VM_Global_State::loader_env;
+ jvalue args[1];
+ args[0].l = string;
+ assert(env->VM_intern);
+ vm_execute_java_method_array((jmethodID)env->VM_intern,
+ (jvalue*)&string, args);
+ assert(!exn_raised());
+ assert(string);
+ assert(string->object);
+
// Atomically update the string structure since some other thread might be trying to make the same update.
// The GC won't be able to enumerate here since GC is disabled, so there are no race conditions with GC.
if (VM_Global_State::loader_env->compress_references) {
COMPRESSED_REFERENCE compressed_lang_string =
- (COMPRESSED_REFERENCE)((POINTER_SIZE_INT)lang_string
- - (POINTER_SIZE_INT)VM_Global_State::loader_env->heap_base);
+ compress_reference(string->object);
assert(is_compressed_reference(compressed_lang_string));
uint32 result = apr_atomic_cas32(
/*destination*/ (volatile uint32 *)&str->intern.compressed_ref,
@@ -348,7 +357,7 @@
// Note the successful write of the object.
gc_heap_write_global_slot_compressed(
(COMPRESSED_REFERENCE *)&str->intern.compressed_ref,
- (Managed_Object_Handle)lang_string);
+ (Managed_Object_Handle)string->object);
// add this string to interned strings
register_interned_string(str);
}
@@ -358,18 +367,19 @@
void *result =
(void *)apr_atomic_casptr(
/*destination*/ (volatile void **)&str->intern.raw_ref,
- /*exchange*/ (void *)lang_string,
+ /*exchange*/ (void *)string->object,
/*comparand*/ (void *)NULL);
if (result == NULL) {
// Note the successful write of the object.
gc_heap_write_global_slot(
(Managed_Object_Handle *)&str->intern.raw_ref,
- (Managed_Object_Handle)lang_string);
+ (Managed_Object_Handle)string->object);
// add this string to interned strings
register_interned_string(str);
}
// Some other thread may have beaten us to the slot.
lang_string = str->intern.raw_ref;
}
+ oh_discard_local_handle(string);
return lang_string;
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp Thu Jun 7 06:53:34 2007
@@ -369,6 +369,10 @@
(class_lookup_field_recursive(vm_env->JavaLangString_Class, "bvalue", "[B") != NULL);
vm_env->JavaLangString_VTable = vm_env->JavaLangString_Class->get_vtable();
+ Class* VM_class = preload_class(vm_env, "org/apache/harmony/kernel/vm/VM");
+ vm_env->VM_intern = class_lookup_method_recursive(VM_class, "intern",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+
TRACE2("init", "preloading exceptions");
vm_env->java_lang_Throwable_Class =
preload_class(vm_env, vm_env->JavaLangThrowable_String);
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/InternMap.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/InternMap.java?view=auto&rev=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/InternMap.java (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/InternMap.java Thu Jun 7 06:53:34 2007
@@ -0,0 +1,155 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.kernel.vm;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * Implements weak hash map specialized for storing interned string pool.
+ * @see java.util.WeakHashMap
+ * @see WeakReference
+ */
+public class InternMap {
+
+ private final ReferenceQueue referenceQueue;
+
+ int elementCount;
+
+ Entry[] elementData;
+
+ private final int loadFactor;
+
+ private int threshold;
+
+ //Simple utility method to isolate unchecked cast for array creation
+ private static Entry[] newEntryArray(int size) {
+ return new Entry[size];
+ }
+
+ private static final class Entry/* extends WeakReference*/ {
+ int hash;
+ Entry next;
+ String key;
+ Entry(String key, ReferenceQueue queue) {
+ //super(key, queue);
+ this.key = key;
+ hash = key.hashCode();
+ }
+ }
+
+ public InternMap(int capacity) {
+ if (capacity >= 0) {
+ elementCount = 0;
+ elementData = newEntryArray(capacity == 0 ? 1 : capacity);
+ loadFactor = 7500; // Default load factor of 0.75
+ computeMaxSize();
+ referenceQueue = new ReferenceQueue();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void computeMaxSize() {
+ threshold = (int) ((long) elementData.length * loadFactor / 10000);
+ }
+
+ void poll()
+ {
+ /*
+ Entry toRemove;
+ while ((toRemove = (Entry)referenceQueue.poll()) != null) {
+ removeEntry(toRemove);
+ }
+ */
+ }
+
+ void removeEntry(Entry toRemove)
+ {
+ Entry entry, last = null;
+ int index = (toRemove.hash & 0x7FFFFFFF) % elementData.length;
+ entry = elementData[index];
+ // Ignore queued entries which cannot be found, the user could
+ // have removed them before they were queued, i.e. using clear()
+ while (entry != null) {
+ if (toRemove == entry) {
+ if (last == null) {
+ elementData[index] = entry.next;
+ } else {
+ last.next = entry.next;
+ }
+ elementCount--;
+ break;
+ }
+ last = entry;
+ entry = entry.next;
+ }
+ }
+
+ public String intern(String key)
+ {
+ int index = 0;
+ Entry entry;
+ String interned = null;
+ if (key == null)
+ return null;
+ int hash = key.hashCode();
+ int length = elementData.length;
+ index = (hash & 0x7FFFFFFF) % length;
+ entry = elementData[index];
+ while (entry != null && !key.equals(interned = (String)entry.key/*get()*/)) {
+ entry = entry.next;
+ }
+
+ // if we found the entry, return it
+ if (entry != null) {
+ return interned;
+ }
+
+ // no interned string found, put a new entry for it
+ if (++elementCount > threshold) {
+ rehash();
+ index = (key.hashCode() & 0x7FFFFFFF) % elementData.length;
+ }
+ entry = new Entry(key, referenceQueue);
+ entry.next = elementData[index];
+ elementData[index] = entry;
+ return key;
+ }
+
+ private void rehash()
+ {
+ poll();
+ int length = elementData.length << 1;
+ if (length == 0) {
+ length = 1;
+ }
+ Entry[] newData = newEntryArray(length);
+ for (int i = 0; i < elementData.length; i++) {
+ Entry entry = elementData[i];
+ while (entry != null) {
+ int index = (entry.hash & 0x7FFFFFFF) % length;
+ Entry next = entry.next;
+ entry.next = newData[index];
+ newData[index] = entry;
+ entry = next;
+ }
+ }
+ elementData = newData;
+ computeMaxSize();
+ }
+}
+
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/InternMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java Thu Jun 7 06:53:34 2007
@@ -22,6 +22,8 @@
package org.apache.harmony.kernel.vm;
import org.apache.harmony.vm.VMStack;
+import java.lang.ref.WeakReference;
+import java.util.WeakHashMap;
public final class VM {
@@ -105,12 +107,20 @@
* @return String that has the same contents as
* argument, but from internal pool
*/
- public static String intern(String s) {
- return intern0(s);
+ public static synchronized String intern(String s)
+ {
+ return internedStrings.intern(s);
}
/**
* Invokes native string interning service.
*/
private static native String intern0(String s);
+
+ private static InternMap internedStrings;
+
+ static {
+ // initialize the storage for interned strings
+ internedStrings = new InternMap(32768);
+ }
}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp Thu Jun 7 06:53:34 2007
@@ -38,10 +38,3 @@
// reuse similar method in VMClassRegistry
return Java_java_lang_VMClassRegistry_getClassLoader0(jenv, NULL, clazz);
}
-
-JNIEXPORT jstring JNICALL
-Java_org_apache_harmony_kernel_vm_VM_intern0(JNIEnv *jenv, jclass, jstring str)
-{
- // call corresponding VM internal function
- return string_intern(jenv, str);
-}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp?view=diff&rev=545183&r1=545182&r2=545183
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/vm_strings.cpp Thu Jun 7 06:53:34 2007
@@ -565,19 +565,6 @@
// Interning of strings
-VMEXPORT jstring string_intern(JNIEnv *jenv, jobject jstr_obj)
-{
- ASSERT_RAISE_AREA;
- jboolean is_copy;
- const char* val = jenv->GetStringUTFChars(jstr_obj, &is_copy);
- String* str = VM_Global_State::loader_env->string_pool.lookup(val);
- if (is_copy == JNI_TRUE) {
- jenv->ReleaseStringUTFChars(jstr_obj, val);
- }
-
- return String_to_interned_jstring(str);
-}
-
jstring String_to_interned_jstring(String* str)
{
ASSERT_RAISE_AREA;