Add full TurboFan support for accessing SeqString contents.

LOG=n

Review URL: https://codereview.chromium.org/1013753016

Cr-Commit-Position: refs/heads/master@{#27465}
This commit is contained in:
svenpanne 2015-03-26 01:36:28 -07:00 committed by Commit bot
parent 46cc8740a9
commit 4518e92706
7 changed files with 150 additions and 0 deletions

View File

@ -116,6 +116,21 @@ ElementAccess AccessBuilder::ForTypedArrayElement(ExternalArrayType type,
return {kUntaggedBase, 0, Type::None(), kMachNone};
}
// static
ElementAccess AccessBuilder::ForSeqStringChar(String::Encoding encoding) {
switch (encoding) {
case String::ONE_BYTE_ENCODING:
return {kTaggedBase, SeqString::kHeaderSize, Type::Unsigned32(),
kMachUint8};
case String::TWO_BYTE_ENCODING:
return {kTaggedBase, SeqString::kHeaderSize, Type::Unsigned32(),
kMachUint16};
}
UNREACHABLE();
return {kUntaggedBase, 0, Type::None(), kMachNone};
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -53,6 +53,9 @@ class AccessBuilder FINAL : public AllStatic {
static ElementAccess ForTypedArrayElement(ExternalArrayType type,
bool is_external);
// Provides access to the charaters of sequential strings.
static ElementAccess ForSeqStringChar(String::Encoding encoding);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
};

View File

@ -53,8 +53,16 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceMathFloor(node);
case Runtime::kInlineMathSqrt:
return ReduceMathSqrt(node);
case Runtime::kInlineOneByteSeqStringGetChar:
return ReduceSeqStringGetChar(node, String::ONE_BYTE_ENCODING);
case Runtime::kInlineOneByteSeqStringSetChar:
return ReduceSeqStringSetChar(node, String::ONE_BYTE_ENCODING);
case Runtime::kInlineStringGetLength:
return ReduceStringGetLength(node);
case Runtime::kInlineTwoByteSeqStringGetChar:
return ReduceSeqStringGetChar(node, String::TWO_BYTE_ENCODING);
case Runtime::kInlineTwoByteSeqStringSetChar:
return ReduceSeqStringSetChar(node, String::TWO_BYTE_ENCODING);
case Runtime::kInlineValueOf:
return ReduceValueOf(node);
default:
@ -221,6 +229,42 @@ Reduction JSIntrinsicLowering::ReduceMathSqrt(Node* node) {
}
Reduction JSIntrinsicLowering::ReduceSeqStringGetChar(
Node* node, String::Encoding encoding) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
node->set_op(
simplified()->LoadElement(AccessBuilder::ForSeqStringChar(encoding)));
node->ReplaceInput(2, effect);
node->ReplaceInput(3, control);
node->TrimInputCount(4);
NodeProperties::ReplaceWithValue(node, node, node);
return Changed(node);
}
Reduction JSIntrinsicLowering::ReduceSeqStringSetChar(
Node* node, String::Encoding encoding) {
// Note: The intrinsic has a strange argument order, so we need to reshuffle.
Node* index = NodeProperties::GetValueInput(node, 0);
Node* chr = NodeProperties::GetValueInput(node, 1);
Node* string = NodeProperties::GetValueInput(node, 2);
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
node->set_op(
simplified()->StoreElement(AccessBuilder::ForSeqStringChar(encoding)));
node->ReplaceInput(0, string);
node->ReplaceInput(1, index);
node->ReplaceInput(2, chr);
node->ReplaceInput(3, effect);
node->ReplaceInput(4, control);
node->TrimInputCount(5);
NodeProperties::RemoveBounds(node);
NodeProperties::ReplaceWithValue(node, string, node);
return Changed(node);
}
Reduction JSIntrinsicLowering::ReduceStringGetLength(Node* node) {
Node* value = NodeProperties::GetValueInput(node, 0);
Node* effect = NodeProperties::GetEffectInput(node);

View File

@ -40,6 +40,8 @@ class JSIntrinsicLowering FINAL : public Reducer {
Reduction ReduceMathClz32(Node* node);
Reduction ReduceMathFloor(Node* node);
Reduction ReduceMathSqrt(Node* node);
Reduction ReduceSeqStringGetChar(Node* node, String::Encoding encoding);
Reduction ReduceSeqStringSetChar(Node* node, String::Encoding encoding);
Reduction ReduceStringGetLength(Node* node);
Reduction ReduceValueOf(Node* node);

View File

@ -1265,6 +1265,15 @@ RUNTIME_FUNCTION(Runtime_StringCharAt) {
}
RUNTIME_FUNCTION(Runtime_OneByteSeqStringGetChar) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_CHECKED(SeqOneByteString, string, 0);
CONVERT_INT32_ARG_CHECKED(index, 1);
return Smi::FromInt(string->SeqOneByteStringGet(index));
}
RUNTIME_FUNCTION(Runtime_OneByteSeqStringSetChar) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 3);
@ -1276,6 +1285,15 @@ RUNTIME_FUNCTION(Runtime_OneByteSeqStringSetChar) {
}
RUNTIME_FUNCTION(Runtime_TwoByteSeqStringGetChar) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_CHECKED(SeqTwoByteString, string, 0);
CONVERT_INT32_ARG_CHECKED(index, 1);
return Smi::FromInt(string->SeqTwoByteStringGet(index));
}
RUNTIME_FUNCTION(Runtime_TwoByteSeqStringSetChar) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 3);

View File

@ -646,7 +646,9 @@ namespace internal {
F(DateField, 2 /* date object, field index */, 1) \
F(StringCharFromCode, 1, 1) \
F(StringCharAt, 2, 1) \
F(OneByteSeqStringGetChar, 2, 1) \
F(OneByteSeqStringSetChar, 3, 1) \
F(TwoByteSeqStringGetChar, 2, 1) \
F(TwoByteSeqStringSetChar, 3, 1) \
F(ObjectEquals, 2, 1) \
F(IsObject, 1, 1) \

View File

@ -176,6 +176,39 @@ TEST(ObjectEquals) {
}
TEST(OneByteSeqStringGetChar) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_OneByteSeqStringGetChar(a,b); })",
flags);
Handle<SeqOneByteString> string =
T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
string->SeqOneByteStringSet(0, 'b');
string->SeqOneByteStringSet(1, 'a');
string->SeqOneByteStringSet(2, 'r');
T.CheckCall(T.Val('b'), string, T.Val(0.0));
T.CheckCall(T.Val('a'), string, T.Val(1));
T.CheckCall(T.Val('r'), string, T.Val(2));
}
TEST(OneByteSeqStringSetChar) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { %_OneByteSeqStringSetChar(a,88,b); })",
flags);
Handle<SeqOneByteString> string =
T.main_isolate()->factory()->NewRawOneByteString(3).ToHandleChecked();
string->SeqOneByteStringSet(0, 'b');
string->SeqOneByteStringSet(1, 'a');
string->SeqOneByteStringSet(2, 'r');
T.Call(T.Val(1), string);
CHECK_EQ('b', string->SeqOneByteStringGet(0));
CHECK_EQ('X', string->SeqOneByteStringGet(1));
CHECK_EQ('r', string->SeqOneByteStringGet(2));
}
TEST(SetValueOf) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_SetValueOf(a,b); })", flags);
@ -247,6 +280,39 @@ TEST(SubString) {
}
TEST(TwoByteSeqStringGetChar) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { return %_TwoByteSeqStringGetChar(a,b); })",
flags);
Handle<SeqTwoByteString> string =
T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
string->SeqTwoByteStringSet(0, 'b');
string->SeqTwoByteStringSet(1, 'a');
string->SeqTwoByteStringSet(2, 'r');
T.CheckCall(T.Val('b'), string, T.Val(0.0));
T.CheckCall(T.Val('a'), string, T.Val(1));
T.CheckCall(T.Val('r'), string, T.Val(2));
}
TEST(TwoByteSeqStringSetChar) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a,b) { %_TwoByteSeqStringSetChar(a,88,b); })",
flags);
Handle<SeqTwoByteString> string =
T.main_isolate()->factory()->NewRawTwoByteString(3).ToHandleChecked();
string->SeqTwoByteStringSet(0, 'b');
string->SeqTwoByteStringSet(1, 'a');
string->SeqTwoByteStringSet(2, 'r');
T.Call(T.Val(1), string);
CHECK_EQ('b', string->SeqTwoByteStringGet(0));
CHECK_EQ('X', string->SeqTwoByteStringGet(1));
CHECK_EQ('r', string->SeqTwoByteStringGet(2));
}
TEST(ValueOf) {
FLAG_turbo_deoptimization = true;
FunctionTester T("(function(a) { return %_ValueOf(a); })", flags);