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) {
// 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.
GotoIf(IntPtrGreaterThan(length, IntPtrConstant(kMaxShortStringLength)),
......
......@@ -2851,7 +2851,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
Node* const second_part =
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);
Goto(&out);
}
......@@ -2864,8 +2865,10 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
Node* const third_part =
SubString(context, string, match_end, subject_end);
Node* result = StringAdd(context, first_part, second_part);
result = StringAdd(context, result, third_part);
Node* result = StringAdd(context, first_part, second_part,
kAllowLargeObjectAllocation);
result =
StringAdd(context, result, third_part, kAllowLargeObjectAllocation);
var_result.Bind(result);
Goto(&out);
......
......@@ -557,7 +557,8 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
{
Label two_byte(this);
// 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());
max_index.Bind(IntPtrConstant(0));
......@@ -591,7 +592,8 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
// At least one of the characters in the string requires a 16-bit
// representation. Allocate a SeqTwoByteString to hold the resulting
// 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
// their corresponding positions in the new 16-bit string.
......
......@@ -959,6 +959,8 @@ Node* CodeStubAssembler::AllocateInNewSpace(int size_in_bytes,
}
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);
}
......@@ -1978,22 +1980,18 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
CSA_SLOW_ASSERT(this, MatchesParameterMode(length, mode));
VARIABLE(var_result, MachineRepresentation::kTagged);
// Compute the SeqOneByteString size and check if it fits into new space.
Label if_lengthiszero(this), if_sizeissmall(this),
if_notsizeissmall(this, Label::kDeferred), if_join(this);
Label if_lengthiszero(this), out(this);
GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
Node* raw_size = GetArrayAllocationSize(
length, UINT8_ELEMENTS, mode,
SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
&if_sizeissmall, &if_notsizeissmall);
BIND(&if_sizeissmall);
{
// Just allocate the SeqOneByteString in new space.
Node* result = AllocateInNewSpace(size, flags);
// Compute the SeqOneByteString size.
Node* raw_size = GetArrayAllocationSize(
length, UINT8_ELEMENTS, mode,
SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
// Just allocate the SeqOneByteString.
Node* result = Allocate(size, flags);
DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex);
StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
......@@ -2003,25 +2001,16 @@ Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
IntPtrConstant(String::kEmptyHashField),
MachineType::PointerRepresentation());
var_result.Bind(result);
Goto(&if_join);
}
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);
Goto(&out);
}
BIND(&if_lengthiszero);
{
var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
Goto(&if_join);
Goto(&out);
}
BIND(&if_join);
BIND(&out);
return var_result.value();
}
......@@ -2051,22 +2040,18 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
Comment("AllocateSeqTwoByteString");
VARIABLE(var_result, MachineRepresentation::kTagged);
// Compute the SeqTwoByteString size and check if it fits into new space.
Label if_lengthiszero(this), if_sizeissmall(this),
if_notsizeissmall(this, Label::kDeferred), if_join(this);
Label if_lengthiszero(this), out(this);
GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
Node* raw_size = GetArrayAllocationSize(
length, UINT16_ELEMENTS, mode,
SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
&if_sizeissmall, &if_notsizeissmall);
BIND(&if_sizeissmall);
{
// Compute the SeqTwoByteString size.
Node* raw_size = GetArrayAllocationSize(
length, UINT16_ELEMENTS, mode,
SeqTwoByteString::kHeaderSize + kObjectAlignmentMask);
Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
// Just allocate the SeqTwoByteString in new space.
Node* result = AllocateInNewSpace(size, flags);
Node* result = Allocate(size, flags);
DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex);
StoreObjectFieldNoWriteBarrier(
......@@ -2077,26 +2062,16 @@ Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
IntPtrConstant(String::kEmptyHashField),
MachineType::PointerRepresentation());
var_result.Bind(result);
Goto(&if_join);
}
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);
Goto(&out);
}
BIND(&if_lengthiszero);
{
var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
Goto(&if_join);
Goto(&out);
}
BIND(&if_join);
BIND(&out);
return var_result.value();
}
......@@ -4013,8 +3988,8 @@ Node* CodeStubAssembler::AllocAndCopyStringCharacters(Node* context, Node* from,
// The subject string is a sequential one-byte string.
BIND(&one_byte_sequential);
{
Node* result =
AllocateSeqOneByteString(context, SmiToWord(character_count));
Node* result = AllocateSeqOneByteString(
context, character_count, SMI_PARAMETERS, kAllowLargeObjectAllocation);
CopyStringCharacters(from, result, from_index, smi_zero, character_count,
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS);
......@@ -4026,8 +4001,8 @@ Node* CodeStubAssembler::AllocAndCopyStringCharacters(Node* context, Node* from,
// The subject string is a sequential two-byte string.
BIND(&two_byte_sequential);
{
Node* result =
AllocateSeqTwoByteString(context, SmiToWord(character_count));
Node* result = AllocateSeqTwoByteString(
context, character_count, SMI_PARAMETERS, kAllowLargeObjectAllocation);
CopyStringCharacters(from, result, from_index, smi_zero, character_count,
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS);
......@@ -4477,7 +4452,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
&two_byte);
// One-byte sequential string case
Node* new_string =
AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS);
AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS, flags);
CopyStringCharacters(var_left.value(), new_string, SmiConstant(0),
SmiConstant(0), left_length, String::ONE_BYTE_ENCODING,
String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
......@@ -4491,7 +4466,7 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
{
// Two-byte sequential string case
new_string =
AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS);
AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS, flags);
CopyStringCharacters(var_left.value(), new_string, SmiConstant(0),
SmiConstant(0), left_length,
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
......
......@@ -306,9 +306,10 @@ TF_STUB(StringAddStub, CodeStubAssembler) {
}
if ((flags & STRING_ADD_CHECK_BOTH) == 0) {
CodeStubAssembler::AllocationFlag allocation_flags =
CodeStubAssembler::AllocationFlags allocation_flags =
(pretenure_flag == TENURED) ? CodeStubAssembler::kPretenured
: CodeStubAssembler::kNone;
allocation_flags |= CodeStubAssembler::kAllowLargeObjectAllocation;
Return(StringAdd(context, left, right, allocation_flags));
} else {
Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE,
......
......@@ -319,8 +319,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(GenerateRandomNumbers) \
V(GlobalPrint) \
V(AllocateInNewSpace) \
V(AllocateSeqOneByteString) \
V(AllocateSeqTwoByteString) \
V(AllocateInTargetSpace) \
V(ObjectCreate) \
V(ObjectHasOwnProperty) \
V(ArrayIndexOf) \
......
......@@ -335,28 +335,6 @@ RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) {
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) {
UNREACHABLE(); // implemented as macro in the parser
}
......
......@@ -281,8 +281,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_INTERNAL(F) \
F(AllocateInNewSpace, 1, 1) \
F(AllocateInTargetSpace, 2, 1) \
F(AllocateSeqOneByteString, 1, 1) \
F(AllocateSeqTwoByteString, 1, 1) \
F(CheckIsBootstrapping, 0, 1) \
F(CreateAsyncFromSyncIterator, 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