From: bmeurer@chromium.org Date: Thu, 7 Nov 2013 13:43:03 +0000 (+0000) Subject: Add new HSeqStringGetChar instruction. X-Git-Tag: upstream/4.7.83~11842 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0990f44f00baaf1c49b74f3a81503e86b7238889;p=platform%2Fupstream%2Fv8.git Add new HSeqStringGetChar instruction. This instruction is required for copying characters from sequential strings in the hydrogenized StringAddStub. BUG=v8:2990 R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/63863005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17565 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index d7ce853..14db24f 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1884,6 +1884,13 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { } +LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { + LOperand* string = UseRegisterAtStart(instr->string()); + LOperand* index = UseRegisterOrConstantAtStart(instr->index()); + return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index)); +} + + LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { LOperand* string = UseRegister(instr->string()); LOperand* index = UseRegisterOrConstant(instr->index()); diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 3827ab3..7574e15 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -156,6 +156,7 @@ class LCodeGen; V(Random) \ V(RegExpLiteral) \ V(Return) \ + V(SeqStringGetChar) \ V(SeqStringSetChar) \ V(ShiftI) \ V(SmiTag) \ @@ -1360,6 +1361,21 @@ class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 1> { }; +class LSeqStringGetChar V8_FINAL : public LTemplateInstruction<1, 2, 0> { + public: + LSeqStringGetChar(LOperand* string, LOperand* index) { + inputs_[0] = string; + inputs_[1] = index; + } + + LOperand* string() const { return inputs_[0]; } + LOperand* index() const { return inputs_[1]; } + + DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char") + DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar) +}; + + class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> { public: LSeqStringSetChar(LOperand* string, diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index c6547bef..bf8b7b9 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1974,6 +1974,34 @@ MemOperand LCodeGen::BuildSeqStringOperand(Register string, } +void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { + String::Encoding encoding = instr->hydrogen()->encoding(); + Register string = ToRegister(instr->string()); + Register result = ToRegister(instr->result()); + + if (FLAG_debug_code) { + Register scratch = scratch0(); + __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset)); + __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); + + __ and_(scratch, scratch, + Operand(kStringRepresentationMask | kStringEncodingMask)); + static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; + static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; + __ cmp(scratch, Operand(encoding == String::ONE_BYTE_ENCODING + ? one_byte_seq_type : two_byte_seq_type)); + __ Check(eq, kUnexpectedStringType); + } + + MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); + if (encoding == String::ONE_BYTE_ENCODING) { + __ ldrb(result, operand); + } else { + __ ldrh(result, operand); + } +} + + void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { String::Encoding encoding = instr->hydrogen()->encoding(); Register string = ToRegister(instr->string()); diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 206ab7e..02abf0b 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3991,6 +3991,26 @@ HInstruction* HShr::New( } +HInstruction* HSeqStringGetChar::New(Zone* zone, + HValue* context, + String::Encoding encoding, + HValue* string, + HValue* index) { + if (FLAG_fold_constants && string->IsConstant() && index->IsConstant()) { + HConstant* c_string = HConstant::cast(string); + HConstant* c_index = HConstant::cast(index); + if (c_string->HasStringValue() && c_index->HasInteger32Value()) { + Handle s = c_string->StringValue(); + int32_t i = c_index->Integer32Value(); + ASSERT_LE(0, i); + ASSERT_LT(i, s->length()); + return H_CONSTANT_INT(s->Get(i)); + } + } + return new(zone) HSeqStringGetChar(encoding, string, index); +} + + #undef H_CONSTANT_INT #undef H_CONSTANT_DOUBLE diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 66050f1..15f3077 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -159,6 +159,7 @@ class LChunkBuilder; V(Return) \ V(Ror) \ V(Sar) \ + V(SeqStringGetChar) \ V(SeqStringSetChar) \ V(Shl) \ V(Shr) \ @@ -7023,6 +7024,56 @@ class HDateField V8_FINAL : public HUnaryOperation { }; +class HSeqStringGetChar V8_FINAL : public HTemplateInstruction<2> { + public: + static HInstruction* New(Zone* zone, + HValue* context, + String::Encoding encoding, + HValue* string, + HValue* index); + + virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { + return (index == 0) ? Representation::Tagged() + : Representation::Integer32(); + } + + String::Encoding encoding() const { return encoding_; } + HValue* string() const { return OperandAt(0); } + HValue* index() const { return OperandAt(1); } + + DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar) + + protected: + virtual bool DataEquals(HValue* other) V8_OVERRIDE { + return encoding() == HSeqStringGetChar::cast(other)->encoding(); + } + + virtual Range* InferRange(Zone* zone) V8_OVERRIDE { + if (encoding() == String::ONE_BYTE_ENCODING) { + return new(zone) Range(0, String::kMaxOneByteCharCode); + } else { + ASSERT_EQ(String::TWO_BYTE_ENCODING, encoding()); + return new(zone) Range(0, String::kMaxUtf16CodeUnit); + } + } + + private: + HSeqStringGetChar(String::Encoding encoding, + HValue* string, + HValue* index) : encoding_(encoding) { + SetOperandAt(0, string); + SetOperandAt(1, index); + set_representation(Representation::Integer32()); + SetFlag(kUseGVN); + SetGVNFlag(kDependsOnStringChars); + } + + virtual bool IsDeletable() const V8_OVERRIDE { return true; } + + String::Encoding encoding_; +}; + + class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<3> { public: DECLARE_INSTRUCTION_FACTORY_P4(HSeqStringSetChar, String::Encoding, diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index b3b0aa0..44b952c 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2078,6 +2078,34 @@ Operand LCodeGen::BuildSeqStringOperand(Register string, } +void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { + String::Encoding encoding = instr->hydrogen()->encoding(); + Register result = ToRegister(instr->result()); + Register string = ToRegister(instr->string()); + + if (FLAG_debug_code) { + __ push(string); + __ mov(string, FieldOperand(string, HeapObject::kMapOffset)); + __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset)); + + __ 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(string, Immediate(encoding == String::ONE_BYTE_ENCODING + ? one_byte_seq_type : two_byte_seq_type)); + __ Check(equal, kUnexpectedStringType); + __ pop(string); + } + + Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); + if (encoding == String::ONE_BYTE_ENCODING) { + __ movzx_b(result, operand); + } else { + __ movzx_w(result, operand); + } +} + + void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { String::Encoding encoding = instr->hydrogen()->encoding(); Register string = ToRegister(instr->string()); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 3390aa6..80dbdd5 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1873,6 +1873,13 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { } +LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { + LOperand* string = UseRegisterAtStart(instr->string()); + LOperand* index = UseRegisterOrConstantAtStart(instr->index()); + return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index)); +} + + LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { LOperand* string = UseRegisterAtStart(instr->string()); LOperand* index = UseRegisterOrConstantAtStart(instr->index()); diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 23acd27..dc26626 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -156,6 +156,7 @@ class LCodeGen; V(PushArgument) \ V(RegExpLiteral) \ V(Return) \ + V(SeqStringGetChar) \ V(SeqStringSetChar) \ V(ShiftI) \ V(SmiTag) \ @@ -1337,6 +1338,21 @@ class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 1> { }; +class LSeqStringGetChar V8_FINAL : public LTemplateInstruction<1, 2, 0> { + public: + LSeqStringGetChar(LOperand* string, LOperand* index) { + inputs_[0] = string; + inputs_[1] = index; + } + + LOperand* string() const { return inputs_[0]; } + LOperand* index() const { return inputs_[1]; } + + DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char") + DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar) +}; + + class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> { public: LSeqStringSetChar(LOperand* string, diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 2c266d2..00bfa4e 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -1366,6 +1366,15 @@ void Assembler::movb(const Operand& dst, Immediate imm) { } +void Assembler::movw(Register dst, const Operand& src) { + EnsureSpace ensure_space(this); + emit(0x66); + emit_optional_rex_32(dst, src); + emit(0x8B); + emit_operand(dst, src); +} + + void Assembler::movw(const Operand& dst, Register src) { EnsureSpace ensure_space(this); emit(0x66); diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index dfa1ebc..c64112d 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -698,6 +698,7 @@ class Assembler : public AssemblerBase { // Move the low 16 bits of a 64-bit register value to a 16-bit // memory location. + void movw(Register dst, const Operand& src); void movw(const Operand& dst, Register src); void movw(const Operand& dst, Immediate imm); diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index a84b569..ba186a8 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -1670,6 +1670,34 @@ Operand LCodeGen::BuildSeqStringOperand(Register string, } +void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { + String::Encoding encoding = instr->hydrogen()->encoding(); + Register result = ToRegister(instr->result()); + Register string = ToRegister(instr->string()); + + if (FLAG_debug_code) { + __ push(string); + __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); + __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); + + __ 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(string, Immediate(encoding == String::ONE_BYTE_ENCODING + ? one_byte_seq_type : two_byte_seq_type)); + __ Check(equal, kUnexpectedStringType); + __ pop(string); + } + + Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); + if (encoding == String::ONE_BYTE_ENCODING) { + __ movzxbl(result, operand); + } else { + __ movzxwl(result, operand); + } +} + + void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { String::Encoding encoding = instr->hydrogen()->encoding(); Register string = ToRegister(instr->string()); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index d90736a..51e3220 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1756,6 +1756,13 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { } +LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) { + LOperand* string = UseRegisterAtStart(instr->string()); + LOperand* index = UseRegisterOrConstantAtStart(instr->index()); + return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index)); +} + + LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) { LOperand* string = UseRegisterAtStart(instr->string()); LOperand* index = UseRegisterOrConstantAtStart(instr->index()); diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index ed17be2..717a07a 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -154,6 +154,7 @@ class LCodeGen; V(Random) \ V(RegExpLiteral) \ V(Return) \ + V(SeqStringGetChar) \ V(SeqStringSetChar) \ V(ShiftI) \ V(SmiTag) \ @@ -1281,6 +1282,21 @@ class LDateField V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; +class LSeqStringGetChar V8_FINAL : public LTemplateInstruction<1, 2, 0> { + public: + LSeqStringGetChar(LOperand* string, LOperand* index) { + inputs_[0] = string; + inputs_[1] = index; + } + + LOperand* string() const { return inputs_[0]; } + LOperand* index() const { return inputs_[1]; } + + DECLARE_CONCRETE_INSTRUCTION(SeqStringGetChar, "seq-string-get-char") + DECLARE_HYDROGEN_ACCESSOR(SeqStringGetChar) +}; + + class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> { public: LSeqStringSetChar(LOperand* string,