The change does not have a negative impact on StringBuilder performance; under variable-string-length microbenchmarks it seems to perform ~15-20% faster than the managed implementation.
}
}
- internal unsafe void InternalSetLength (int newLength)
- {
- if (newLength > length)
- throw new ArgumentOutOfRangeException ("newLength", "newLength as to be <= length");
-
- // zero terminate, we can pass string objects directly via pinvoke
- // we also zero the rest of the string, since the new GC needs to be
- // able to handle the changing size (it will skip the 0 bytes).
- fixed (char * pStr = &start_char) {
- char *p = pStr + newLength;
- char *end = pStr + length;
- while (p < end) {
- p [0] = '\0';
- p++;
- }
- }
- length = newLength;
- }
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void InternalSetLength (int newLength);
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.MayFail)]
// When modifying it, GetCaseInsensitiveHashCode() should be modified as well.
return G_MAXINT;
}
+void
+mono_gc_set_string_length (MonoString *str, gint32 new_length)
+{
+ mono_unichar2 *new_end = str->chars + new_length;
+
+ /* zero the discarded string. This null-delimits the string and allows
+ * the space to be reclaimed by SGen. */
+
+ memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2));
+ str->length = new_length;
+}
+
gboolean
mono_gc_user_markers_supported (void)
{
*/
gboolean mono_gc_is_disabled (void) MONO_INTERNAL;
+void mono_gc_set_string_length (MonoString *str, gint32 new_length) MONO_INTERNAL;
+
#if defined(__MACH__)
void mono_gc_register_mach_exception_thread (pthread_t thread) MONO_INTERNAL;
pthread_t mono_gc_get_mach_exception_thread (void) MONO_INTERNAL;
ICALL(STRING_9, "InternalAllocateStr", ves_icall_System_String_InternalAllocateStr)
ICALL(STRING_10, "InternalIntern", ves_icall_System_String_InternalIntern)
ICALL(STRING_11, "InternalIsInterned", ves_icall_System_String_InternalIsInterned)
+ICALL(STRING_12, "InternalSetLength", ves_icall_System_String_InternalSetLength)
ICALL_TYPE(TENC, "System.Text.Encoding", TENC_1)
ICALL(TENC_1, "InternalCodePage", ves_icall_System_Text_Encoding_InternalCodePage)
return MAX_SMALL_OBJ_SIZE;
}
+void
+mono_gc_set_string_length (MonoString *str, gint32 new_length)
+{
+ mono_unichar2 *new_end = str->chars + new_length;
+
+ /* zero the discarded string. This null-delimits the string and allows
+ * the space to be reclaimed by SGen. */
+
+ if (nursery_canaries_enabled () && sgen_ptr_in_nursery (str)) {
+ CHECK_CANARY_FOR_OBJECT (str);
+ memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2) + CANARY_SIZE);
+ memcpy (new_end + 1 , CANARY_STRING, CANARY_SIZE);
+ } else {
+ memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2));
+ }
+
+ str->length = new_length;
+}
+
gboolean
mono_gc_user_markers_supported (void)
{
return (limit - 2 - offsetof (MonoString, chars)) / 2;
}
+
+void
+ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length)
+{
+ mono_gc_set_string_length (str, new_length);
+}
+
int
ves_icall_System_String_GetLOSLimit (void) MONO_INTERNAL;
+void
+ves_icall_System_String_InternalSetLength (MonoString *str, gint32 new_length) MONO_INTERNAL;
+
#endif /* _MONO_CLI_STRING_ICALLS_H_ */