[turbofan] Use proper string map in NewConsString.

Finally address that long-standing TODO where ConsString allocation in
TurboFan would always go for the two byte map instead of choosing the
one byte map if the inputs are one byte strings.

Bug: v8:5269, v8:7109
Change-Id: Ibcfceaf499ceebef0ef928ebc5f204bcacf29bc0
Reviewed-on: https://chromium-review.googlesource.com/799700
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49744}
This commit is contained in:
Benedikt Meurer 2017-11-30 11:53:02 +01:00 committed by Commit Bot
parent cf7fa2eb08
commit ced5628226
2 changed files with 100 additions and 5 deletions

View File

@ -2504,11 +2504,35 @@ Node* EffectControlLinearizer::LowerNewConsString(Node* node) {
Node* first = node->InputAt(1);
Node* second = node->InputAt(2);
// TODO(turbofan): We currently just use the cons_string_map here for
// the sake of simplicity; we could also try to be smarter here and
// use the one_byte_cons_string_map instead when the resulting ConsString
// contains only one byte characters.
Node* result_map = jsgraph()->HeapConstant(factory()->cons_string_map());
// Determine the instance types of {first} and {second}.
Node* first_map = __ LoadField(AccessBuilder::ForMap(), first);
Node* first_instance_type =
__ LoadField(AccessBuilder::ForMapInstanceType(), first_map);
Node* second_map = __ LoadField(AccessBuilder::ForMap(), second);
Node* second_instance_type =
__ LoadField(AccessBuilder::ForMapInstanceType(), second_map);
// Determine the proper map for the resulting ConsString.
// If both {first} and {second} are one-byte strings, we
// create a new ConsOneByteString, otherwise we create a
// new ConsString instead.
auto if_onebyte = __ MakeLabel();
auto if_twobyte = __ MakeLabel();
auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer);
STATIC_ASSERT(kOneByteStringTag != 0);
STATIC_ASSERT(kTwoByteStringTag == 0);
Node* instance_type = __ Word32And(first_instance_type, second_instance_type);
Node* encoding =
__ Word32And(instance_type, __ Int32Constant(kStringEncodingMask));
__ Branch(__ Word32Equal(encoding, __ Int32Constant(kTwoByteStringTag)),
&if_twobyte, &if_onebyte);
__ Bind(&if_onebyte);
__ Goto(&done,
jsgraph()->HeapConstant(factory()->cons_one_byte_string_map()));
__ Bind(&if_twobyte);
__ Goto(&done, jsgraph()->HeapConstant(factory()->cons_string_map()));
__ Bind(&done);
Node* result_map = done.PhiAt(0);
// Allocate the resulting ConsString.
Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(ConsString::kSize));

View File

@ -0,0 +1,71 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --expose-externalize-string
(function() {
function foo(s) {
return "abcdefghijklm" + s;
}
assertTrue(isOneByteString(foo("0")));
assertTrue(isOneByteString(foo("0")));
%OptimizeFunctionOnNextCall(foo);
assertTrue(isOneByteString(foo("0")));
})();
(function() {
function foo(s) {
return s + "abcdefghijklm";
}
assertTrue(isOneByteString(foo("0")));
assertTrue(isOneByteString(foo("0")));
%OptimizeFunctionOnNextCall(foo);
assertTrue(isOneByteString(foo("0")));
})();
(function() {
function foo(s) {
return "abcdefghijklm" + s;
}
assertFalse(isOneByteString(foo("\u1234")));
assertFalse(isOneByteString(foo("\u1234")));
%OptimizeFunctionOnNextCall(foo);
assertFalse(isOneByteString(foo("\u1234")));
})();
(function() {
function foo(s) {
return s + "abcdefghijklm";
}
assertFalse(isOneByteString(foo("\u1234")));
assertFalse(isOneByteString(foo("\u1234")));
%OptimizeFunctionOnNextCall(foo);
assertFalse(isOneByteString(foo("\u1234")));
})();
(function() {
function foo(s) {
return "abcdefghijkl\u1234" + s;
}
assertFalse(isOneByteString(foo("0")));
assertFalse(isOneByteString(foo("0")));
%OptimizeFunctionOnNextCall(foo);
assertFalse(isOneByteString(foo("0")));
})();
(function() {
function foo(s) {
return s + "abcdefghijkl\u1234";
}
assertFalse(isOneByteString(foo("0")));
assertFalse(isOneByteString(foo("0")));
%OptimizeFunctionOnNextCall(foo);
assertFalse(isOneByteString(foo("0")));
})();