Revision: 17886
Author:   [email protected]
Date:     Tue Nov 19 16:41:07 2013 UTC
Log:      Fixed crashes exposed though fuzzing.

The %_OneByteSeqStringSetChar intrinsic expects its arguments to be checked before being called for efficiency reasons, but the fuzzer provided no such checks. Now the intrinsic is robust to bad input if FLAG_debug_code is set.

[email protected]
TEST=test/mjsunit/regress/regress-320948.js
BUG=chromium:320948
LOG=Y

Review URL: https://codereview.chromium.org/72813004
http://code.google.com/p/v8/source/detail?r=17886

Added:
 /branches/bleeding_edge/test/mjsunit/regress/regress-320948.js
Modified:
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/full-codegen.h
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.h
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h
 /branches/bleeding_edge/test/mjsunit/fuzz-natives-part1.js
 /branches/bleeding_edge/test/mjsunit/fuzz-natives-part2.js
 /branches/bleeding_edge/test/mjsunit/fuzz-natives-part3.js
 /branches/bleeding_edge/test/mjsunit/fuzz-natives-part4.js

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-320948.js Tue Nov 19 16:41:07 2013 UTC
@@ -0,0 +1,81 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --debug-code
+
+var one_byte = %NewString(10, true);
+var two_byte = %NewString(10, false);
+
+function foo1(s, arg1, arg2) {
+  return %_OneByteSeqStringSetChar(s, arg1, arg2)
+}
+foo1(one_byte, 0, 0);
+assertThrows("{ foo1(4, 0, 0); }");
+assertThrows("{ foo1(one_byte, new Object(), 0); }");
+assertThrows("{ foo1(one_byte, 0, new Object()); }");
+assertThrows("{ foo1(one_byte, 100000, 100; }");
+assertThrows("{ foo1(one_byte, -1, 100; }");
+
+function bar1(s, arg1, arg2) {
+  return %_OneByteSeqStringSetChar(s, arg1, arg2)
+}
+
+bar1(one_byte, 0, 0);
+bar1(one_byte, 0, 0);
+bar1(one_byte, 0, 0);
+%OptimizeFunctionOnNextCall(bar1);
+bar1(one_byte, 0, 0);
+assertThrows("{ bar1(4, 0, 0); }");
+assertThrows("{ bar1(one_byte, new Object(), 0); }");
+assertThrows("{ bar1(one_byte, 0, new Object()); }");
+assertThrows("{ bar1(one_byte, 100000, 100; }");
+assertThrows("{ bar1(one_byte, -1, 100; }");
+
+function foo2(s, arg1, arg2) {
+  return %_TwoByteSeqStringSetChar(s, arg1, arg2)
+}
+foo2(two_byte, 0, 0);
+assertThrows("{ foo2(4, 0, 0); }");
+assertThrows("{ foo2(two_byte, new Object(), 0); }");
+assertThrows("{ foo2(two_byte, 0, new Object()); }");
+assertThrows("{ foo2(two_byte, 100000, 100; }");
+assertThrows("{ foo2(two_byte, -1, 100; }");
+
+function bar2(s, arg1, arg2) {
+  return %_TwoByteSeqStringSetChar(s, arg1, arg2)
+}
+
+bar2(two_byte, 0, 0);
+bar2(two_byte, 0, 0);
+bar2(two_byte, 0, 0);
+%OptimizeFunctionOnNextCall(bar2);
+bar2(two_byte, 0, 0);
+assertThrows("{ bar2(4, 0, 0); }");
+assertThrows("{ bar2(two_byte, new Object(), 0); }");
+assertThrows("{ bar2(two_byte, 0, new Object()); }");
+assertThrows("{ bar2(two_byte, 100000, 100; }");
+assertThrows("{ bar2(two_byte, -1, 100; }");
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Nov 19 12:59:09 2013 UTC +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue Nov 19 16:41:07 2013 UTC
@@ -3483,31 +3483,6 @@
   __ bind(&done);
   context()->Plug(r0);
 }
-
-
-void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
-                                                  Register index,
-                                                  Register value,
-                                                  uint32_t encoding_mask) {
-  __ SmiTst(index);
-  __ Check(eq, kNonSmiIndex);
-  __ SmiTst(value);
-  __ Check(eq, kNonSmiValue);
-
-  __ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
-  __ cmp(index, ip);
-  __ Check(lt, kIndexIsTooLarge);
-
-  __ cmp(index, Operand(Smi::FromInt(0)));
-  __ Check(ge, kIndexIsNegative);
-
-  __ 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, kUnexpectedStringType);
-}


 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
@@ -3524,8 +3499,14 @@
   __ Pop(index, value);

   if (FLAG_debug_code) {
+    __ SmiTst(value);
+    __ ThrowIf(ne, kNonSmiValue);
+    __ SmiTst(index);
+    __ ThrowIf(ne, kNonSmiIndex);
+    __ SmiUntag(index, index);
static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+    __ SmiTag(index, index);
   }

   __ SmiUntag(value, value);
@@ -3551,8 +3532,14 @@
   __ Pop(index, value);

   if (FLAG_debug_code) {
+    __ SmiTst(value);
+    __ ThrowIf(ne, kNonSmiValue);
+    __ SmiTst(index);
+    __ ThrowIf(ne, kNonSmiIndex);
+    __ SmiUntag(index, index);
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+    __ SmiTag(index, index);
   }

   __ SmiUntag(value, value);
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Mon Nov 18 14:17:33 2013 UTC +++ /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Nov 19 16:41:07 2013 UTC
@@ -1906,10 +1906,13 @@


 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
-  LOperand* string = UseRegister(instr->string());
-  LOperand* index = UseRegisterOrConstant(instr->index());
-  LOperand* value = UseRegister(instr->value());
-  return new(zone()) LSeqStringSetChar(string, index, value);
+  LOperand* string = UseRegisterAtStart(instr->string());
+  LOperand* index = FLAG_debug_code
+      ? UseRegisterAtStart(instr->index())
+      : UseRegisterOrConstantAtStart(instr->index());
+  LOperand* value = UseRegisterAtStart(instr->value());
+ LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL;
+  return new(zone()) LSeqStringSetChar(context, string, index, value);
 }


=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Tue Nov 12 11:53:13 2013 UTC +++ /branches/bleeding_edge/src/arm/lithium-arm.h Tue Nov 19 16:41:07 2013 UTC
@@ -1401,19 +1401,21 @@
 };


-class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> {
+class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 4, 0> {
  public:
-  LSeqStringSetChar(LOperand* string,
+  LSeqStringSetChar(LOperand* context,
+                    LOperand* string,
                     LOperand* index,
                     LOperand* value) {
-    inputs_[0] = string;
-    inputs_[1] = index;
-    inputs_[2] = value;
+    inputs_[0] = context;
+    inputs_[1] = string;
+    inputs_[2] = index;
+    inputs_[3] = value;
   }

-  LOperand* string() { return inputs_[0]; }
-  LOperand* index() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
+  LOperand* string() { return inputs_[1]; }
+  LOperand* index() { return inputs_[2]; }
+  LOperand* value() { return inputs_[3]; }

   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
   DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Nov 15 13:49:41 2013 UTC +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Nov 19 16:41:07 2013 UTC
@@ -2027,17 +2027,13 @@
   Register value = ToRegister(instr->value());

   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));
+    Register index = ToRegister(instr->index());
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);
+    int encoding_mask =
+        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
+        ? one_byte_seq_type : two_byte_seq_type;
+    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
   }

MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding);
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue Nov 19 06:39:36 2013 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue Nov 19 16:41:07 2013 UTC
@@ -3389,6 +3389,42 @@
   }
   return stack_passed_words;
 }
+
+
+void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
+                                               Register index,
+                                               Register value,
+                                               uint32_t encoding_mask) {
+  Label is_object;
+  SmiTst(string);
+  ThrowIf(eq, kNonObject);
+
+  ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
+  ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
+
+  and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
+  cmp(ip, Operand(encoding_mask));
+  ThrowIf(ne, kUnexpectedStringType);
+
+ // The index is assumed to be untagged coming in, tag it to compare with the + // string length without using a temp register, it is restored at the end of
+  // this function.
+  Label index_tag_ok, index_tag_bad;
+  TrySmiTag(index, index, &index_tag_bad);
+  b(&index_tag_ok);
+  bind(&index_tag_bad);
+  Throw(kIndexIsTooLarge);
+  bind(&index_tag_ok);
+
+  ldr(ip, FieldMemOperand(string, String::kLengthOffset));
+  cmp(index, ip);
+  ThrowIf(ge, kIndexIsTooLarge);
+
+  cmp(index, Operand(Smi::FromInt(0)));
+  ThrowIf(lt, kIndexIsNegative);
+
+  SmiUntag(index, index);
+}


 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments,
@@ -3772,6 +3808,52 @@
   vmsr(ip);
   bind(&done);
 }
+
+
+void MacroAssembler::Throw(BailoutReason reason) {
+  Label throw_start;
+  bind(&throw_start);
+#ifdef DEBUG
+  const char* msg = GetBailoutReason(reason);
+  if (msg != NULL) {
+    RecordComment("Throw message: ");
+    RecordComment(msg);
+  }
+#endif
+
+  mov(r0, Operand(Smi::FromInt(reason)));
+  push(r0);
+  // Disable stub call restrictions to always allow calls to throw.
+  if (!has_frame_) {
+    // We don't actually want to generate a pile of code for this, so just
+    // claim there is a stack frame, without generating one.
+    FrameScope scope(this, StackFrame::NONE);
+    CallRuntime(Runtime::kThrowMessage, 1);
+  } else {
+    CallRuntime(Runtime::kThrowMessage, 1);
+  }
+  // will not return here
+  if (is_const_pool_blocked()) {
+    // If the calling code cares throw the exact number of
+    // instructions generated, we insert padding here to keep the size
+    // of the ThrowMessage macro constant.
+    static const int kExpectedThrowMessageInstructions = 10;
+    int throw_instructions = InstructionsGeneratedSince(&throw_start);
+    ASSERT(throw_instructions <= kExpectedThrowMessageInstructions);
+    while (throw_instructions++ < kExpectedThrowMessageInstructions) {
+      nop();
+    }
+  }
+}
+
+
+void MacroAssembler::ThrowIf(Condition cc, BailoutReason reason) {
+  Label L;
+  b(NegateCondition(cc), &L);
+  Throw(reason);
+  // will not return here
+  bind(&L);
+}


 void MacroAssembler::LoadInstanceDescriptors(Register map,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Fri Nov 8 17:35:58 2013 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue Nov 19 16:41:07 2013 UTC
@@ -661,6 +661,12 @@
   // handler chain.
   void ThrowUncatchable(Register value);

+  // Throw a message string as an exception.
+  void Throw(BailoutReason reason);
+
+  // Throw a message string as an exception if a condition is not true.
+  void ThrowIf(Condition cc, BailoutReason reason);
+
// ---------------------------------------------------------------------------
   // Inline caching support

@@ -1341,6 +1347,11 @@

   void JumpIfNotUniqueName(Register reg, Label* not_unique_name);

+  void EmitSeqStringSetCharCheck(Register string,
+                                 Register index,
+                                 Register value,
+                                 uint32_t encoding_mask);
+
// ---------------------------------------------------------------------------
   // Patching helpers.

=======================================
--- /branches/bleeding_edge/src/full-codegen.h  Mon Oct 14 09:41:41 2013 UTC
+++ /branches/bleeding_edge/src/full-codegen.h  Tue Nov 19 16:41:07 2013 UTC
@@ -497,11 +497,6 @@
   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,
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Tue Nov 19 11:41:04 2013 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Nov 19 16:41:07 2013 UTC
@@ -7282,31 +7282,35 @@
 };


-class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<3> {
+class HSeqStringSetChar V8_FINAL : public HTemplateInstruction<4> {
  public:
-  DECLARE_INSTRUCTION_FACTORY_P4(HSeqStringSetChar, String::Encoding,
-                                 HValue*, HValue*, HValue*);
+  DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(
+      HSeqStringSetChar, String::Encoding,
+      HValue*, HValue*, HValue*);

   String::Encoding encoding() { return encoding_; }
-  HValue* string() { return OperandAt(0); }
-  HValue* index() { return OperandAt(1); }
-  HValue* value() { return OperandAt(2); }
+  HValue* context() { return OperandAt(0); }
+  HValue* string() { return OperandAt(1); }
+  HValue* index() { return OperandAt(2); }
+  HValue* value() { return OperandAt(3); }

virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
-    return (index == 0) ? Representation::Tagged()
+    return (index <= 1) ? Representation::Tagged()
                         : Representation::Integer32();
   }

   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)

  private:
-  HSeqStringSetChar(String::Encoding encoding,
+  HSeqStringSetChar(HValue* context,
+                    String::Encoding encoding,
                     HValue* string,
                     HValue* index,
                     HValue* value) : encoding_(encoding) {
-    SetOperandAt(0, string);
-    SetOperandAt(1, index);
-    SetOperandAt(2, value);
+    SetOperandAt(0, context);
+    SetOperandAt(1, string);
+    SetOperandAt(2, index);
+    SetOperandAt(3, value);
     set_representation(Representation::Tagged());
     SetGVNFlag(kChangesStringChars);
   }
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Tue Nov 19 11:52:47 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Tue Nov 19 16:41:07 2013 UTC
@@ -1869,6 +1869,11 @@
           // We can safely skip the write barrier for storing map here.
           AddStoreMapConstantNoWriteBarrier(string, map);

+ // Length must be stored into the string before we copy characters to
+          // make debug verification code happy.
+          Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
+                                length);
+
           // Copy bytes from the left string.
           BuildCopySeqStringChars(
               left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
@@ -1900,6 +1905,11 @@
           // We can safely skip the write barrier for storing map here.
           AddStoreMapConstantNoWriteBarrier(string, map);

+ // Length must be stored into the string before we copy characters to
+          // make debug verification code happy.
+          Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
+                                length);
+
           // Copy bytes from the left string.
           BuildCopySeqStringChars(
               left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
@@ -1921,8 +1931,6 @@
         HValue* string = Pop();
         Add<HStoreNamedField>(string, HObjectAccess::ForStringHashField(),
                               Add<HConstant>(String::kEmptyHashField));
-        Add<HStoreNamedField>(string, HObjectAccess::ForStringLength(),
-                              length);
         Push(string);
       }
       if_sameencodingandsequential.JoinContinuation(&handled);
@@ -9715,9 +9723,10 @@
   HValue* value = Pop();
   HValue* index = Pop();
   HValue* string = Pop();
-  HSeqStringSetChar* result = New<HSeqStringSetChar>(
-      String::ONE_BYTE_ENCODING, string, index, value);
-  return ast_context()->ReturnInstruction(result, call->id());
+  Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
+                         index, value);
+  Add<HSimulate>(call->id(), FIXED_SIMULATE);
+  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
 }


@@ -9730,9 +9739,10 @@
   HValue* value = Pop();
   HValue* index = Pop();
   HValue* string = Pop();
-  HSeqStringSetChar* result = New<HSeqStringSetChar>(
-      String::TWO_BYTE_ENCODING, string, index, value);
-  return ast_context()->ReturnInstruction(result, call->id());
+  Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
+                         index, value);
+  Add<HSimulate>(call->id(), FIXED_SIMULATE);
+  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
 }


=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue Nov 19 12:59:09 2013 UTC +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue Nov 19 16:41:07 2013 UTC
@@ -3438,32 +3438,6 @@
   __ bind(&done);
   context()->Plug(result);
 }
-
-
-void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
-                                                  Register index,
-                                                  Register value,
-                                                  uint32_t encoding_mask) {
-  __ test(index, Immediate(kSmiTagMask));
-  __ Check(zero, kNonSmiIndex);
-  __ test(value, Immediate(kSmiTagMask));
-  __ Check(zero, kNonSmiValue);
-
-  __ cmp(index, FieldOperand(string, String::kLengthOffset));
-  __ Check(less, kIndexIsTooLarge);
-
-  __ cmp(index, Immediate(Smi::FromInt(0)));
-  __ Check(greater_equal, kIndexIsNegative);
-
-  __ 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, kUnexpectedStringType);
-  __ pop(value);
-}


 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
@@ -3482,12 +3456,20 @@
   __ pop(index);

   if (FLAG_debug_code) {
- static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+    __ test(value, Immediate(kSmiTagMask));
+    __ ThrowIf(not_zero, kNonSmiValue);
+    __ test(index, Immediate(kSmiTagMask));
+    __ ThrowIf(not_zero, kNonSmiValue);
   }

   __ SmiUntag(value);
   __ SmiUntag(index);
+
+  if (FLAG_debug_code) {
+ static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
__ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
            value);
   context()->Plug(string);
@@ -3509,8 +3491,14 @@
   __ pop(index);

   if (FLAG_debug_code) {
+    __ test(value, Immediate(kSmiTagMask));
+    __ ThrowIf(not_zero, kNonSmiValue);
+    __ test(index, Immediate(kSmiTagMask));
+    __ ThrowIf(not_zero, kNonSmiValue);
+    __ SmiUntag(index);
static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+    __ SmiTag(index);
   }

   __ SmiUntag(value);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon Nov 18 14:17:33 2013 UTC +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Nov 19 16:41:07 2013 UTC
@@ -2130,17 +2130,14 @@
   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));
+    Register value = ToRegister(instr->value());
+    Register index = ToRegister(instr->index());
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);
+    int encoding_mask =
+        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
+        ? one_byte_seq_type : two_byte_seq_type;
+    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
   }

Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon Nov 18 14:17:33 2013 UTC +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Nov 19 16:41:07 2013 UTC
@@ -1890,15 +1890,38 @@
   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
   return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
 }
+
+
+LOperand* LChunkBuilder::GetSeqStringSetCharOperand(HSeqStringSetChar* instr) {
+  if (instr->encoding() == String::ONE_BYTE_ENCODING) {
+    if (FLAG_debug_code) {
+      return UseFixed(instr->value(), eax);
+    } else {
+      return UseFixedOrConstant(instr->value(), eax);
+    }
+  } else {
+    if (FLAG_debug_code) {
+      return UseRegisterAtStart(instr->value());
+    } else {
+      return UseRegisterOrConstantAtStart(instr->value());
+    }
+  }
+}


 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
   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);
+  LOperand* index = FLAG_debug_code
+      ? UseRegisterAtStart(instr->index())
+      : UseRegisterOrConstantAtStart(instr->index());
+  LOperand* value = GetSeqStringSetCharOperand(instr);
+ LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), esi) : NULL;
+  LInstruction* result = new(zone()) LSeqStringSetChar(context, string,
+                                                       index, value);
+  if (FLAG_debug_code) {
+    result = MarkAsCall(result, instr);
+  }
+  return result;
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Nov 12 11:53:13 2013 UTC +++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Nov 19 16:41:07 2013 UTC
@@ -1377,19 +1377,21 @@
 };


-class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> {
+class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 4, 0> {
  public:
-  LSeqStringSetChar(LOperand* string,
+  LSeqStringSetChar(LOperand* context,
+                    LOperand* string,
                     LOperand* index,
                     LOperand* value) {
-    inputs_[0] = string;
-    inputs_[1] = index;
-    inputs_[2] = value;
+    inputs_[0] = context;
+    inputs_[1] = string;
+    inputs_[2] = index;
+    inputs_[3] = value;
   }

-  LOperand* string() { return inputs_[0]; }
-  LOperand* index() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
+  LOperand* string() { return inputs_[1]; }
+  LOperand* index() { return inputs_[2]; }
+  LOperand* value() { return inputs_[3]; }

   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
   DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
@@ -2917,6 +2919,8 @@

   enum CanDeoptimize { CAN_DEOPTIMIZE_EAGERLY, CANNOT_DEOPTIMIZE_EAGERLY };

+  LOperand* GetSeqStringSetCharOperand(HSeqStringSetChar* instr);
+
   // Marks a call for the register allocator.  Assigns a pointer map to
   // support GC and lazy deoptimization.  Assigns an environment to support
   // eager deoptimization if CAN_DEOPTIMIZE_EAGERLY.
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Nov 18 11:44:06 2013 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Nov 19 16:41:07 2013 UTC
@@ -3063,6 +3063,40 @@
   // will not return here
   int3();
 }
+
+
+void MacroAssembler::Throw(BailoutReason reason) {
+#ifdef DEBUG
+  const char* msg = GetBailoutReason(reason);
+  if (msg != NULL) {
+    RecordComment("Throw message: ");
+    RecordComment(msg);
+  }
+#endif
+
+  push(eax);
+  push(Immediate(Smi::FromInt(reason)));
+  // Disable stub call restrictions to always allow calls to throw.
+  if (!has_frame_) {
+    // We don't actually want to generate a pile of code for this, so just
+    // claim there is a stack frame, without generating one.
+    FrameScope scope(this, StackFrame::NONE);
+    CallRuntime(Runtime::kThrowMessage, 1);
+  } else {
+    CallRuntime(Runtime::kThrowMessage, 1);
+  }
+  // will not return here
+  int3();
+}
+
+
+void MacroAssembler::ThrowIf(Condition cc, BailoutReason reason) {
+  Label L;
+  j(NegateCondition(cc), &L);
+  Throw(reason);
+  // will not return here
+  bind(&L);
+}


 void MacroAssembler::LoadInstanceDescriptors(Register map,
@@ -3228,6 +3262,42 @@

   bind(&succeed);
 }
+
+
+void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
+                                               Register index,
+                                               Register value,
+                                               uint32_t encoding_mask) {
+  Label is_object;
+  JumpIfNotSmi(string, &is_object, Label::kNear);
+  Throw(kNonObject);
+  bind(&is_object);
+
+  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));
+  pop(value);
+  ThrowIf(not_equal, kUnexpectedStringType);
+
+ // The index is assumed to be untagged coming in, tag it to compare with the + // string length without using a temp register, it is restored at the end of
+  // this function.
+  SmiTag(index);
+  // Can't use overflow here directly, compiler can't seem to disambiguate.
+  ThrowIf(NegateCondition(no_overflow), kIndexIsTooLarge);
+
+  cmp(index, FieldOperand(string, String::kLengthOffset));
+  ThrowIf(greater_equal, kIndexIsTooLarge);
+
+  cmp(index, Immediate(Smi::FromInt(0)));
+  ThrowIf(less, kIndexIsNegative);
+
+  // Restore the index
+  SmiUntag(index);
+}


void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Fri Nov 8 17:35:58 2013 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Tue Nov 19 16:41:07 2013 UTC
@@ -583,6 +583,12 @@
   // Throw past all JS frames to the top JS entry frame.
   void ThrowUncatchable(Register value);

+  // Throw a message string as an exception.
+  void Throw(BailoutReason reason);
+
+  // Throw a message string as an exception if a condition is not true.
+  void ThrowIf(Condition cc, BailoutReason reason);
+
// ---------------------------------------------------------------------------
   // Inline caching support

@@ -941,6 +947,11 @@
   void JumpIfNotUniqueName(Operand operand, Label* not_unique_name,
                            Label::Distance distance = Label::kFar);

+  void EmitSeqStringSetCharCheck(Register string,
+                                 Register index,
+                                 Register value,
+                                 uint32_t encoding_mask);
+
   static int SafepointRegisterStackIndex(Register reg) {
     return SafepointRegisterStackIndex(reg.code());
   }
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Nov 19 13:38:15 2013 UTC
+++ /branches/bleeding_edge/src/objects.h       Tue Nov 19 16:41:07 2013 UTC
@@ -1196,6 +1196,7 @@
V(kNonSmiIndex, "Non-smi index") \ V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \ V(kNonSmiValue, "Non-smi value") \ + V(kNonObject, "Non-object value") \ V(kNotEnoughVirtualRegistersForValues, \ "not enough virtual registers for values") \ V(kNotEnoughSpillSlotsForOsr, \
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Nov 19 11:52:47 2013 UTC
+++ /branches/bleeding_edge/src/runtime.cc      Tue Nov 19 16:41:07 2013 UTC
@@ -9449,6 +9449,17 @@
 }


+RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowMessage) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_SMI_ARG_CHECKED(message_id, 0);
+  const char* message = GetBailoutReason(
+      static_cast<BailoutReason>(message_id));
+  Handle<Name> message_handle =
+      isolate->factory()->NewStringFromAscii(CStrVector(message));
+  return isolate->Throw(*message_handle);
+}
+

 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
   SealHandleScope shs(isolate);
=======================================
--- /branches/bleeding_edge/src/runtime.h       Fri Nov 15 16:37:15 2013 UTC
+++ /branches/bleeding_edge/src/runtime.h       Tue Nov 19 16:41:07 2013 UTC
@@ -408,6 +408,7 @@
   F(ReThrow, 1, 1) \
   F(ThrowReferenceError, 1, 1) \
   F(ThrowNotDateError, 0, 1) \
+  F(ThrowMessage, 1, 1) \
   F(StackGuard, 0, 1) \
   F(Interrupt, 0, 1) \
   F(PromoteScheduledException, 0, 1) \
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue Nov 19 12:59:09 2013 UTC +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue Nov 19 16:41:07 2013 UTC
@@ -3405,30 +3405,6 @@
   __ bind(&done);
   context()->Plug(rax);
 }
-
-
-void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
-                                                  Register index,
-                                                  Register value,
-                                                  uint32_t encoding_mask) {
-  __ Check(masm()->CheckSmi(index), kNonSmiIndex);
-  __ Check(masm()->CheckSmi(value), kNonSmiValue);
-
-  __ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
-  __ Check(less, kIndexIsTooLarge);
-
-  __ SmiCompare(index, Smi::FromInt(0));
-  __ Check(greater_equal, kIndexIsNegative);
-
-  __ 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, kUnexpectedStringType);
-  __ pop(value);
-}


 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
@@ -3446,12 +3422,18 @@
   __ pop(index);

   if (FLAG_debug_code) {
- static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+    __ ThrowIf(NegateCondition(__ CheckSmi(value)), kNonSmiValue);
+    __ ThrowIf(NegateCondition(__ CheckSmi(index)), kNonSmiValue);
   }

   __ SmiToInteger32(value, value);
   __ SmiToInteger32(index, index);
+
+  if (FLAG_debug_code) {
+ static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
__ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
           value);
   context()->Plug(string);
@@ -3473,12 +3455,18 @@
   __ pop(index);

   if (FLAG_debug_code) {
- static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+    __ ThrowIf(NegateCondition(__ CheckSmi(value)), kNonSmiValue);
+    __ ThrowIf(NegateCondition(__ CheckSmi(index)), kNonSmiValue);
   }

   __ SmiToInteger32(value, value);
   __ SmiToInteger32(index, index);
+
+  if (FLAG_debug_code) {
+ static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
__ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
           value);
   context()->Plug(rax);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon Nov 18 14:17:33 2013 UTC +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Nov 19 16:41:07 2013 UTC
@@ -1732,17 +1732,14 @@
   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));
+    Register value = ToRegister(instr->value());
+    Register index = ToRegister(instr->index());
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);
+    int encoding_mask =
+        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
+        ? one_byte_seq_type : two_byte_seq_type;
+    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
   }

Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Mon Nov 18 14:17:33 2013 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.cc Tue Nov 19 16:41:07 2013 UTC
@@ -1796,9 +1796,19 @@

 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
   LOperand* string = UseRegisterAtStart(instr->string());
-  LOperand* index = UseRegisterOrConstantAtStart(instr->index());
-  LOperand* value = UseRegisterOrConstantAtStart(instr->value());
-  return new(zone()) LSeqStringSetChar(string, index, value);
+  LOperand* index = FLAG_debug_code
+      ? UseRegisterAtStart(instr->index())
+      : UseRegisterOrConstantAtStart(instr->index());
+  LOperand* value = FLAG_debug_code
+      ? UseRegisterAtStart(instr->value())
+      : UseRegisterOrConstantAtStart(instr->value());
+ LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), rsi) : NULL;
+  LInstruction* result = new(zone()) LSeqStringSetChar(context, string,
+                                                       index, value);
+  if (FLAG_debug_code) {
+    result = MarkAsCall(result, instr);
+  }
+  return result;
 }


=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Tue Nov 12 11:53:13 2013 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.h Tue Nov 19 16:41:07 2013 UTC
@@ -1339,19 +1339,21 @@
 };


-class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 3, 0> {
+class LSeqStringSetChar V8_FINAL : public LTemplateInstruction<1, 4, 0> {
  public:
-  LSeqStringSetChar(LOperand* string,
+  LSeqStringSetChar(LOperand* context,
+                    LOperand* string,
                     LOperand* index,
                     LOperand* value) {
-    inputs_[0] = string;
-    inputs_[1] = index;
-    inputs_[2] = value;
+    inputs_[0] = context;
+    inputs_[1] = string;
+    inputs_[2] = index;
+    inputs_[3] = value;
   }

-  LOperand* string() { return inputs_[0]; }
-  LOperand* index() { return inputs_[1]; }
-  LOperand* value() { return inputs_[2]; }
+  LOperand* string() { return inputs_[1]; }
+  LOperand* index() { return inputs_[2]; }
+  LOperand* value() { return inputs_[3]; }

   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar, "seq-string-set-char")
   DECLARE_HYDROGEN_ACCESSOR(SeqStringSetChar)
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Nov 18 11:44:06 2013 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Nov 19 16:41:07 2013 UTC
@@ -3204,6 +3204,39 @@
   }
   bind(&done);
 }
+
+
+void MacroAssembler::Throw(BailoutReason reason) {
+#ifdef DEBUG
+  const char* msg = GetBailoutReason(reason);
+  if (msg != NULL) {
+    RecordComment("Throw message: ");
+    RecordComment(msg);
+  }
+#endif
+
+  push(rax);
+  Push(Smi::FromInt(reason));
+  if (!has_frame_) {
+    // We don't actually want to generate a pile of code for this, so just
+    // claim there is a stack frame, without generating one.
+    FrameScope scope(this, StackFrame::NONE);
+    CallRuntime(Runtime::kThrowMessage, 1);
+  } else {
+    CallRuntime(Runtime::kThrowMessage, 1);
+  }
+  // Control will not return here.
+  int3();
+}
+
+
+void MacroAssembler::ThrowIf(Condition cc, BailoutReason reason) {
+  Label L;
+  j(NegateCondition(cc), &L);
+  Throw(reason);
+  // will not return here
+  bind(&L);
+}


 void MacroAssembler::LoadInstanceDescriptors(Register map,
@@ -4629,6 +4662,39 @@
   return num_arguments - kRegisterPassedArguments;
 #endif
 }
+
+
+void MacroAssembler::EmitSeqStringSetCharCheck(Register string,
+                                               Register index,
+                                               Register value,
+                                               uint32_t encoding_mask) {
+  Label is_object;
+  JumpIfNotSmi(string, &is_object);
+  Throw(kNonObject);
+  bind(&is_object);
+
+  push(value);
+  movq(value, FieldOperand(string, HeapObject::kMapOffset));
+  movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+  andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+  cmpq(value, Immediate(encoding_mask));
+  pop(value);
+  ThrowIf(not_equal, kUnexpectedStringType);
+
+ // The index is assumed to be untagged coming in, tag it to compare with the + // string length without using a temp register, it is restored at the end of
+  // this function.
+  Integer32ToSmi(index, index);
+  SmiCompare(index, FieldOperand(string, String::kLengthOffset));
+  ThrowIf(greater_equal, kIndexIsTooLarge);
+
+  SmiCompare(index, Smi::FromInt(0));
+  ThrowIf(less, kIndexIsNegative);
+
+  // Restore the index
+  SmiToInteger32(index, index);
+}


 void MacroAssembler::PrepareCallCFunction(int num_arguments) {
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Nov 11 18:00:52 2013 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue Nov 19 16:41:07 2013 UTC
@@ -792,6 +792,11 @@
       Label* on_fail,
       Label::Distance near_jump = Label::kFar);

+  void EmitSeqStringSetCharCheck(Register string,
+                                 Register index,
+                                 Register value,
+                                 uint32_t encoding_mask);
+
   // Checks if the given register or operand is a unique name
   void JumpIfNotUniqueName(Register reg, Label* not_unique_name,
                            Label::Distance distance = Label::kFar);
@@ -1058,6 +1063,12 @@
   // Propagate an uncatchable exception out of the current JS stack.
   void ThrowUncatchable(Register value);

+  // Throw a message string as an exception.
+  void Throw(BailoutReason reason);
+
+  // Throw a message string as an exception if a condition is not true.
+  void ThrowIf(Condition cc, BailoutReason reason);
+
// ---------------------------------------------------------------------------
   // Inline caching support

=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives-part1.js Mon Nov 18 13:57:49 2013 UTC +++ /branches/bleeding_edge/test/mjsunit/fuzz-natives-part1.js Tue Nov 19 16:41:07 2013 UTC
@@ -116,6 +116,7 @@

 var knownProblems = {
   "Abort": true,
+  "ThrowMessage": true,

   // Avoid calling the concat operation, because weird lengths
   // may lead to out-of-memory.  Ditto for StringBuilderJoin.
=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives-part2.js Mon Nov 18 13:57:49 2013 UTC +++ /branches/bleeding_edge/test/mjsunit/fuzz-natives-part2.js Tue Nov 19 16:41:07 2013 UTC
@@ -116,6 +116,7 @@

 var knownProblems = {
   "Abort": true,
+  "ThrowMessage": true,

   // Avoid calling the concat operation, because weird lengths
   // may lead to out-of-memory.  Ditto for StringBuilderJoin.
=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives-part3.js Mon Nov 18 13:57:49 2013 UTC +++ /branches/bleeding_edge/test/mjsunit/fuzz-natives-part3.js Tue Nov 19 16:41:07 2013 UTC
@@ -116,6 +116,7 @@

 var knownProblems = {
   "Abort": true,
+  "ThrowMessage": true,

   // Avoid calling the concat operation, because weird lengths
   // may lead to out-of-memory.  Ditto for StringBuilderJoin.
=======================================
--- /branches/bleeding_edge/test/mjsunit/fuzz-natives-part4.js Mon Nov 18 13:57:49 2013 UTC +++ /branches/bleeding_edge/test/mjsunit/fuzz-natives-part4.js Tue Nov 19 16:41:07 2013 UTC
@@ -116,6 +116,7 @@

 var knownProblems = {
   "Abort": true,
+  "ThrowMessage": true,

   // Avoid calling the concat operation, because weird lengths
   // may lead to out-of-memory.  Ditto for StringBuilderJoin.

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to