Commit 9e2fd36c authored by danno's avatar danno Committed by Commit bot

[stubs]: Support 1->2 byte copies in CopyStringCharacters

In the process, add a more general mechanism for passing around
and amending list of CodeStubAssembler Variables. That change
makes it possible to more easily add Variables to loops that are
generated by utility functions, e.g. BuildFastLoop.

LOG=N

Review-Url: https://codereview.chromium.org/2461363002
Cr-Commit-Position: refs/heads/master@{#40700}
parent fe552636
...@@ -2073,47 +2073,66 @@ void CodeStubAssembler::CopyFixedArrayElements( ...@@ -2073,47 +2073,66 @@ void CodeStubAssembler::CopyFixedArrayElements(
Comment("] CopyFixedArrayElements"); Comment("] CopyFixedArrayElements");
} }
void CodeStubAssembler::CopyStringCharacters(compiler::Node* from_string, void CodeStubAssembler::CopyStringCharacters(
compiler::Node* to_string, compiler::Node* from_string, compiler::Node* to_string,
compiler::Node* from_index, compiler::Node* from_index, compiler::Node* to_index,
compiler::Node* to_index, compiler::Node* character_count, String::Encoding from_encoding,
compiler::Node* character_count, String::Encoding to_encoding, ParameterMode mode) {
String::Encoding encoding, bool from_one_byte = from_encoding == String::ONE_BYTE_ENCODING;
ParameterMode mode) { bool to_one_byte = to_encoding == String::ONE_BYTE_ENCODING;
bool one_byte = encoding == String::ONE_BYTE_ENCODING; DCHECK_IMPLIES(to_one_byte, from_one_byte);
Comment(one_byte ? "CopyStringCharacters ONE_BYTE_ENCODING" Comment("CopyStringCharacters %s -> %s",
: "CopyStringCharacters TWO_BYTE_ENCODING"); from_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING",
to_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING");
ElementsKind kind = one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
int header_size = (one_byte ? SeqOneByteString::kHeaderSize ElementsKind from_kind = from_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
: SeqTwoByteString::kHeaderSize) - ElementsKind to_kind = to_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
kHeapObjectTag; STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
Node* from_offset = ElementOffsetFromIndex(from_index, kind, mode); int header_size = SeqOneByteString::kHeaderSize - kHeapObjectTag;
Node* to_offset = ElementOffsetFromIndex(to_index, kind, mode); Node* from_offset =
Node* byte_count = ElementOffsetFromIndex(character_count, kind, mode); ElementOffsetFromIndex(from_index, from_kind, mode, header_size);
Node* to_offset =
ElementOffsetFromIndex(to_index, to_kind, mode, header_size);
Node* byte_count = ElementOffsetFromIndex(character_count, from_kind, mode);
Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count); Node* limit_offset = IntPtrAddFoldConstants(from_offset, byte_count);
// Prepare the fast loop // Prepare the fast loop
MachineType type = one_byte ? MachineType::Uint8() : MachineType::Uint16(); MachineType type =
MachineRepresentation rep = from_one_byte ? MachineType::Uint8() : MachineType::Uint16();
one_byte ? MachineRepresentation::kWord8 : MachineRepresentation::kWord16; MachineRepresentation rep = to_one_byte ? MachineRepresentation::kWord8
int increment = -(1 << ElementsKindToShiftSize(kind)); : MachineRepresentation::kWord16;
int from_increment = 1 << ElementsKindToShiftSize(from_kind);
Node* to_string_adjusted = IntPtrAddFoldConstants( int to_increment = 1 << ElementsKindToShiftSize(to_kind);
to_string, IntPtrSubFoldConstants(to_offset, from_offset));
limit_offset = Variable current_to_offset(this, MachineType::PointerRepresentation());
IntPtrAddFoldConstants(limit_offset, IntPtrConstant(header_size)); VariableList vars({&current_to_offset}, zone());
from_offset = current_to_offset.Bind(to_offset);
IntPtrAddFoldConstants(from_offset, IntPtrConstant(header_size)); int to_index_constant = 0, from_index_constant = 0;
Smi* to_index_smi = nullptr;
BuildFastLoop(MachineType::PointerRepresentation(), limit_offset, from_offset, Smi* from_index_smi = nullptr;
[from_string, to_string_adjusted, type, rep]( bool index_same = (from_encoding == to_encoding) &&
CodeStubAssembler* assembler, Node* offset) { (from_index == to_index ||
(ToInt32Constant(from_index, from_index_constant) &&
ToInt32Constant(to_index, to_index_constant) &&
from_index_constant == to_index_constant) ||
(ToSmiConstant(from_index, from_index_smi) &&
ToSmiConstant(to_index, to_index_smi) &&
to_index_smi == from_index_smi));
BuildFastLoop(vars, MachineType::PointerRepresentation(), from_offset,
limit_offset,
[from_string, to_string, &current_to_offset, to_increment, type,
rep, index_same](CodeStubAssembler* assembler, Node* offset) {
Node* value = assembler->Load(type, from_string, offset); Node* value = assembler->Load(type, from_string, offset);
assembler->StoreNoWriteBarrier(rep, to_string_adjusted, assembler->StoreNoWriteBarrier(
offset, value); rep, to_string,
index_same ? offset : current_to_offset.value(), value);
if (!index_same) {
current_to_offset.Bind(assembler->IntPtrAdd(
current_to_offset.value(),
assembler->IntPtrConstant(to_increment)));
}
}, },
increment); from_increment, IndexAdvanceMode::kPost);
} }
Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array, Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array,
...@@ -2982,6 +3001,7 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, ...@@ -2982,6 +3001,7 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
Node* result = Node* result =
a->AllocateSeqOneByteString(context, a->SmiToWord(character_count)); a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
String::ONE_BYTE_ENCODING,
String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
var_result.Bind(result); var_result.Bind(result);
...@@ -2995,6 +3015,7 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context, ...@@ -2995,6 +3015,7 @@ Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
Node* result = Node* result =
a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count)); a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count));
a->CopyStringCharacters(from, result, from_index, smi_zero, character_count, a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
String::TWO_BYTE_ENCODING,
String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
var_result.Bind(result); var_result.Bind(result);
...@@ -3297,9 +3318,11 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, ...@@ -3297,9 +3318,11 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS); AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS);
CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
SmiConstant(Smi::kZero), left_length, SmiConstant(Smi::kZero), left_length,
String::ONE_BYTE_ENCODING, SMI_PARAMETERS); String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
SMI_PARAMETERS);
CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length, CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), left_length,
right_length, String::ONE_BYTE_ENCODING, SMI_PARAMETERS); right_length, String::ONE_BYTE_ENCODING,
String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
result.Bind(new_string); result.Bind(new_string);
Goto(&done_native); Goto(&done_native);
...@@ -3309,10 +3332,11 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right, ...@@ -3309,10 +3332,11 @@ Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
new_string = AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS); new_string = AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS);
CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero), CopyStringCharacters(left, new_string, SmiConstant(Smi::kZero),
SmiConstant(Smi::kZero), left_length, SmiConstant(Smi::kZero), left_length,
String::TWO_BYTE_ENCODING, SMI_PARAMETERS); String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
SMI_PARAMETERS);
CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero), CopyStringCharacters(right, new_string, SmiConstant(Smi::kZero),
left_length, right_length, String::TWO_BYTE_ENCODING, left_length, right_length, String::TWO_BYTE_ENCODING,
SMI_PARAMETERS); String::TWO_BYTE_ENCODING, SMI_PARAMETERS);
result.Bind(new_string); result.Bind(new_string);
Goto(&done_native); Goto(&done_native);
} }
...@@ -6964,12 +6988,15 @@ Node* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector, ...@@ -6964,12 +6988,15 @@ Node* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector,
} }
void CodeStubAssembler::BuildFastLoop( void CodeStubAssembler::BuildFastLoop(
const CodeStubAssembler::VariableList& vars,
MachineRepresentation index_rep, Node* start_index, Node* end_index, MachineRepresentation index_rep, Node* start_index, Node* end_index,
std::function<void(CodeStubAssembler* assembler, Node* index)> body, std::function<void(CodeStubAssembler* assembler, Node* index)> body,
int increment, IndexAdvanceMode mode) { int increment, IndexAdvanceMode mode) {
Variable var(this, index_rep); Variable var(this, index_rep);
VariableList vars_copy(vars, zone());
vars_copy.Add(&var, zone());
var.Bind(start_index); var.Bind(start_index);
Label loop(this, &var); Label loop(this, vars_copy);
Label after_loop(this); Label after_loop(this);
// Introduce an explicit second check of the termination condition before the // Introduce an explicit second check of the termination condition before the
// loop that helps turbofan generate better code. If there's only a single // loop that helps turbofan generate better code. If there's only a single
......
...@@ -518,7 +518,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -518,7 +518,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Copies |character_count| elements from |from_string| to |to_string| // Copies |character_count| elements from |from_string| to |to_string|
// starting at the |from_index|'th character. |from_string| and |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. // 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 // |from_index|, |to_index| and |character_count| must be either Smis or
// intptr_ts depending on |mode| s.t. 0 <= |from_index| <= |from_index| + // 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| <= from_string.length and 0 <= |to_index| <= |to_index| +
...@@ -528,7 +529,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -528,7 +529,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* from_index, compiler::Node* from_index,
compiler::Node* to_index, compiler::Node* to_index,
compiler::Node* character_count, compiler::Node* character_count,
String::Encoding encoding, ParameterMode mode); String::Encoding from_encoding,
String::Encoding to_encoding, ParameterMode mode);
// Loads an element from |array| of |from_kind| elements by given |offset| // 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 // (NOTE: not index!), does a hole check if |if_hole| is provided and
...@@ -1022,12 +1024,22 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1022,12 +1024,22 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
enum class IndexAdvanceMode { kPre, kPost }; enum class IndexAdvanceMode { kPre, kPost };
void BuildFastLoop(
const VariableList& var_list, MachineRepresentation index_rep,
compiler::Node* start_index, compiler::Node* end_index,
std::function<void(CodeStubAssembler* assembler, compiler::Node* index)>
body,
int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre);
void BuildFastLoop( void BuildFastLoop(
MachineRepresentation index_rep, compiler::Node* start_index, MachineRepresentation index_rep, compiler::Node* start_index,
compiler::Node* end_index, compiler::Node* end_index,
std::function<void(CodeStubAssembler* assembler, compiler::Node* index)> std::function<void(CodeStubAssembler* assembler, compiler::Node* index)>
body, body,
int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre); int increment, IndexAdvanceMode mode = IndexAdvanceMode::kPre) {
BuildFastLoop(VariableList(0, zone()), index_rep, start_index, end_index,
body, increment, mode);
}
enum class ForEachDirection { kForward, kReverse }; enum class ForEachDirection { kForward, kReverse };
......
...@@ -1066,16 +1066,15 @@ bool CodeAssembler::Variable::IsBound() const { ...@@ -1066,16 +1066,15 @@ bool CodeAssembler::Variable::IsBound() const {
return impl_->value_ != nullptr; return impl_->value_ != nullptr;
} }
CodeAssembler::Label::Label(CodeAssembler* assembler, int merged_value_count, CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
CodeAssembler::Variable** merged_variables, Variable** vars, CodeAssembler::Label::Type type)
CodeAssembler::Label::Type type)
: bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) { : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
void* buffer = assembler->zone()->New(sizeof(RawMachineLabel)); void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
label_ = new (buffer) label_ = new (buffer)
RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
: RawMachineLabel::kNonDeferred); : RawMachineLabel::kNonDeferred);
for (int i = 0; i < merged_value_count; ++i) { for (size_t i = 0; i < vars_count; ++i) {
variable_phis_[merged_variables[i]->impl_] = nullptr; variable_phis_[vars[i]->impl_] = nullptr;
} }
} }
......
...@@ -212,6 +212,8 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -212,6 +212,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
CodeAssembler* assembler_; CodeAssembler* assembler_;
}; };
typedef ZoneList<Variable*> VariableList;
// =========================================================================== // ===========================================================================
// Base Assembler // Base Assembler
// =========================================================================== // ===========================================================================
...@@ -492,12 +494,15 @@ class CodeAssembler::Label { ...@@ -492,12 +494,15 @@ class CodeAssembler::Label {
CodeAssembler* assembler, CodeAssembler* assembler,
CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred) CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
: CodeAssembler::Label(assembler, 0, nullptr, type) {} : CodeAssembler::Label(assembler, 0, nullptr, type) {}
Label(CodeAssembler* assembler, CodeAssembler::Variable* merged_variable, Label(CodeAssembler* assembler, const VariableList& merged_variables,
CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred) CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
: CodeAssembler::Label(assembler, 1, &merged_variable, type) {} : CodeAssembler::Label(assembler, merged_variables.length(),
Label(CodeAssembler* assembler, int merged_variable_count, &(merged_variables[0]), type) {}
CodeAssembler::Variable** merged_variables, Label(CodeAssembler* assembler, size_t count, Variable** vars,
CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred); CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred);
Label(CodeAssembler* assembler, CodeAssembler::Variable* merged_variable,
CodeAssembler::Label::Type type = CodeAssembler::Label::kNonDeferred)
: Label(assembler, 1, &merged_variable, type) {}
~Label() {} ~Label() {}
private: private:
......
...@@ -160,6 +160,13 @@ class ZoneList final : public List<T, ZoneAllocationPolicy> { ...@@ -160,6 +160,13 @@ class ZoneList final : public List<T, ZoneAllocationPolicy> {
ZoneList(int capacity, Zone* zone) ZoneList(int capacity, Zone* zone)
: List<T, ZoneAllocationPolicy>(capacity, ZoneAllocationPolicy(zone)) {} : List<T, ZoneAllocationPolicy>(capacity, ZoneAllocationPolicy(zone)) {}
// Construct a new ZoneList from a std::initializer_list
ZoneList(std::initializer_list<T> list, Zone* zone)
: List<T, ZoneAllocationPolicy>(static_cast<int>(list.size()),
ZoneAllocationPolicy(zone)) {
for (auto& i : list) Add(i, zone);
}
void* operator new(size_t size, Zone* zone) { return zone->New(size); } void* operator new(size_t size, Zone* zone) { return zone->New(size); }
// Construct a new ZoneList by copying the elements of the given ZoneList. // Construct a new ZoneList by copying the elements of the given ZoneList.
......
...@@ -1785,5 +1785,141 @@ TEST(PopAndReturnVariable) { ...@@ -1785,5 +1785,141 @@ TEST(PopAndReturnVariable) {
} }
} }
TEST(OneToTwoByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2);
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.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode();
CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
uc16 array[] = {1000, 1001, 1002, 1003, 1004};
Vector<const uc16> str(array);
Handle<String> string2 =
isolate->factory()->NewStringFromTwoByte(str).ToHandleChecked();
FunctionTester ft(code, 2);
ft.Call(string1, string2);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[0],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[1],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[1]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[2],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[2]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[3],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[3]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[4],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[4]);
}
TEST(OneToOneByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2);
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.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode();
CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
uint8_t array[] = {100, 101, 102, 103, 104};
Vector<const uint8_t> str(array);
Handle<String> string2 =
isolate->factory()->NewStringFromOneByte(str).ToHandleChecked();
FunctionTester ft(code, 2);
ft.Call(string1, string2);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[0],
Handle<SeqOneByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[1],
Handle<SeqOneByteString>::cast(string2)->GetChars()[1]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[2],
Handle<SeqOneByteString>::cast(string2)->GetChars()[2]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[3],
Handle<SeqOneByteString>::cast(string2)->GetChars()[3]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[4],
Handle<SeqOneByteString>::cast(string2)->GetChars()[4]);
}
TEST(OneToOneByteStringCopyNonZeroStart) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2);
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.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode();
CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
uint8_t array[] = {100, 101, 102, 103, 104};
Vector<const uint8_t> str(array);
Handle<String> string2 =
isolate->factory()->NewStringFromOneByte(str).ToHandleChecked();
FunctionTester ft(code, 2);
ft.Call(string1, string2);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[0],
Handle<SeqOneByteString>::cast(string2)->GetChars()[3]);
CHECK_EQ(Handle<SeqOneByteString>::cast(string1)->GetChars()[1],
Handle<SeqOneByteString>::cast(string2)->GetChars()[4]);
CHECK_EQ(100, Handle<SeqOneByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(101, Handle<SeqOneByteString>::cast(string2)->GetChars()[1]);
CHECK_EQ(102, Handle<SeqOneByteString>::cast(string2)->GetChars()[2]);
}
TEST(TwoToTwoByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2);
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.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode();
CHECK(!code.is_null());
uc16 array1[] = {2000, 2001, 2002, 2003, 2004};
Vector<const uc16> str1(array1);
Handle<String> string1 =
isolate->factory()->NewStringFromTwoByte(str1).ToHandleChecked();
uc16 array2[] = {1000, 1001, 1002, 1003, 1004};
Vector<const uc16> str2(array2);
Handle<String> string2 =
isolate->factory()->NewStringFromTwoByte(str2).ToHandleChecked();
FunctionTester ft(code, 2);
ft.Call(string1, string2);
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[0],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[0]);
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[1],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[1]);
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[2],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[2]);
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[3],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[3]);
CHECK_EQ(Handle<SeqTwoByteString>::cast(string1)->GetChars()[4],
Handle<SeqTwoByteString>::cast(string2)->GetChars()[4]);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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