Commit 051e4593 authored by yangguo@chromium.org's avatar yangguo@chromium.org

MIPS: Improve array to string conversion.

Port r13144 (71c45300)

BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/11573017
Patch from Akos Palfi <palfia@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13230 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 19a6575e
......@@ -517,6 +517,50 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
}
void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
String::Encoding encoding,
Register string,
Register index,
Register value) {
if (FLAG_debug_code) {
__ And(at, index, Operand(kSmiTagMask));
__ Check(eq, "Non-smi index", at, Operand(zero_reg));
__ And(at, value, Operand(kSmiTagMask));
__ Check(eq, "Non-smi value", at, Operand(zero_reg));
__ lw(at, FieldMemOperand(string, String::kLengthOffset));
__ Check(lt, "Index is too large", at, Operand(index));
__ Check(ge, "Index is negative", index, Operand(Smi::FromInt(0)));
__ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
__ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
__ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
__ Check(eq, "Unexpected string type", at,
Operand(encoding == String::ONE_BYTE_ENCODING
? one_byte_seq_type : two_byte_seq_type));
}
__ Addu(at,
string,
Operand(SeqString::kHeaderSize - kHeapObjectTag));
__ SmiUntag(value);
STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
if (encoding == String::ONE_BYTE_ENCODING) {
__ SmiUntag(index);
__ Addu(at, at, index);
__ sb(value, MemOperand(at));
} else {
// No need to untag a smi for two-byte addressing.
__ Addu(at, at, index);
__ sh(value, MemOperand(at));
}
}
static MemOperand ExpConstant(int index, Register base) {
return MemOperand(base, index * kDoubleSize);
}
......
......@@ -3146,6 +3146,38 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
}
void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(3, args->length());
VisitForStackValue(args->at(1)); // index
VisitForStackValue(args->at(2)); // value
__ pop(a2);
__ pop(a1);
VisitForAccumulatorValue(args->at(0)); // string
static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
SeqStringSetCharGenerator::Generate(masm_, encoding, v0, a1, a2);
context()->Plug(v0);
}
void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
ASSERT_EQ(3, args->length());
VisitForStackValue(args->at(1)); // index
VisitForStackValue(args->at(2)); // value
__ pop(a2);
__ pop(a1);
VisitForAccumulatorValue(args->at(0)); // string
static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
SeqStringSetCharGenerator::Generate(masm_, encoding, v0, a1, a2);
context()->Plug(v0);
}
void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
// Load the arguments on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
......
......@@ -1389,6 +1389,15 @@ void LCodeGen::DoDateField(LDateField* instr) {
}
void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
SeqStringSetCharGenerator::Generate(masm(),
instr->encoding(),
ToRegister(instr->string()),
ToRegister(instr->index()),
ToRegister(instr->value()));
}
void LCodeGen::DoBitNotI(LBitNotI* instr) {
Register input = ToRegister(instr->value());
Register result = ToRegister(instr->result());
......
......@@ -1531,6 +1531,16 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
}
LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
LOperand* string = UseRegister(instr->string());
LOperand* index = UseRegister(instr->index());
LOperand* value = UseRegister(instr->value());
LSeqStringSetChar* result =
new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
LOperand* value = UseRegisterOrConstantAtStart(instr->index());
LOperand* length = UseRegister(instr->length());
......
......@@ -148,6 +148,7 @@ class LCodeGen;
V(Random) \
V(RegExpLiteral) \
V(Return) \
V(SeqStringSetChar) \
V(ShiftI) \
V(SmiTag) \
V(SmiUntag) \
......@@ -1143,6 +1144,30 @@ class LDateField: public LTemplateInstruction<1, 1, 1> {
};
class LSeqStringSetChar: public LTemplateInstruction<1, 3, 0> {
public:
LSeqStringSetChar(String::Encoding encoding,
LOperand* string,
LOperand* index,
LOperand* value) : encoding_(encoding) {
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_;
};
class LThrow: public LTemplateInstruction<0, 1, 0> {
public:
explicit LThrow(LOperand* 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