From: bmeurer@chromium.org Date: Wed, 6 Nov 2013 13:09:22 +0000 (+0000) Subject: Improve implementation of HSeqStringSetChar. X-Git-Tag: upstream/4.7.83~11872 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=980739a29c2752386dbe986e9e8cb84657094163;p=platform%2Fupstream%2Fv8.git Improve implementation of HSeqStringSetChar. This improves the generated code for HSeqStringSetChar across all platforms, taking advantage of constant operands whenever possible. It also drops the unused DefineSameAsFirst constraint for the register allocator on x64 and ia32, where it caused unnecessary spills when the string operand was live across the HSeqStringSetChar instruction. A new GVN flag StringChars is introduced to express dependencies between HSeqStringSetChar, HStringCharCodeAt and the upcoming HSeqStringGetChar (the GVNFlags type is now 64bit in size). Also improves the test case. TEST=mjsunit/string-natives R=mstarzinger@chromium.org, yangguo@chromium.org Review URL: https://codereview.chromium.org/57383004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17521 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 86d5d2b..d7ce853 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1888,7 +1888,7 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { LOperand* string = UseRegister(instr->string()); LOperand* index = UseRegisterOrConstant(instr->index()); LOperand* value = UseRegister(instr->value()); - return new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); + return new(zone()) LSeqStringSetChar(string, index, value); } diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index ed07229..3827ab3 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -1362,25 +1362,20 @@ class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 1> { class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> { public: - LSeqStringSetChar(String::Encoding encoding, - LOperand* string, + LSeqStringSetChar(LOperand* string, LOperand* index, - LOperand* value) : encoding_(encoding) { + LOperand* value) { inputs_[0] = string; inputs_[1] = index; inputs_[2] = value; } - String::Encoding encoding() { return encoding_; } LOperand* string() { return inputs_[0]; } LOperand* index() { return inputs_[1]; } LOperand* value() { return inputs_[2]; } DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char") DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar) - - private: - String::Encoding encoding_; }; diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index fbe8e17..8eca27d 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1924,14 +1924,37 @@ void LCodeGen::DoDateField(LDateField* instr) { } +MemOperand LCodeGen::BuildSeqStringOperand(Register string, + LOperand* index, + String::Encoding encoding) { + if (index->IsConstantOperand()) { + int offset = ToInteger32(LConstantOperand::cast(index)); + if (encoding == String::TWO_BYTE_ENCODING) { + offset *= kUC16Size; + } + STATIC_ASSERT(kCharSize == 1); + return FieldMemOperand(string, SeqString::kHeaderSize + offset); + } + Register scratch = scratch0(); + ASSERT(!scratch.is(string)); + ASSERT(!scratch.is(ToRegister(index))); + if (encoding == String::ONE_BYTE_ENCODING) { + __ add(scratch, string, Operand(ToRegister(index))); + } else { + STATIC_ASSERT(kUC16Size == 2); + __ add(scratch, string, Operand(ToRegister(index), LSL, 1)); + } + return FieldMemOperand(scratch, SeqString::kHeaderSize); +} + + void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { + String::Encoding encoding = instr->hydrogen()->encoding(); Register string = ToRegister(instr->string()); - LOperand* index_op = instr->index(); Register value = ToRegister(instr->value()); - Register scratch = scratch0(); - String::Encoding encoding = instr->encoding(); if (FLAG_debug_code) { + Register scratch = scratch0(); __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); @@ -1944,24 +1967,11 @@ void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { __ Check(eq, kUnexpectedStringType); } - if (index_op->IsConstantOperand()) { - int constant_index = ToInteger32(LConstantOperand::cast(index_op)); - if (encoding == String::ONE_BYTE_ENCODING) { - __ strb(value, - FieldMemOperand(string, SeqString::kHeaderSize + constant_index)); - } else { - __ strh(value, - FieldMemOperand(string, SeqString::kHeaderSize + constant_index * 2)); - } + MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); + if (encoding == String::ONE_BYTE_ENCODING) { + __ strb(value, operand); } else { - Register index = ToRegister(index_op); - if (encoding == String::ONE_BYTE_ENCODING) { - __ add(scratch, string, Operand(index)); - __ strb(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); - } else { - __ add(scratch, string, Operand(index, LSL, 1)); - __ strh(value, FieldMemOperand(scratch, SeqString::kHeaderSize)); - } + __ strh(value, operand); } } diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index a9b85c8..cbd6b9c 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -273,6 +273,10 @@ class LCodeGen: public LCodeGenBase { Register ToRegister(int index) const; DwVfpRegister ToDoubleRegister(int index) const; + MemOperand BuildSeqStringOperand(Register string, + LOperand* index, + String::Encoding encoding); + void EmitIntegerMathAbs(LMathAbs* instr); // Support for recording safepoint and position information. diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 80773bf..66050f1 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -208,7 +208,8 @@ class LChunkBuilder; V(GlobalVars) \ V(InobjectFields) \ V(OsrEntries) \ - V(ExternalMemory) + V(ExternalMemory) \ + V(StringChars) #define DECLARE_ABSTRACT_INSTRUCTION(type) \ @@ -542,7 +543,7 @@ class DecompositionResult V8_FINAL BASE_EMBEDDED { }; -typedef EnumSet GVNFlagSet; +typedef EnumSet GVNFlagSet; class HValue : public ZoneObject { @@ -6750,6 +6751,7 @@ class HStringCharCodeAt V8_FINAL : public HTemplateInstruction<3> { set_representation(Representation::Integer32()); SetFlag(kUseGVN); SetGVNFlag(kDependsOnMaps); + SetGVNFlag(kDependsOnStringChars); SetGVNFlag(kChangesNewSpacePromotion); } @@ -7047,6 +7049,7 @@ class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<3> { SetOperandAt(1, index); SetOperandAt(2, value); set_representation(Representation::Tagged()); + SetGVNFlag(kChangesStringChars); } String::Encoding encoding_; diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index 40345d8..24c6b92 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -553,6 +553,16 @@ void Assembler::mov_w(const Operand& dst, Register src) { } +void Assembler::mov_w(const Operand& dst, int16_t imm16) { + EnsureSpace ensure_space(this); + EMIT(0x66); + EMIT(0xC7); + emit_operand(eax, dst); + EMIT(static_cast(imm16 & 0xff)); + EMIT(static_cast(imm16 >> 8)); +} + + void Assembler::mov(Register dst, int32_t imm32) { EnsureSpace ensure_space(this); EMIT(0xB8 | dst.code()); diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 57f496f..a82b517 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -735,6 +735,7 @@ class Assembler : public AssemblerBase { void mov_w(Register dst, const Operand& src); void mov_w(const Operand& dst, Register src); + void mov_w(const Operand& dst, int16_t imm16); void mov(Register dst, int32_t imm32); void mov(Register dst, const Immediate& x); diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc index 4e4d552..d7b28d5 100644 --- a/src/ia32/disasm-ia32.cc +++ b/src/ia32/disasm-ia32.cc @@ -1205,6 +1205,13 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, AppendToBuffer("mov_w "); data += PrintRightOperand(data); AppendToBuffer(",%s", NameOfCPURegister(regop)); + } else if (*data == 0xC7) { + data++; + AppendToBuffer("%s ", "mov_w"); + data += PrintRightOperand(data); + int imm = *reinterpret_cast(data); + AppendToBuffer(",0x%x", imm); + data += 2; } else if (*data == 0x0F) { data++; if (*data == 0x38) { diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index a69ef12..b3b0aa0 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2059,32 +2059,62 @@ void LCodeGen::DoDateField(LDateField* instr) { } +Operand LCodeGen::BuildSeqStringOperand(Register string, + LOperand* index, + String::Encoding encoding) { + if (index->IsConstantOperand()) { + int offset = ToRepresentation(LConstantOperand::cast(index), + Representation::Integer32()); + if (encoding == String::TWO_BYTE_ENCODING) { + offset *= kUC16Size; + } + STATIC_ASSERT(kCharSize == 1); + return FieldOperand(string, SeqString::kHeaderSize + offset); + } + return FieldOperand( + string, ToRegister(index), + encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2, + SeqString::kHeaderSize); +} + + void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { + String::Encoding encoding = instr->hydrogen()->encoding(); Register string = ToRegister(instr->string()); - Register index = ToRegister(instr->index()); - Register value = ToRegister(instr->value()); - String::Encoding encoding = instr->encoding(); if (FLAG_debug_code) { - __ push(value); - __ mov(value, FieldOperand(string, HeapObject::kMapOffset)); - __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset)); + __ push(string); + __ mov(string, FieldOperand(string, HeapObject::kMapOffset)); + __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset)); - __ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); + __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; - __ cmp(value, Immediate(encoding == String::ONE_BYTE_ENCODING - ? one_byte_seq_type : two_byte_seq_type)); + __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING + ? one_byte_seq_type : two_byte_seq_type)); __ Check(equal, kUnexpectedStringType); - __ pop(value); + __ pop(string); } - if (encoding == String::ONE_BYTE_ENCODING) { - __ mov_b(FieldOperand(string, index, times_1, SeqString::kHeaderSize), - value); + Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); + if (instr->value()->IsConstantOperand()) { + int value = ToRepresentation(LConstantOperand::cast(instr->value()), + Representation::Integer32()); + ASSERT_LE(0, value); + if (encoding == String::ONE_BYTE_ENCODING) { + ASSERT_LE(value, String::kMaxOneByteCharCode); + __ mov_b(operand, static_cast(value)); + } else { + ASSERT_LE(value, String::kMaxUtf16CodeUnit); + __ mov_w(operand, static_cast(value)); + } } else { - __ mov_w(FieldOperand(string, index, times_2, SeqString::kHeaderSize), - value); + Register value = ToRegister(instr->value()); + if (encoding == String::ONE_BYTE_ENCODING) { + __ mov_b(operand, value); + } else { + __ mov_w(operand, value); + } } } diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index 78bc69d..77a37a6 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -295,6 +295,10 @@ class LCodeGen: public LCodeGenBase { uint32_t offset, uint32_t additional_index = 0); + Operand BuildSeqStringOperand(Register string, + LOperand* index, + String::Encoding encoding); + void EmitIntegerMathAbs(LMathAbs* instr); // Support for recording safepoint and position information. diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index fdddef3..3390aa6 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -580,6 +580,14 @@ LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) { } +LOperand* LChunkBuilder::UseFixedOrConstant(HValue* value, + Register fixed_register) { + return CanBeImmediateConstant(value) + ? chunk_->DefineConstantOperand(HConstant::cast(value)) + : UseFixed(value, fixed_register); +} + + LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) { return CanBeImmediateConstant(value) ? chunk_->DefineConstantOperand(HConstant::cast(value)) @@ -1866,13 +1874,12 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { - LOperand* string = UseRegister(instr->string()); - LOperand* index = UseRegister(instr->index()); - ASSERT(ecx.is_byte_register()); - LOperand* value = UseFixed(instr->value(), ecx); - LSeqStringSetChar* result = - new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); - return DefineSameAsFirst(result); + LOperand* string = UseRegisterAtStart(instr->string()); + LOperand* index = UseRegisterOrConstantAtStart(instr->index()); + LOperand* value = (instr->encoding() == String::ONE_BYTE_ENCODING) + ? UseFixedOrConstant(instr->value(), eax) + : UseRegisterOrConstantAtStart(instr->value()); + return new(zone()) LSeqStringSetChar(string, index, value); } diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 752fdd4..23acd27 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -1339,25 +1339,20 @@ class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 1> { class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> { public: - LSeqStringSetChar(String::Encoding encoding, - LOperand* string, + LSeqStringSetChar(LOperand* string, LOperand* index, - LOperand* value) : encoding_(encoding) { + LOperand* value) { inputs_[0] = string; inputs_[1] = index; inputs_[2] = value; } - String::Encoding encoding() { return encoding_; } LOperand* string() { return inputs_[0]; } LOperand* index() { return inputs_[1]; } LOperand* value() { return inputs_[2]; } DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char") DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar) - - private: - String::Encoding encoding_; }; @@ -2832,6 +2827,10 @@ class LChunkBuilder V8_FINAL BASE_EMBEDDED { MUST_USE_RESULT LOperand* UseOrConstant(HValue* value); MUST_USE_RESULT LOperand* UseOrConstantAtStart(HValue* value); + // An input operand in a fixed register or a constant operand. + MUST_USE_RESULT LOperand* UseFixedOrConstant(HValue* value, + Register fixed_register); + // An input operand in a register or a constant operand. MUST_USE_RESULT LOperand* UseRegisterOrConstant(HValue* value); MUST_USE_RESULT LOperand* UseRegisterOrConstantAtStart(HValue* value); diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 99e2ad4..a7fd880 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -1357,6 +1357,15 @@ void Assembler::movb(const Operand& dst, Register src) { } +void Assembler::movb(const Operand& dst, Immediate imm) { + EnsureSpace ensure_space(this); + emit_optional_rex_32(dst); + emit(0xC6); + emit_operand(0x0, dst); + emit(static_cast(imm.value_)); +} + + void Assembler::movw(const Operand& dst, Register src) { EnsureSpace ensure_space(this); emit(0x66); @@ -1366,6 +1375,17 @@ void Assembler::movw(const Operand& dst, Register src) { } +void Assembler::movw(const Operand& dst, Immediate imm) { + EnsureSpace ensure_space(this); + emit(0x66); + emit_optional_rex_32(dst); + emit(0xC7); + emit_operand(0x0, dst); + emit(static_cast(imm.value_ & 0xff)); + emit(static_cast(imm.value_ >> 8)); +} + + void Assembler::movl(Register dst, const Operand& src) { EnsureSpace ensure_space(this); emit_optional_rex_32(dst, src); diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 584b3a5..4204a8c 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -694,10 +694,12 @@ class Assembler : public AssemblerBase { void movb(Register dst, const Operand& src); void movb(Register dst, Immediate imm); void movb(const Operand& dst, Register src); + void movb(const Operand& dst, Immediate imm); // Move the low 16 bits of a 64-bit register value to a 16-bit // memory location. void movw(const Operand& dst, Register src); + void movw(const Operand& dst, Immediate imm); void movl(Register dst, Register src); void movl(Register dst, const Operand& src); diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index 70d410d..667561b 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -1565,9 +1565,15 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector out_buffer, } else { AppendToBuffer("mov%c ", operand_size_code()); data += PrintRightOperand(data); - int32_t imm = *reinterpret_cast(data); - AppendToBuffer(",0x%x", imm); - data += 4; + if (operand_size() == OPERAND_WORD_SIZE) { + int16_t imm = *reinterpret_cast(data); + AppendToBuffer(",0x%x", imm); + data += 2; + } else { + int32_t imm = *reinterpret_cast(data); + AppendToBuffer(",0x%x", imm); + data += 4; + } } } break; diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 5c6a580..93eb616 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -1632,32 +1632,60 @@ void LCodeGen::DoDateField(LDateField* instr) { } +Operand LCodeGen::BuildSeqStringOperand(Register string, + LOperand* index, + String::Encoding encoding) { + if (index->IsConstantOperand()) { + int offset = ToInteger32(LConstantOperand::cast(index)); + if (encoding == String::TWO_BYTE_ENCODING) { + offset *= kUC16Size; + } + STATIC_ASSERT(kCharSize == 1); + return FieldOperand(string, SeqString::kHeaderSize + offset); + } + return FieldOperand( + string, ToRegister(index), + encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2, + SeqString::kHeaderSize); +} + + void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { + String::Encoding encoding = instr->hydrogen()->encoding(); Register string = ToRegister(instr->string()); - Register index = ToRegister(instr->index()); - Register value = ToRegister(instr->value()); - String::Encoding encoding = instr->encoding(); if (FLAG_debug_code) { - __ push(value); - __ movq(value, FieldOperand(string, HeapObject::kMapOffset)); - __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset)); + __ push(string); + __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); + __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); - __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask)); + __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; - __ cmpq(value, Immediate(encoding == String::ONE_BYTE_ENCODING - ? one_byte_seq_type : two_byte_seq_type)); + __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING + ? one_byte_seq_type : two_byte_seq_type)); __ Check(equal, kUnexpectedStringType); - __ pop(value); + __ pop(string); } - if (encoding == String::ONE_BYTE_ENCODING) { - __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize), - value); + Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); + if (instr->value()->IsConstantOperand()) { + int value = ToInteger32(LConstantOperand::cast(instr->value())); + ASSERT_LE(0, value); + if (encoding == String::ONE_BYTE_ENCODING) { + ASSERT_LE(value, String::kMaxOneByteCharCode); + __ movb(operand, Immediate(value)); + } else { + ASSERT_LE(value, String::kMaxUtf16CodeUnit); + __ movw(operand, Immediate(value)); + } } else { - __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize), - value); + Register value = ToRegister(instr->value()); + if (encoding == String::ONE_BYTE_ENCODING) { + __ movb(operand, value); + } else { + __ movw(operand, value); + } } } diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index f3f202a..090f961 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -242,6 +242,10 @@ class LCodeGen: public LCodeGenBase { uint32_t offset, uint32_t additional_index = 0); + Operand BuildSeqStringOperand(Register string, + LOperand* index, + String::Encoding encoding); + void EmitIntegerMathAbs(LMathAbs* instr); void EmitSmiMathAbs(LMathAbs* instr); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 6262e7e..d90736a 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1757,13 +1757,10 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { - LOperand* string = UseRegister(instr->string()); - LOperand* index = UseRegister(instr->index()); - ASSERT(rcx.is_byte_register()); - LOperand* value = UseFixed(instr->value(), rcx); - LSeqStringSetChar* result = - new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value); - return DefineSameAsFirst(result); + LOperand* string = UseRegisterAtStart(instr->string()); + LOperand* index = UseRegisterOrConstantAtStart(instr->index()); + LOperand* value = UseRegisterOrConstantAtStart(instr->value()); + return new(zone()) LSeqStringSetChar(string, index, value); } diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index 06cb171..ed17be2 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -1283,25 +1283,20 @@ class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 0> { class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> { public: - LSeqStringSetChar(String::Encoding encoding, - LOperand* string, + LSeqStringSetChar(LOperand* string, LOperand* index, - LOperand* value) : encoding_(encoding) { + LOperand* value) { inputs_[0] = string; inputs_[1] = index; inputs_[2] = value; } - String::Encoding encoding() { return encoding_; } LOperand* string() { return inputs_[0]; } LOperand* index() { return inputs_[1]; } LOperand* value() { return inputs_[2]; } DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char") DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar) - - private: - String::Encoding encoding_; }; diff --git a/test/mjsunit/string-natives.js b/test/mjsunit/string-natives.js index b1ec875..cd1cde1 100644 --- a/test/mjsunit/string-natives.js +++ b/test/mjsunit/string-natives.js @@ -29,15 +29,23 @@ function test() { var s1 = %NewString(26, true); + for (i = 0; i < 26; i++) %_OneByteSeqStringSetChar(s1, i, 65); + assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAA", s1); + %_OneByteSeqStringSetChar(s1, 25, 66); + assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAB", s1); for (i = 0; i < 26; i++) %_OneByteSeqStringSetChar(s1, i, i+65); assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", s1); s1 = %TruncateString(s1, 13); assertEquals("ABCDEFGHIJKLM", s1); var s2 = %NewString(26, false); + for (i = 0; i < 26; i++) %_TwoByteSeqStringSetChar(s2, i, 65); + assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAA", s2); + %_TwoByteSeqStringSetChar(s2, 25, 66); + assertEquals("AAAAAAAAAAAAAAAAAAAAAAAAAB", s2); for (i = 0; i < 26; i++) %_TwoByteSeqStringSetChar(s2, i, i+65); assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", s2); - s2 = %TruncateString(s1, 13); + s2 = %TruncateString(s2, 13); assertEquals("ABCDEFGHIJKLM", s2); var s3 = %NewString(26, false);