Commit d8ce7cd3 authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Commit Bot

[CSA][cleanup] TNodified some CSA methods relating to Strings

This is a CL in a string of CLs that aims to TNodify CSA. In particular,
there were some loads that were done in AnyTagged instead of
TaggedPointer. TNode-ifying them brings improvement in pointer
compression since we are able to decompress using the Pointer
decompression.

Bug: v8:6949, v8:9396
Change-Id: I368d4f85348f3560a7f71bf66ebc7c4dd978a8dd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1752854Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63274}
parent 017a68c0
...@@ -33,9 +33,7 @@ class IntlBuiltinsAssembler : public CodeStubAssembler { ...@@ -33,9 +33,7 @@ class IntlBuiltinsAssembler : public CodeStubAssembler {
}; };
TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
Node* const string = Parameter(Descriptor::kString); TNode<String> const string = CAST(Parameter(Descriptor::kString));
CSA_ASSERT(this, IsString(string));
Label call_c(this), return_string(this), runtime(this, Label::kDeferred); Label call_c(this), return_string(this), runtime(this, Label::kDeferred);
...@@ -49,7 +47,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { ...@@ -49,7 +47,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
state(), string, ToDirectStringAssembler::kDontUnpackSlicedStrings); state(), string, ToDirectStringAssembler::kDontUnpackSlicedStrings);
to_direct.TryToDirect(&runtime); to_direct.TryToDirect(&runtime);
Node* const instance_type = to_direct.instance_type(); TNode<Int32T> const instance_type = to_direct.instance_type();
CSA_ASSERT(this, CSA_ASSERT(this,
Word32BinaryNot(IsIndirectStringInstanceType(instance_type))); Word32BinaryNot(IsIndirectStringInstanceType(instance_type)));
GotoIfNot(IsOneByteStringInstanceType(instance_type), &runtime); GotoIfNot(IsOneByteStringInstanceType(instance_type), &runtime);
...@@ -67,7 +65,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { ...@@ -67,7 +65,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
VARIABLE(var_cursor, MachineType::PointerRepresentation(), VARIABLE(var_cursor, MachineType::PointerRepresentation(),
IntPtrConstant(0)); IntPtrConstant(0));
Node* const start_address = to_direct.PointerToData(&call_c); TNode<RawPtrT> const start_address = to_direct.PointerToData(&call_c);
TNode<IntPtrT> const end_address = TNode<IntPtrT> const end_address =
Signed(IntPtrAdd(start_address, ChangeUint32ToWord(length))); Signed(IntPtrAdd(start_address, ChangeUint32ToWord(length)));
...@@ -105,7 +103,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) { ...@@ -105,7 +103,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
// String ConvertOneByteToLower(String src, String dst); // String ConvertOneByteToLower(String src, String dst);
BIND(&call_c); BIND(&call_c);
{ {
Node* const src = to_direct.string(); TNode<String> const src = to_direct.string();
Node* const function_addr = Node* const function_addr =
ExternalConstant(ExternalReference::intl_convert_one_byte_to_lower()); ExternalConstant(ExternalReference::intl_convert_one_byte_to_lower());
......
...@@ -128,9 +128,10 @@ Node* StringBuiltinsAssembler::PointerToStringDataAtIndex( ...@@ -128,9 +128,10 @@ Node* StringBuiltinsAssembler::PointerToStringDataAtIndex(
return IntPtrAdd(string_data, offset_in_bytes); return IntPtrAdd(string_data, offset_in_bytes);
} }
void StringBuiltinsAssembler::GenerateStringEqual(Node* left, Node* right) { void StringBuiltinsAssembler::GenerateStringEqual(TNode<String> left,
VARIABLE(var_left, MachineRepresentation::kTagged, left); TNode<String> right) {
VARIABLE(var_right, MachineRepresentation::kTagged, right); TVARIABLE(String, var_left, left);
TVARIABLE(String, var_right, right);
Label if_equal(this), if_notequal(this), if_indirect(this, Label::kDeferred), Label if_equal(this), if_notequal(this), if_indirect(this, Label::kDeferred),
restart(this, {&var_left, &var_right}); restart(this, {&var_left, &var_right});
...@@ -142,11 +143,11 @@ void StringBuiltinsAssembler::GenerateStringEqual(Node* left, Node* right) { ...@@ -142,11 +143,11 @@ void StringBuiltinsAssembler::GenerateStringEqual(Node* left, Node* right) {
Goto(&restart); Goto(&restart);
BIND(&restart); BIND(&restart);
Node* lhs = var_left.value(); TNode<String> lhs = var_left.value();
Node* rhs = var_right.value(); TNode<String> rhs = var_right.value();
Node* lhs_instance_type = LoadInstanceType(lhs); TNode<Uint16T> lhs_instance_type = LoadInstanceType(lhs);
Node* rhs_instance_type = LoadInstanceType(rhs); TNode<Uint16T> rhs_instance_type = LoadInstanceType(rhs);
StringEqual_Core(lhs, lhs_instance_type, rhs, rhs_instance_type, lhs_length, StringEqual_Core(lhs, lhs_instance_type, rhs, rhs_instance_type, lhs_length,
&if_equal, &if_notequal, &if_indirect); &if_equal, &if_notequal, &if_indirect);
...@@ -324,11 +325,10 @@ TF_BUILTIN(SubString, StringBuiltinsAssembler) { ...@@ -324,11 +325,10 @@ TF_BUILTIN(SubString, StringBuiltinsAssembler) {
Return(SubString(string, SmiUntag(from), SmiUntag(to))); Return(SubString(string, SmiUntag(from), SmiUntag(to)));
} }
void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* left, void StringBuiltinsAssembler::GenerateStringRelationalComparison(
Node* right, TNode<String> left, TNode<String> right, Operation op) {
Operation op) { TVARIABLE(String, var_left, left);
VARIABLE(var_left, MachineRepresentation::kTagged, left); TVARIABLE(String, var_right, right);
VARIABLE(var_right, MachineRepresentation::kTagged, right);
Variable* input_vars[2] = {&var_left, &var_right}; Variable* input_vars[2] = {&var_left, &var_right};
Label if_less(this), if_equal(this), if_greater(this); Label if_less(this), if_equal(this), if_greater(this);
...@@ -336,18 +336,18 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* left, ...@@ -336,18 +336,18 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* left,
Goto(&restart); Goto(&restart);
BIND(&restart); BIND(&restart);
Node* lhs = var_left.value(); TNode<String> lhs = var_left.value();
Node* rhs = var_right.value(); TNode<String> rhs = var_right.value();
// Fast check to see if {lhs} and {rhs} refer to the same String object. // Fast check to see if {lhs} and {rhs} refer to the same String object.
GotoIf(WordEqual(lhs, rhs), &if_equal); GotoIf(WordEqual(lhs, rhs), &if_equal);
// Load instance types of {lhs} and {rhs}. // Load instance types of {lhs} and {rhs}.
Node* lhs_instance_type = LoadInstanceType(lhs); TNode<Uint16T> lhs_instance_type = LoadInstanceType(lhs);
Node* rhs_instance_type = LoadInstanceType(rhs); TNode<Uint16T> rhs_instance_type = LoadInstanceType(rhs);
// Combine the instance types into a single 16-bit value, so we can check // Combine the instance types into a single 16-bit value, so we can check
// both of them at once. // both of them at once.
Node* both_instance_types = Word32Or( TNode<Word32T> both_instance_types = Word32Or(
lhs_instance_type, Word32Shl(rhs_instance_type, Int32Constant(8))); lhs_instance_type, Word32Shl(rhs_instance_type, Int32Constant(8)));
// Check that both {lhs} and {rhs} are flat one-byte strings. // Check that both {lhs} and {rhs} are flat one-byte strings.
...@@ -496,32 +496,32 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* left, ...@@ -496,32 +496,32 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* left,
} }
TF_BUILTIN(StringEqual, StringBuiltinsAssembler) { TF_BUILTIN(StringEqual, StringBuiltinsAssembler) {
Node* left = Parameter(Descriptor::kLeft); TNode<String> left = CAST(Parameter(Descriptor::kLeft));
Node* right = Parameter(Descriptor::kRight); TNode<String> right = CAST(Parameter(Descriptor::kRight));
GenerateStringEqual(left, right); GenerateStringEqual(left, right);
} }
TF_BUILTIN(StringLessThan, StringBuiltinsAssembler) { TF_BUILTIN(StringLessThan, StringBuiltinsAssembler) {
Node* left = Parameter(Descriptor::kLeft); TNode<String> left = CAST(Parameter(Descriptor::kLeft));
Node* right = Parameter(Descriptor::kRight); TNode<String> right = CAST(Parameter(Descriptor::kRight));
GenerateStringRelationalComparison(left, right, Operation::kLessThan); GenerateStringRelationalComparison(left, right, Operation::kLessThan);
} }
TF_BUILTIN(StringLessThanOrEqual, StringBuiltinsAssembler) { TF_BUILTIN(StringLessThanOrEqual, StringBuiltinsAssembler) {
Node* left = Parameter(Descriptor::kLeft); TNode<String> left = CAST(Parameter(Descriptor::kLeft));
Node* right = Parameter(Descriptor::kRight); TNode<String> right = CAST(Parameter(Descriptor::kRight));
GenerateStringRelationalComparison(left, right, Operation::kLessThanOrEqual); GenerateStringRelationalComparison(left, right, Operation::kLessThanOrEqual);
} }
TF_BUILTIN(StringGreaterThan, StringBuiltinsAssembler) { TF_BUILTIN(StringGreaterThan, StringBuiltinsAssembler) {
Node* left = Parameter(Descriptor::kLeft); TNode<String> left = CAST(Parameter(Descriptor::kLeft));
Node* right = Parameter(Descriptor::kRight); TNode<String> right = CAST(Parameter(Descriptor::kRight));
GenerateStringRelationalComparison(left, right, Operation::kGreaterThan); GenerateStringRelationalComparison(left, right, Operation::kGreaterThan);
} }
TF_BUILTIN(StringGreaterThanOrEqual, StringBuiltinsAssembler) { TF_BUILTIN(StringGreaterThanOrEqual, StringBuiltinsAssembler) {
Node* left = Parameter(Descriptor::kLeft); TNode<String> left = CAST(Parameter(Descriptor::kLeft));
Node* right = Parameter(Descriptor::kRight); TNode<String> right = CAST(Parameter(Descriptor::kRight));
GenerateStringRelationalComparison(left, right, GenerateStringRelationalComparison(left, right,
Operation::kGreaterThanOrEqual); Operation::kGreaterThanOrEqual);
} }
...@@ -682,12 +682,9 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { ...@@ -682,12 +682,9 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
} }
void StringBuiltinsAssembler::StringIndexOf( void StringBuiltinsAssembler::StringIndexOf(
Node* const subject_string, Node* const search_string, Node* const position, TNode<String> const subject_string, TNode<String> const search_string,
const std::function<void(Node*)>& f_return) { TNode<Smi> const position,
CSA_ASSERT(this, IsString(subject_string)); const std::function<void(TNode<Smi>)>& f_return) {
CSA_ASSERT(this, IsString(search_string));
CSA_ASSERT(this, TaggedIsSmi(position));
TNode<IntPtrT> const int_zero = IntPtrConstant(0); TNode<IntPtrT> const int_zero = IntPtrConstant(0);
TNode<IntPtrT> const search_length = LoadStringLengthAsWord(search_string); TNode<IntPtrT> const search_length = LoadStringLengthAsWord(search_string);
TNode<IntPtrT> const subject_length = LoadStringLengthAsWord(subject_string); TNode<IntPtrT> const subject_length = LoadStringLengthAsWord(subject_string);
...@@ -719,13 +716,13 @@ void StringBuiltinsAssembler::StringIndexOf( ...@@ -719,13 +716,13 @@ void StringBuiltinsAssembler::StringIndexOf(
search_to_direct.TryToDirect(&call_runtime_unchecked); search_to_direct.TryToDirect(&call_runtime_unchecked);
// Load pointers to string data. // Load pointers to string data.
Node* const subject_ptr = TNode<RawPtrT> const subject_ptr =
subject_to_direct.PointerToData(&call_runtime_unchecked); subject_to_direct.PointerToData(&call_runtime_unchecked);
Node* const search_ptr = TNode<RawPtrT> const search_ptr =
search_to_direct.PointerToData(&call_runtime_unchecked); search_to_direct.PointerToData(&call_runtime_unchecked);
Node* const subject_offset = subject_to_direct.offset(); TNode<IntPtrT> const subject_offset = subject_to_direct.offset();
Node* const search_offset = search_to_direct.offset(); TNode<IntPtrT> const search_offset = search_to_direct.offset();
// Like String::IndexOf, the actual matching is done by the optimized // Like String::IndexOf, the actual matching is done by the optimized
// SearchString method in string-search.h. Dispatch based on string instance // SearchString method in string-search.h. Dispatch based on string instance
...@@ -844,9 +841,9 @@ void StringBuiltinsAssembler::StringIndexOf( ...@@ -844,9 +841,9 @@ void StringBuiltinsAssembler::StringIndexOf(
// Simplified version of the runtime call where the types of the arguments // Simplified version of the runtime call where the types of the arguments
// are already known due to type checks in this stub. // are already known due to type checks in this stub.
Comment("Call Runtime Unchecked"); Comment("Call Runtime Unchecked");
Node* result = TNode<Smi> result =
CallRuntime(Runtime::kStringIndexOfUnchecked, NoContextConstant(), CAST(CallRuntime(Runtime::kStringIndexOfUnchecked, NoContextConstant(),
subject_string, search_string, position); subject_string, search_string, position));
f_return(result); f_return(result);
} }
} }
...@@ -855,11 +852,11 @@ void StringBuiltinsAssembler::StringIndexOf( ...@@ -855,11 +852,11 @@ void StringBuiltinsAssembler::StringIndexOf(
// #sec-string.prototype.indexof // #sec-string.prototype.indexof
// Unchecked helper for builtins lowering. // Unchecked helper for builtins lowering.
TF_BUILTIN(StringIndexOf, StringBuiltinsAssembler) { TF_BUILTIN(StringIndexOf, StringBuiltinsAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver); TNode<String> receiver = CAST(Parameter(Descriptor::kReceiver));
Node* search_string = Parameter(Descriptor::kSearchString); TNode<String> search_string = CAST(Parameter(Descriptor::kSearchString));
Node* position = Parameter(Descriptor::kPosition); TNode<Smi> position = CAST(Parameter(Descriptor::kPosition));
StringIndexOf(receiver, search_string, position, StringIndexOf(receiver, search_string, position,
[this](Node* result) { this->Return(result); }); [this](TNode<Smi> result) { this->Return(result); });
} }
// ES6 String.prototype.includes(searchString [, position]) // ES6 String.prototype.includes(searchString [, position])
...@@ -926,13 +923,15 @@ void StringIncludesIndexOfAssembler::Generate(SearchVariant variant, ...@@ -926,13 +923,15 @@ void StringIncludesIndexOfAssembler::Generate(SearchVariant variant,
GotoIfNot(IsString(receiver), &call_runtime); GotoIfNot(IsString(receiver), &call_runtime);
GotoIfNot(IsString(search), &call_runtime); GotoIfNot(IsString(search), &call_runtime);
StringIndexOf(receiver, search, position, [&](Node* result) { StringIndexOf(CAST(receiver), CAST(search), CAST(position),
CSA_ASSERT(this, TaggedIsSmi(result)); [&](TNode<Smi> result) {
arguments.PopAndReturn((variant == kIndexOf) if (variant == kIndexOf) {
? result arguments.PopAndReturn(result);
: SelectBooleanConstant(SmiGreaterThanOrEqual( } else {
CAST(result), SmiConstant(0)))); arguments.PopAndReturn(SelectBooleanConstant(
}); SmiGreaterThanOrEqual(result, SmiConstant(0))));
}
});
} }
BIND(&call_runtime); BIND(&call_runtime);
{ {
...@@ -1517,8 +1516,8 @@ TNode<JSArray> StringBuiltinsAssembler::StringToArray( ...@@ -1517,8 +1516,8 @@ TNode<JSArray> StringBuiltinsAssembler::StringToArray(
TNode<FixedArray> elements = CAST(AllocateFixedArray( TNode<FixedArray> elements = CAST(AllocateFixedArray(
PACKED_ELEMENTS, length, AllocationFlag::kAllowLargeObjectAllocation)); PACKED_ELEMENTS, length, AllocationFlag::kAllowLargeObjectAllocation));
// Don't allocate anything while {string_data} is live! // Don't allocate anything while {string_data} is live!
TNode<RawPtrT> string_data = UncheckedCast<RawPtrT>( TNode<RawPtrT> string_data =
to_direct.PointerToData(&fill_thehole_and_call_runtime)); to_direct.PointerToData(&fill_thehole_and_call_runtime);
TNode<IntPtrT> string_data_offset = to_direct.offset(); TNode<IntPtrT> string_data_offset = to_direct.offset();
TNode<Object> cache = LoadRoot(RootIndex::kSingleCharacterStringCache); TNode<Object> cache = LoadRoot(RootIndex::kSingleCharacterStringCache);
...@@ -1818,10 +1817,11 @@ void StringTrimAssembler::Generate(String::TrimMode mode, ...@@ -1818,10 +1817,11 @@ void StringTrimAssembler::Generate(String::TrimMode mode,
ToDirectStringAssembler to_direct(state(), string); ToDirectStringAssembler to_direct(state(), string);
to_direct.TryToDirect(&if_runtime); to_direct.TryToDirect(&if_runtime);
Node* const string_data = to_direct.PointerToData(&if_runtime); TNode<RawPtrT> const string_data = to_direct.PointerToData(&if_runtime);
Node* const instance_type = to_direct.instance_type(); TNode<Int32T> const instance_type = to_direct.instance_type();
Node* const is_stringonebyte = IsOneByteStringInstanceType(instance_type); TNode<BoolT> const is_stringonebyte =
Node* const string_data_offset = to_direct.offset(); IsOneByteStringInstanceType(instance_type);
TNode<IntPtrT> const string_data_offset = to_direct.offset();
TVARIABLE(IntPtrT, var_start, IntPtrConstant(0)); TVARIABLE(IntPtrT, var_start, IntPtrConstant(0));
TVARIABLE(IntPtrT, var_end, IntPtrSub(string_length, IntPtrConstant(1))); TVARIABLE(IntPtrT, var_end, IntPtrSub(string_length, IntPtrConstant(1)));
......
...@@ -58,16 +58,17 @@ class StringBuiltinsAssembler : public CodeStubAssembler { ...@@ -58,16 +58,17 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
void ConvertAndBoundsCheckStartArgument(Node* context, Variable* var_start, void ConvertAndBoundsCheckStartArgument(Node* context, Variable* var_start,
Node* start, Node* string_length); Node* start, Node* string_length);
void GenerateStringEqual(Node* left, Node* right); void GenerateStringEqual(TNode<String> left, TNode<String> right);
void GenerateStringRelationalComparison(Node* left, Node* right, void GenerateStringRelationalComparison(TNode<String> left,
Operation op); TNode<String> right, Operation op);
using StringAtAccessor = std::function<TNode<Object>( using StringAtAccessor = std::function<TNode<Object>(
TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index)>; TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index)>;
void StringIndexOf(Node* const subject_string, Node* const search_string, void StringIndexOf(TNode<String> const subject_string,
Node* const position, TNode<String> const search_string,
const std::function<void(Node*)>& f_return); TNode<Smi> const position,
const std::function<void(TNode<Smi>)>& f_return);
TNode<Smi> IndexOfDollarChar(Node* const context, Node* const string); TNode<Smi> IndexOfDollarChar(Node* const context, Node* const string);
......
...@@ -6886,10 +6886,9 @@ TNode<Int32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string, ...@@ -6886,10 +6886,9 @@ TNode<Int32T> CodeStubAssembler::StringCharCodeAt(SloppyTNode<String> string,
ToDirectStringAssembler to_direct(state(), string); ToDirectStringAssembler to_direct(state(), string);
to_direct.TryToDirect(&if_runtime); to_direct.TryToDirect(&if_runtime);
Node* const offset = IntPtrAdd(index, to_direct.offset()); TNode<IntPtrT> const offset = IntPtrAdd(index, to_direct.offset());
Node* const instance_type = to_direct.instance_type(); TNode<Int32T> const instance_type = to_direct.instance_type();
TNode<RawPtrT> const string_data = to_direct.PointerToData(&if_runtime);
Node* const string_data = to_direct.PointerToData(&if_runtime);
// Check if the {string} is a TwoByteSeqString or a OneByteSeqString. // Check if the {string} is a TwoByteSeqString or a OneByteSeqString.
Branch(IsOneByteStringInstanceType(instance_type), &if_stringisonebyte, Branch(IsOneByteStringInstanceType(instance_type), &if_stringisonebyte,
...@@ -7050,7 +7049,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -7050,7 +7049,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
TNode<String> direct_string = to_direct.TryToDirect(&runtime); TNode<String> direct_string = to_direct.TryToDirect(&runtime);
TNode<IntPtrT> offset = IntPtrAdd(from, to_direct.offset()); TNode<IntPtrT> offset = IntPtrAdd(from, to_direct.offset());
Node* const instance_type = to_direct.instance_type(); TNode<Int32T> const instance_type = to_direct.instance_type();
// The subject string can only be external or sequential string of either // The subject string can only be external or sequential string of either
// encoding at this point. // encoding at this point.
...@@ -7108,7 +7107,8 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -7108,7 +7107,8 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
// Handle external string. // Handle external string.
BIND(&external_string); BIND(&external_string);
{ {
Node* const fake_sequential_string = to_direct.PointerToString(&runtime); TNode<RawPtrT> const fake_sequential_string =
to_direct.PointerToString(&runtime);
var_result = AllocAndCopyStringCharacters( var_result = AllocAndCopyStringCharacters(
fake_sequential_string, instance_type, offset, substr_length); fake_sequential_string, instance_type, offset, substr_length);
...@@ -7163,21 +7163,13 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -7163,21 +7163,13 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
} }
ToDirectStringAssembler::ToDirectStringAssembler( ToDirectStringAssembler::ToDirectStringAssembler(
compiler::CodeAssemblerState* state, Node* string, Flags flags) compiler::CodeAssemblerState* state, TNode<String> string, Flags flags)
: CodeStubAssembler(state), : CodeStubAssembler(state),
var_string_(this, MachineRepresentation::kTagged, string), var_string_(string, this),
var_instance_type_(this, MachineRepresentation::kWord32), var_instance_type_(LoadInstanceType(string), this),
var_offset_(this, MachineType::PointerRepresentation()), var_offset_(IntPtrConstant(0), this),
var_is_external_(this, MachineRepresentation::kWord32), var_is_external_(Int32Constant(0), this),
flags_(flags) { flags_(flags) {}
CSA_ASSERT(this, TaggedIsNotSmi(string));
CSA_ASSERT(this, IsString(string));
var_string_.Bind(string);
var_offset_.Bind(IntPtrConstant(0));
var_instance_type_.Bind(LoadInstanceType(string));
var_is_external_.Bind(Int32Constant(0));
}
TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) { TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
VariableList vars({&var_string_, &var_offset_, &var_instance_type_}, zone()); VariableList vars({&var_string_, &var_offset_, &var_instance_type_}, zone());
...@@ -7203,7 +7195,7 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) { ...@@ -7203,7 +7195,7 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
}; };
STATIC_ASSERT(arraysize(values) == arraysize(labels)); STATIC_ASSERT(arraysize(values) == arraysize(labels));
Node* const representation = Word32And( TNode<Word32T> const representation = Word32And(
var_instance_type_.value(), Int32Constant(kStringRepresentationMask)); var_instance_type_.value(), Int32Constant(kStringRepresentationMask));
Switch(representation, if_bailout, values, labels, arraysize(values)); Switch(representation, if_bailout, values, labels, arraysize(values));
} }
...@@ -7212,13 +7204,15 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) { ...@@ -7212,13 +7204,15 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
// Flat cons strings have an empty second part. // Flat cons strings have an empty second part.
BIND(&if_iscons); BIND(&if_iscons);
{ {
Node* const string = var_string_.value(); TNode<String> const string = var_string_.value();
GotoIfNot(IsEmptyString(LoadObjectField(string, ConsString::kSecondOffset)), GotoIfNot(IsEmptyString(
LoadObjectField<String>(string, ConsString::kSecondOffset)),
if_bailout); if_bailout);
Node* const lhs = LoadObjectField(string, ConsString::kFirstOffset); TNode<String> const lhs =
var_string_.Bind(lhs); LoadObjectField<String>(string, ConsString::kFirstOffset);
var_instance_type_.Bind(LoadInstanceType(lhs)); var_string_ = lhs;
var_instance_type_ = LoadInstanceType(lhs);
Goto(&dispatch); Goto(&dispatch);
} }
...@@ -7229,14 +7223,15 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) { ...@@ -7229,14 +7223,15 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
if (!FLAG_string_slices || (flags_ & kDontUnpackSlicedStrings)) { if (!FLAG_string_slices || (flags_ & kDontUnpackSlicedStrings)) {
Goto(if_bailout); Goto(if_bailout);
} else { } else {
Node* const string = var_string_.value(); TNode<String> const string = var_string_.value();
Node* const sliced_offset = TNode<IntPtrT> const sliced_offset =
LoadAndUntagObjectField(string, SlicedString::kOffsetOffset); LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
var_offset_.Bind(IntPtrAdd(var_offset_.value(), sliced_offset)); var_offset_ = IntPtrAdd(var_offset_.value(), sliced_offset);
Node* const parent = LoadObjectField(string, SlicedString::kParentOffset); TNode<String> const parent =
var_string_.Bind(parent); LoadObjectField<String>(string, SlicedString::kParentOffset);
var_instance_type_.Bind(LoadInstanceType(parent)); var_string_ = parent;
var_instance_type_ = LoadInstanceType(parent);
Goto(&dispatch); Goto(&dispatch);
} }
...@@ -7245,24 +7240,24 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) { ...@@ -7245,24 +7240,24 @@ TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
// Thin string. Fetch the actual string. // Thin string. Fetch the actual string.
BIND(&if_isthin); BIND(&if_isthin);
{ {
Node* const string = var_string_.value(); TNode<String> const string = var_string_.value();
Node* const actual_string = TNode<String> const actual_string =
LoadObjectField(string, ThinString::kActualOffset); LoadObjectField<String>(string, ThinString::kActualOffset);
Node* const actual_instance_type = LoadInstanceType(actual_string); TNode<Uint16T> const actual_instance_type = LoadInstanceType(actual_string);
var_string_.Bind(actual_string); var_string_ = actual_string;
var_instance_type_.Bind(actual_instance_type); var_instance_type_ = actual_instance_type;
Goto(&dispatch); Goto(&dispatch);
} }
// External string. // External string.
BIND(&if_isexternal); BIND(&if_isexternal);
var_is_external_.Bind(Int32Constant(1)); var_is_external_ = Int32Constant(1);
Goto(&out); Goto(&out);
BIND(&out); BIND(&out);
return CAST(var_string_.value()); return var_string_.value();
} }
TNode<RawPtrT> ToDirectStringAssembler::TryToSequential( TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
...@@ -7291,7 +7286,7 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential( ...@@ -7291,7 +7286,7 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
GotoIf(IsUncachedExternalStringInstanceType(var_instance_type_.value()), GotoIf(IsUncachedExternalStringInstanceType(var_instance_type_.value()),
if_bailout); if_bailout);
TNode<String> string = CAST(var_string_.value()); TNode<String> string = var_string_.value();
TNode<IntPtrT> result = TNode<IntPtrT> result =
LoadObjectField<IntPtrT>(string, ExternalString::kResourceDataOffset); LoadObjectField<IntPtrT>(string, ExternalString::kResourceDataOffset);
if (ptr_kind == PTR_TO_STRING) { if (ptr_kind == PTR_TO_STRING) {
...@@ -7306,35 +7301,33 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential( ...@@ -7306,35 +7301,33 @@ TNode<RawPtrT> ToDirectStringAssembler::TryToSequential(
return var_result.value(); return var_result.value();
} }
void CodeStubAssembler::BranchIfCanDerefIndirectString(Node* string, void CodeStubAssembler::BranchIfCanDerefIndirectString(
Node* instance_type, TNode<String> string, TNode<Int32T> instance_type, Label* can_deref,
Label* can_deref, Label* cannot_deref) {
Label* cannot_deref) {
CSA_ASSERT(this, IsString(string));
Node* representation = Node* representation =
Word32And(instance_type, Int32Constant(kStringRepresentationMask)); Word32And(instance_type, Int32Constant(kStringRepresentationMask));
GotoIf(Word32Equal(representation, Int32Constant(kThinStringTag)), can_deref); GotoIf(Word32Equal(representation, Int32Constant(kThinStringTag)), can_deref);
GotoIf(Word32NotEqual(representation, Int32Constant(kConsStringTag)), GotoIf(Word32NotEqual(representation, Int32Constant(kConsStringTag)),
cannot_deref); cannot_deref);
// Cons string. // Cons string.
Node* rhs = LoadObjectField(string, ConsString::kSecondOffset); TNode<String> rhs =
LoadObjectField<String>(string, ConsString::kSecondOffset);
GotoIf(IsEmptyString(rhs), can_deref); GotoIf(IsEmptyString(rhs), can_deref);
Goto(cannot_deref); Goto(cannot_deref);
} }
Node* CodeStubAssembler::DerefIndirectString(TNode<String> string, TNode<String> CodeStubAssembler::DerefIndirectString(
TNode<Int32T> instance_type, TNode<String> string, TNode<Int32T> instance_type, Label* cannot_deref) {
Label* cannot_deref) {
Label deref(this); Label deref(this);
BranchIfCanDerefIndirectString(string, instance_type, &deref, cannot_deref); BranchIfCanDerefIndirectString(string, instance_type, &deref, cannot_deref);
BIND(&deref); BIND(&deref);
STATIC_ASSERT(static_cast<int>(ThinString::kActualOffset) == STATIC_ASSERT(static_cast<int>(ThinString::kActualOffset) ==
static_cast<int>(ConsString::kFirstOffset)); static_cast<int>(ConsString::kFirstOffset));
return LoadObjectField(string, ThinString::kActualOffset); return LoadObjectField<String>(string, ThinString::kActualOffset);
} }
void CodeStubAssembler::DerefIndirectString(Variable* var_string, void CodeStubAssembler::DerefIndirectString(TVariable<String>* var_string,
Node* instance_type) { TNode<Int32T> instance_type) {
#ifdef DEBUG #ifdef DEBUG
Label can_deref(this), cannot_deref(this); Label can_deref(this), cannot_deref(this);
BranchIfCanDerefIndirectString(var_string->value(), instance_type, &can_deref, BranchIfCanDerefIndirectString(var_string->value(), instance_type, &can_deref,
...@@ -7347,12 +7340,12 @@ void CodeStubAssembler::DerefIndirectString(Variable* var_string, ...@@ -7347,12 +7340,12 @@ void CodeStubAssembler::DerefIndirectString(Variable* var_string,
STATIC_ASSERT(static_cast<int>(ThinString::kActualOffset) == STATIC_ASSERT(static_cast<int>(ThinString::kActualOffset) ==
static_cast<int>(ConsString::kFirstOffset)); static_cast<int>(ConsString::kFirstOffset));
var_string->Bind( *var_string =
LoadObjectField(var_string->value(), ThinString::kActualOffset)); LoadObjectField<String>(var_string->value(), ThinString::kActualOffset);
} }
void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string, void CodeStubAssembler::MaybeDerefIndirectString(TVariable<String>* var_string,
Node* instance_type, TNode<Int32T> instance_type,
Label* did_deref, Label* did_deref,
Label* cannot_deref) { Label* cannot_deref) {
Label deref(this); Label deref(this);
...@@ -7366,11 +7359,10 @@ void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string, ...@@ -7366,11 +7359,10 @@ void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string,
} }
} }
void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left, void CodeStubAssembler::MaybeDerefIndirectStrings(
Node* left_instance_type, TVariable<String>* var_left, TNode<Int32T> left_instance_type,
Variable* var_right, TVariable<String>* var_right, TNode<Int32T> right_instance_type,
Node* right_instance_type, Label* did_something) {
Label* did_something) {
Label did_nothing_left(this), did_something_left(this), Label did_nothing_left(this), did_something_left(this),
didnt_do_anything(this); didnt_do_anything(this);
MaybeDerefIndirectString(var_left, left_instance_type, &did_something_left, MaybeDerefIndirectString(var_left, left_instance_type, &did_something_left,
...@@ -7435,13 +7427,13 @@ TNode<String> CodeStubAssembler::StringAdd(Node* context, TNode<String> left, ...@@ -7435,13 +7427,13 @@ TNode<String> CodeStubAssembler::StringAdd(Node* context, TNode<String> left,
BIND(&non_cons); BIND(&non_cons);
Comment("Full string concatenate"); Comment("Full string concatenate");
Node* left_instance_type = LoadInstanceType(var_left.value()); TNode<Int32T> left_instance_type = LoadInstanceType(var_left.value());
Node* right_instance_type = LoadInstanceType(var_right.value()); TNode<Int32T> right_instance_type = LoadInstanceType(var_right.value());
// Compute intersection and difference of instance types. // Compute intersection and difference of instance types.
Node* ored_instance_types = TNode<Word32T> ored_instance_types =
Word32Or(left_instance_type, right_instance_type); Word32Or(left_instance_type, right_instance_type);
Node* xored_instance_types = TNode<Word32T> xored_instance_types =
Word32Xor(left_instance_type, right_instance_type); Word32Xor(left_instance_type, right_instance_type);
// Check if both strings have the same encoding and both are sequential. // Check if both strings have the same encoding and both are sequential.
...@@ -8343,7 +8335,8 @@ void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex, ...@@ -8343,7 +8335,8 @@ void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
Goto(if_keyisunique); Goto(if_keyisunique);
BIND(&if_thinstring); BIND(&if_thinstring);
var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset)); var_unique->Bind(
LoadObjectField<String>(CAST(key), ThinString::kActualOffset));
Goto(if_keyisunique); Goto(if_keyisunique);
BIND(&if_hascachedindex); BIND(&if_hascachedindex);
...@@ -14003,7 +13996,7 @@ void CodeStubAssembler::SetPropertyLength(TNode<Context> context, ...@@ -14003,7 +13996,7 @@ void CodeStubAssembler::SetPropertyLength(TNode<Context> context,
TNode<String> CodeStubAssembler::TaggedToDirectString(TNode<Object> value, TNode<String> CodeStubAssembler::TaggedToDirectString(TNode<Object> value,
Label* fail) { Label* fail) {
ToDirectStringAssembler to_direct(state(), value); ToDirectStringAssembler to_direct(state(), CAST(value));
to_direct.TryToDirect(fail); to_direct.TryToDirect(fail);
to_direct.PointerToData(fail); to_direct.PointerToData(fail);
return CAST(value); return CAST(value);
......
...@@ -2422,21 +2422,27 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2422,21 +2422,27 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// 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.
void BranchIfCanDerefIndirectString(Node* string, Node* instance_type, void BranchIfCanDerefIndirectString(TNode<String> string,
TNode<Int32T> instance_type,
Label* can_deref, Label* cannot_deref); Label* can_deref, Label* cannot_deref);
// Unpack an indirect (thin or flat cons) string type. // Unpack an indirect (thin or flat cons) string type.
void DerefIndirectString(Variable* var_string, Node* instance_type); void DerefIndirectString(TVariable<String>* var_string,
TNode<Int32T> instance_type);
// Check if |var_string| has an indirect (thin or flat cons) string type, // Check if |var_string| has an indirect (thin or flat cons) string type,
// and unpack it if so. // and unpack it if so.
void MaybeDerefIndirectString(Variable* var_string, Node* instance_type, void MaybeDerefIndirectString(TVariable<String>* var_string,
Label* did_deref, Label* cannot_deref); TNode<Int32T> instance_type, Label* did_deref,
Label* cannot_deref);
// Check if |var_left| or |var_right| has an indirect (thin or flat cons) // Check if |var_left| or |var_right| has an indirect (thin or flat cons)
// string type, and unpack it/them if so. Fall through if nothing was done. // string type, and unpack it/them if so. Fall through if nothing was done.
void MaybeDerefIndirectStrings(Variable* var_left, Node* left_instance_type, void MaybeDerefIndirectStrings(TVariable<String>* var_left,
Variable* var_right, Node* right_instance_type, TNode<Int32T> left_instance_type,
TVariable<String>* var_right,
TNode<Int32T> right_instance_type,
Label* did_something); Label* did_something);
Node* DerefIndirectString(TNode<String> string, TNode<Int32T> instance_type, TNode<String> DerefIndirectString(TNode<String> string,
Label* cannot_deref); TNode<Int32T> instance_type,
Label* cannot_deref);
TNode<String> StringFromSingleUTF16EncodedCodePoint(TNode<Int32T> codepoint); TNode<String> StringFromSingleUTF16EncodedCodePoint(TNode<Int32T> codepoint);
...@@ -3705,8 +3711,8 @@ class ToDirectStringAssembler : public CodeStubAssembler { ...@@ -3705,8 +3711,8 @@ class ToDirectStringAssembler : public CodeStubAssembler {
}; };
using Flags = base::Flags<Flag>; using Flags = base::Flags<Flag>;
ToDirectStringAssembler(compiler::CodeAssemblerState* state, Node* string, ToDirectStringAssembler(compiler::CodeAssemblerState* state,
Flags flags = Flags()); TNode<String> string, Flags flags = Flags());
// Converts flat cons, thin, and sliced strings and returns the direct // Converts flat cons, thin, and sliced strings and returns the direct
// string. The result can be either a sequential or external string. // string. The result can be either a sequential or external string.
...@@ -3726,20 +3732,18 @@ class ToDirectStringAssembler : public CodeStubAssembler { ...@@ -3726,20 +3732,18 @@ class ToDirectStringAssembler : public CodeStubAssembler {
return TryToSequential(PTR_TO_STRING, if_bailout); return TryToSequential(PTR_TO_STRING, if_bailout);
} }
Node* string() { return var_string_.value(); } TNode<String> string() { return var_string_.value(); }
Node* instance_type() { return var_instance_type_.value(); } TNode<Int32T> instance_type() { return var_instance_type_.value(); }
TNode<IntPtrT> offset() { TNode<IntPtrT> offset() { return var_offset_.value(); }
return UncheckedCast<IntPtrT>(var_offset_.value()); TNode<Word32T> is_external() { return var_is_external_.value(); }
}
Node* is_external() { return var_is_external_.value(); }
private: private:
TNode<RawPtrT> TryToSequential(StringPointerKind ptr_kind, Label* if_bailout); TNode<RawPtrT> TryToSequential(StringPointerKind ptr_kind, Label* if_bailout);
Variable var_string_; TVariable<String> var_string_;
Variable var_instance_type_; TVariable<Int32T> var_instance_type_;
Variable var_offset_; TVariable<IntPtrT> var_offset_;
Variable var_is_external_; TVariable<Word32T> var_is_external_;
const Flags flags_; const Flags flags_;
}; };
......
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