[cleanup] Refactor CodeStubAssembler::NewConsString().

Remove the duplication of the allocation logic via the
AllocateOneByteConsString and AllocateTwoByteConsString helpers, and
instead just have a diamond to figure out the result map. This reduces
code size of the StringAdd_CheckNone builtin and even seems to be
beneficial performance wise. It seems to improve the performance on
the `bench-dom-serialize.js` test by around 1% just doing this.

Drive-by-fix: Remove the `flags` from CodeStubAssembler::StringAdd()
and its helpers, since we no longer support pretenuring of string
additions (for quite a while now).

Bug: v8:8834, v8:8939
Change-Id: Ia23e02c974b5f572930fcd45be0643094ab2fa98
Doc: https://bit.ly/fast-string-concatenation-in-javascript
Reviewed-on: https://chromium-review.googlesource.com/c/1498133
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59993}
This commit is contained in:
Benedikt Meurer 2019-03-04 08:45:08 +01:00 committed by Commit Bot
parent 0edcb2239a
commit 8dd8bd56d1
2 changed files with 30 additions and 82 deletions

View File

@ -3307,52 +3307,9 @@ TNode<String> CodeStubAssembler::AllocateSlicedTwoByteString(
offset); offset);
} }
TNode<String> CodeStubAssembler::AllocateConsString(RootIndex map_root_index, TNode<String> CodeStubAssembler::AllocateConsString(TNode<Uint32T> length,
TNode<Uint32T> length, TNode<String> left,
TNode<String> first, TNode<String> right) {
TNode<String> second,
AllocationFlags flags) {
DCHECK(map_root_index == RootIndex::kConsOneByteStringMap ||
map_root_index == RootIndex::kConsStringMap);
Node* result = Allocate(ConsString::kSize, flags);
DCHECK(RootsTable::IsImmortalImmovable(map_root_index));
StoreMapNoWriteBarrier(result, map_root_index);
StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length,
MachineRepresentation::kWord32);
StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset,
Int32Constant(String::kEmptyHashField),
MachineRepresentation::kWord32);
bool const new_space = !(flags & kPretenured);
if (new_space) {
StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first,
MachineRepresentation::kTagged);
StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second,
MachineRepresentation::kTagged);
} else {
StoreObjectField(result, ConsString::kFirstOffset, first);
StoreObjectField(result, ConsString::kSecondOffset, second);
}
return CAST(result);
}
TNode<String> CodeStubAssembler::AllocateOneByteConsString(
TNode<Uint32T> length, TNode<String> first, TNode<String> second,
AllocationFlags flags) {
return AllocateConsString(RootIndex::kConsOneByteStringMap, length, first,
second, flags);
}
TNode<String> CodeStubAssembler::AllocateTwoByteConsString(
TNode<Uint32T> length, TNode<String> first, TNode<String> second,
AllocationFlags flags) {
return AllocateConsString(RootIndex::kConsStringMap, length, first, second,
flags);
}
TNode<String> CodeStubAssembler::NewConsString(TNode<Uint32T> length,
TNode<String> left,
TNode<String> right,
AllocationFlags flags) {
// Added string can be a cons string. // Added string can be a cons string.
Comment("Allocating ConsString"); Comment("Allocating ConsString");
Node* left_instance_type = LoadInstanceType(left); Node* left_instance_type = LoadInstanceType(left);
@ -3377,8 +3334,8 @@ TNode<String> CodeStubAssembler::NewConsString(TNode<Uint32T> length,
STATIC_ASSERT(kOneByteDataHintTag != 0); STATIC_ASSERT(kOneByteDataHintTag != 0);
Label one_byte_map(this); Label one_byte_map(this);
Label two_byte_map(this); Label two_byte_map(this);
TVARIABLE(String, result); TVARIABLE(Map, result_map);
Label done(this, &result); Label done(this, &result_map);
GotoIf(IsSetWord32(anded_instance_types, GotoIf(IsSetWord32(anded_instance_types,
kStringEncodingMask | kOneByteDataHintTag), kStringEncodingMask | kOneByteDataHintTag),
&one_byte_map); &one_byte_map);
@ -3389,18 +3346,30 @@ TNode<String> CodeStubAssembler::NewConsString(TNode<Uint32T> length,
&two_byte_map, &one_byte_map); &two_byte_map, &one_byte_map);
BIND(&one_byte_map); BIND(&one_byte_map);
Comment("One-byte ConsString"); {
result = AllocateOneByteConsString(length, left, right, flags); Comment("One-byte ConsString");
Goto(&done); result_map = CAST(LoadRoot(RootIndex::kConsOneByteStringMap));
Goto(&done);
}
BIND(&two_byte_map); BIND(&two_byte_map);
Comment("Two-byte ConsString"); {
result = AllocateTwoByteConsString(length, left, right, flags); Comment("Two-byte ConsString");
Goto(&done); result_map = CAST(LoadRoot(RootIndex::kConsStringMap));
Goto(&done);
}
BIND(&done); BIND(&done);
Node* result = AllocateInNewSpace(ConsString::kSize);
return result.value(); StoreMapNoWriteBarrier(result, result_map.value());
StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length,
MachineRepresentation::kWord32);
StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldOffset,
Int32Constant(String::kEmptyHashField),
MachineRepresentation::kWord32);
StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, left);
StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, right);
return CAST(result);
} }
TNode<NameDictionary> CodeStubAssembler::AllocateNameDictionary( TNode<NameDictionary> CodeStubAssembler::AllocateNameDictionary(
@ -7197,8 +7166,7 @@ void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left,
} }
TNode<String> CodeStubAssembler::StringAdd(Node* context, TNode<String> left, TNode<String> CodeStubAssembler::StringAdd(Node* context, TNode<String> left,
TNode<String> right, TNode<String> right) {
AllocationFlags flags) {
TVARIABLE(String, result); TVARIABLE(String, result);
Label check_right(this), runtime(this, Label::kDeferred), cons(this), Label check_right(this), runtime(this, Label::kDeferred), cons(this),
done(this, &result), done_native(this, &result); done(this, &result), done_native(this, &result);
@ -7234,7 +7202,7 @@ TNode<String> CodeStubAssembler::StringAdd(Node* context, TNode<String> left,
&non_cons); &non_cons);
result = result =
NewConsString(new_length, var_left.value(), var_right.value(), flags); AllocateConsString(new_length, var_left.value(), var_right.value());
Goto(&done_native); Goto(&done_native);
BIND(&non_cons); BIND(&non_cons);

View File

@ -1463,26 +1463,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<String> parent, TNode<String> parent,
TNode<Smi> offset); TNode<Smi> offset);
// Allocate a one-byte ConsString with the given length, first and second
// parts. |length| is expected to be tagged, and |first| and |second| are
// expected to be one-byte strings.
TNode<String> AllocateOneByteConsString(TNode<Uint32T> length,
TNode<String> first,
TNode<String> second,
AllocationFlags flags = kNone);
// Allocate a two-byte ConsString with the given length, first and second
// parts. |length| is expected to be tagged, and |first| and |second| are
// expected to be two-byte strings.
TNode<String> AllocateTwoByteConsString(TNode<Uint32T> length,
TNode<String> first,
TNode<String> second,
AllocationFlags flags = kNone);
// Allocate an appropriate one- or two-byte ConsString with the first and // Allocate an appropriate one- or two-byte ConsString with the first and
// second parts specified by |left| and |right|. // second parts specified by |left| and |right|.
TNode<String> NewConsString(TNode<Uint32T> length, TNode<String> left, TNode<String> AllocateConsString(TNode<Uint32T> length, TNode<String> left,
TNode<String> right, TNode<String> right);
AllocationFlags flags = kNone);
TNode<NameDictionary> AllocateNameDictionary(int at_least_space_for); TNode<NameDictionary> AllocateNameDictionary(int at_least_space_for);
TNode<NameDictionary> AllocateNameDictionary( TNode<NameDictionary> AllocateNameDictionary(
@ -2285,7 +2269,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Return a new string object produced by concatenating |first| with |second|. // Return a new string object produced by concatenating |first| with |second|.
TNode<String> StringAdd(Node* context, TNode<String> first, TNode<String> StringAdd(Node* context, TNode<String> first,
TNode<String> second, AllocationFlags flags = kNone); TNode<String> second);
// Check if |string| is an indirect (thin or flat cons) string type that can // Check if |string| is an indirect (thin or flat cons) string type that can
// be dereferenced by DerefIndirectString. // be dereferenced by DerefIndirectString.
@ -3426,10 +3410,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Uint32T> length, TNode<Uint32T> length,
TNode<String> parent, TNode<Smi> offset); TNode<String> parent, TNode<Smi> offset);
TNode<String> AllocateConsString(RootIndex map_root_index,
TNode<Uint32T> length, TNode<String> first,
TNode<String> second, AllocationFlags flags);
// Allocate a MutableHeapNumber without initializing its value. // Allocate a MutableHeapNumber without initializing its value.
TNode<MutableHeapNumber> AllocateMutableHeapNumber(); TNode<MutableHeapNumber> AllocateMutableHeapNumber();