Commit 8123f5c3 authored by Toon Verwaest's avatar Toon Verwaest Committed by Commit Bot

[csa] Type CSA code related to String length accesses

Bug: v8:7065
Cq-Include-Trybots: master.tryserver.v8:v8_linux_noi18n_rel_ng
Change-Id: I7882b719f72561cd22b874eae239000936fad35c
Reviewed-on: https://chromium-review.googlesource.com/768874
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49381}
parent 0ef8da26
......@@ -2342,7 +2342,8 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant) {
TNode<String> search_element_string = CAST(search_element);
Label continue_loop(this), next_iteration(this, &index_var),
slow_compare(this), runtime(this, Label::kDeferred);
Node* search_length = LoadAndUntagStringLength(search_element_string);
TNode<IntPtrT> search_length =
LoadStringLengthAsWord(search_element_string);
Goto(&next_iteration);
BIND(&next_iteration);
GotoIfNot(UintPtrLessThan(index_var.value(), array_length),
......@@ -2352,7 +2353,7 @@ void ArrayIncludesIndexofAssembler::Generate(SearchVariant variant) {
GotoIf(WordEqual(search_element_string, element_k), &return_found);
Node* element_k_type = LoadInstanceType(element_k);
GotoIfNot(IsStringInstanceType(element_k_type), &continue_loop);
Branch(WordEqual(search_length, LoadAndUntagStringLength(element_k)),
Branch(WordEqual(search_length, LoadStringLengthAsWord(element_k)),
&slow_compare, &continue_loop);
BIND(&slow_compare);
......
......@@ -214,6 +214,7 @@ namespace internal {
TFH(LoadIC_Miss, LoadWithVector) \
TFH(LoadIC_Slow, LoadWithVector) \
TFH(LoadIC_StringLength, LoadWithVector) \
TFH(LoadIC_StringWrapperLength, LoadWithVector) \
TFH(LoadIC_Uninitialized, LoadWithVector) \
TFH(StoreGlobalIC_Slow, StoreWithVector) \
TFH(StoreIC_Miss, StoreWithVector) \
......
......@@ -13,10 +13,14 @@ namespace v8 {
namespace internal {
TF_BUILTIN(LoadIC_StringLength, CodeStubAssembler) {
Node* string = Parameter(Descriptor::kReceiver);
Return(LoadStringLengthAsSmi(string));
}
TF_BUILTIN(LoadIC_StringWrapperLength, CodeStubAssembler) {
Node* value = Parameter(Descriptor::kReceiver);
Node* string = LoadJSValueValue(value);
Node* result = LoadStringLength(string);
Return(result);
Return(LoadStringLengthAsSmi(string));
}
TF_BUILTIN(KeyedLoadIC_Miss, CodeStubAssembler) {
......
......@@ -28,8 +28,8 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
Label call_c(this), return_string(this), runtime(this, Label::kDeferred);
// Early exit on empty strings.
Node* const length = SmiUntag(LoadStringLength(string));
GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_string);
TNode<Smi> const length = LoadStringLengthAsSmi(string);
GotoIf(SmiEqual(length, SmiConstant(0)), &return_string);
// Unpack strings if possible, and bail to runtime unless we get a one-byte
// flat string.
......@@ -47,8 +47,7 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
Node* const dst = AllocateSeqOneByteString(context, length);
const int kMaxShortStringLength = 24; // Determined empirically.
GotoIf(IntPtrGreaterThan(length, IntPtrConstant(kMaxShortStringLength)),
&call_c);
GotoIf(SmiGreaterThan(length, SmiConstant(kMaxShortStringLength)), &call_c);
{
Node* const dst_ptr = PointerToSeqStringData(dst);
......@@ -56,7 +55,8 @@ TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
IntPtrConstant(0));
Node* const start_address = to_direct.PointerToData(&call_c);
Node* const end_address = IntPtrAdd(start_address, length);
TNode<IntPtrT> const end_address =
Signed(IntPtrAdd(start_address, SmiUntag(length)));
Node* const to_lower_table_addr = ExternalConstant(
ExternalReference::intl_to_latin1_lower_table(isolate()));
......
This diff is collapsed.
This diff is collapsed.
......@@ -20,15 +20,16 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
Node* match_start_index, Node* match_end_index,
Node* replace_string);
void StringEqual_Core(Node* context, Node* lhs, Node* lhs_instance_type,
Node* rhs, Node* rhs_instance_type, Node* length,
Label* if_equal, Label* if_not_equal,
Label* if_indirect);
Node* rhs, Node* rhs_instance_type,
TNode<IntPtrT> length, Label* if_equal,
Label* if_not_equal, Label* if_indirect);
protected:
void StringEqual_Loop(Node* lhs, Node* lhs_instance_type,
MachineType lhs_type, Node* rhs,
Node* rhs_instance_type, MachineType rhs_type,
Node* length, Label* if_equal, Label* if_not_equal);
TNode<IntPtrT> length, Label* if_equal,
Label* if_not_equal);
Node* DirectStringData(Node* string, Node* string_instance_type);
void DispatchOnStringEncodings(Node* const lhs_instance_type,
......@@ -57,8 +58,8 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
SloppyTNode<Smi> limit);
TNode<Uint32T> LoadSurrogatePairAt(SloppyTNode<String> string,
SloppyTNode<Smi> length,
SloppyTNode<Smi> index,
SloppyTNode<IntPtrT> length,
SloppyTNode<IntPtrT> index,
UnicodeEncoding encoding);
void StringIndexOf(Node* const subject_string, Node* const search_string,
......
This diff is collapsed.
......@@ -536,10 +536,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<Uint32T> LoadNameHash(SloppyTNode<Name> name,
Label* if_hash_not_computed = nullptr);
// Load length field of a String object.
TNode<Smi> LoadStringLength(SloppyTNode<String> object);
// Load length field of a String object as intptr_t value.
TNode<IntPtrT> LoadAndUntagStringLength(SloppyTNode<String> object);
TNode<IntPtrT> LoadStringLengthAsWord(SloppyTNode<String> object);
// Load length field of a String object as Smi value.
TNode<Smi> LoadStringLengthAsSmi(SloppyTNode<String> object);
// Loads a pointer to the sequential String char array.
Node* PointerToSeqStringData(Node* seq_string);
// Load value field of a JSValue object.
......@@ -701,36 +701,36 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
MutableMode mode = IMMUTABLE);
// Allocate a SeqOneByteString with the given length.
Node* AllocateSeqOneByteString(int length, AllocationFlags flags = kNone);
Node* AllocateSeqOneByteString(Node* context, Node* length,
ParameterMode mode = INTPTR_PARAMETERS,
Node* AllocateSeqOneByteString(Node* context, TNode<Smi> length,
AllocationFlags flags = kNone);
// Allocate a SeqTwoByteString with the given length.
Node* AllocateSeqTwoByteString(int length, AllocationFlags flags = kNone);
Node* AllocateSeqTwoByteString(Node* context, Node* length,
ParameterMode mode = INTPTR_PARAMETERS,
Node* AllocateSeqTwoByteString(Node* context, TNode<Smi> length,
AllocationFlags flags = kNone);
// Allocate a SlicedOneByteString with the given length, parent and offset.
// |length| and |offset| are expected to be tagged.
Node* AllocateSlicedOneByteString(Node* length, Node* parent, Node* offset);
Node* AllocateSlicedOneByteString(TNode<Smi> length, Node* parent,
Node* offset);
// Allocate a SlicedTwoByteString with the given length, parent and offset.
// |length| and |offset| are expected to be tagged.
Node* AllocateSlicedTwoByteString(Node* length, Node* parent, Node* offset);
Node* AllocateSlicedTwoByteString(TNode<Smi> length, Node* parent,
Node* 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.
Node* AllocateOneByteConsString(Node* length, Node* first, Node* second,
Node* AllocateOneByteConsString(TNode<Smi> length, Node* first, Node* 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.
Node* AllocateTwoByteConsString(Node* length, Node* first, Node* second,
Node* AllocateTwoByteConsString(TNode<Smi> length, Node* first, Node* second,
AllocationFlags flags = kNone);
// Allocate an appropriate one- or two-byte ConsString with the first and
// second parts specified by |left| and |right|.
Node* NewConsString(Node* context, Node* length, Node* left, Node* right,
Node* NewConsString(Node* context, TNode<Smi> length, Node* left, Node* right,
AllocationFlags flags = kNone);
Node* AllocateNameDictionary(int at_least_space_for);
......@@ -911,15 +911,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// starting at the |from_index|'th character. |from_string| and |to_string|
// can either be one-byte strings or two-byte strings, although if
// |from_string| is two-byte, then |to_string| must be two-byte.
// |from_index|, |to_index| and |character_count| must be either Smis or
// intptr_ts depending on |mode| s.t. 0 <= |from_index| <= |from_index| +
// |character_count| <= from_string.length and 0 <= |to_index| <= |to_index| +
// |character_count| <= to_string.length.
// |from_index|, |to_index| and |character_count| must be intptr_ts s.t. 0 <=
// |from_index| <= |from_index| + |character_count| <= from_string.length and
// 0 <= |to_index| <= |to_index| + |character_count| <= to_string.length.
void CopyStringCharacters(Node* from_string, Node* to_string,
Node* from_index, Node* to_index,
Node* character_count,
TNode<IntPtrT> from_index, TNode<IntPtrT> to_index,
TNode<IntPtrT> character_count,
String::Encoding from_encoding,
String::Encoding to_encoding, ParameterMode mode);
String::Encoding to_encoding);
// Loads an element from |array| of |from_kind| elements by given |offset|
// (NOTE: not index!), does a hole check if |if_hole| is provided and
......@@ -994,7 +993,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Type conversions.
// Throws a TypeError for {method_name} if {value} is not coercible to Object,
// or returns the {value} converted to a String otherwise.
Node* ToThisString(Node* context, Node* value, char const* method_name);
TNode<String> ToThisString(Node* context, Node* value,
char const* method_name);
// Throws a TypeError for {method_name} if {value} is neither of the given
// {primitive_type} nor a JSValue wrapping a value of {primitive_type}, or
// returns the {value} (or wrapped value) otherwise.
......@@ -1132,9 +1132,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// String helpers.
// Load a character from a String (might flatten a ConsString).
TNode<Uint32T> StringCharCodeAt(
SloppyTNode<String> string, Node* index,
ParameterMode parameter_mode = SMI_PARAMETERS);
TNode<Uint32T> StringCharCodeAt(SloppyTNode<String> string,
SloppyTNode<IntPtrT> index);
// Return the single character string with only {code}.
Node* StringFromCharCode(Node* code);
......@@ -1201,7 +1200,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Convert any object to a String.
TNode<String> ToString(SloppyTNode<Context> context,
SloppyTNode<Object> input);
Node* ToString_Inline(Node* const context, Node* const input);
TNode<String> ToString_Inline(SloppyTNode<Context> context,
SloppyTNode<Object> input);
// Convert any object to a Primitive.
Node* JSReceiverToPrimitive(Node* context, Node* input);
......@@ -1818,7 +1818,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Support for printf-style debugging
void Print(const char* s);
void Print(const char* prefix, Node* tagged_value);
inline void Print(Node* tagged_value) { return Print(nullptr, tagged_value); }
inline void Print(SloppyTNode<Object> tagged_value) {
return Print(nullptr, tagged_value);
}
template <class... TArgs>
Node* MakeTypeError(MessageTemplate::Template message, Node* context,
......@@ -1887,11 +1889,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* EmitKeyedSloppyArguments(Node* receiver, Node* key, Node* value,
Label* bailout);
Node* AllocateSlicedString(Heap::RootListIndex map_root_index, Node* length,
Node* parent, Node* offset);
Node* AllocateSlicedString(Heap::RootListIndex map_root_index,
TNode<Smi> length, Node* parent, Node* offset);
Node* AllocateConsString(Heap::RootListIndex map_root_index, Node* length,
Node* first, Node* second, AllocationFlags flags);
Node* AllocateConsString(Heap::RootListIndex map_root_index,
TNode<Smi> length, Node* first, Node* second,
AllocationFlags flags);
// Implements DescriptorArray::number_of_entries.
// Returns an untagged int32.
......@@ -1905,8 +1908,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
void GenerateEqual_Same(Node* value, Label* if_equal, Label* if_notequal,
Variable* var_type_feedback = nullptr);
Node* AllocAndCopyStringCharacters(Node* context, Node* from,
Node* from_instance_type, Node* from_index,
Node* character_count);
Node* from_instance_type,
TNode<IntPtrT> from_index,
TNode<Smi> character_count);
static const int kElementLoopUnrollThreshold = 8;
......
......@@ -894,6 +894,7 @@ class RuntimeCallTimer final {
V(LoadIC_Premonomorphic) \
V(LoadIC_SlowStub) \
V(LoadIC_StringLength) \
V(LoadIC_StringWrapperLength) \
V(StoreIC_HandlerCacheHit_Accessor) \
V(StoreIC_NonReceiver) \
V(StoreIC_Premonomorphic) \
......
......@@ -294,9 +294,9 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
Comment("indexed string");
Node* intptr_index = TryToIntptr(p->name, miss);
Node* length = SmiUntag(LoadStringLength(holder));
Node* length = LoadStringLengthAsWord(holder);
GotoIf(UintPtrGreaterThanOrEqual(intptr_index, length), &if_oob);
Node* code = StringCharCodeAt(holder, intptr_index, INTPTR_PARAMETERS);
Node* code = StringCharCodeAt(holder, intptr_index);
Node* result = StringFromCharCode(code);
Return(result);
......
......@@ -710,16 +710,14 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
Handle<Object> receiver = lookup->GetReceiver();
if (receiver->IsString() &&
*lookup->name() == isolate()->heap()->length_string()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldDH);
FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset,
FieldIndex::kTagged);
return LoadHandler::LoadField(isolate(), index);
TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
return BUILTIN_CODE(isolate(), LoadIC_StringLength);
}
if (receiver->IsStringWrapper() &&
*lookup->name() == isolate()->heap()->length_string()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_StringLength);
return BUILTIN_CODE(isolate(), LoadIC_StringLength);
TRACE_HANDLER_STATS(isolate(), LoadIC_StringWrapperLength);
return BUILTIN_CODE(isolate(), LoadIC_StringWrapperLength);
}
// Use specialized code for getting prototype of functions.
......
......@@ -101,12 +101,12 @@ class StubTester {
FunctionTester tester_;
};
TEST(RunStringLengthStub) {
TEST(RunStringWrapperLengthStub) {
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
StubTester tester(isolate, zone, Builtins::kLoadIC_StringLength);
StubTester tester(isolate, zone, Builtins::kLoadIC_StringWrapperLength);
// Actuall call through to the stub, verifying its result.
const char* testString = "Und das Lamm schrie HURZ!";
......
......@@ -1573,11 +1573,9 @@ TEST(OneToTwoByteStringCopy) {
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeStubAssembler m(asm_tester.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
m.SmiConstant(Smi::FromInt(0)), m.SmiConstant(Smi::FromInt(5)),
String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS);
m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
m.IntPtrConstant(0), m.IntPtrConstant(5),
String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING);
m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
......@@ -1606,11 +1604,9 @@ TEST(OneToOneByteStringCopy) {
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeStubAssembler m(asm_tester.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
m.SmiConstant(Smi::FromInt(0)), m.SmiConstant(Smi::FromInt(5)),
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS);
m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
m.IntPtrConstant(0), m.IntPtrConstant(5),
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING);
m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
......@@ -1639,11 +1635,9 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeStubAssembler m(asm_tester.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
m.SmiConstant(Smi::FromInt(3)), m.SmiConstant(Smi::FromInt(2)),
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS);
m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
m.IntPtrConstant(3), m.IntPtrConstant(2),
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING);
m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
......@@ -1669,11 +1663,9 @@ TEST(TwoToTwoByteStringCopy) {
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeStubAssembler m(asm_tester.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
m.SmiConstant(Smi::FromInt(0)), m.SmiConstant(Smi::FromInt(5)),
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS);
m.CopyStringCharacters(m.Parameter(0), m.Parameter(1), m.IntPtrConstant(0),
m.IntPtrConstant(0), m.IntPtrConstant(5),
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING);
m.Return(m.SmiConstant(Smi::FromInt(0)));
uc16 array1[] = {2000, 2001, 2002, 2003, 2004};
......
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