Commit f6d73509 authored by jgruber's avatar jgruber Committed by Commit Bot

[csa] Refactor large-object handling in string allocation

CSA::AllocateSeq{One,Two}ByteString used its own home-grown handling to
allocate very large strings. This CL refactors both methods to use
AllocationFlags::kAllowLargeObjectAllocation instead. Callers now need
to specify explicitly if large-object allocation is possible or not.

Bug: chromium:636391
Cq-Include-Trybots: master.tryserver.v8:v8_linux_noi18n_rel_ng
Change-Id: I0b7ffb0b083f4e977cea42c500f8f2ee1c60519f
Reviewed-on: https://chromium-review.googlesource.com/625738Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47504}
parent 942c61ab
...@@ -43,7 +43,8 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { ...@@ -43,7 +43,8 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
// For short strings, do the conversion in CSA through the lookup table. // For short strings, do the conversion in CSA through the lookup table.
Node* const dst = AllocateSeqOneByteString(context, length); Node* const dst = AllocateSeqOneByteString(context, length, INTPTR_PARAMETERS,
kAllowLargeObjectAllocation);
const int kMaxShortStringLength = 24; // Determined empirically. const int kMaxShortStringLength = 24; // Determined empirically.
GotoIf(IntPtrGreaterThan(length, IntPtrConstant(kMaxShortStringLength)), GotoIf(IntPtrGreaterThan(length, IntPtrConstant(kMaxShortStringLength)),
......
...@@ -2851,7 +2851,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( ...@@ -2851,7 +2851,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
Node* const second_part = Node* const second_part =
SubString(context, string, match_end, subject_end); SubString(context, string, match_end, subject_end);
Node* const result = StringAdd(context, first_part, second_part); Node* const result = StringAdd(context, first_part, second_part,
kAllowLargeObjectAllocation);
var_result.Bind(result); var_result.Bind(result);
Goto(&out); Goto(&out);
} }
...@@ -2864,8 +2865,10 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( ...@@ -2864,8 +2865,10 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
Node* const third_part = Node* const third_part =
SubString(context, string, match_end, subject_end); SubString(context, string, match_end, subject_end);
Node* result = StringAdd(context, first_part, second_part); Node* result = StringAdd(context, first_part, second_part,
result = StringAdd(context, result, third_part); kAllowLargeObjectAllocation);
result =
StringAdd(context, result, third_part, kAllowLargeObjectAllocation);
var_result.Bind(result); var_result.Bind(result);
Goto(&out); Goto(&out);
......
...@@ -557,7 +557,8 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { ...@@ -557,7 +557,8 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
{ {
Label two_byte(this); Label two_byte(this);
// Assume that the resulting string contains only one-byte characters. // Assume that the resulting string contains only one-byte characters.
Node* one_byte_result = AllocateSeqOneByteString(context, argc); Node* one_byte_result = AllocateSeqOneByteString(
context, argc, INTPTR_PARAMETERS, kAllowLargeObjectAllocation);
VARIABLE(max_index, MachineType::PointerRepresentation()); VARIABLE(max_index, MachineType::PointerRepresentation());
max_index.Bind(IntPtrConstant(0)); max_index.Bind(IntPtrConstant(0));
...@@ -591,7 +592,8 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { ...@@ -591,7 +592,8 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
// At least one of the characters in the string requires a 16-bit // At least one of the characters in the string requires a 16-bit
// representation. Allocate a SeqTwoByteString to hold the resulting // representation. Allocate a SeqTwoByteString to hold the resulting
// string. // string.
Node* two_byte_result = AllocateSeqTwoByteString(context, argc); Node* two_byte_result = AllocateSeqTwoByteString(
context, argc, INTPTR_PARAMETERS, kAllowLargeObjectAllocation);
// Copy the characters that have already been put in the 8-bit string into // Copy the characters that have already been put in the 8-bit string into
// their corresponding positions in the new 16-bit string. // their corresponding positions in the new 16-bit string.
......
...@@ -959,6 +959,8 @@ Node* CodeStubAssembler::AllocateInNewSpace(int size_in_bytes, ...@@ -959,6 +959,8 @@ Node* CodeStubAssembler::AllocateInNewSpace(int size_in_bytes,
} }
Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) { Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) {
DCHECK_IMPLIES(size_in_bytes > kMaxRegularHeapObjectSize,
(flags & kAllowLargeObjectAllocation) != 0);
return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags); return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags);
} }
...@@ -1978,22 +1980,18 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, ...@@ -1978,22 +1980,18 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
CSA_SLOW_ASSERT(this, MatchesParameterMode(length, mode)); CSA_SLOW_ASSERT(this, MatchesParameterMode(length, mode));
VARIABLE(var_result, MachineRepresentation::kTagged); VARIABLE(var_result, MachineRepresentation::kTagged);
// Compute the SeqOneByteString size and check if it fits into new space. Label if_lengthiszero(this), out(this);
Label if_lengthiszero(this), if_sizeissmall(this),
if_notsizeissmall(this, Label::kDeferred), if_join(this);
GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero); GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
{
// Compute the SeqOneByteString size.
Node* raw_size = GetArrayAllocationSize( Node* raw_size = GetArrayAllocationSize(
length, UINT8_ELEMENTS, mode, length, UINT8_ELEMENTS, mode,
SeqOneByteString::kHeaderSize + kObjectAlignmentMask); SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
&if_sizeissmall, &if_notsizeissmall);
BIND(&if_sizeissmall); // Just allocate the SeqOneByteString.
{ Node* result = Allocate(size, flags);
// Just allocate the SeqOneByteString in new space.
Node* result = AllocateInNewSpace(size, flags);
DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex)); DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex); StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex);
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
...@@ -2003,25 +2001,16 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length, ...@@ -2003,25 +2001,16 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
IntPtrConstant(String::kEmptyHashField), IntPtrConstant(String::kEmptyHashField),
MachineType::PointerRepresentation()); MachineType::PointerRepresentation());
var_result.Bind(result); var_result.Bind(result);
Goto(&if_join); Goto(&out);
}
BIND(&if_notsizeissmall);
{
// We might need to allocate in large object space, go to the runtime.
Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context,
ParameterToTagged(length, mode));
var_result.Bind(result);
Goto(&if_join);
} }
BIND(&if_lengthiszero); BIND(&if_lengthiszero);
{ {
var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
Goto(&if_join); Goto(&out);
} }
BIND(&if_join); BIND(&out);
return var_result.value(); return var_result.value();
} }
...@@ -2051,22 +2040,18 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, ...@@ -2051,22 +2040,18 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
Comment("AllocateSeqTwoByteString"); Comment("AllocateSeqTwoByteString");
VARIABLE(var_result, MachineRepresentation::kTagged); VARIABLE(var_result, MachineRepresentation::kTagged);
// Compute the SeqTwoByteString size and check if it fits into new space. Label if_lengthiszero(this), out(this);
Label if_lengthiszero(this), if_sizeissmall(this),
if_notsizeissmall(this, Label::kDeferred), if_join(this);
GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero); GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
{
// Compute the SeqTwoByteString size.
Node* raw_size = GetArrayAllocationSize( Node* raw_size = GetArrayAllocationSize(
length, UINT16_ELEMENTS, mode, length, UINT16_ELEMENTS, mode,
SeqOneByteString::kHeaderSize + kObjectAlignmentMask); SeqTwoByteString::kHeaderSize + kObjectAlignmentMask);
Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask)); Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
&if_sizeissmall, &if_notsizeissmall);
BIND(&if_sizeissmall);
{
// Just allocate the SeqTwoByteString in new space. // Just allocate the SeqTwoByteString in new space.
Node* result = AllocateInNewSpace(size, flags); Node* result = Allocate(size, flags);
DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex)); DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex); StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex);
StoreObjectFieldNoWriteBarrier( StoreObjectFieldNoWriteBarrier(
...@@ -2077,26 +2062,16 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length, ...@@ -2077,26 +2062,16 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
IntPtrConstant(String::kEmptyHashField), IntPtrConstant(String::kEmptyHashField),
MachineType::PointerRepresentation()); MachineType::PointerRepresentation());
var_result.Bind(result); var_result.Bind(result);
Goto(&if_join); Goto(&out);
}
BIND(&if_notsizeissmall);
{
// We might need to allocate in large object space, go to the runtime.
Node* result =
CallRuntime(Runtime::kAllocateSeqTwoByteString, context,
mode == SMI_PARAMETERS ? length : SmiFromWord(length));
var_result.Bind(result);
Goto(&if_join);
} }
BIND(&if_lengthiszero); BIND(&if_lengthiszero);
{ {
var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex)); var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
Goto(&if_join); Goto(&out);
} }
BIND(&if_join); BIND(&out);
return var_result.value(); return var_result.value();
} }
...@@ -4013,8 +3988,8 @@ Node* CodeStubAssembler::AllocAndCopyStringCharacters(Node* context, Node* from, ...@@ -4013,8 +3988,8 @@ Node* CodeStubAssembler::AllocAndCopyStringCharacters(Node* context, Node* from,
// The subject string is a sequential one-byte string. // The subject string is a sequential one-byte string.
BIND(&one_byte_sequential); BIND(&one_byte_sequential);
{ {
Node* result = Node* result = AllocateSeqOneByteString(
AllocateSeqOneByteString(context, SmiToWord(character_count)); context, character_count, SMI_PARAMETERS, kAllowLargeObjectAllocation);
CopyStringCharacters(from, result, from_index, smi_zero, character_count, CopyStringCharacters(from, result, from_index, smi_zero, character_count,
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
...@@ -4026,8 +4001,8 @@ Node* CodeStubAssembler::AllocAndCopyStringCharacters(Node* context, Node* from, ...@@ -4026,8 +4001,8 @@ Node* CodeStubAssembler::AllocAndCopyStringCharacters(Node* context, Node* from,
// The subject string is a sequential two-byte string. // The subject string is a sequential two-byte string.
BIND(&two_byte_sequential); BIND(&two_byte_sequential);
{ {
Node* result = Node* result = AllocateSeqTwoByteString(
AllocateSeqTwoByteString(context, SmiToWord(character_count)); context, character_count, SMI_PARAMETERS, kAllowLargeObjectAllocation);
CopyStringCharacters(from, result, from_index, smi_zero, character_count, CopyStringCharacters(from, result, from_index, smi_zero, character_count,
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
...@@ -4477,7 +4452,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, ...@@ -4477,7 +4452,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
&two_byte); &two_byte);
// One-byte sequential string case // One-byte sequential string case
Node* new_string = Node* new_string =
AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS); AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS, flags);
CopyStringCharacters(var_left.value(), new_string, SmiConstant(0), CopyStringCharacters(var_left.value(), new_string, SmiConstant(0),
SmiConstant(0), left_length, String::ONE_BYTE_ENCODING, SmiConstant(0), left_length, String::ONE_BYTE_ENCODING,
String::ONE_BYTE_ENCODING, SMI_PARAMETERS); String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
...@@ -4491,7 +4466,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, ...@@ -4491,7 +4466,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
{ {
// Two-byte sequential string case // Two-byte sequential string case
new_string = new_string =
AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS); AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS, flags);
CopyStringCharacters(var_left.value(), new_string, SmiConstant(0), CopyStringCharacters(var_left.value(), new_string, SmiConstant(0),
SmiConstant(0), left_length, SmiConstant(0), left_length,
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
......
...@@ -306,9 +306,10 @@ TF_STUB(StringAddStub, CodeStubAssembler) { ...@@ -306,9 +306,10 @@ TF_STUB(StringAddStub, CodeStubAssembler) {
} }
if ((flags & STRING_ADD_CHECK_BOTH) == 0) { if ((flags & STRING_ADD_CHECK_BOTH) == 0) {
CodeStubAssembler::AllocationFlag allocation_flags = CodeStubAssembler::AllocationFlags allocation_flags =
(pretenure_flag == TENURED) ? CodeStubAssembler::kPretenured (pretenure_flag == TENURED) ? CodeStubAssembler::kPretenured
: CodeStubAssembler::kNone; : CodeStubAssembler::kNone;
allocation_flags |= CodeStubAssembler::kAllowLargeObjectAllocation;
Return(StringAdd(context, left, right, allocation_flags)); Return(StringAdd(context, left, right, allocation_flags));
} else { } else {
Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE,
......
...@@ -319,8 +319,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { ...@@ -319,8 +319,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(GenerateRandomNumbers) \ V(GenerateRandomNumbers) \
V(GlobalPrint) \ V(GlobalPrint) \
V(AllocateInNewSpace) \ V(AllocateInNewSpace) \
V(AllocateSeqOneByteString) \ V(AllocateInTargetSpace) \
V(AllocateSeqTwoByteString) \
V(ObjectCreate) \ V(ObjectCreate) \
V(ObjectHasOwnProperty) \ V(ObjectHasOwnProperty) \
V(ArrayIndexOf) \ V(ArrayIndexOf) \
......
...@@ -335,28 +335,6 @@ RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) { ...@@ -335,28 +335,6 @@ RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) {
return *isolate->factory()->NewFillerObject(size, double_align, space); return *isolate->factory()->NewFillerObject(size, double_align, space);
} }
RUNTIME_FUNCTION(Runtime_AllocateSeqOneByteString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_SMI_ARG_CHECKED(length, 0);
if (length == 0) return isolate->heap()->empty_string();
Handle<SeqOneByteString> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate->factory()->NewRawOneByteString(length));
return *result;
}
RUNTIME_FUNCTION(Runtime_AllocateSeqTwoByteString) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_SMI_ARG_CHECKED(length, 0);
if (length == 0) return isolate->heap()->empty_string();
Handle<SeqTwoByteString> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate->factory()->NewRawTwoByteString(length));
return *result;
}
RUNTIME_FUNCTION(Runtime_IS_VAR) { RUNTIME_FUNCTION(Runtime_IS_VAR) {
UNREACHABLE(); // implemented as macro in the parser UNREACHABLE(); // implemented as macro in the parser
} }
......
...@@ -281,8 +281,6 @@ namespace internal { ...@@ -281,8 +281,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_INTERNAL(F) \ #define FOR_EACH_INTRINSIC_INTERNAL(F) \
F(AllocateInNewSpace, 1, 1) \ F(AllocateInNewSpace, 1, 1) \
F(AllocateInTargetSpace, 2, 1) \ F(AllocateInTargetSpace, 2, 1) \
F(AllocateSeqOneByteString, 1, 1) \
F(AllocateSeqTwoByteString, 1, 1) \
F(CheckIsBootstrapping, 0, 1) \ F(CheckIsBootstrapping, 0, 1) \
F(CreateAsyncFromSyncIterator, 1, 1) \ F(CreateAsyncFromSyncIterator, 1, 1) \
F(CreateListFromArrayLike, 1, 1) \ F(CreateListFromArrayLike, 1, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment