Commit e2c8e454 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

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@17562 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ef0c647c
......@@ -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());
......
......@@ -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,
......
......@@ -1948,6 +1948,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());
......
......@@ -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<String> 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
......
......@@ -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,
......
......@@ -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 {
__ mov_w(result, operand);
}
}
void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
String::Encoding encoding = instr->hydrogen()->encoding();
Register string = ToRegister(instr->string());
......
......@@ -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());
......
......@@ -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,
......
......@@ -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);
......
......@@ -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);
......
......@@ -1650,6 +1650,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 {
__ movw(result, operand);
}
}
void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
String::Encoding encoding = instr->hydrogen()->encoding();
Register string = ToRegister(instr->string());
......
......@@ -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());
......
......@@ -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,
......
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