[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:
parent
0edcb2239a
commit
8dd8bd56d1
@ -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);
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user