Commit 787157dd authored by danno's avatar danno Committed by Commit bot

[stubs] Port StringAddStub to TF

In the process:
- Add ToString to the CodeStubAssembler and use it where appropriate
- Add constant-folding versions of IntPtrAdd/IntPtrSub to simplify code
  in element offset computation, especially for strings.

BUG=chromium:608675
LOG=N

Review-Url: https://codereview.chromium.org/2407813002
Cr-Commit-Position: refs/heads/master@{#40379}
parent 34fa66c0
......@@ -183,11 +183,7 @@ void Builtins::Generate_ToString(CodeStubAssembler* assembler) {
}
assembler->Bind(&is_number);
{
// TODO(tebbi): inline as soon as NumberToString is in the CodeStubAssembler
Callable callable = CodeFactory::NumberToString(assembler->isolate());
assembler->Return(assembler->CallStub(callable, context, input));
}
{ assembler->Return(assembler->NumberToString(context, input)); }
assembler->Bind(&not_heap_number);
{
......
......@@ -1530,7 +1530,7 @@ compiler::Node* ReplaceFastPath(CodeStubAssembler* a, compiler::Node* context,
Node* const second_part =
a->SubString(context, subject_string, match_end, subject_end);
Node* const result = a->StringConcat(context, first_part, second_part);
Node* const result = a->StringAdd(context, first_part, second_part);
var_result.Bind(result);
a->Goto(&out);
}
......@@ -1543,8 +1543,8 @@ compiler::Node* ReplaceFastPath(CodeStubAssembler* a, compiler::Node* context,
Node* const third_part =
a->SubString(context, subject_string, match_end, subject_end);
Node* result = a->StringConcat(context, first_part, second_part);
result = a->StringConcat(context, result, third_part);
Node* result = a->StringAdd(context, first_part, second_part);
result = a->StringAdd(context, result, third_part);
var_result.Bind(result);
a->Goto(&out);
......
This diff is collapsed.
......@@ -104,6 +104,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* IntPtrOrSmiConstant(int value, ParameterMode mode);
compiler::Node* IntPtrAddFoldConstants(compiler::Node* left,
compiler::Node* right);
compiler::Node* IntPtrSubFoldConstants(compiler::Node* left,
compiler::Node* right);
// Float64 operations.
compiler::Node* Float64Ceil(compiler::Node* x);
compiler::Node* Float64Floor(compiler::Node* x);
......@@ -351,13 +356,17 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* AllocateHeapNumberWithValue(compiler::Node* value,
MutableMode mode = IMMUTABLE);
// Allocate a SeqOneByteString with the given length.
compiler::Node* AllocateSeqOneByteString(int length);
compiler::Node* AllocateSeqOneByteString(compiler::Node* context,
compiler::Node* length);
compiler::Node* AllocateSeqOneByteString(int length,
AllocationFlags flags = kNone);
compiler::Node* AllocateSeqOneByteString(
compiler::Node* context, compiler::Node* length,
ParameterMode mode = INTPTR_PARAMETERS, AllocationFlags flags = kNone);
// Allocate a SeqTwoByteString with the given length.
compiler::Node* AllocateSeqTwoByteString(int length);
compiler::Node* AllocateSeqTwoByteString(compiler::Node* context,
compiler::Node* length);
compiler::Node* AllocateSeqTwoByteString(int length,
AllocationFlags flags = kNone);
compiler::Node* AllocateSeqTwoByteString(
compiler::Node* context, compiler::Node* length,
ParameterMode mode = INTPTR_PARAMETERS, AllocationFlags flags = kNone);
// Allocate a SlicedOneByteString with the given length, parent and offset.
// |length| and |offset| are expected to be tagged.
......@@ -375,13 +384,21 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// expected to be one-byte strings.
compiler::Node* AllocateOneByteConsString(compiler::Node* length,
compiler::Node* first,
compiler::Node* second);
compiler::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.
compiler::Node* AllocateTwoByteConsString(compiler::Node* length,
compiler::Node* first,
compiler::Node* second);
compiler::Node* second,
AllocationFlags flags = kNone);
// Allocate an appropriate one- or two-byte ConsString with the first and
// second parts specified by |first| and |second|.
compiler::Node* NewConsString(compiler::Node* context, compiler::Node* length,
compiler::Node* left, compiler::Node* right,
AllocationFlags flags = kNone);
// Allocate a RegExpResult with the given length (the number of captures,
// including the match itself), index (the index where the match starts),
......@@ -456,16 +473,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Copies |character_count| elements from |from_string| to |to_string|
// starting at the |from_index|'th character. |from_string| and |to_string|
// must be either both one-byte strings or both two-byte strings.
// |from_index|, |to_index| and |character_count| must be Smis 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 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.
void CopyStringCharacters(compiler::Node* from_string,
compiler::Node* to_string,
compiler::Node* from_index,
compiler::Node* to_index,
compiler::Node* character_count,
String::Encoding encoding);
String::Encoding encoding, ParameterMode mode);
// 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
......@@ -555,8 +572,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* from, compiler::Node* to);
// Return a new string object produced by concatenating |first| with |second|.
compiler::Node* StringConcat(compiler::Node* context, compiler::Node* first,
compiler::Node* second);
compiler::Node* StringAdd(compiler::Node* context, compiler::Node* first,
compiler::Node* second,
AllocationFlags flags = kNone);
// Return the first index >= {from} at which {needle_char} was found in
// {string}, or -1 if such an index does not exist. The returned value is
......@@ -584,6 +602,13 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Convert any object to a Number.
compiler::Node* ToNumber(compiler::Node* context, compiler::Node* input);
// Convert any object to a String.
compiler::Node* ToString(compiler::Node* context, compiler::Node* input);
// Convert any object to a Primitive.
compiler::Node* JSReceiverToPrimitive(compiler::Node* context,
compiler::Node* input);
enum ToIntegerTruncationMode {
kNoTruncation,
kTruncateMinusZero,
......@@ -910,10 +935,16 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
ParameterMode mode = INTPTR_PARAMETERS,
ForEachDirection direction = ForEachDirection::kReverse);
compiler::Node* GetArrayAllocationSize(compiler::Node* element_count,
ElementsKind kind, ParameterMode mode,
int header_size) {
return ElementOffsetFromIndex(element_count, kind, mode, header_size);
}
compiler::Node* GetFixedArrayAllocationSize(compiler::Node* element_count,
ElementsKind kind,
ParameterMode mode) {
return ElementOffsetFromIndex(element_count, kind, mode,
return GetArrayAllocationSize(element_count, kind, mode,
FixedArray::kHeaderSize);
}
......
......@@ -1120,34 +1120,6 @@ HValue* CodeStubGraphBuilderBase::BuildToPrimitive(HValue* input,
return Pop();
}
template <>
HValue* CodeStubGraphBuilder<StringAddStub>::BuildCodeInitializedStub() {
StringAddStub* stub = casted_stub();
StringAddFlags flags = stub->flags();
PretenureFlag pretenure_flag = stub->pretenure_flag();
HValue* left = GetParameter(Descriptor::kLeft);
HValue* right = GetParameter(Descriptor::kRight);
// Make sure that both arguments are strings if not known in advance.
if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
left =
BuildToString(left, (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT);
}
if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
right = BuildToString(right,
(flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT);
}
return BuildStringAdd(left, right, HAllocationMode(pretenure_flag));
}
Handle<Code> StringAddStub::GenerateCode() {
return DoGenerateCode(this);
}
template <>
HValue* CodeStubGraphBuilder<ToBooleanICStub>::BuildCodeInitializedStub() {
ToBooleanICStub* stub = casted_stub();
......
......@@ -345,6 +345,38 @@ void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT
os << "StringAddStub_" << flags() << "_" << pretenure_flag();
}
void StringAddStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
Node* left = assembler->Parameter(Descriptor::kLeft);
Node* right = assembler->Parameter(Descriptor::kRight);
Node* context = assembler->Parameter(Descriptor::kContext);
if ((flags() & STRING_ADD_CHECK_LEFT) != 0) {
DCHECK((flags() & STRING_ADD_CONVERT) != 0);
// TODO(danno): The ToString and JSReceiverToPrimitive below could be
// combined to avoid duplicate smi and instance type checks.
left = assembler->ToString(context,
assembler->JSReceiverToPrimitive(context, left));
}
if ((flags() & STRING_ADD_CHECK_RIGHT) != 0) {
DCHECK((flags() & STRING_ADD_CONVERT) != 0);
// TODO(danno): The ToString and JSReceiverToPrimitive below could be
// combined to avoid duplicate smi and instance type checks.
right = assembler->ToString(
context, assembler->JSReceiverToPrimitive(context, right));
}
if ((flags() & STRING_ADD_CHECK_BOTH) == 0) {
CodeStubAssembler::AllocationFlag flags =
(pretenure_flag() == TENURED) ? CodeStubAssembler::kPretenured
: CodeStubAssembler::kNone;
assembler->Return(assembler->StringAdd(context, left, right, flags));
} else {
Callable callable = CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE,
pretenure_flag());
assembler->TailCallStub(callable, context, left, right);
}
}
InlineCacheState CompareICStub::GetICState() const {
CompareICState::State state = Max(left(), right());
......@@ -2167,13 +2199,6 @@ void BinaryOpWithAllocationSiteStub::InitializeDescriptor(
FUNCTION_ADDR(Runtime_BinaryOpIC_MissWithAllocationSite));
}
void StringAddStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
descriptor->Initialize(Runtime::FunctionForId(Runtime::kStringAdd)->entry);
descriptor->SetMissHandler(Runtime::kStringAdd);
}
void GetPropertyStub::GenerateAssembly(CodeStubAssembler* assembler) const {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
......
......@@ -60,7 +60,6 @@ class ObjectLiteral;
V(CallICTrampoline) \
V(KeyedStoreICTrampoline) \
/* --- HydrogenCodeStubs --- */ \
V(StringAdd) \
/* These builtins w/ JS linkage are */ \
/* just fast-cases of C++ builtins. They */ \
/* require varg support from TF */ \
......@@ -119,6 +118,7 @@ class ObjectLiteral;
V(LoadScriptContextField) \
V(StoreScriptContextField) \
V(NumberToString) \
V(StringAdd) \
V(GetProperty) \
V(LoadIC) \
V(KeyedLoadICTF) \
......@@ -1610,22 +1610,21 @@ class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
};
class StringAddStub final : public HydrogenCodeStub {
class StringAddStub final : public TurboFanCodeStub {
public:
StringAddStub(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag)
: HydrogenCodeStub(isolate) {
set_sub_minor_key(StringAddFlagsBits::encode(flags) |
PretenureFlagBits::encode(pretenure_flag));
: TurboFanCodeStub(isolate) {
minor_key_ = (StringAddFlagsBits::encode(flags) |
PretenureFlagBits::encode(pretenure_flag));
}
StringAddFlags flags() const {
return StringAddFlagsBits::decode(sub_minor_key());
return StringAddFlagsBits::decode(minor_key_);
}
PretenureFlag pretenure_flag() const {
return PretenureFlagBits::decode(sub_minor_key());
return PretenureFlagBits::decode(minor_key_);
}
private:
......@@ -1635,7 +1634,7 @@ class StringAddStub final : public HydrogenCodeStub {
void PrintBaseName(std::ostream& os) const override; // NOLINT
DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub);
};
......
......@@ -148,6 +148,20 @@ bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
return m.HasValue();
}
bool CodeAssembler::ToSmiConstant(Node* node, Smi*& out_value) {
if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
node = node->InputAt(0);
} else {
return false;
}
IntPtrMatcher m(node);
if (m.HasValue()) {
out_value = Smi::cast(bit_cast<Object*>(m.Value()));
return true;
}
return false;
}
bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
IntPtrMatcher m(node);
if (m.HasValue()) out_value = m.Value();
......
......@@ -229,6 +229,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool ToInt32Constant(Node* node, int32_t& out_value);
bool ToInt64Constant(Node* node, int64_t& out_value);
bool ToSmiConstant(Node* node, Smi*& out_value);
bool ToIntPtrConstant(Node* node, intptr_t& out_value);
Node* Parameter(int value);
......
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