Improve SeqStringSetChar implementation.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 23 May 2013 09:51:06 +0000 (09:51 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 23 May 2013 09:51:06 +0000 (09:51 +0000)
R=jkummerow@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/15743006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14769 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

15 files changed:
src/arm/codegen-arm.cc
src/arm/full-codegen-arm.cc
src/arm/lithium-codegen-arm.cc
src/codegen.h
src/full-codegen.h
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/codegen-ia32.cc
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/x64/codegen-x64.cc
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
test/mjsunit/string-fromcharcode.js

index 7bf253a333315be948cc1125b42da7ce646b9ff2..5b2980aeb4d2bfb580eef2b9fe446efcc65e49fe 100644 (file)
@@ -504,50 +504,6 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ SmiTst(index);
-    __ Check(eq, "Non-smi index");
-    __ SmiTst(value);
-    __ Check(eq, "Non-smi value");
-
-    __ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
-    __ cmp(index, ip);
-    __ Check(lt, "Index is too large");
-
-    __ cmp(index, Operand(Smi::FromInt(0)));
-    __ Check(ge, "Index is negative");
-
-    __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
-    __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
-
-    __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING
-                           ? one_byte_seq_type : two_byte_seq_type));
-    __ Check(eq, "Unexpected string type");
-  }
-
-  __ add(ip,
-         string,
-         Operand(SeqString::kHeaderSize - kHeapObjectTag));
-  __ SmiUntag(value, value);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    // Smis are tagged by left shift by 1, thus LSR by 1 to smi-untag inline.
-    __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
-  } else {
-    // No need to untag a smi for two-byte addressing.
-    __ strh(value, MemOperand(ip, index));  // LSL(1 - kSmiTagSize).
-  }
-}
-
-
 static MemOperand ExpConstant(int index, Register base) {
   return MemOperand(base, index * kDoubleSize);
 }
index 33a499c27576db73d574cee2d9569ab84f24daba..967a4d41ea2400beb75defcbaeaa401e0d4c52ea 100644 (file)
@@ -3425,19 +3425,56 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ SmiTst(index);
+  __ Check(eq, "Non-smi index");
+  __ SmiTst(value);
+  __ Check(eq, "Non-smi value");
+
+  __ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
+  __ cmp(index, ip);
+  __ Check(lt, "Index is too large");
+
+  __ cmp(index, Operand(Smi::FromInt(0)));
+  __ Check(ge, "Index is negative");
+
+  __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
+
+  __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
+  __ cmp(ip, Operand(encoding_mask));
+  __ Check(eq, "Unexpected string type");
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = r0;
+  Register index = r1;
+  Register value = r2;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(r2);
-  __ pop(r1);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, r0, r1, r2);
-  context()->Plug(r0);
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiUntag(value, value);
+  __ add(ip,
+         string,
+         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
+  __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
+  context()->Plug(string);
 }
 
 
@@ -3445,15 +3482,28 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = r0;
+  Register index = r1;
+  Register value = r2;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(r2);
-  __ pop(r1);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, r0, r1, r2);
-  context()->Plug(r0);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiUntag(value, value);
+  __ add(ip,
+         string,
+         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+  __ strh(value, MemOperand(ip, index));
+  context()->Plug(string);
 }
 
 
index c75be961f35aaf88f2d2843057b4930a7d3f2d02..c57baea75ec3032f096d86e62981563f75b62272 100644 (file)
@@ -2008,11 +2008,34 @@ void LCodeGen::DoDateField(LDateField* instr) {
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  Register string = ToRegister(instr->string());
+  Register index = ToRegister(instr->index());
+  Register value = ToRegister(instr->value());
+  String::Encoding encoding = instr->encoding();
+
+  if (FLAG_debug_code) {
+    __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
+    __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
+
+    __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    __ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING
+                           ? one_byte_seq_type : two_byte_seq_type));
+    __ Check(eq, "Unexpected string type");
+  }
+
+  __ add(ip,
+         string,
+         Operand(SeqString::kHeaderSize - kHeapObjectTag));
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ strb(value, MemOperand(ip, index));
+  } else {
+    // MemOperand with ip as the base register is not allowed for strh, so
+    // we do the address calculation explicitly.
+    __ add(ip, ip, Operand(index, LSL, 1));
+    __ strh(value, MemOperand(ip));
+  }
 }
 
 
index 09907c4a20c94f088c4c1cd0100de1fbbd9dfb5d..53ff2e1a1a939b97be45949fab804788b6d8156c 100644 (file)
@@ -113,18 +113,6 @@ class ElementsTransitionGenerator : public AllStatic {
 };
 
 
-class SeqStringSetCharGenerator : public AllStatic {
- public:
-  static void Generate(MacroAssembler* masm,
-                       String::Encoding encoding,
-                       Register string,
-                       Register index,
-                       Register value);
- private:
-  DISALLOW_COPY_AND_ASSIGN(SeqStringSetCharGenerator);
-};
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_CODEGEN_H_
index 32242b297b430a48f904073f71edf61a5577c780..68263a5dc611dc71d46872275728e5f15f1945d6 100644 (file)
@@ -491,6 +491,11 @@ class FullCodeGenerator: public AstVisitor {
   INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
 #undef EMIT_INLINE_RUNTIME_CALL
 
+  void EmitSeqStringSetCharCheck(Register string,
+                                 Register index,
+                                 Register value,
+                                 uint32_t encoding_mask);
+
   // Platform-specific code for resuming generators.
   void EmitGeneratorResume(Expression *generator,
                            Expression *value,
index ecfc859abde54cff0ce801869dfb36130f58dd16..5a103e44ed96b547fe80dfc2e3478dca0fe82eb1 100644 (file)
@@ -6272,6 +6272,7 @@ class HSeqStringSetChar: public HTemplateInstruction<3> {
     SetOperandAt(0, string);
     SetOperandAt(1, index);
     SetOperandAt(2, value);
+    set_representation(Representation::Tagged());
   }
 
   String::Encoding encoding() { return encoding_; }
@@ -6280,7 +6281,8 @@ class HSeqStringSetChar: public HTemplateInstruction<3> {
   HValue* value() { return OperandAt(2); }
 
   virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Tagged();
+    return (index == 0) ? Representation::Tagged()
+                        : Representation::Integer32();
   }
 
   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
index 6bb9fe218bc2bbc7be2aa2e9156c01b44e58d8e5..0c50b6cc9f8321d7b20ea3f1c074986e9d9cc6aa 100644 (file)
@@ -11463,9 +11463,6 @@ void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
   HValue* value = Pop();
   HValue* index = Pop();
   HValue* string = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* char_code = BuildStringCharCodeAt(context, string, index);
-  AddInstruction(char_code);
   HSeqStringSetChar* result = new(zone()) HSeqStringSetChar(
       String::TWO_BYTE_ENCODING, string, index, value);
   return ast_context()->ReturnInstruction(result, call->id());
index 7663c6a7fd37bd58b466a68db8b4eb86cc436cbc..d56223889351751fd480f95f42146ff53cb39d7e 100644 (file)
@@ -1057,50 +1057,6 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ test(index, Immediate(kSmiTagMask));
-    __ Check(zero, "Non-smi index");
-    __ test(value, Immediate(kSmiTagMask));
-    __ Check(zero, "Non-smi value");
-
-    __ cmp(index, FieldOperand(string, String::kLengthOffset));
-    __ Check(less, "Index is too large");
-
-    __ cmp(index, Immediate(Smi::FromInt(0)));
-    __ Check(greater_equal, "Index is negative");
-
-    __ push(value);
-    __ mov(value, FieldOperand(string, HeapObject::kMapOffset));
-    __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
-
-    __ and_(value, 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));
-    __ Check(equal, "Unexpected string type");
-    __ pop(value);
-  }
-
-  __ SmiUntag(value);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    __ SmiUntag(index);
-    __ mov_b(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
-             value);
-  } else {
-    // No need to untag a smi for two-byte addressing.
-    __ mov_w(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
-             value);
-  }
-}
-
-
 static Operand ExpConstant(int index) {
   return Operand::StaticVariable(ExternalReference::math_exp_constants(index));
 }
index 1bc72ec3143cc2c5fea383ab870783811bf9e54a..bf5e02b1c04c7ede08123ee376ba59dd274ee48d 100644 (file)
@@ -3373,19 +3373,57 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ test(index, Immediate(kSmiTagMask));
+  __ Check(zero, "Non-smi index");
+  __ test(value, Immediate(kSmiTagMask));
+  __ Check(zero, "Non-smi value");
+
+  __ cmp(index, FieldOperand(string, String::kLengthOffset));
+  __ Check(less, "Index is too large");
+
+  __ cmp(index, Immediate(Smi::FromInt(0)));
+  __ Check(greater_equal, "Index is negative");
+
+  __ push(value);
+  __ mov(value, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+  __ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+  __ cmp(value, Immediate(encoding_mask));
+  __ Check(equal, "Unexpected string type");
+  __ pop(value);
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = eax;
+  Register index = ebx;
+  Register value = ecx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(ecx);
-  __ pop(ebx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, eax, ebx, ecx);
-  context()->Plug(eax);
+
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiUntag(value);
+  __ SmiUntag(index);
+  __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
+           value);
+  context()->Plug(string);
 }
 
 
@@ -3393,15 +3431,26 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = eax;
+  Register index = ebx;
+  Register value = ecx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(ecx);
-  __ pop(ebx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, eax, ebx, ecx);
-  context()->Plug(eax);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiUntag(value);
+  // No need to untag a smi for two-byte addressing.
+  __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
+           value);
+  context()->Plug(string);
 }
 
 
index 954f34cfa05f3c21bbd97289ac96f4bf944eec28..ec24cf92256622dd50b9e582c7098bd7a442059b 100644 (file)
@@ -1901,11 +1901,32 @@ void LCodeGen::DoDateField(LDateField* instr) {
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  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));
+
+    __ and_(value, 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));
+    __ Check(equal, "Unexpected string type");
+    __ pop(value);
+  }
+
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ mov_b(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
+             value);
+  } else {
+    __ mov_w(FieldOperand(string, index, times_2, SeqString::kHeaderSize),
+             value);
+  }
 }
 
 
index 0a098cb3bd3e704b90954678c7ac3e1274d8b08c..3e6931c27431e5861c9bf65d3bce5ad28bc1cbf1 100644 (file)
@@ -1845,7 +1845,6 @@ LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
   LOperand* string = UseRegister(instr->string());
   LOperand* index = UseRegister(instr->index());
   ASSERT(ecx.is_byte_register());
-  // TODO(titzer): the machine code for this instruction overwrites ecx! fix!
   LOperand* value = UseFixed(instr->value(), ecx);
   LSeqStringSetChar* result =
       new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
index 6f32f7cf04ea63c348b01dc844f960e81cc4fbe8..2ac56a144cdfdddc185f0f5e452afc38e759a413 100644 (file)
@@ -624,46 +624,6 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ Check(masm->CheckSmi(index), "Non-smi index");
-    __ Check(masm->CheckSmi(value), "Non-smi value");
-
-    __ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
-    __ Check(less, "Index is too large");
-
-    __ SmiCompare(index, Smi::FromInt(0));
-    __ Check(greater_equal, "Index is negative");
-
-    __ push(value);
-    __ movq(value, FieldOperand(string, HeapObject::kMapOffset));
-    __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
-
-    __ andb(value, 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));
-    __ Check(equal, "Unexpected string type");
-    __ pop(value);
-  }
-
-  __ SmiToInteger32(value, value);
-  __ SmiToInteger32(index, index);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
-            value);
-  } else {
-    __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize),
-            value);
-  }
-}
-
-
 void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
                                    XMMRegister input,
                                    XMMRegister result,
index 22c6fae18730258b90eb9a69839632cbf265658f..e88e1a540da9efb3ab32488c4baa432c2fa0bfa1 100644 (file)
@@ -3345,19 +3345,54 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ Check(masm()->CheckSmi(index), "Non-smi index");
+  __ Check(masm()->CheckSmi(value), "Non-smi value");
+
+  __ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
+  __ Check(less, "Index is too large");
+
+  __ SmiCompare(index, Smi::FromInt(0));
+  __ Check(greater_equal, "Index is negative");
+
+  __ push(value);
+  __ movq(value, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+  __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+  __ cmpq(value, Immediate(encoding_mask));
+  __ Check(equal, "Unexpected string type");
+  __ pop(value);
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = rax;
+  Register index = rbx;
+  Register value = rcx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(rcx);
-  __ pop(rbx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, rax, rbx, rcx);
-  context()->Plug(rax);
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiToInteger32(value, value);
+  __ SmiToInteger32(index, index);
+  __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
+          value);
+  context()->Plug(string);
 }
 
 
@@ -3365,14 +3400,25 @@ void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = rax;
+  Register index = rbx;
+  Register value = rcx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(rcx);
-  __ pop(rbx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, rax, rbx, rcx);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiToInteger32(value, value);
+  __ SmiToInteger32(index, index);
+  __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
+          value);
   context()->Plug(rax);
 }
 
index 02a1539e7f902ad24308f1f355d3819df751eb25..a3f210ec07b18cde21579d65559141c34681a2c7 100644 (file)
@@ -1672,11 +1672,32 @@ void LCodeGen::DoDateField(LDateField* instr) {
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  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));
+
+    __ andb(value, 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));
+    __ Check(equal, "Unexpected string type");
+    __ pop(value);
+  }
+
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
+            value);
+  } else {
+    __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize),
+            value);
+  }
 }
 
 
index 631c04349f4a17ab694df32d9f06cd2bc2f5a1bd..ad3f7a96fb140310f1fe4de1af71b1d7d473079f 100644 (file)
@@ -103,6 +103,10 @@ for (var i = 0; i < 10; i++) {
   test(i);
 }
 
+assertEquals("AAAA", String.fromCharCode(65, 65, 65, 65));
+assertEquals("AAAA", String.fromCharCode(65, 65, 65, 65));
+%OptimizeFunctionOnNextCall(String.fromCharCode);
+assertEquals("AAAA", String.fromCharCode(65, 65, 65, 65));
 
 // Test the custom IC works correctly when the map changes.
 for (var i = 0; i < 10; i++) {