[vm] Internal-only String.intern.

TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/50648
Change-Id: I02e89c0def9913f12bf7fdd2ef8f3ff6cba231e3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/278808
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2023-01-19 17:49:08 +00:00 committed by Commit Queue
parent f9524f8509
commit e210ee3577
5 changed files with 51 additions and 0 deletions

View file

@ -245,6 +245,12 @@ DEFINE_NATIVE_ENTRY(StringBase_joinReplaceAllResult, 0, 4) {
return result.ptr();
}
DEFINE_NATIVE_ENTRY(StringBase_intern, 0, 1) {
const String& receiver =
String::CheckedHandle(zone, arguments->NativeArgAt(0));
return Symbols::New(thread, receiver);
}
DEFINE_NATIVE_ENTRY(OneByteString_substringUnchecked, 0, 3) {
const String& receiver =
String::CheckedHandle(zone, arguments->NativeArgAt(0));

View file

@ -0,0 +1,24 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:_internal" show intern;
import "package:expect/expect.dart";
@pragma("vm:never-inline")
String genString(int i) => "abc-${i}-xyz";
main() {
int random = Object().hashCode;
var a = genString(random);
var b = genString(random);
Expect.notIdentical(a, b);
var internedA = intern(a);
Expect.equals(a, internedA);
// Likely, but not guarenteed: Expect.identical(a, internedA);
var internedB = intern(b);
Expect.equals(b, internedB);
// Likely, but not guarenteed: Expect.identical(a, internedB);
Expect.identical(internedA, internedB);
}

View file

@ -0,0 +1,17 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// VMOptions=--old_gen_heap_size=20
import "dart:_internal" show intern;
@pragma("vm:never-inline")
use(x) => x;
main() {
const MB = 1 << 20;
for (var i = 0; i < 20 * MB; i++) {
use(intern((i.toString()))); // Should not hit OutOfMemory
}
}

View file

@ -125,6 +125,7 @@ namespace dart {
V(StringBase_createFromCodePoints, 3) \
V(StringBase_substringUnchecked, 3) \
V(StringBase_joinReplaceAllResult, 4) \
V(StringBase_intern, 1) \
V(StringBuffer_createStringFromUint16Array, 3) \
V(OneByteString_substringUnchecked, 3) \
V(OneByteString_allocateFromOneByteList, 3) \

View file

@ -431,3 +431,6 @@ class FinalizerEntry {
@FfiNative<Void Function(Handle, IntPtr)>('FinalizerEntry_SetExternalSize')
external void setExternalSize(int externalSize);
}
@pragma("vm:external-name", "StringBase_intern")
external String intern(String str);