Upgrade V8 to 2.2.21
authorRyan Dahl <ry@tinyclouds.org>
Sat, 3 Jul 2010 06:36:33 +0000 (08:36 +0200)
committerRyan Dahl <ry@tinyclouds.org>
Sat, 3 Jul 2010 06:37:05 +0000 (08:37 +0200)
54 files changed:
deps/v8/ChangeLog
deps/v8/benchmarks/README.txt
deps/v8/benchmarks/base.js
deps/v8/benchmarks/crypto.js
deps/v8/benchmarks/deltablue.js
deps/v8/benchmarks/earley-boyer.js
deps/v8/benchmarks/raytrace.js
deps/v8/benchmarks/regexp.js
deps/v8/benchmarks/revisions.html
deps/v8/benchmarks/richards.js
deps/v8/benchmarks/run.html
deps/v8/benchmarks/splay.js
deps/v8/src/arm/assembler-arm.cc
deps/v8/src/arm/assembler-arm.h
deps/v8/src/arm/codegen-arm.cc
deps/v8/src/arm/codegen-arm.h
deps/v8/src/arm/constants-arm.cc
deps/v8/src/arm/disasm-arm.cc
deps/v8/src/arm/ic-arm.cc
deps/v8/src/arm/macro-assembler-arm.cc
deps/v8/src/arm/macro-assembler-arm.h
deps/v8/src/arm/simulator-arm.cc
deps/v8/src/code-stubs.h
deps/v8/src/debug-debugger.js
deps/v8/src/handles.cc
deps/v8/src/handles.h
deps/v8/src/ia32/codegen-ia32.cc
deps/v8/src/json.js
deps/v8/src/jsregexp.cc
deps/v8/src/objects.cc
deps/v8/src/regexp-macro-assembler.cc
deps/v8/src/regexp.js
deps/v8/src/runtime.cc
deps/v8/src/runtime.js
deps/v8/src/type-info.h
deps/v8/src/version.cc
deps/v8/src/x64/assembler-x64.cc
deps/v8/src/x64/codegen-x64.cc
deps/v8/src/x64/disasm-x64.cc
deps/v8/src/x64/macro-assembler-x64.cc
deps/v8/src/x64/virtual-frame-x64.cc
deps/v8/test/cctest/SConscript
deps/v8/test/cctest/test-api.cc
deps/v8/test/cctest/test-disasm-arm.cc
deps/v8/test/cctest/test-type-info.cc [new file with mode: 0644]
deps/v8/test/es5conform/README
deps/v8/test/es5conform/es5conform.status
deps/v8/test/mjsunit/debug-setbreakpoint.js
deps/v8/test/mjsunit/math-sqrt.js
deps/v8/test/mjsunit/mod.js [new file with mode: 0644]
deps/v8/test/mjsunit/regress/regress-753.js [new file with mode: 0644]
deps/v8/test/mjsunit/to_number_order.js
deps/v8/test/mozilla/mozilla.status
deps/v8/tools/stats-viewer.py

index a8c6186..8b58faa 100644 (file)
@@ -1,3 +1,18 @@
+2010-06-30: Version 2.2.21
+
+        Fix bug in externalizing some ASCII strings (Chromium issue 47824).
+
+        Update JSON.stringify to floor the space parameter (issue 753).
+
+        Update the Mozilla test expectations to the newest version.
+
+        Update the ES5 Conformance Test expectations to the latest version.
+
+        Update the V8 benchmark suite.
+
+        Provide actual breakpoints locations in response to setBreakpoint
+        and listBreakpoints requests.
+
 2010-06-28: Version 2.2.20
         Fix bug with for-in on x64 platform (issue 748).
 
index 8e08159..800b4f5 100644 (file)
@@ -66,6 +66,12 @@ extensions enabled.
 Changes from Version 5 to Version 6
 ===================================
 
-Removed dead code from the RayTrace benchmark and changed the Splay
-benchmark to avoid converting the same numeric key to a string over
-and over again.
+Removed dead code from the RayTrace benchmark and fixed a couple of
+typos in the DeltaBlue implementation. Changed the Splay benchmark to
+avoid converting the same numeric key to a string over and over again
+and to avoid inserting and removing the same element repeatedly thus
+increasing pressure on the memory subsystem.
+
+Furthermore, the benchmark runner was changed to run the benchmarks
+for at least a few times to stabilize the reported numbers on slower
+machines.
index ce30841..0388da6 100644 (file)
@@ -198,15 +198,33 @@ BenchmarkSuite.prototype.NotifyError = function(error) {
 
 // Runs a single benchmark for at least a second and computes the
 // average time it takes to run a single iteration.
-BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark) {
-  var elapsed = 0;
-  var start = new Date();
-  for (var n = 0; elapsed < 1000; n++) {
-    benchmark.run();
-    elapsed = new Date() - start;
+BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) {
+  function Measure(data) {
+    var elapsed = 0;
+    var start = new Date();
+    for (var n = 0; elapsed < 1000; n++) {
+      benchmark.run();
+      elapsed = new Date() - start;
+    }
+    if (data != null) {
+      data.runs += n;
+      data.elapsed += elapsed;
+    }
+  }
+
+  if (data == null) {
+    // Measure the benchmark once for warm up and throw the result
+    // away. Return a fresh data object.
+    Measure(null);
+    return { runs: 0, elapsed: 0 };
+  } else {
+    Measure(data);
+    // If we've run too few iterations, we continue for another second.
+    if (data.runs < 32) return data;
+    var usec = (data.elapsed * 1000) / data.runs;
+    this.NotifyStep(new BenchmarkResult(benchmark, usec));
+    return null;
   }
-  var usec = (elapsed * 1000) / n;
-  this.NotifyStep(new BenchmarkResult(benchmark, usec));
 }
 
 
@@ -220,6 +238,7 @@ BenchmarkSuite.prototype.RunStep = function(runner) {
   var length = this.benchmarks.length;
   var index = 0;
   var suite = this;
+  var data;
 
   // Run the setup, the actual benchmark, and the tear down in three
   // separate steps to allow the framework to yield between any of the
@@ -241,12 +260,13 @@ BenchmarkSuite.prototype.RunStep = function(runner) {
 
   function RunNextBenchmark() {
     try {
-      suite.RunSingleBenchmark(suite.benchmarks[index]);
+      data = suite.RunSingleBenchmark(suite.benchmarks[index], data);
     } catch (e) {
       suite.NotifyError(e);
       return null;
     }
-    return RunNextTearDown;
+    // If data is null, we're done with this benchmark.
+    return (data == null) ? RunNextTearDown : RunNextBenchmark();
   }
 
   function RunNextTearDown() {
index 12b88ef..7e9829d 100644 (file)
@@ -31,7 +31,7 @@
 
 
 // The code has been adapted for use as a benchmark by Google.
-var Crypto = new BenchmarkSuite('Crypto', 203037, [
+var Crypto = new BenchmarkSuite('Crypto', 110465, [
   new Benchmark("Encrypt", encrypt),
   new Benchmark("Decrypt", decrypt)
 ]);
index 7e25d2e..4af8387 100644 (file)
 // more like a JavaScript program.
 
 
-var DeltaBlue = new BenchmarkSuite('DeltaBlue', 71104, [
+var DeltaBlue = new BenchmarkSuite('DeltaBlue', 30282, [
   new Benchmark('DeltaBlue', deltaBlue)
 ]);
 
 
 /**
- * A JavaScript implementation of the DeltaBlue constrain-solving
+ * A JavaScript implementation of the DeltaBlue constraint-solving
  * algorithm, as described in:
  *
  * "The DeltaBlue Algorithm: An Incremental Constraint Hierarchy Solver"
@@ -349,13 +349,13 @@ function BinaryConstraint(var1, var2, strength) {
 BinaryConstraint.inheritsFrom(Constraint);
 
 /**
- * Decides if this constratint can be satisfied and which way it
+ * Decides if this constraint can be satisfied and which way it
  * should flow based on the relative strength of the variables related,
  * and record that decision.
  */
 BinaryConstraint.prototype.chooseMethod = function (mark) {
   if (this.v1.mark == mark) {
-    this.direction = (this.v1.mark != mark && Strength.stronger(this.strength, this.v2.walkStrength))
+    this.direction = (this.v2.mark != mark && Strength.stronger(this.strength, this.v2.walkStrength))
       ? Direction.FORWARD
       : Direction.NONE;
   }
index 3c7f922..b1efe4a 100644 (file)
@@ -1,7 +1,7 @@
 // This file is automatically generated by scheme2js, except for the
 // benchmark harness code at the beginning and end of the file.
 
-var EarleyBoyer = new BenchmarkSuite('EarleyBoyer', 765819, [
+var EarleyBoyer = new BenchmarkSuite('EarleyBoyer', 280581, [
   new Benchmark("Earley", function () { BgL_earleyzd2benchmarkzd2(); }),
   new Benchmark("Boyer", function () { BgL_nboyerzd2benchmarkzd2(); })
 ]);
index da4d592..eaf61a1 100644 (file)
@@ -8,7 +8,7 @@
 // untouched. This file also contains a copy of parts of the Prototype
 // JavaScript framework which is used by the ray tracer.
 
-var RayTrace = new BenchmarkSuite('RayTrace', 932666, [
+var RayTrace = new BenchmarkSuite('RayTrace', 533115, [
   new Benchmark('RayTrace', renderScene)
 ]);
 
index dce15b8..f9f816c 100644 (file)
@@ -35,7 +35,7 @@
 // letters in the data are encoded using ROT13 in a way that does not
 // affect how the regexps match their input.
 
-var RegRxp = new BenchmarkSuite('RegExp', 995230, [
+var RegRxp = new BenchmarkSuite('RegExp', 601250, [
   new Benchmark("RegExp", runRegExpBenchmark)
 ]);
 
index b03aa12..1c54f63 100644 (file)
@@ -22,10 +22,15 @@ the benchmark suite.
 
 <div class="subtitle"><h3>Version 6 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v6/run.html">link</a>)</h3></div>
 
-<p>Removed dead code from the RayTrace benchmark and changed the Splay
-benchmark to avoid converting the same numeric key to a string over
-and over again.
-</p>
+<p>Removed dead code from the RayTrace benchmark and fixed a couple of
+typos in the DeltaBlue implementation. Changed the Splay benchmark to
+avoid converting the same numeric key to a string over and over again
+and to avoid inserting and removing the same element repeatedly thus
+increasing pressure on the memory subsystem.</p>
+
+<p>Furthermore, the benchmark runner was changed to run the benchmarks
+for at least a few times to stabilize the reported numbers on slower
+machines.</p>
 
 <div class="subtitle"><h3>Version 5 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v5/run.html">link</a>)</h3></div>
 
index c9368ef..b5736f7 100644 (file)
@@ -35,7 +35,7 @@
 // Martin Richards.
 
 
-var Richards = new BenchmarkSuite('Richards', 34886, [
+var Richards = new BenchmarkSuite('Richards', 20687, [
   new Benchmark("Richards", runRichards)
 ]);
 
index 30036b7..05bfffe 100644 (file)
@@ -116,7 +116,7 @@ higher scores means better performance: <em>Bigger is better!</em>
 <li><b>RegExp</b><br>Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages
 (<i>1614 lines</i>).
 </li>
-<li><b>Splay</b><br>Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (<i>379 lines</i>).</li>
+<li><b>Splay</b><br>Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (<i>394 lines</i>).</li>
 </ul>
 
 <p>
index d8c8f04..d63ab8b 100644 (file)
@@ -33,7 +33,7 @@
 // also has to deal with a lot of changes to the large tree object
 // graph.
 
-var Splay = new BenchmarkSuite('Splay', 126125, [
+var Splay = new BenchmarkSuite('Splay', 21915, [
   new Benchmark("Splay", SplayRun, SplaySetup, SplayTearDown)
 ]);
 
@@ -231,8 +231,23 @@ SplayTree.prototype.find = function(key) {
 
 
 /**
+ * @return {SplayTree.Node} Node having the maximum key value.
+ */
+SplayTree.prototype.findMax = function(opt_startNode) {
+  if (this.isEmpty()) {
+    return null;
+  }
+  var current = opt_startNode || this.root_;
+  while (current.right) {
+    current = current.right;
+  }
+  return current;
+};
+
+
+/**
  * @return {SplayTree.Node} Node having the maximum key value that
- *     is less or equal to the specified key value.
+ *     is less than the specified key value.
  */
 SplayTree.prototype.findGreatestLessThan = function(key) {
   if (this.isEmpty()) {
@@ -243,7 +258,7 @@ SplayTree.prototype.findGreatestLessThan = function(key) {
   this.splay_(key);
   // Now the result is either the root node or the greatest node in
   // the left subtree.
-  if (this.root_.key <= key) {
+  if (this.root_.key < key) {
     return this.root_;
   } else if (this.root_.left) {
     return this.findMax(this.root_.left);
index f8d98db..c8170b3 100644 (file)
@@ -2112,6 +2112,18 @@ void Assembler::vmrs(Register dst, Condition cond) {
 }
 
 
+
+void Assembler::vsqrt(const DwVfpRegister dst,
+                      const DwVfpRegister src,
+                      const Condition cond) {
+  // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) |
+  // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0)
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 |
+       dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code());
+}
+
+
 // Pseudo instructions.
 void Assembler::nop(int type) {
   // This is mov rx, rx.
index 54b584a..8a4173d 100644 (file)
@@ -988,6 +988,9 @@ class Assembler : public Malloced {
             const Condition cond = al);
   void vmrs(const Register dst,
             const Condition cond = al);
+  void vsqrt(const DwVfpRegister dst,
+             const DwVfpRegister src,
+             const Condition cond = al);
 
   // Pseudo instructions
   void nop(int type = 0);
index b6639ae..f923c09 100644 (file)
@@ -4279,22 +4279,147 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
 }
 
 
-// Generates the Math.pow method - currently just calls runtime.
+// Generates the Math.pow method.
 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 2);
   Load(args->at(0));
   Load(args->at(1));
-  frame_->CallRuntime(Runtime::kMath_pow, 2);
-  frame_->EmitPush(r0);
+
+  if (!CpuFeatures::IsSupported(VFP3)) {
+    frame_->CallRuntime(Runtime::kMath_pow, 2);
+    frame_->EmitPush(r0);
+  } else {
+    CpuFeatures::Scope scope(VFP3);
+    JumpTarget runtime, done;
+    Label not_minus_half, allocate_return;
+
+    Register scratch1 = VirtualFrame::scratch0();
+    Register scratch2 = VirtualFrame::scratch1();
+
+    // Get base and exponent to registers.
+    Register exponent = frame_->PopToRegister();
+    Register base = frame_->PopToRegister(exponent);
+
+    // Set the frame for the runtime jump target. The code below jumps to the
+    // jump target label so the frame needs to be established before that.
+    ASSERT(runtime.entry_frame() == NULL);
+    runtime.set_entry_frame(frame_);
+
+    __ BranchOnSmi(exponent, runtime.entry_label());
+
+    // Special handling of raising to the power of -0.5 and 0.5. First check
+    // that the value is a heap number and that the lower bits (which for both
+    // values are zero).
+    Register heap_number_map = r6;
+    __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+    __ ldr(scratch1, FieldMemOperand(exponent, HeapObject::kMapOffset));
+    __ ldr(scratch2, FieldMemOperand(exponent, HeapNumber::kMantissaOffset));
+    __ cmp(scratch1, heap_number_map);
+    runtime.Branch(ne);
+    __ tst(scratch2, scratch2);
+    runtime.Branch(ne);
+
+    // Load the e
+    __ ldr(scratch1, FieldMemOperand(exponent, HeapNumber::kExponentOffset));
+
+    // Compare exponent with -0.5.
+    __ cmp(scratch1, Operand(0xbfe00000));
+    __ b(ne, &not_minus_half);
+
+    // Get the double value from the base into vfp register d0.
+    __ ObjectToDoubleVFPRegister(base, d0,
+                                 scratch1, scratch2, heap_number_map, s0,
+                                 runtime.entry_label(),
+                                 AVOID_NANS_AND_INFINITIES);
+
+    // Load 1.0 into d2.
+    __ mov(scratch2, Operand(0x3ff00000));
+    __ mov(scratch1, Operand(0));
+    __ vmov(d2, scratch1, scratch2);
+
+    // Calculate the reciprocal of the square root. 1/sqrt(x) = sqrt(1/x).
+    __ vdiv(d0, d2, d0);
+    __ vsqrt(d0, d0);
+
+    __ b(&allocate_return);
+
+    __ bind(&not_minus_half);
+    // Compare exponent with 0.5.
+    __ cmp(scratch1, Operand(0x3fe00000));
+    runtime.Branch(ne);
+
+      // Get the double value from the base into vfp register d0.
+    __ ObjectToDoubleVFPRegister(base, d0,
+                                 scratch1, scratch2, heap_number_map, s0,
+                                 runtime.entry_label(),
+                                 AVOID_NANS_AND_INFINITIES);
+    __ vsqrt(d0, d0);
+
+    __ bind(&allocate_return);
+    __ AllocateHeapNumberWithValue(
+        base, d0, scratch1, scratch2, heap_number_map, runtime.entry_label());
+    done.Jump();
+
+    runtime.Bind();
+
+    // Push back the arguments again for the runtime call.
+    frame_->EmitPush(base);
+    frame_->EmitPush(exponent);
+    frame_->CallRuntime(Runtime::kMath_pow, 2);
+    __ Move(base, r0);
+
+    done.Bind();
+    frame_->EmitPush(base);
+  }
 }
 
 
-// Generates the Math.sqrt method - currently just calls runtime.
+// Generates the Math.sqrt method.
 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
   ASSERT(args->length() == 1);
   Load(args->at(0));
-  frame_->CallRuntime(Runtime::kMath_sqrt, 1);
-  frame_->EmitPush(r0);
+
+  if (!CpuFeatures::IsSupported(VFP3)) {
+    frame_->CallRuntime(Runtime::kMath_sqrt, 1);
+    frame_->EmitPush(r0);
+  } else {
+    CpuFeatures::Scope scope(VFP3);
+    JumpTarget runtime, done;
+
+    Register scratch1 = VirtualFrame::scratch0();
+    Register scratch2 = VirtualFrame::scratch1();
+
+    // Get the value from the frame.
+    Register tos = frame_->PopToRegister();
+
+    // Set the frame for the runtime jump target. The code below jumps to the
+    // jump target label so the frame needs to be established before that.
+    ASSERT(runtime.entry_frame() == NULL);
+    runtime.set_entry_frame(frame_);
+
+    Register heap_number_map = r6;
+    __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
+    // Get the double value from the heap number into vfp register d0.
+    __ ObjectToDoubleVFPRegister(tos, d0,
+                                 scratch1, scratch2, heap_number_map, s0,
+                                 runtime.entry_label());
+
+    // Calculate the square root of d0 and place result in a heap number object.
+    __ vsqrt(d0, d0);
+    __ AllocateHeapNumberWithValue(
+        tos, d0, scratch1, scratch2, heap_number_map, runtime.entry_label());
+    done.Jump();
+
+    runtime.Bind();
+    // Push back the argument again for the runtime call.
+    frame_->EmitPush(tos);
+    frame_->CallRuntime(Runtime::kMath_sqrt, 1);
+    __ Move(tos, r0);
+
+    done.Bind();
+    frame_->EmitPush(tos);
+  }
 }
 
 
@@ -6257,7 +6382,6 @@ bool CodeGenerator::HasValidEntryRegisters() { return true; }
 #undef __
 #define __ ACCESS_MASM(masm)
 
-
 Handle<String> Reference::GetName() {
   ASSERT(type_ == NAMED);
   Property* property = expression_->AsProperty();
@@ -6621,7 +6745,7 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
   __ bind(&not_special);
   // Count leading zeros.  Uses mantissa for a scratch register on pre-ARM5.
   // Gets the wrong answer for 0, but we already checked for that case above.
-  __ CountLeadingZeros(source_, mantissa, zeros_);
+  __ CountLeadingZeros(zeros_, source_, mantissa);
   // Compute exponent and or it into the exponent register.
   // We use mantissa as a scratch register here.  Use a fudge factor to
   // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts
@@ -7350,7 +7474,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
 
     // If we have floating point hardware, inline ADD, SUB, MUL, and DIV,
     // using registers d7 and d6 for the double values.
-    if (use_fp_registers) {
+    if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       __ mov(r7, Operand(rhs, ASR, kSmiTagSize));
       __ vmov(s15, r7);
@@ -7358,8 +7482,12 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
       __ mov(r7, Operand(lhs, ASR, kSmiTagSize));
       __ vmov(s13, r7);
       __ vcvt_f64_s32(d6, s13);
+      if (!use_fp_registers) {
+        __ vmov(r2, r3, d7);
+        __ vmov(r0, r1, d6);
+      }
     } else {
-      // Write Smi from rhs to r3 and r2 in double format.  r3 is scratch.
+      // Write Smi from rhs to r3 and r2 in double format.  r9 is scratch.
       __ mov(r7, Operand(rhs));
       ConvertToDoubleStub stub1(r3, r2, r7, r9);
       __ push(lr);
@@ -7434,12 +7562,15 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
     __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
     }
 
-    if (use_fp_registers) {
+    if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       // Convert smi in r0 to double in d7.
       __ mov(r7, Operand(r0, ASR, kSmiTagSize));
       __ vmov(s15, r7);
       __ vcvt_f64_s32(d7, s15);
+      if (!use_fp_registers) {
+        __ vmov(r2, r3, d7);
+      }
     } else {
       // Write Smi from r0 to r3 and r2 in double format.
       __ mov(r7, Operand(r0));
@@ -7490,12 +7621,15 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
     __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
     }
 
-    if (use_fp_registers) {
+    if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
       // Convert smi in r1 to double in d6.
       __ mov(r7, Operand(r1, ASR, kSmiTagSize));
       __ vmov(s13, r7);
       __ vcvt_f64_s32(d6, s13);
+      if (!use_fp_registers) {
+        __ vmov(r0, r1, d6);
+      }
     } else {
       // Write Smi from r1 to r1 and r0 in double format.
       __ mov(r7, Operand(r1));
@@ -7942,6 +8076,173 @@ static void MultiplyByKnownInt2(
 }
 
 
+// This uses versions of the sum-of-digits-to-see-if-a-number-is-divisible-by-3
+// trick.  See http://en.wikipedia.org/wiki/Divisibility_rule
+// Takes the sum of the digits base (mask + 1) repeatedly until we have a
+// number from 0 to mask.  On exit the 'eq' condition flags are set if the
+// answer is exactly the mask.
+void IntegerModStub::DigitSum(MacroAssembler* masm,
+                              Register lhs,
+                              int mask,
+                              int shift,
+                              Label* entry) {
+  ASSERT(mask > 0);
+  ASSERT(mask <= 0xff);  // This ensures we don't need ip to use it.
+  Label loop;
+  __ bind(&loop);
+  __ and_(ip, lhs, Operand(mask));
+  __ add(lhs, ip, Operand(lhs, LSR, shift));
+  __ bind(entry);
+  __ cmp(lhs, Operand(mask));
+  __ b(gt, &loop);
+}
+
+
+void IntegerModStub::DigitSum(MacroAssembler* masm,
+                              Register lhs,
+                              Register scratch,
+                              int mask,
+                              int shift1,
+                              int shift2,
+                              Label* entry) {
+  ASSERT(mask > 0);
+  ASSERT(mask <= 0xff);  // This ensures we don't need ip to use it.
+  Label loop;
+  __ bind(&loop);
+  __ bic(scratch, lhs, Operand(mask));
+  __ and_(ip, lhs, Operand(mask));
+  __ add(lhs, ip, Operand(lhs, LSR, shift1));
+  __ add(lhs, lhs, Operand(scratch, LSR, shift2));
+  __ bind(entry);
+  __ cmp(lhs, Operand(mask));
+  __ b(gt, &loop);
+}
+
+
+// Splits the number into two halves (bottom half has shift bits).  The top
+// half is subtracted from the bottom half.  If the result is negative then
+// rhs is added.
+void IntegerModStub::ModGetInRangeBySubtraction(MacroAssembler* masm,
+                                                Register lhs,
+                                                int shift,
+                                                int rhs) {
+  int mask = (1 << shift) - 1;
+  __ and_(ip, lhs, Operand(mask));
+  __ sub(lhs, ip, Operand(lhs, LSR, shift), SetCC);
+  __ add(lhs, lhs, Operand(rhs), LeaveCC, mi);
+}
+
+
+void IntegerModStub::ModReduce(MacroAssembler* masm,
+                               Register lhs,
+                               int max,
+                               int denominator) {
+  int limit = denominator;
+  while (limit * 2 <= max) limit *= 2;
+  while (limit >= denominator) {
+    __ cmp(lhs, Operand(limit));
+    __ sub(lhs, lhs, Operand(limit), LeaveCC, ge);
+    limit >>= 1;
+  }
+}
+
+
+void IntegerModStub::ModAnswer(MacroAssembler* masm,
+                               Register result,
+                               Register shift_distance,
+                               Register mask_bits,
+                               Register sum_of_digits) {
+  __ add(result, mask_bits, Operand(sum_of_digits, LSL, shift_distance));
+  __ Ret();
+}
+
+
+// See comment for class.
+void IntegerModStub::Generate(MacroAssembler* masm) {
+  __ mov(lhs_, Operand(lhs_, LSR, shift_distance_));
+  __ bic(odd_number_, odd_number_, Operand(1));
+  __ mov(odd_number_, Operand(odd_number_, LSL, 1));
+  // We now have (odd_number_ - 1) * 2 in the register.
+  // Build a switch out of branches instead of data because it avoids
+  // having to teach the assembler about intra-code-object pointers
+  // that are not in relative branch instructions.
+  Label mod3, mod5, mod7, mod9, mod11, mod13, mod15, mod17, mod19;
+  Label mod21, mod23, mod25;
+  { Assembler::BlockConstPoolScope block_const_pool(masm);
+    __ add(pc, pc, Operand(odd_number_));
+    // When you read pc it is always 8 ahead, but when you write it you always
+    // write the actual value.  So we put in two nops to take up the slack.
+    __ nop();
+    __ nop();
+    __ b(&mod3);
+    __ b(&mod5);
+    __ b(&mod7);
+    __ b(&mod9);
+    __ b(&mod11);
+    __ b(&mod13);
+    __ b(&mod15);
+    __ b(&mod17);
+    __ b(&mod19);
+    __ b(&mod21);
+    __ b(&mod23);
+    __ b(&mod25);
+  }
+
+  // For each denominator we find a multiple that is almost only ones
+  // when expressed in binary.  Then we do the sum-of-digits trick for
+  // that number.  If the multiple is not 1 then we have to do a little
+  // more work afterwards to get the answer into the 0-denominator-1
+  // range.
+  DigitSum(masm, lhs_, 3, 2, &mod3);  // 3 = b11.
+  __ sub(lhs_, lhs_, Operand(3), LeaveCC, eq);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, 0xf, 4, &mod5);  // 5 * 3 = b1111.
+  ModGetInRangeBySubtraction(masm, lhs_, 2, 5);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, 7, 3, &mod7);  // 7 = b111.
+  __ sub(lhs_, lhs_, Operand(7), LeaveCC, eq);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, 0x3f, 6, &mod9);  // 7 * 9 = b111111.
+  ModGetInRangeBySubtraction(masm, lhs_, 3, 9);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, r5, 0x3f, 6, 3, &mod11);  // 5 * 11 = b110111.
+  ModReduce(masm, lhs_, 0x3f, 11);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, r5, 0xff, 8, 5, &mod13);  // 19 * 13 = b11110111.
+  ModReduce(masm, lhs_, 0xff, 13);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, 0xf, 4, &mod15);  // 15 = b1111.
+  __ sub(lhs_, lhs_, Operand(15), LeaveCC, eq);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, 0xff, 8, &mod17);  // 15 * 17 = b11111111.
+  ModGetInRangeBySubtraction(masm, lhs_, 4, 17);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, r5, 0xff, 8, 5, &mod19);  // 13 * 19 = b11110111.
+  ModReduce(masm, lhs_, 0xff, 19);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, 0x3f, 6, &mod21);  // 3 * 21 = b111111.
+  ModReduce(masm, lhs_, 0x3f, 21);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, r5, 0xff, 8, 7, &mod23);  // 11 * 23 = b11111101.
+  ModReduce(masm, lhs_, 0xff, 23);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+
+  DigitSum(masm, lhs_, r5, 0x7f, 7, 6, &mod25);  // 5 * 25 = b1111101.
+  ModReduce(masm, lhs_, 0x7f, 25);
+  ModAnswer(masm, result_, shift_distance_, mask_bits_, lhs_);
+}
+
+
 const char* GenericBinaryOpStub::GetName() {
   if (name_ != NULL) return name_;
   const int len = 100;
@@ -8069,7 +8370,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
     case Token::MOD: {
       Label not_smi;
       if (ShouldGenerateSmiCode() && specialized_on_rhs_) {
-        Label smi_is_unsuitable;
+        Label lhs_is_unsuitable;
         __ BranchOnNotSmi(lhs, &not_smi);
         if (IsPowerOf2(constant_rhs_)) {
           if (op_ == Token::MOD) {
@@ -8090,14 +8391,14 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
             __ eor(rhs, rhs, Operand(0x80000000u), SetCC);
             // Next two instructions are conditional on the answer being -0.
             __ mov(rhs, Operand(Smi::FromInt(constant_rhs_)), LeaveCC, eq);
-            __ b(eq, &smi_is_unsuitable);
+            __ b(eq, &lhs_is_unsuitable);
             // We need to subtract the dividend.  Eg. -3 % 4 == -3.
             __ sub(result, rhs, Operand(Smi::FromInt(constant_rhs_)));
           } else {
             ASSERT(op_ == Token::DIV);
             __ tst(lhs,
                    Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1)));
-            __ b(ne, &smi_is_unsuitable);  // Go slow on negative or remainder.
+            __ b(ne, &lhs_is_unsuitable);  // Go slow on negative or remainder.
             int shift = 0;
             int d = constant_rhs_;
             while ((d & 1) == 0) {
@@ -8110,7 +8411,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
         } else {
           // Not a power of 2.
           __ tst(lhs, Operand(0x80000000u));
-          __ b(ne, &smi_is_unsuitable);
+          __ b(ne, &lhs_is_unsuitable);
           // Find a fixed point reciprocal of the divisor so we can divide by
           // multiplying.
           double divisor = 1.0 / constant_rhs_;
@@ -8145,7 +8446,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
           // (lhs / rhs) where / indicates integer division.
           if (op_ == Token::DIV) {
             __ cmp(lhs, Operand(scratch, LSL, required_scratch_shift));
-            __ b(ne, &smi_is_unsuitable);  // There was a remainder.
+            __ b(ne, &lhs_is_unsuitable);  // There was a remainder.
             __ mov(result, Operand(scratch2, LSL, kSmiTagSize));
           } else {
             ASSERT(op_ == Token::MOD);
@@ -8153,14 +8454,21 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
           }
         }
         __ Ret();
-        __ bind(&smi_is_unsuitable);
+        __ bind(&lhs_is_unsuitable);
       } else if (op_ == Token::MOD &&
                  runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
                  runtime_operands_type_ != BinaryOpIC::STRINGS) {
         // Do generate a bit of smi code for modulus even though the default for
         // modulus is not to do it, but as the ARM processor has no coprocessor
-        // support for modulus checking for smis makes sense.
+        // support for modulus checking for smis makes sense.  We can handle
+        // 1 to 25 times any power of 2.  This covers over half the numbers from
+        // 1 to 100 including all of the first 25.  (Actually the constants < 10
+        // are handled above by reciprocal multiplication.  We only get here for
+        // those cases if the right hand side is not a constant or for cases
+        // like 192 which is 3*2^6 and ends up in the 3 case in the integer mod
+        // stub.)
         Label slow;
+        Label not_power_of_2;
         ASSERT(!ShouldGenerateSmiCode());
         ASSERT(kSmiTag == 0);  // Adjust code below.
         // Check for two positive smis.
@@ -8168,13 +8476,42 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
         __ tst(smi_test_reg, Operand(0x80000000u | kSmiTagMask));
         __ b(ne, &slow);
         // Check that rhs is a power of two and not zero.
+        Register mask_bits = r3;
         __ sub(scratch, rhs, Operand(1), SetCC);
         __ b(mi, &slow);
-        __ tst(rhs, scratch);
-        __ b(ne, &slow);
+        __ and_(mask_bits, rhs, Operand(scratch), SetCC);
+        __ b(ne, &not_power_of_2);
         // Calculate power of two modulus.
         __ and_(result, lhs, Operand(scratch));
         __ Ret();
+
+        __ bind(&not_power_of_2);
+        __ eor(scratch, scratch, Operand(mask_bits));
+        // At least two bits are set in the modulus.  The high one(s) are in
+        // mask_bits and the low one is scratch + 1.
+        __ and_(mask_bits, scratch, Operand(lhs));
+        Register shift_distance = scratch;
+        scratch = no_reg;
+
+        // The rhs consists of a power of 2 multiplied by some odd number.
+        // The power-of-2 part we handle by putting the corresponding bits
+        // from the lhs in the mask_bits register, and the power in the
+        // shift_distance register.  Shift distance is never 0 due to Smi
+        // tagging.
+        __ CountLeadingZeros(r4, shift_distance, shift_distance);
+        __ rsb(shift_distance, r4, Operand(32));
+
+        // Now we need to find out what the odd number is. The last bit is
+        // always 1.
+        Register odd_number = r4;
+        __ mov(odd_number, Operand(rhs, LSR, shift_distance));
+        __ cmp(odd_number, Operand(25));
+        __ b(gt, &slow);
+
+        IntegerModStub stub(
+            result, shift_distance, odd_number, mask_bits, lhs, r5);
+        __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);  // Tail call.
+
         __ bind(&slow);
       }
       HandleBinaryOpSlowCases(
index 925d267..2d8a935 100644 (file)
@@ -881,6 +881,102 @@ class StringCompareStub: public CodeStub {
 };
 
 
+// This stub can do a fast mod operation without using fp.
+// It is tail called from the GenericBinaryOpStub and it always
+// returns an answer.  It never causes GC so it doesn't need a real frame.
+//
+// The inputs are always positive Smis.  This is never called
+// where the denominator is a power of 2.  We handle that separately.
+//
+// If we consider the denominator as an odd number multiplied by a power of 2,
+// then:
+// * The exponent (power of 2) is in the shift_distance register.
+// * The odd number is in the odd_number register.  It is always in the range
+//   of 3 to 25.
+// * The bits from the numerator that are to be copied to the answer (there are
+//   shift_distance of them) are in the mask_bits register.
+// * The other bits of the numerator have been shifted down and are in the lhs
+//   register.
+class IntegerModStub : public CodeStub {
+ public:
+  IntegerModStub(Register result,
+                 Register shift_distance,
+                 Register odd_number,
+                 Register mask_bits,
+                 Register lhs,
+                 Register scratch)
+      : result_(result),
+        shift_distance_(shift_distance),
+        odd_number_(odd_number),
+        mask_bits_(mask_bits),
+        lhs_(lhs),
+        scratch_(scratch) {
+    // We don't code these in the minor key, so they should always be the same.
+    // We don't really want to fix that since this stub is rather large and we
+    // don't want many copies of it.
+    ASSERT(shift_distance_.is(r9));
+    ASSERT(odd_number_.is(r4));
+    ASSERT(mask_bits_.is(r3));
+    ASSERT(scratch_.is(r5));
+  }
+
+ private:
+  Register result_;
+  Register shift_distance_;
+  Register odd_number_;
+  Register mask_bits_;
+  Register lhs_;
+  Register scratch_;
+
+  // Minor key encoding in 16 bits.
+  class ResultRegisterBits: public BitField<int, 0, 4> {};
+  class LhsRegisterBits: public BitField<int, 4, 4> {};
+
+  Major MajorKey() { return IntegerMod; }
+  int MinorKey() {
+    // Encode the parameters in a unique 16 bit value.
+    return ResultRegisterBits::encode(result_.code())
+           | LhsRegisterBits::encode(lhs_.code());
+  }
+
+  void Generate(MacroAssembler* masm);
+
+  const char* GetName() { return "IntegerModStub"; }
+
+  // Utility functions.
+  void DigitSum(MacroAssembler* masm,
+                Register lhs,
+                int mask,
+                int shift,
+                Label* entry);
+  void DigitSum(MacroAssembler* masm,
+                Register lhs,
+                Register scratch,
+                int mask,
+                int shift1,
+                int shift2,
+                Label* entry);
+  void ModGetInRangeBySubtraction(MacroAssembler* masm,
+                                  Register lhs,
+                                  int shift,
+                                  int rhs);
+  void ModReduce(MacroAssembler* masm,
+                 Register lhs,
+                 int max,
+                 int denominator);
+  void ModAnswer(MacroAssembler* masm,
+                 Register result,
+                 Register shift_distance,
+                 Register mask_bits,
+                 Register sum_of_digits);
+
+
+#ifdef DEBUG
+  void Print() { PrintF("IntegerModStub\n"); }
+#endif
+};
+
+
 // This stub can convert a signed int32 to a heap number (double).  It does
 // not work for int32s that are in Smi range!  No GC occurs during this stub
 // so you don't have to set up the frame.
index 4e186d1..002e4c1 100644 (file)
@@ -85,7 +85,7 @@ const char* VFPRegisters::names_[kNumVFPRegisters] = {
 
 const char* VFPRegisters::Name(int reg, bool is_double) {
   ASSERT((0 <= reg) && (reg < kNumVFPRegisters));
-  return names_[reg + is_double ? kNumVFPSingleRegisters : 0];
+  return names_[reg + (is_double ? kNumVFPSingleRegisters : 0)];
 }
 
 
index 4005369..fb17d45 100644 (file)
@@ -1038,7 +1038,8 @@ void Decoder::DecodeUnconditional(Instr* instr) {
 // Dd = vmul(Dn, Dm)
 // Dd = vdiv(Dn, Dm)
 // vcmp(Dd, Dm)
-// VMRS
+// vmrs
+// Dd = vsqrt(Dm)
 void Decoder::DecodeTypeVFP(Instr* instr) {
   ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
   ASSERT(instr->Bits(11, 9) == 0x5);
@@ -1056,6 +1057,8 @@ void Decoder::DecodeTypeVFP(Instr* instr) {
       } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
                  (instr->Opc3Field() & 0x1)) {
         DecodeVCMP(instr);
+      } else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) {
+        Format(instr, "vsqrt.f64'cond 'Dd, 'Dm");
       } else {
         Unknown(instr);  // Not used by V8.
       }
index 134dfa3..0af1036 100644 (file)
@@ -1722,7 +1722,7 @@ static void ConvertIntToFloat(MacroAssembler* masm,
     // Count leading zeros.
     // Gets the wrong answer for 0, but we already checked for that case above.
     Register zeros = scratch2;
-    __ CountLeadingZeros(ival, scratch1, zeros);
+    __ CountLeadingZeros(zeros, ival, scratch1);
 
     // Compute exponent and or it into the exponent register.
     __ rsb(scratch1,
index df7565f..630e0b8 100644 (file)
@@ -1369,6 +1369,56 @@ void MacroAssembler::IntegerToDoubleConversionWithVFP3(Register inReg,
 }
 
 
+void MacroAssembler::ObjectToDoubleVFPRegister(Register object,
+                                               DwVfpRegister result,
+                                               Register scratch1,
+                                               Register scratch2,
+                                               Register heap_number_map,
+                                               SwVfpRegister scratch3,
+                                               Label* not_number,
+                                               ObjectToDoubleFlags flags) {
+  Label done;
+  if ((flags & OBJECT_NOT_SMI) == 0) {
+    Label not_smi;
+    BranchOnNotSmi(object, &not_smi);
+    // Remove smi tag and convert to double.
+    mov(scratch1, Operand(object, ASR, kSmiTagSize));
+    vmov(scratch3, scratch1);
+    vcvt_f64_s32(result, scratch3);
+    b(&done);
+    bind(&not_smi);
+  }
+  // Check for heap number and load double value from it.
+  ldr(scratch1, FieldMemOperand(object, HeapObject::kMapOffset));
+  sub(scratch2, object, Operand(kHeapObjectTag));
+  cmp(scratch1, heap_number_map);
+  b(ne, not_number);
+  if ((flags & AVOID_NANS_AND_INFINITIES) != 0) {
+    // If exponent is all ones the number is either a NaN or +/-Infinity.
+    ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
+    Sbfx(scratch1,
+         scratch1,
+         HeapNumber::kExponentShift,
+         HeapNumber::kExponentBits);
+    // All-one value sign extend to -1.
+    cmp(scratch1, Operand(-1));
+    b(eq, not_number);
+  }
+  vldr(result, scratch2, HeapNumber::kValueOffset);
+  bind(&done);
+}
+
+
+void MacroAssembler::SmiToDoubleVFPRegister(Register smi,
+                                            DwVfpRegister value,
+                                            Register scratch1,
+                                            SwVfpRegister scratch2) {
+  mov(scratch1, Operand(smi, ASR, kSmiTagSize));
+  vmov(scratch2, scratch1);
+  vcvt_f64_s32(value, scratch2);
+}
+
+
 void MacroAssembler::GetLeastBitsFromSmi(Register dst,
                                          Register src,
                                          int num_least_bits) {
@@ -1686,14 +1736,31 @@ void MacroAssembler::AllocateHeapNumber(Register result,
 }
 
 
-void MacroAssembler::CountLeadingZeros(Register source,
-                                       Register scratch,
-                                       Register zeros) {
+void MacroAssembler::AllocateHeapNumberWithValue(Register result,
+                                                 DwVfpRegister value,
+                                                 Register scratch1,
+                                                 Register scratch2,
+                                                 Register heap_number_map,
+                                                 Label* gc_required) {
+  AllocateHeapNumber(result, scratch1, scratch2, heap_number_map, gc_required);
+  sub(scratch1, result, Operand(kHeapObjectTag));
+  vstr(value, scratch1, HeapNumber::kValueOffset);
+}
+
+
+void MacroAssembler::CountLeadingZeros(Register zeros,   // Answer.
+                                       Register source,  // Input.
+                                       Register scratch) {
+  ASSERT(!zeros.is(source) || !source.is(zeros));
+  ASSERT(!zeros.is(scratch));
+  ASSERT(!scratch.is(ip));
+  ASSERT(!source.is(ip));
+  ASSERT(!zeros.is(ip));
 #ifdef CAN_USE_ARMV5_INSTRUCTIONS
   clz(zeros, source);  // This instruction is only supported after ARM5.
 #else
   mov(zeros, Operand(0));
-  mov(scratch, source);
+  Move(scratch, source);
   // Top 16.
   tst(scratch, Operand(0xffff0000));
   add(zeros, zeros, Operand(16), LeaveCC, eq);
index e02a6c8..c3f45a6 100644 (file)
@@ -67,6 +67,17 @@ enum AllocationFlags {
 };
 
 
+// Flags used for the ObjectToDoubleVFPRegister function.
+enum ObjectToDoubleFlags {
+  // No special flags.
+  NO_OBJECT_TO_DOUBLE_FLAGS = 0,
+  // Object is known to be a non smi.
+  OBJECT_NOT_SMI = 1 << 0,
+  // Don't load NaNs or infinities, branch to the non number case instead.
+  AVOID_NANS_AND_INFINITIES = 1 << 1
+};
+
+
 // MacroAssembler implements a collection of frequently used macros.
 class MacroAssembler: public Assembler {
  public:
@@ -381,6 +392,13 @@ class MacroAssembler: public Assembler {
                           Register scratch2,
                           Register heap_number_map,
                           Label* gc_required);
+  void AllocateHeapNumberWithValue(Register result,
+                                   DwVfpRegister value,
+                                   Register scratch1,
+                                   Register scratch2,
+                                   Register heap_number_map,
+                                   Label* gc_required);
+
 
   // ---------------------------------------------------------------------------
   // Support functions.
@@ -469,12 +487,35 @@ class MacroAssembler: public Assembler {
                                          Register outHighReg,
                                          Register outLowReg);
 
+  // Load the value of a number object into a VFP double register. If the object
+  // is not a number a jump to the label not_number is performed and the VFP
+  // double register is unchanged.
+  void ObjectToDoubleVFPRegister(
+      Register object,
+      DwVfpRegister value,
+      Register scratch1,
+      Register scratch2,
+      Register heap_number_map,
+      SwVfpRegister scratch3,
+      Label* not_number,
+      ObjectToDoubleFlags flags = NO_OBJECT_TO_DOUBLE_FLAGS);
+
+  // Load the value of a smi object into a VFP double register. The register
+  // scratch1 can be the same register as smi in which case smi will hold the
+  // untagged value afterwards.
+  void SmiToDoubleVFPRegister(Register smi,
+                              DwVfpRegister value,
+                              Register scratch1,
+                              SwVfpRegister scratch2);
+
   // Count leading zeros in a 32 bit word.  On ARM5 and later it uses the clz
   // instruction.  On pre-ARM5 hardware this routine gives the wrong answer
-  // for 0 (31 instead of 32).
-  void CountLeadingZeros(Register source,
-                         Register scratch,
-                         Register zeros);
+  // for 0 (31 instead of 32).  Source and scratch can be the same in which case
+  // the source is clobbered.  Source and zeros can also be the same in which
+  // case scratch should be a different register.
+  void CountLeadingZeros(Register zeros,
+                         Register source,
+                         Register scratch);
 
   // ---------------------------------------------------------------------------
   // Runtime calls
index 77776c2..6240cd4 100644 (file)
@@ -26,6 +26,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <stdlib.h>
+#include <math.h>
 #include <cstdarg>
 #include "v8.h"
 
@@ -2262,7 +2263,8 @@ static int GlueRegCode(bool last_bit, int vm, int m) {
 // Dd = vmul(Dn, Dm)
 // Dd = vdiv(Dn, Dm)
 // vcmp(Dd, Dm)
-// VMRS
+// vmrs
+// Dd = vsqrt(Dm)
 void Simulator::DecodeTypeVFP(Instr* instr) {
   ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
   ASSERT(instr->Bits(11, 9) == 0x5);
@@ -2284,6 +2286,11 @@ void Simulator::DecodeTypeVFP(Instr* instr) {
       } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
                  (instr->Opc3Field() & 0x1)) {
         DecodeVCMP(instr);
+      } else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) {
+        // vsqrt
+        double dm_value = get_double_from_d_register(vm);
+        double dd_value = sqrt(dm_value);
+        set_d_register_from_double(vd, dd_value);
       } else {
         UNREACHABLE();  // Not used by V8.
       }
index de2ad56..e5a222f 100644 (file)
@@ -46,6 +46,7 @@ namespace internal {
   V(RecordWrite)                         \
   V(ConvertToDouble)                     \
   V(WriteInt32ToHeapNumber)              \
+  V(IntegerMod)                          \
   V(StackCheck)                          \
   V(FastNewClosure)                      \
   V(FastNewContext)                      \
index d5e91cb..c808c87 100644 (file)
@@ -236,6 +236,7 @@ function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
   this.active_ = true;
   this.condition_ = null;
   this.ignoreCount_ = 0;
+  this.break_points_ = [];
 }
 
 
@@ -289,6 +290,15 @@ ScriptBreakPoint.prototype.column = function() {
 };
 
 
+ScriptBreakPoint.prototype.actual_locations = function() {
+  var locations = [];
+  for (var i = 0; i < this.break_points_.length; i++) {
+    locations.push(this.break_points_[i].actual_location);
+  }
+  return locations;
+}
+
+
 ScriptBreakPoint.prototype.update_positions = function(line, column) {
   this.line_ = line;
   this.column_ = column;
@@ -334,10 +344,8 @@ ScriptBreakPoint.prototype.setIgnoreCount = function(ignoreCount) {
   this.ignoreCount_ = ignoreCount;
 
   // Set ignore count on all break points created from this script break point.
-  for (var i = 0; i < break_points.length; i++) {
-    if (break_points[i].script_break_point() === this) {
-      break_points[i].setIgnoreCount(ignoreCount);
-    }
+  for (var i = 0; i < this.break_points_.length; i++) {
+    this.break_points_[i].setIgnoreCount(ignoreCount);
   }
 };
 
@@ -379,20 +387,23 @@ ScriptBreakPoint.prototype.set = function (script) {
   }
 
   // Convert the line and column into an absolute position within the script.
-  var pos = Debug.findScriptSourcePosition(script, this.line(), column);
+  var position = Debug.findScriptSourcePosition(script, this.line(), column);
 
   // If the position is not found in the script (the script might be shorter
   // than it used to be) just ignore it.
-  if (pos === null) return;
+  if (position === null) return;
 
   // Create a break point object and set the break point.
-  break_point = MakeBreakPoint(pos, this.line(), this.column(), this);
+  break_point = MakeBreakPoint(position, this.line(), this.column(), this);
   break_point.setIgnoreCount(this.ignoreCount());
-  pos = %SetScriptBreakPoint(script, pos, break_point);
-  if (!IS_UNDEFINED(pos)) {
-    this.actual_location = script.locationFromPosition(pos);
-  }
-
+  var actual_position = %SetScriptBreakPoint(script, position, break_point);
+  if (IS_UNDEFINED(actual_position)) {
+    actual_position = position;
+  }
+  var actual_location = script.locationFromPosition(actual_position, true);
+  break_point.actual_location = { line: actual_location.line,
+                                  column: actual_location.column };
+  this.break_points_.push(break_point);
   return break_point;
 };
 
@@ -409,6 +420,7 @@ ScriptBreakPoint.prototype.clear = function () {
     }
   }
   break_points = remaining_break_points;
+  this.break_points_ = [];
 };
 
 
@@ -554,6 +566,19 @@ Debug.findBreakPoint = function(break_point_number, remove) {
   }
 };
 
+Debug.findBreakPointActualLocations = function(break_point_number) {
+  for (var i = 0; i < script_break_points.length; i++) {
+    if (script_break_points[i].number() == break_point_number) {
+      return script_break_points[i].actual_locations();
+    }
+  }
+  for (var i = 0; i < break_points.length; i++) {
+    if (break_points[i].number() == break_point_number) {
+      return [break_points[i].actual_location];
+    }
+  }
+  return [];
+}
 
 Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
   if (!IS_FUNCTION(func)) throw new Error('Parameters have wrong types.');
@@ -585,7 +610,12 @@ Debug.setBreakPoint = function(func, opt_line, opt_column, opt_condition) {
   } else {
     // Set a break point directly on the function.
     var break_point = MakeBreakPoint(source_position, opt_line, opt_column);
-    %SetFunctionBreakPoint(func, source_position, break_point);
+    var actual_position =
+        %SetFunctionBreakPoint(func, source_position, break_point);
+    actual_position += this.sourcePosition(func);
+    var actual_location = script.locationFromPosition(actual_position, true);
+    break_point.actual_location = { line: actual_location.line,
+                                    column: actual_location.column };
     break_point.setCondition(opt_condition);
     return break_point.number();
   }
@@ -1482,8 +1512,10 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
     }
     response.body.line = break_point.line();
     response.body.column = break_point.column();
+    response.body.actual_locations = break_point.actual_locations();
   } else {
     response.body.type = 'function';
+    response.body.actual_locations = [break_point.actual_location];
   }
 };
 
@@ -1598,7 +1630,8 @@ DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(request, resp
       hit_count: break_point.hit_count(),
       active: break_point.active(),
       condition: break_point.condition(),
-      ignoreCount: break_point.ignoreCount()
+      ignoreCount: break_point.ignoreCount(),
+      actual_locations: break_point.actual_locations()
     }
     
     if (break_point.type() == Debug.ScriptBreakPointType.ScriptId) {
index c90365c..f2adab7 100644 (file)
@@ -197,7 +197,17 @@ void TransformToFastProperties(Handle<JSObject> object,
 
 void FlattenString(Handle<String> string) {
   CALL_HEAP_FUNCTION_VOID(string->TryFlatten());
+}
+
+
+Handle<String> FlattenGetString(Handle<String> string) {
+  Handle<String> result;
+  CALL_AND_RETRY(string->TryFlatten(),
+                 { result = Handle<String>(String::cast(__object__));
+                   break; },
+                 return Handle<String>());
   ASSERT(string->IsFlat());
+  return result;
 }
 
 
index 96b17a6..1e14daf 100644 (file)
@@ -193,8 +193,14 @@ void NormalizeProperties(Handle<JSObject> object,
 void NormalizeElements(Handle<JSObject> object);
 void TransformToFastProperties(Handle<JSObject> object,
                                int unused_property_fields);
+
+// Flattens a string.
 void FlattenString(Handle<String> str);
 
+// Flattens a string and returns the underlying external or sequential
+// string.
+Handle<String> FlattenGetString(Handle<String> str);
+
 Handle<Object> SetProperty(Handle<JSObject> object,
                            Handle<String> key,
                            Handle<Object> value,
index c0c5442..1a847c1 100644 (file)
@@ -11686,16 +11686,18 @@ void CompareStub::Generate(MacroAssembler* masm) {
       __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
       __ ret(0);
     } else {
-      Label return_equal;
       Label heap_number;
-      // If it's not a heap number, then return equal.
       __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
              Immediate(Factory::heap_number_map()));
-      __ j(equal, &heap_number);
-      __ bind(&return_equal);
-      __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
-      __ ret(0);
-
+      if (cc_ == equal) {
+        __ j(equal, &heap_number);
+        // Identical objects are equal for operators ==, !=, and ===.
+        __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
+        __ ret(0);
+      } else {
+        // Identical objects must call ToPrimitive for <, <=, >, and >=.
+        __ j(not_equal, &not_identical);
+      }
       __ bind(&heap_number);
       // It is a heap number, so return non-equal if it's NaN and equal if
       // it's not NaN.
index e5ee03d..cdb10be 100644 (file)
@@ -241,7 +241,7 @@ function JSONStringify(value, replacer, space) {
   }
   var gap;
   if (IS_NUMBER(space)) {
-    space = $Math.min(space, 10);
+    space = $Math.min(ToInteger(space), 10);
     gap = "";
     for (var i = 0; i < space; i++) {
       gap += " ";
index 3e9c5ea..9f98782 100644 (file)
@@ -356,7 +356,16 @@ int RegExpImpl::IrregexpPrepare(Handle<JSRegExp> regexp,
   if (!subject->IsFlat()) {
     FlattenString(subject);
   }
-  bool is_ascii = subject->IsAsciiRepresentation();
+  // Check the asciiness of the underlying storage.
+  bool is_ascii;
+  {
+    AssertNoAllocation no_gc;
+    String* sequential_string = *subject;
+    if (subject->IsConsString()) {
+      sequential_string =  ConsString::cast(*subject)->first();
+    }
+    is_ascii = sequential_string->IsAsciiRepresentation();
+  }
   if (!EnsureCompiledIrregexp(regexp, is_ascii)) {
     return -1;
   }
@@ -381,6 +390,11 @@ RegExpImpl::IrregexpResult RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
   ASSERT(index <= subject->length());
   ASSERT(subject->IsFlat());
 
+  // A flat ASCII string might have a two-byte first part.
+  if (subject->IsConsString()) {
+    subject = Handle<String>(ConsString::cast(*subject)->first());
+  }
+
 #ifndef V8_INTERPRETED_REGEXP
   ASSERT(output.length() >=
       (IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
@@ -407,7 +421,7 @@ RegExpImpl::IrregexpResult RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
     // If result is RETRY, the string has changed representation, and we
     // must restart from scratch.
     // In this case, it means we must make sure we are prepared to handle
-    // the, potentially, differen subject (the string can switch between
+    // the, potentially, different subject (the string can switch between
     // being internal and external, and even between being ASCII and UC16,
     // but the characters are always the same).
     IrregexpPrepare(regexp, subject);
index 5a057e1..883b28e 100644 (file)
@@ -678,7 +678,7 @@ Object* String::SlowTryFlatten(PretenureFlag pretenure) {
 
 
 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
-  // Externalizing twice leaks the external resouce, so it's
+  // Externalizing twice leaks the external resource, so it's
   // prohibited by the API.
   ASSERT(!this->IsExternalString());
 #ifdef DEBUG
index fc65947..09797ca 100644 (file)
@@ -120,8 +120,6 @@ NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match(
   int start_offset = previous_index;
   int end_offset = subject_ptr->length();
 
-  bool is_ascii = subject->IsAsciiRepresentation();
-
   // The string has been flattened, so it it is a cons string it contains the
   // full string in the first part.
   if (StringShape(subject_ptr).IsCons()) {
@@ -129,7 +127,7 @@ NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match(
     subject_ptr = ConsString::cast(subject_ptr)->first();
   }
   // Ensure that an underlying string has the same ascii-ness.
-  ASSERT(subject_ptr->IsAsciiRepresentation() == is_ascii);
+  bool is_ascii = subject_ptr->IsAsciiRepresentation();
   ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
   // String is now either Sequential or External
   int char_size_shift = is_ascii ? 0 : 1;
index f0945b3..58e620d 100644 (file)
@@ -296,14 +296,14 @@ function RegExpTest(string) {
     return cache.answer;
   }
 
-  // Remove irrelevant preceeding '.*' in a test regexp. The expression  
-  // checks whether this.source starts with '.*' and that the third 
+  // Remove irrelevant preceeding '.*' in a test regexp. The expression
+  // checks whether this.source starts with '.*' and that the third
   // char is not a '?'
   if (%_StringCharCodeAt(this.source,0) == 46 && // '.'
-      %_StringCharCodeAt(this.source,1) == 42 && // '*' 
-      %_StringCharCodeAt(this.source,2) != 63) { // '?' 
+      %_StringCharCodeAt(this.source,1) == 42 && // '*'
+      %_StringCharCodeAt(this.source,2) != 63) { // '?'
     if (!%_ObjectEquals(regexp_key, this)) {
-      regexp_key = this; 
+      regexp_key = this;
       regexp_val = new $RegExp(this.source.substring(2, this.source.length),
                                (this.global ? 'g' : '')
                                + (this.ignoreCase ? 'i' : '')
@@ -311,7 +311,7 @@ function RegExpTest(string) {
     }
     if (!regexp_val.test(s)) return false;
   }
-  
+
   var length = s.length;
   var i = this.global ? TO_INTEGER(lastIndex) : 0;
 
index 8625053..22e80b3 100644 (file)
@@ -2782,13 +2782,17 @@ int Runtime::StringMatch(Handle<String> sub,
   // algorithm is unnecessary overhead.
   if (pattern_length == 1) {
     AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
-    if (sub->IsAsciiRepresentation()) {
+    String* seq_sub = *sub;
+    if (seq_sub->IsConsString()) {
+      seq_sub = ConsString::cast(seq_sub)->first();
+    }
+    if (seq_sub->IsAsciiRepresentation()) {
       uc16 pchar = pat->Get(0);
       if (pchar > String::kMaxAsciiCharCode) {
         return -1;
       }
       Vector<const char> ascii_vector =
-        sub->ToAsciiVector().SubVector(start_index, subject_length);
+          seq_sub->ToAsciiVector().SubVector(start_index, subject_length);
       const void* pos = memchr(ascii_vector.start(),
                                static_cast<const char>(pchar),
                                static_cast<size_t>(ascii_vector.length()));
@@ -2798,7 +2802,9 @@ int Runtime::StringMatch(Handle<String> sub,
       return static_cast<int>(reinterpret_cast<const char*>(pos)
           - ascii_vector.start() + start_index);
     }
-    return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
+    return SingleCharIndexOf(seq_sub->ToUC16Vector(),
+                             pat->Get(0),
+                             start_index);
   }
 
   if (!pat->IsFlat()) {
@@ -2806,19 +2812,29 @@ int Runtime::StringMatch(Handle<String> sub,
   }
 
   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
+  // Extract flattened substrings of cons strings before determining asciiness.
+  String* seq_sub = *sub;
+  if (seq_sub->IsConsString()) {
+    seq_sub = ConsString::cast(seq_sub)->first();
+  }
+  String* seq_pat = *pat;
+  if (seq_pat->IsConsString()) {
+    seq_pat = ConsString::cast(seq_pat)->first();
+  }
+
   // dispatch on type of strings
-  if (pat->IsAsciiRepresentation()) {
-    Vector<const char> pat_vector = pat->ToAsciiVector();
-    if (sub->IsAsciiRepresentation()) {
-      return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
+  if (seq_pat->IsAsciiRepresentation()) {
+    Vector<const char> pat_vector = seq_pat->ToAsciiVector();
+    if (seq_sub->IsAsciiRepresentation()) {
+      return StringSearch(seq_sub->ToAsciiVector(), pat_vector, start_index);
     }
-    return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
+    return StringSearch(seq_sub->ToUC16Vector(), pat_vector, start_index);
   }
-  Vector<const uc16> pat_vector = pat->ToUC16Vector();
-  if (sub->IsAsciiRepresentation()) {
-    return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
+  Vector<const uc16> pat_vector = seq_pat->ToUC16Vector();
+  if (seq_sub->IsAsciiRepresentation()) {
+    return StringSearch(seq_sub->ToAsciiVector(), pat_vector, start_index);
   }
-  return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
+  return StringSearch(seq_sub->ToUC16Vector(), pat_vector, start_index);
 }
 
 
@@ -9063,7 +9079,7 @@ static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
   // Set break point.
   Debug::SetBreakPoint(shared, break_point_object_arg, &source_position);
 
-  return Heap::undefined_value();
+  return Smi::FromInt(source_position);
 }
 
 
index 3e4d473..ab6e3e9 100644 (file)
@@ -112,7 +112,7 @@ function STRICT_EQUALS(x) {
 // the result when either (or both) the operands are NaN.
 function COMPARE(x, ncr) {
   var left;
-
+  var right;
   // Fast cases for string, numbers and undefined compares.
   if (IS_STRING(this)) {
     if (IS_STRING(x)) return %_StringCompare(this, x);
@@ -123,14 +123,18 @@ function COMPARE(x, ncr) {
     if (IS_UNDEFINED(x)) return ncr;
     left = this;
   } else if (IS_UNDEFINED(this)) {
+    if (!IS_UNDEFINED(x)) {
+      %ToPrimitive(x, NUMBER_HINT);
+    }
+    return ncr;
+  } else if (IS_UNDEFINED(x)) {
+    %ToPrimitive(this, NUMBER_HINT);
     return ncr;
   } else {
-    if (IS_UNDEFINED(x)) return ncr;
     left = %ToPrimitive(this, NUMBER_HINT);
   }
 
-  // Default implementation.
-  var right = %ToPrimitive(x, NUMBER_HINT);
+  right = %ToPrimitive(x, NUMBER_HINT);
   if (IS_STRING(left) && IS_STRING(right)) {
     return %_StringCompare(left, right);
   } else {
index 9d20bc1..91ecab8 100644 (file)
@@ -79,7 +79,7 @@ class TypeInfo {
 
   // Decode compact representation.  Very sensitive to enum values below!
   static TypeInfo ExpandedRepresentation(int three_bit_representation) {
-    Type t = static_cast<Type>(three_bit_representation >= 6 ?
+    Type t = static_cast<Type>(three_bit_representation > 4 ?
                                three_bit_representation + 2 :
                                three_bit_representation);
     t = (t == kUnknownType) ? t : static_cast<Type>(t | kPrimitiveType);
index 4cc7e1b..68c2e73 100644 (file)
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     2
-#define BUILD_NUMBER      20
+#define BUILD_NUMBER      21
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
index 2bb92d7..c19e2ba 100644 (file)
@@ -1563,7 +1563,7 @@ void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
 void Assembler::movsxbq(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
-  emit_rex_32(dst, src);
+  emit_rex_64(dst, src);
   emit(0x0F);
   emit(0xBE);
   emit_operand(dst, src);
@@ -1601,7 +1601,7 @@ void Assembler::movsxlq(Register dst, const Operand& src) {
 void Assembler::movzxbq(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
-  emit_rex_64(dst, src);
+  emit_optional_rex_32(dst, src);
   emit(0x0F);
   emit(0xB6);
   emit_operand(dst, src);
@@ -1621,7 +1621,7 @@ void Assembler::movzxbl(Register dst, const Operand& src) {
 void Assembler::movzxwq(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
-  emit_rex_64(dst, src);
+  emit_optional_rex_32(dst, src);
   emit(0x0F);
   emit(0xB7);
   emit_operand(dst, src);
index 0c4cd16..a6d31be 100644 (file)
@@ -856,7 +856,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
       __ j(equal, &adapted);
 
       // No arguments adaptor frame. Copy fixed number of arguments.
-      __ movq(rax, Immediate(scope()->num_parameters()));
+      __ Set(rax, scope()->num_parameters());
       for (int i = 0; i < scope()->num_parameters(); i++) {
         __ push(frame_->ParameterAt(i));
       }
@@ -5342,13 +5342,18 @@ void CodeGenerator::ToBoolean(ControlDestination* dest) {
     }
     // Smi => false iff zero.
     __ SmiCompare(value.reg(), Smi::FromInt(0));
-    dest->false_target()->Branch(equal);
-    Condition is_smi = masm_->CheckSmi(value.reg());
-    dest->true_target()->Branch(is_smi);
-    __ xorpd(xmm0, xmm0);
-    __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset));
-    value.Unuse();
-    dest->Split(not_zero);
+    if (value.is_smi()) {
+      value.Unuse();
+      dest->Split(not_zero);
+    } else {
+      dest->false_target()->Branch(equal);
+      Condition is_smi = masm_->CheckSmi(value.reg());
+      dest->true_target()->Branch(is_smi);
+      __ xorpd(xmm0, xmm0);
+      __ ucomisd(xmm0, FieldOperand(value.reg(), HeapNumber::kValueOffset));
+      value.Unuse();
+      dest->Split(not_zero);
+    }
   } else {
     // Fast case checks.
     // 'false' => false.
@@ -8959,23 +8964,32 @@ void CompareStub::Generate(MacroAssembler* masm) {
     // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
     // so we do the second best thing - test it ourselves.
     // Note: if cc_ != equal, never_nan_nan_ is not used.
-    __ Set(rax, EQUAL);
+    // We cannot set rax to EQUAL until just before return because
+    // rax must be unchanged on jump to not_identical.
+
     if (never_nan_nan_ && (cc_ == equal)) {
+      __ Set(rax, EQUAL);
       __ ret(0);
     } else {
       Label heap_number;
-      // If it's not a heap number, then return equal.
+      // If it's not a heap number, then return equal for (in)equality operator.
       __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
              Factory::heap_number_map());
-      __ j(equal, &heap_number);
-      __ ret(0);
+      if (cc_ == equal) {
+        __ j(equal, &heap_number);
+        __ Set(rax, EQUAL);
+        __ ret(0);
+      } else {
+        // Identical objects must still be converted to primitive for < and >.
+        __ j(not_equal, &not_identical);
+      }
 
       __ bind(&heap_number);
       // It is a heap number, so return  equal if it's not NaN.
       // For NaN, return 1 for every condition except greater and
       // greater-equal.  Return -1 for them, so the comparison yields
       // false for all conditions except not-equal.
-
+      __ Set(rax, EQUAL);
       __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
       __ ucomisd(xmm0, xmm0);
       __ setcc(parity_even, rax);
@@ -9058,16 +9072,16 @@ void CompareStub::Generate(MacroAssembler* masm) {
     Label non_number_comparison;
     Label unordered;
     FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
+    __ xorl(rax, rax);
+    __ xorl(rcx, rcx);
     __ ucomisd(xmm0, xmm1);
 
     // Don't base result on EFLAGS when a NaN is involved.
     __ j(parity_even, &unordered);
     // Return a result of -1, 0, or 1, based on EFLAGS.
-    __ movq(rax, Immediate(0));  // equal
-    __ movq(rcx, Immediate(1));
-    __ cmovq(above, rax, rcx);
-    __ movq(rcx, Immediate(-1));
-    __ cmovq(below, rax, rcx);
+    __ setcc(above, rax);
+    __ setcc(below, rcx);
+    __ subq(rax, rcx);
     __ ret(2 * kPointerSize);  // rax, rdx were pushed
 
     // If one of the numbers was NaN, then the result is always false.
index 002a5eb..06a8c79 100644 (file)
@@ -468,20 +468,20 @@ int DisassemblerX64::PrintRightOperandHelper(
         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
           // index == rsp means no index. Only use sib byte with no index for
           // rsp and r12 base.
-          AppendToBuffer("[%s]", (this->*register_name)(base));
+          AppendToBuffer("[%s]", NameOfCPURegister(base));
           return 2;
         } else if (base == 5) {
           // base == rbp means no base register (when mod == 0).
           int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
           AppendToBuffer("[%s*%d+0x%x]",
-                         (this->*register_name)(index),
+                         NameOfCPURegister(index),
                          1 << scale, disp);
           return 6;
         } else if (index != 4 && base != 5) {
           // [base+index*scale]
           AppendToBuffer("[%s+%s*%d]",
-                         (this->*register_name)(base),
-                         (this->*register_name)(index),
+                         NameOfCPURegister(base),
+                         NameOfCPURegister(index),
                          1 << scale);
           return 2;
         } else {
@@ -489,7 +489,7 @@ int DisassemblerX64::PrintRightOperandHelper(
           return 1;
         }
       } else {
-        AppendToBuffer("[%s]", (this->*register_name)(rm));
+        AppendToBuffer("[%s]", NameOfCPURegister(rm));
         return 1;
       }
       break;
@@ -503,21 +503,21 @@ int DisassemblerX64::PrintRightOperandHelper(
                               : *reinterpret_cast<char*>(modrmp + 2);
         if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
           if (-disp > 0) {
-            AppendToBuffer("[%s-0x%x]", (this->*register_name)(base), -disp);
+            AppendToBuffer("[%s-0x%x]", NameOfCPURegister(base), -disp);
           } else {
-            AppendToBuffer("[%s+0x%x]", (this->*register_name)(base), disp);
+            AppendToBuffer("[%s+0x%x]", NameOfCPURegister(base), disp);
           }
         } else {
           if (-disp > 0) {
             AppendToBuffer("[%s+%s*%d-0x%x]",
-                           (this->*register_name)(base),
-                           (this->*register_name)(index),
+                           NameOfCPURegister(base),
+                           NameOfCPURegister(index),
                            1 << scale,
                            -disp);
           } else {
             AppendToBuffer("[%s+%s*%d+0x%x]",
-                           (this->*register_name)(base),
-                           (this->*register_name)(index),
+                           NameOfCPURegister(base),
+                           NameOfCPURegister(index),
                            1 << scale,
                            disp);
           }
@@ -528,9 +528,9 @@ int DisassemblerX64::PrintRightOperandHelper(
         int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
                               : *reinterpret_cast<char*>(modrmp + 1);
         if (-disp > 0) {
-        AppendToBuffer("[%s-0x%x]", (this->*register_name)(rm), -disp);
+        AppendToBuffer("[%s-0x%x]", NameOfCPURegister(rm), -disp);
         } else {
-        AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
+        AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp);
         }
         return (mod == 2) ? 5 : 2;
       }
index 32cd2db..3b2c789 100644 (file)
@@ -351,7 +351,7 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
   // arguments passed in because it is constant. At some point we
   // should remove this need and make the runtime routine entry code
   // smarter.
-  movq(rax, Immediate(num_arguments));
+  Set(rax, num_arguments);
   movq(rbx, ExternalReference(f));
   CEntryStub ces(f->result_size);
   CallStub(&ces);
@@ -360,7 +360,7 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
 
 void MacroAssembler::CallExternalReference(const ExternalReference& ext,
                                            int num_arguments) {
-  movq(rax, Immediate(num_arguments));
+  Set(rax, num_arguments);
   movq(rbx, ext);
 
   CEntryStub stub(1);
@@ -382,7 +382,7 @@ void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
   // arguments passed in because it is constant. At some point we
   // should remove this need and make the runtime routine entry code
   // smarter.
-  movq(rax, Immediate(num_arguments));
+  Set(rax, num_arguments);
   JumpToExternalReference(ext, result_size);
 }
 
@@ -640,9 +640,9 @@ Condition MacroAssembler::CheckBothSmi(Register first, Register second) {
   if (first.is(second)) {
     return CheckSmi(first);
   }
-  movl(kScratchRegister, first);
-  orl(kScratchRegister, second);
-  testb(kScratchRegister, Immediate(kSmiTagMask));
+  ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
+  leal(kScratchRegister, Operand(first, second, times_1, 0));
+  testb(kScratchRegister, Immediate(0x03));
   return zero;
 }
 
@@ -1937,7 +1937,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
     if (expected.immediate() == actual.immediate()) {
       definitely_matches = true;
     } else {
-      movq(rax, Immediate(actual.immediate()));
+      Set(rax, actual.immediate());
       if (expected.immediate() ==
               SharedFunctionInfo::kDontAdaptArgumentsSentinel) {
         // Don't worry about adapting arguments for built-ins that
@@ -1946,7 +1946,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
         // arguments.
         definitely_matches = true;
       } else {
-        movq(rbx, Immediate(expected.immediate()));
+        Set(rbx, expected.immediate());
       }
     }
   } else {
@@ -1957,7 +1957,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
       cmpq(expected.reg(), Immediate(actual.immediate()));
       j(equal, &invoke);
       ASSERT(expected.reg().is(rbx));
-      movq(rax, Immediate(actual.immediate()));
+      Set(rax, actual.immediate());
     } else if (!expected.reg().is(actual.reg())) {
       // Both expected and actual are in (different) registers. This
       // is the case when we invoke functions using call and apply.
index f5e17fd..3a0b72f 100644 (file)
@@ -1221,7 +1221,7 @@ Result VirtualFrame::CallConstructor(int arg_count) {
   // call trampolines per different arguments counts encountered.
   Result num_args = cgen()->allocator()->Allocate(rax);
   ASSERT(num_args.is_valid());
-  __ movq(num_args.reg(), Immediate(arg_count));
+  __ Set(num_args.reg(), arg_count);
 
   function.Unuse();
   num_args.Unuse();
index 876c104..18388c0 100644 (file)
@@ -69,8 +69,9 @@ SOURCES = {
     'test-sockets.cc',
     'test-spaces.cc',
     'test-strings.cc',
-    'test-threads.cc',
     'test-thread-termination.cc',
+    'test-threads.cc',
+    'test-type-info.cc',
     'test-unbound-queue.cc',
     'test-utils.cc',
     'test-version.cc'
index 0cf3f7b..be5ecba 100644 (file)
@@ -58,7 +58,7 @@ using ::v8::Function;
 using ::v8::AccessorInfo;
 using ::v8::Extension;
 
-namespace i = ::v8::internal;
+namespace i = ::i;
 
 
 static void ExpectString(const char* code, const char* expected) {
@@ -381,11 +381,11 @@ THREADED_TEST(ScriptUsingStringResource) {
     CHECK(source->IsExternal());
     CHECK_EQ(resource,
              static_cast<TestResource*>(source->GetExternalStringResource()));
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     CHECK_EQ(0, TestResource::dispose_count);
   }
-  v8::internal::CompilationCache::Clear();
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::CompilationCache::Clear();
+  i::Heap::CollectAllGarbage(false);
   CHECK_EQ(1, TestResource::dispose_count);
 }
 
@@ -402,11 +402,11 @@ THREADED_TEST(ScriptUsingAsciiStringResource) {
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  v8::internal::CompilationCache::Clear();
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::CompilationCache::Clear();
+  i::Heap::CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
 
@@ -427,11 +427,11 @@ THREADED_TEST(ScriptMakingExternalString) {
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     CHECK_EQ(0, TestResource::dispose_count);
   }
-  v8::internal::CompilationCache::Clear();
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::CompilationCache::Clear();
+  i::Heap::CollectAllGarbage(false);
   CHECK_EQ(1, TestResource::dispose_count);
 }
 
@@ -453,11 +453,11 @@ THREADED_TEST(ScriptMakingExternalAsciiString) {
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  v8::internal::CompilationCache::Clear();
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::CompilationCache::Clear();
+  i::Heap::CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
 
@@ -645,11 +645,11 @@ TEST(ExternalStringWithDisposeHandling) {
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  v8::internal::CompilationCache::Clear();
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::CompilationCache::Clear();
+  i::Heap::CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
   CHECK_EQ(0, TestAsciiResource::dispose_count);
 
@@ -666,11 +666,11 @@ TEST(ExternalStringWithDisposeHandling) {
     Local<Value> value = script->Run();
     CHECK(value->IsNumber());
     CHECK_EQ(7, value->Int32Value());
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     CHECK_EQ(0, TestAsciiResource::dispose_count);
   }
-  v8::internal::CompilationCache::Clear();
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::CompilationCache::Clear();
+  i::Heap::CollectAllGarbage(false);
   CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
   CHECK_EQ(1, TestAsciiResource::dispose_count);
 }
@@ -708,7 +708,7 @@ THREADED_TEST(StringConcat) {
     CHECK(value->IsNumber());
     CHECK_EQ(68, value->Int32Value());
   }
-  v8::internal::CompilationCache::Clear();
+  i::CompilationCache::Clear();
   i::Heap::CollectAllGarbage(false);
   i::Heap::CollectAllGarbage(false);
 }
@@ -1881,7 +1881,7 @@ static const char* js_code_causing_out_of_memory =
 // that come after them so they cannot run in parallel.
 TEST(OutOfMemory) {
   // It's not possible to read a snapshot into a heap with different dimensions.
-  if (v8::internal::Snapshot::IsEnabled()) return;
+  if (i::Snapshot::IsEnabled()) return;
   // Set heap limits.
   static const int K = 1024;
   v8::ResourceConstraints constraints;
@@ -1922,7 +1922,7 @@ v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
 
 TEST(OutOfMemoryNested) {
   // It's not possible to read a snapshot into a heap with different dimensions.
-  if (v8::internal::Snapshot::IsEnabled()) return;
+  if (i::Snapshot::IsEnabled()) return;
   // Set heap limits.
   static const int K = 1024;
   v8::ResourceConstraints constraints;
@@ -1951,7 +1951,7 @@ TEST(OutOfMemoryNested) {
 
 TEST(HugeConsStringOutOfMemory) {
   // It's not possible to read a snapshot into a heap with different dimensions.
-  if (v8::internal::Snapshot::IsEnabled()) return;
+  if (i::Snapshot::IsEnabled()) return;
   v8::HandleScope scope;
   LocalContext context;
   // Set heap limits.
@@ -6811,7 +6811,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
   int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
   ++(*call_count);
   if ((*call_count) % 20 == 0) {
-    v8::internal::Heap::CollectAllGarbage(true);
+    i::Heap::CollectAllGarbage(true);
   }
   return v8::Handle<Value>();
 }
@@ -7620,8 +7620,8 @@ THREADED_TEST(ObjectProtoToString) {
 
 
 bool ApiTestFuzzer::fuzzing_ = false;
-v8::internal::Semaphore* ApiTestFuzzer::all_tests_done_=
-  v8::internal::OS::CreateSemaphore(0);
+i::Semaphore* ApiTestFuzzer::all_tests_done_=
+  i::OS::CreateSemaphore(0);
 int ApiTestFuzzer::active_tests_;
 int ApiTestFuzzer::tests_being_run_;
 int ApiTestFuzzer::current_;
@@ -7899,7 +7899,7 @@ THREADED_TEST(LockUnlockLock) {
 
 static int GetGlobalObjectsCount() {
   int count = 0;
-  v8::internal::HeapIterator it;
+  i::HeapIterator it;
   for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
     if (object->IsJSGlobalObject()) count++;
   return count;
@@ -7912,11 +7912,11 @@ static int GetSurvivingGlobalObjectsCount() {
   // the first garbage collection but some of the maps have already
   // been marked at that point.  Therefore some of the maps are not
   // collected until the second garbage collection.
-  v8::internal::Heap::CollectAllGarbage(false);
-  v8::internal::Heap::CollectAllGarbage(false);
+  i::Heap::CollectAllGarbage(false);
+  i::Heap::CollectAllGarbage(false);
   int count = GetGlobalObjectsCount();
 #ifdef DEBUG
-  if (count > 0) v8::internal::Heap::TracePathToGlobal();
+  if (count > 0) i::Heap::TracePathToGlobal();
 #endif
   return count;
 }
@@ -10021,7 +10021,7 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
 
 
 THREADED_TEST(ExternalByteArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalByteArray, int8_t>(
+  ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
       v8::kExternalByteArray,
       -128,
       127);
@@ -10029,7 +10029,7 @@ THREADED_TEST(ExternalByteArray) {
 
 
 THREADED_TEST(ExternalUnsignedByteArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalUnsignedByteArray, uint8_t>(
+  ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
       v8::kExternalUnsignedByteArray,
       0,
       255);
@@ -10037,7 +10037,7 @@ THREADED_TEST(ExternalUnsignedByteArray) {
 
 
 THREADED_TEST(ExternalShortArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalShortArray, int16_t>(
+  ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
       v8::kExternalShortArray,
       -32768,
       32767);
@@ -10045,7 +10045,7 @@ THREADED_TEST(ExternalShortArray) {
 
 
 THREADED_TEST(ExternalUnsignedShortArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalUnsignedShortArray, uint16_t>(
+  ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
       v8::kExternalUnsignedShortArray,
       0,
       65535);
@@ -10053,7 +10053,7 @@ THREADED_TEST(ExternalUnsignedShortArray) {
 
 
 THREADED_TEST(ExternalIntArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalIntArray, int32_t>(
+  ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
       v8::kExternalIntArray,
       INT_MIN,   // -2147483648
       INT_MAX);  //  2147483647
@@ -10061,7 +10061,7 @@ THREADED_TEST(ExternalIntArray) {
 
 
 THREADED_TEST(ExternalUnsignedIntArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalUnsignedIntArray, uint32_t>(
+  ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
       v8::kExternalUnsignedIntArray,
       0,
       UINT_MAX);  // 4294967295
@@ -10069,7 +10069,7 @@ THREADED_TEST(ExternalUnsignedIntArray) {
 
 
 THREADED_TEST(ExternalFloatArray) {
-  ExternalArrayTestHelper<v8::internal::ExternalFloatArray, float>(
+  ExternalArrayTestHelper<i::ExternalFloatArray, float>(
       v8::kExternalFloatArray,
       -500,
       500);
@@ -10547,7 +10547,7 @@ TEST(Regress528) {
     other_context->Enter();
     CompileRun(source_simple);
     other_context->Exit();
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     if (GetGlobalObjectsCount() == 1) break;
   }
   CHECK_GE(2, gc_count);
@@ -10569,7 +10569,7 @@ TEST(Regress528) {
     other_context->Enter();
     CompileRun(source_eval);
     other_context->Exit();
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     if (GetGlobalObjectsCount() == 1) break;
   }
   CHECK_GE(2, gc_count);
@@ -10596,7 +10596,7 @@ TEST(Regress528) {
     other_context->Enter();
     CompileRun(source_exception);
     other_context->Exit();
-    v8::internal::Heap::CollectAllGarbage(false);
+    i::Heap::CollectAllGarbage(false);
     if (GetGlobalObjectsCount() == 1) break;
   }
   CHECK_GE(2, gc_count);
@@ -10859,7 +10859,7 @@ THREADED_TEST(AddToJSFunctionResultCache) {
       "    return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
       "  return 'PASSED';"
       "})()";
-  v8::internal::Heap::ClearJSFunctionResultCaches();
+  i::Heap::ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -10883,7 +10883,7 @@ THREADED_TEST(FillJSFunctionResultCache) {
       "    return 'FAILED: k0CacheSize is too small';"
       "  return 'PASSED';"
       "})()";
-  v8::internal::Heap::ClearJSFunctionResultCaches();
+  i::Heap::ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -10908,7 +10908,7 @@ THREADED_TEST(RoundRobinGetFromCache) {
       "  };"
       "  return 'PASSED';"
       "})()";
-  v8::internal::Heap::ClearJSFunctionResultCaches();
+  i::Heap::ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -10933,7 +10933,7 @@ THREADED_TEST(ReverseGetFromCache) {
       "  };"
       "  return 'PASSED';"
       "})()";
-  v8::internal::Heap::ClearJSFunctionResultCaches();
+  i::Heap::ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
 
@@ -10951,6 +10951,87 @@ THREADED_TEST(TestEviction) {
       "  };"
       "  return 'PASSED';"
       "})()";
-  v8::internal::Heap::ClearJSFunctionResultCaches();
+  i::Heap::ClearJSFunctionResultCaches();
   ExpectString(code, "PASSED");
 }
+
+
+THREADED_TEST(TwoByteStringInAsciiCons) {
+  // See Chromium issue 47824.
+  v8::HandleScope scope;
+
+  LocalContext context;
+  const char* init_code =
+      "var str1 = 'abelspendabel';"
+      "var str2 = str1 + str1 + str1;"
+      "str2;";
+  Local<Value> result = CompileRun(init_code);
+
+  CHECK(result->IsString());
+  i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
+  int length = string->length();
+  CHECK(string->IsAsciiRepresentation());
+
+  FlattenString(string);
+  i::Handle<i::String> flat_string = FlattenGetString(string);
+
+  CHECK(string->IsAsciiRepresentation());
+  CHECK(flat_string->IsAsciiRepresentation());
+
+  // Create external resource.
+  uint16_t* uc16_buffer = new uint16_t[length + 1];
+
+  i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
+  uc16_buffer[length] = 0;
+
+  TestResource resource(uc16_buffer);
+
+  flat_string->MakeExternal(&resource);
+
+  CHECK(flat_string->IsTwoByteRepresentation());
+
+  // At this point, we should have a Cons string which is flat and ASCII,
+  // with a first half that is a two-byte string (although it only contains
+  // ASCII characters). This is a valid sequence of steps, and it can happen
+  // in real pages.
+
+  CHECK(string->IsAsciiRepresentation());
+  i::ConsString* cons = i::ConsString::cast(*string);
+  CHECK_EQ(0, cons->second()->length());
+  CHECK(cons->first()->IsTwoByteRepresentation());
+
+  // Check that some string operations work.
+
+  // Atom RegExp.
+  Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
+  CHECK_EQ(6, reresult->Int32Value());
+
+  // Nonatom RegExp.
+  reresult = CompileRun("str2.match(/abe./g).length;");
+  CHECK_EQ(6, reresult->Int32Value());
+
+  reresult = CompileRun("str2.search(/bel/g);");
+  CHECK_EQ(1, reresult->Int32Value());
+
+  reresult = CompileRun("str2.search(/be./g);");
+  CHECK_EQ(1, reresult->Int32Value());
+
+  ExpectTrue("/bel/g.test(str2);");
+
+  ExpectTrue("/be./g.test(str2);");
+
+  reresult = CompileRun("/bel/g.exec(str2);");
+  CHECK(!reresult->IsNull());
+
+  reresult = CompileRun("/be./g.exec(str2);");
+  CHECK(!reresult->IsNull());
+
+  ExpectString("str2.substring(2, 10);", "elspenda");
+
+  ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
+
+  ExpectString("str2.charAt(2);", "e");
+
+  reresult = CompileRun("str2.charCodeAt(2);");
+  CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
+}
index 5903fe6..18e641d 100644 (file)
@@ -401,3 +401,38 @@ TEST(Type3) {
   VERIFY_RUN();
 }
 
+
+
+TEST(Vfp) {
+  SETUP();
+
+  if (CpuFeatures::IsSupported(VFP3)) {
+    CpuFeatures::Scope scope(VFP3);
+    COMPARE(vadd(d0, d1, d2),
+            "ee310b02       vadd.f64 d0, d1, d2");
+    COMPARE(vadd(d3, d4, d5, mi),
+            "4e343b05       vadd.f64mi d3, d4, d5");
+
+    COMPARE(vsub(d0, d1, d2),
+            "ee310b42       vsub.f64 d0, d1, d2");
+    COMPARE(vsub(d3, d4, d5, ne),
+            "1e343b45       vsub.f64ne d3, d4, d5");
+
+    COMPARE(vmul(d2, d1, d0),
+            "ee212b00       vmul.f64 d2, d1, d0");
+    COMPARE(vmul(d6, d4, d5, cc),
+            "3e246b05       vmul.f64cc d6, d4, d5");
+
+    COMPARE(vdiv(d2, d2, d2),
+            "ee822b02       vdiv.f64 d2, d2, d2");
+    COMPARE(vdiv(d6, d7, d7, hi),
+            "8e876b07       vdiv.f64hi d6, d7, d7");
+
+    COMPARE(vsqrt(d0, d0),
+            "eeb10bc0       vsqrt.f64 d0, d0");
+    COMPARE(vsqrt(d2, d3, ne),
+            "1eb12bc3       vsqrt.f64ne d2, d3");
+  }
+
+  VERIFY_RUN();
+}
diff --git a/deps/v8/test/cctest/test-type-info.cc b/deps/v8/test/cctest/test-type-info.cc
new file mode 100644 (file)
index 0000000..59dd83d
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2010 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.
+
+
+#include "cctest.h"
+#include "type-info.h"
+
+namespace v8 {
+namespace internal {
+
+TEST(ThreeBitRepresentation) {
+  // Numeric types and unknown should fit into the short
+  // representation.
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::Unknown().ThreeBitRepresentation()).IsUnknown());
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::Number().ThreeBitRepresentation()).IsNumber());
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::Integer32().ThreeBitRepresentation()).IsInteger32());
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::Smi().ThreeBitRepresentation()).IsSmi());
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::Double().ThreeBitRepresentation()).IsDouble());
+
+  // Other types should map to unknown.
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::Primitive().ThreeBitRepresentation()).IsUnknown());
+  CHECK(TypeInfo::ExpandedRepresentation(
+      TypeInfo::String().ThreeBitRepresentation()).IsUnknown());
+}
+
+} }  // namespace v8::internal
index 9cfc92b..675249e 100644 (file)
@@ -4,7 +4,7 @@ tests from
 
   https://es5conform.svn.codeplex.com/svn
 
-in revision 62998 as 'data' in this directory.  Using later version
+in revision 71525 as 'data' in this directory.  Using later version
 may be possible but the tests are only known to pass (and indeed run)
 with that revision.
 
index 9d9dc3c..8e1e941 100644 (file)
@@ -29,91 +29,107 @@ prefix es5conform
 def UNIMPLEMENTED = PASS || FAIL
 def FAIL_OK = FAIL, OKAY
 
-chapter07: UNIMPLEMENTED
-chapter08: UNIMPLEMENTED
-chapter10: UNIMPLEMENTED
-chapter11: UNIMPLEMENTED
-chapter12: UNIMPLEMENTED
-chapter13: UNIMPLEMENTED
-chapter14: UNIMPLEMENTED
-chapter15/15.1: UNIMPLEMENTED
-chapter15/15.2/15.2.3/15.2.3.1: UNIMPLEMENTED
+# Non UTF8 characters in test files.
+chapter10/10.4/10.4.2/10.4.2-3-c-2-s: FAIL_OK
+chapter10/10.4/10.4.2/10.4.2-3-c-1-s: FAIL_OK
+chapter10/10.4/10.4.2/10.4.2-2-c-1: FAIL_OK
+
+# We do not implement the error chekcs specified in the production rules
+# of 11.1.5 (Object initializer).
+# We are compatible with Safari and Firefox.
+chapter11/11.1/11.1.5: UNIMPLEMENTED
+
+# Delete returns true in eval even when it should return false.
+# Please see http://code.google.com/p/v8/issues/detail?id=759
+chapter11/11.4/11.4.1//11.4.1-4.a-5: FAIL
+chapter11/11.4/11.4.1//11.4.1-4.a-7: FAIL
+
+
+# We do not have a global object called 'global' as required by tests.
+chapter15/15.1: FAIL_OK
+
+# NOT IMPLEMENTED: seal
 chapter15/15.2/15.2.3/15.2.3.8: UNIMPLEMENTED
+# NOT IMPLEMENTED: freeze
 chapter15/15.2/15.2.3/15.2.3.9: UNIMPLEMENTED
+# NOT IMPLEMENTED: preventExtensions
 chapter15/15.2/15.2.3/15.2.3.10: UNIMPLEMENTED
+# NOT IMPLEMENTED: isSealed
 chapter15/15.2/15.2.3/15.2.3.11: UNIMPLEMENTED
+# NOT IMPLEMENTED: isFrozen
 chapter15/15.2/15.2.3/15.2.3.12: UNIMPLEMENTED
+# NOT IMPLEMENTED: isExtensible
 chapter15/15.2/15.2.3/15.2.3.13: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: seal
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-20: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-20: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: freeze
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-21: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-21: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: preventExtensions
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-22: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-22: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: isSealed
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-23: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-23: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: isFrozen
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-24: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-24: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: isExtensible
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-25: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-25: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: bind
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-38: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-38: UNIMPLEMENTED
 
-# NaN is writable
+# NaN is writable. We are compatible with JSC.
 chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-178: FAIL_OK
-# Infinity is writable
+# Infinity is writable. We are compatible with JSC.
 chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-179: FAIL_OK
-# undefined is writable
+# undefined is writable. We are compatible with JSC.
 chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-180: FAIL_OK
 
-# Our Function object has a "arguments" property which is used as a non
-# property in in the test
+# Our Function object has an "arguments" property which is used as a
+# non-property in the test.
 chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-183: FAIL_OK
 
-# Our Function object has a "caller" property which is used as a non
-# property in in the test
+# Our Function object has a "caller" property which is used as a
+# non-property in in the test.
 chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-184: FAIL_OK
 
-# Our function object has a name property which is used as a non
-# property in the test
+# Our function object has a name property which is used as a
+# non-property in the test.
 chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-188: FAIL_OK
 
 # NOT IMPLEMENTED: RegExp.prototype.source
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: RegExp.prototype.global
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: RegExp.prototype.ignoreCase
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214: UNIMPLEMENTED
 
 # NOT IMPLEMENTED: RegExp.prototype.multiline
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215: FAIL_OK
+chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215: UNIMPLEMENTED
 
 # All of the tests below marked SUBSETFAIL (in 15.2.3.4) fail because 
 # the tests assumes that objects can not have more properties
 # than those described in the spec - but according to spec they can 
 # have additional properties.
 # All compareArray calls in these tests could be exchanged with a 
-# isSubsetOfArray call (I will upload a path to the es5conform site)
+# isSubsetOfArray call (I will upload a path to the es5conform site).
 
 # SUBSETFAIL
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-1: FAIL_OK
 
-# SUBSETFAIL + we do not implement all methods on Object
+# SUBSETFAIL + we do not implement all methods on Object.
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-2: FAIL_OK
 
 # SUBSETFAIL
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-3: FAIL_OK
 
-# SUBSETFAIL + we do not implement Function.prototype.bind
+# SUBSETFAIL + we do not implement Function.prototype.bind.
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-4: FAIL_OK
 
 # SUBSETFAIL
@@ -134,29 +150,29 @@ chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-9: FAIL_OK
 # SUBSETFAIL
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-11: FAIL_OK
 
-# We do not implement all methods on RegExp
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-13: FAIL_OK
+# We do not implement all methods on RegExp.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-13: FAIL
 
 # SUBSETFAIL
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-14: FAIL_OK
 
-# EvalError.prototype does not have message property
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-15: FAIL_OK
+# EvalError.prototype does not have message property.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-15: FAIL
 
-# Rangeerror.prototype does not have message property
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-16: FAIL_OK
+# Rangeerror.prototype does not have message property.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-16: FAIL
 
-# ReferenceError.prototype does not have message property
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-17: FAIL_OK
+# ReferenceError.prototype does not have message property.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-17: FAIL
 
-# SyntaxError.prototype does not have message property
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-18: FAIL_OK
+# SyntaxError.prototype does not have message property.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-18: FAIL
 
-# TypeError.prototype does not have message property
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-19: FAIL_OK
+# TypeError.prototype does not have message property.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-19: FAIL
 
-# URIError.prototype does not have message property
-chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-20: FAIL_OK
+# URIError.prototype does not have message property.
+chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-20: FAIL
 
 # SUBSETFAIL
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-22: FAIL_OK
@@ -200,68 +216,65 @@ chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-34: FAIL_OK
 # SUBSETFAIL
 chapter15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-35: FAIL_OK
 
+# NOT IMPLEMENTED: bind on Function.prototype.
+chapter15/15.3/15.3.4/15.3.4.5/15.3.4.5-0-1: UNIMPLEMENTED
 
-# We fail this because Object.keys returns numbers for element indices
-# rather than strings.
-#chapter15/15.2/15.2.3/15.2.3.14/15.2.3.14-3-3: FAIL_OK
-
-chapter15/15.3: UNIMPLEMENTED
-
-chapter15/15.4/15.4.4/15.4.4.14: UNIMPLEMENTED
-chapter15/15.4/15.4.4/15.4.4.15: UNIMPLEMENTED
-chapter15/15.4/15.4.4/15.4.4.20: UNIMPLEMENTED
-chapter15/15.4/15.4.4/15.4.4.21: UNIMPLEMENTED
-chapter15/15.4/15.4.4/15.4.4.22: UNIMPLEMENTED
+# Bad test - the spec does not say anything about throwing errors
+# on calling Array.prototype.indexOf with undefined as argument.
+chapter15/15.4/15.4.4/15.4.4.14/15.4.4.14-1-1: FAIL_OK
 
-# Wrong test - because this is not given as argument to arr.every
-# this._15_4_4_16_5_1 evaluates to undefined
-chapter15/15.4/15.4.4/15.4.4.16/15.4.4.16-5-1: FAIL_OK
+# Bad test - the spec does not say anything about throwing errors
+# on calling Array.prototype.indexOf with null as argument.
+chapter15/15.4/15.4.4/15.4.4.14/15.4.4.14-1-2: FAIL_OK
 
-# In test case the element is not appended - it is added in the middle of 
-# the array
-chapter15/15.4/15.4.4/15.4.4.16/15.4.4.16-7-1: FAIL_OK
-
-# We fail because the test assumes that if the reference to array is deleted it
-# is not longer traversed
-chapter15/15.4/15.4.4/15.4.4.16/15.4.4.16-7-7: FAIL_OK
-
-# if (val>1) in test should be if (val>2)
-chapter15/15.4/15.4.4/15.4.4.16/15.4.4.16-8-10: FAIL_OK
-
-# Wrong assumption - according to spec some returns a Boolean, not a number
-chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-4-9: FAIL_OK
-
-# Same as 15.4.4.16-5-1
-chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-5-1: FAIL_OK
-
-# Same as 15.4.4.16-7-1
-chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-7-1: FAIL_OK
-
-# Same as 15.4.4.16-7-7
-chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-7-7: FAIL_OK
-
-# Same as 15.4.4.16-10-8
+# Bad test - the test at the end should be "i === true".
 chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-8-10: FAIL_OK
 
-# Same as 15.4.4.16-5-1
-chapter15/15.4/15.4.4/15.4.4.18/15.4.4.18-5-1: FAIL_OK
-
-# Same as 15.4.4.16-7-7
-chapter15/15.4/15.4.4/15.4.4.18/15.4.4.18-7-6: FAIL_OK
-
-# Same as 15.4.4.16-5-1
-chapter15/15.4/15.4.4/15.4.4.19/15.4.4.19-5-1: FAIL_OK
-
-# Same as 15.4.4.16-7-7
-chapter15/15.4/15.4.4/15.4.4.19/15.4.4.19-8-7: FAIL_OK
-
+# Bad test - according to spec some returns a Boolean, not a number.
+chapter15/15.4/15.4.4/15.4.4.17/15.4.4.17-4-9: FAIL_OK
 
-chapter15/15.5: UNIMPLEMENTED
-chapter15/15.6: UNIMPLEMENTED
-chapter15/15.7: UNIMPLEMENTED
-chapter15/15.9: UNIMPLEMENTED
-chapter15/15.10: UNIMPLEMENTED
-chapter15/15.12: UNIMPLEMENTED
+# Bad test - uses unitialized variable a in precondition check.
+chapter15/15.4/15.4.4/15.4.4.19/15.4.4.19-9-3: FAIL_OK
+
+# We do not implement Array mapping functions correctly if array
+# entries are added for nonexistent entries smaller than length by
+# the callback function. We are compatible with JSC.
+# See http://code.google.com/p/v8/issues/detail?id=755
+chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-1: FAIL_OK
+
+# Bad tests, path in test file is wrong. This will crash the test
+# script so we mark it SKIP.
+chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-c-ii-4: SKIP
+chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-c-ii-4-s: SKIP
+
+# Bad test - deleting the property on o in callbackfn will
+# have no effect on the actual array on which reduceRight is called.
+chapter15/15.4/15.4.4/15.4.4.22/15.4.4.22-9-7: FAIL_OK
+
+# We do not implement trim correctly on null and undefined.
+chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-1-1: FAIL
+chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-1-2: FAIL
+
+# We do not correctly recognize \uFEFF as whitespace
+chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-10: FAIL
+chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-18: FAIL
+chapter15/15.5/15.5.4/15.5.4.20/15.5.4.20-4-34: FAIL
+
+# RegExp.prototype is not of type RegExp - we are bug compatible with JSC.
+chapter15/15.10/15.10.6/15.10.6: FAIL_OK
+
+# We do not have the properties of a RegExp instance on RegExp.prototype.
+# The spec says we should - but we are currently bug compatible with JSC.
+chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-1: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.1/15.10.7.1-2: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.2/15.10.7.2-1: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.2/15.10.7.2-2: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.3/15.10.7.3-1: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.3/15.10.7.3-2: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.4/15.10.7.4-1: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.4/15.10.7.4-2: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.5/15.10.7.5-1: FAIL_OK
+chapter15/15.10/15.10.7/15.10.7.5/15.10.7.5-2: FAIL_OK
 
 [ $arch == mips ]
 
index 9661c95..8201d63 100644 (file)
@@ -63,6 +63,7 @@ function testArguments(dcp, arguments, success, is_script) {
   } else {
     assertFalse(response.success, request + ' -> ' + json_response);
   }
+  return response;
 }
 
 function listener(event, exec_state, event_data, data) {
@@ -75,7 +76,7 @@ function listener(event, exec_state, event_data, data) {
     var request = '{' + base_request + '}'
     var response = safeEval(dcp.processDebugJSONRequest(request));
     assertFalse(response.success);
-    
+
     var mirror;
 
     testArguments(dcp, '{}', false);
@@ -118,6 +119,12 @@ function listener(event, exec_state, event_data, data) {
 
     testArguments(dcp, '{"type":"script","target":"sourceUrlScript","line":0}', true, true);
 
+    // Set a break point on a line with the comment, and check that actual position
+    // is the next line after the comment.
+    request = '{"type":"scriptId","target":' + g_script_id + ',"line":' + (g_line + 1) + '}';
+    response = testArguments(dcp, request, true, false);
+    assertEquals(g_line + 2, response.body.actual_locations[0].line);
+
     // Indicate that all was processed.
     listenerComplete = true;
   }
@@ -185,8 +192,3 @@ Debug.setListener(breakListener);
 sourceUrlFunc();
 
 assertTrue(breakListenerCalled, "Break listener not called on breakpoint set by sourceURL");
-
-// Set a break point on a line with the comment, and check that actual position
-// is the next line after the comment.
-var number = Debug.setScriptBreakPointById(g_script_id, g_line + 1);
-assertEquals(g_line + 2, Debug.findBreakPoint(number).actual_location.line);
index ae29b74..fb00d5b 100644 (file)
 
 // Tests the special cases specified by ES 15.8.2.17
 
+function test(expected_sqrt, value) {
+  assertEquals(expected_sqrt, Math.sqrt(value));
+  if (isFinite(value)) { 
+    assertEquals(expected_sqrt, Math.pow(value, 0.5));
+  }
+}
+
 // Simple sanity check
-assertEquals(2, Math.sqrt(4));
-assertEquals(0.1, Math.sqrt(0.01));
+test(2, 4);
+test(0.1, 0.01);
 
 // Spec tests
-assertEquals(NaN, Math.sqrt(NaN));
-assertEquals(NaN, Math.sqrt(-1));
-assertEquals(+0, Math.sqrt(+0));
-assertEquals(-0, Math.sqrt(-0));
-assertEquals(Infinity, Math.sqrt(Infinity));
+test(NaN, NaN);
+test(NaN, -1);
+test(+0, +0);
+test(-0, -0);
+test(Infinity, Infinity);
 // -Infinity is smaller than 0 so it should return NaN
-assertEquals(NaN, Math.sqrt(-Infinity));
-
-
+test(NaN, -Infinity);
 
diff --git a/deps/v8/test/mjsunit/mod.js b/deps/v8/test/mjsunit/mod.js
new file mode 100644 (file)
index 0000000..8ad98fa
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2010 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.
+
+function foo() {
+  for (var i = 1; i < 100; i++) {
+    var answer = 1;
+    for (var j = 1; j < 100; j++) {
+      if (answer == i) answer = 0;
+      // Positive case.
+      print(j + " % " + i + " = " + answer);
+      m = j % i;
+      assertEquals(answer, m, j + " % " + i);
+      m = j % (-i);
+      assertEquals(answer, m, j + " % -" + i);
+      // Negative case.
+      m = (-j) % i;
+      assertEquals(-answer, m, j + " % " + i);
+      // Check for negative zero.
+      if (answer == 0) assertEquals(-Infinity, 1/m);
+      m = (-j) % (-i);
+      assertEquals(-answer, m, j + " % -" + i);
+      // Check for negative zero.
+      if (answer == 0) assertEquals(-Infinity, 1/m);
+      answer++;
+    }
+  }
+}
+
+foo();
diff --git a/deps/v8/test/mjsunit/regress/regress-753.js b/deps/v8/test/mjsunit/regress/regress-753.js
new file mode 100644 (file)
index 0000000..6a6d87b
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2010 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.
+
+// Test that JSON.stringify correctly truncates floating point numbers.
+// This test is based on chapter15/15.12/15.12.3/15.12.3-6-a-2.js in the
+// ES5 conformance tests.
+
+// See: http://code.google.com/p/v8/issues/detail?id=753
+
+var obj = {a1: {b1: [1,2,3,4], b2: {c1: 1, c2: 2}},a2: 'a2'};
+assertEquals(JSON.stringify(obj,null, 5.99999), JSON.stringify(obj,null, 5));
+
index 1329bad..d17e600 100644 (file)
@@ -40,6 +40,14 @@ assertEquals(2, Math.max(v,w));
 assertEquals("hestfisk", x, "max");
 
 x = "";
+assertEquals(1, Math.max(v,v));
+assertEquals("hesthest", x, "max_identical");
+
+x = "";
+assertEquals(2, Math.min(w,w));
+assertEquals("fiskfisk", x, "max");
+
+x = "";
 assertEquals(Math.atan2(1, 2), Math.atan2(v, w));
 // JSC says fiskhest.
 assertEquals("hestfisk", x, "atan2");
@@ -122,8 +130,86 @@ x = "";
 new Date().setUTCFullYear(year, month, date, hours, minutes, seconds, ms);
 assertEquals("123", x, "Date.setUTCFullYear");
 
+x = "";
 var a = { valueOf: function() { x += "hest"; return 97; } };
 var b = { valueOf: function() { x += "fisk"; return 98; } };
 assertEquals("ab", String.fromCharCode(a, b), "String.fromCharCode");
+assertEquals("hestfisk", x, "String.fromCharCode valueOf order");
+
+
+
+// Test whether valueOf is called when comparing identical objects
+x = "";
+assertTrue(a < b, "Compare objects a < b");
+assertEquals("hestfisk", x, "Compare objects a < b valueOf order");
+
+x = "";
+assertFalse(a < a, "Compare objects a < a");
+// assertEquals("hesthest", x, "Compare objects a < a valueOf order");
+
+x = "";
+assertTrue(a == a, "Compare objects a == a");
+assertEquals("", x, "Compare objects a == a valueOf not called");
+
+x = "";
+assertFalse(b > b, "Compare objects b > b");
+assertEquals("fiskfisk", x, "Compare objects b > b valueOf order");
+
+x = "";
+assertTrue(b >= b, "Compare objects b >= b");
+assertEquals("fiskfisk", x, "Compare objects b >= b valueOf order");
+
+x = "";
+assertFalse(a > b, "Compare objects a > b");
+assertEquals("fiskhest", x, "Compare objects a > b valueOf order");
+
+x = "";
+assertFalse(a > void(0), "Compare objects a > undefined");
+assertEquals("hest", x, "Compare objects a > undefined valueOf order");
+
+x = "";
+assertFalse(void(0) > b, "Compare objects undefined > b");
+assertEquals("fisk", x, "Compare objects undefined > b valueOf order");
+
+
+function identical_object_comparison() {
+  x = "";
+  assertTrue(a < b, "Compare objects a < b");
+  assertEquals("hestfisk", x, "Compare objects a < b valueOf order");
+
+  x = "";
+  assertFalse(a < a, "Compare objects a < a");
+  //  assertEquals("hesthest", x, "Compare objects a < a valueOf order");
+
+  x = "";
+  assertTrue(a == a, "Compare objects a == a");
+  assertEquals("", x, "Compare objects a == a valueOf not called");
+
+  x = "";
+  assertFalse(b > b, "Compare objects b > b");
+  assertEquals("fiskfisk", x, "Compare objects b > b valueOf order");
+
+  x = "";
+  assertTrue(b >= b, "Compare objects b >= b");
+  assertEquals("fiskfisk", x, "Compare objects b >= b valueOf order");
+
+  x = "";
+  assertFalse(a > b, "Compare objects a > b");
+  assertEquals("fiskhest", x, "Compare objects a > b valueOf order");
+
+  x = "";
+  assertFalse(a > void(0), "Compare objects a > undefined");
+  assertEquals("hest", x, "Compare objects a > undefined valueOf order");
+
+  x = "";
+  assertFalse(void(0) > b, "Compare objects undefined > b");
+  assertEquals("fisk", x, "Compare objects undefined > b valueOf order");
+}
+
+// Call inside loop to test optimization and possible caching.
+for (i = 0; i < 3; ++i) {
+  identical_object_comparison();
+}
+
 
 print("ok");
index b4ec444..28fc063 100644 (file)
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 # This file is up to date with respect to Mozilla's CVS repository as of
-# 2008-09-02.  If new tests are added to Mozilla's CVS it may need to be
+# 2010-06-29. If new tests are added to Mozilla's CVS it may need to be
 # updated.
 
 # To get the mozilla tests:
 # cd /path/to/checkout/test/mozilla
 # rm -rf data
-# cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -D 2008-09-02 mozilla/js/tests
+# cvs -d :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot co -D 2010-06-29 mozilla/js/tests
 # mv mozilla/js/tests data
 # rm -rf mozilla
 
@@ -53,6 +53,10 @@ def FAIL_OK = FAIL, OKAY
 js1_5/Regress/regress-271716-n: SKIP
 
 
+# This test uses a unitialized variable. A Bug has been filed:
+# https://bugzilla.mozilla.org/show_bug.cgi?id=575575
+js1_5/Array/regress-465980-02: SKIP
+
 # These tests are simply wrong (i.e., they do not test what they intend
 # to test).
 # In particular, these two compare numbers to NaN with != in the current
@@ -226,6 +230,10 @@ ecma_3/Function/regress-313570: FAIL_OK
 
 # toPrecision argument restricted to range 1..21 in JSC/V8
 js1_5/Regress/regress-452346: FAIL_OK
+ecma_3/Number/15.7.4.7-1: FAIL_OK
+
+# toExponential argument restricted to range 0..20 in JSC/V8
+ecma_3/Number/15.7.4.6-1: FAIL_OK
 
 # Array.prototype.slice with zero arguments return undefined in JSC/V8, 
 # empty array in Spider/TraceMonkey.
@@ -234,8 +242,9 @@ js1_5/Array/regress-451483: FAIL_OK
 
 #:=== RegExp:=== 
 # To be compatible with JSC we silently ignore flags that do not make
-# sense.  This test expects us to throw exceptions.  
+# sense.  These tests expects us to throw exceptions.  
 ecma_3/RegExp/regress-57631: FAIL_OK
+ecma_3/RegExp/15.10.4.1-6: FAIL_OK
 
 # PCRE doesn't allow subpattern nesting deeper than 200, this tests
 # depth 500.  JSC detects the case, and return null from the match,
@@ -315,6 +324,11 @@ js1_5/Regress/regress-234389: FAIL_OK
 js1_5/Regress/regress-320119: FAIL_OK
 
 
+# We do not recognize a multiline comment as newline character.
+# We are compatible with JSC.
+ecma_3/LexicalConventions/7.4-01: FAIL_OK
+
+
 # No support for toSource().
 js1_5/Regress/regress-248444: FAIL_OK
 js1_5/Regress/regress-313967-01: FAIL_OK
@@ -347,6 +361,7 @@ ecma/GlobalObject/15.1.2.7: FAIL_OK
 # print strings for errors. Non-ECMA behavior.
 js1_2/function/tostring-2: FAIL_OK
 js1_2/Objects/toString-001: FAIL_OK
+js1_5/LexicalConventions/regress-469940: FAIL_OK
 js1_5/Exceptions/regress-332472: FAIL_OK
 js1_5/Regress/regress-173067: FAIL_OK
 js1_5/Regress/regress-355556: FAIL_OK
@@ -386,11 +401,7 @@ js1_5/decompilation/regress-461110: FAIL_OK
 # Tests that use uneval.  Non-ECMA.
 js1_5/GC/regress-418128: FAIL_OK
 js1_5/extensions/regress-465276: FAIL_OK
-
-
-# Tests that use __count__.  Non-ECMA.
-js1_5/extensions/regress-434837-01: FAIL_OK
-
+js1_5/Error/regress-465377: FAIL_OK
 
 # Tests that use the watch method.  Non-ECMA.
 js1_5/extensions/regress-435345-01: FAIL_OK
@@ -432,6 +443,7 @@ js1_5/Object/regress-362872-01: FAIL_OK
 js1_5/Object/regress-362872-02: FAIL_OK
 js1_5/Regress/regress-361467: FAIL_OK
 js1_5/Regress/regress-385393-06: FAIL_OK
+js1_5/Regress/regress-506567: FAIL_OK
 
 
 # Use special Mozilla getter/setter syntax
@@ -484,6 +496,11 @@ js1_2/Array/array_split_1: FAIL_OK
 # The concat() method is defined in Array.prototype; not Array.
 js1_5/Array/regress-313153: FAIL_OK
 
+# The join() method is defined on Array.prototype; not Array.
+js1_5/Array/regress-474529: FAIL_OK
+
+# The lastIndexOf() method is defined on Array.prototype, not Array.
+ecma_3/Array/15.5.4.8-01: FAIL_OK
 
 # Properties fileName, and lineNumber of Error instances are
 # not supported. Mozilla specific extension.
@@ -552,6 +569,10 @@ js1_5/Regress/regress-352604: FAIL_OK
 js1_5/Regress/regress-417893: FAIL_OK
 
 
+# Unsupported use of "[]" as function parameter. We match JSC. 
+js1_5/Regress/regress-416737-01: FAIL_OK
+js1_5/Regress/regress-416737-02: FAIL_OK
+
 
 ##################### FAILING TESTS #####################
 
@@ -596,6 +617,11 @@ ecma_3/String/15.5.4.11: FAIL
 # Marked as: Will not fix. V8 throws an acceptable RangeError.
 js1_5/Expressions/regress-394673: FAIL
 
+
+# Bug 762: http://code.google.com/p/v8/issues/detail?id=762
+# We do not correctly handle assignments within "with"
+/ecma_3/Statements/12.10-01: FAIL
+
 ##################### MOZILLA EXTENSION TESTS #####################
 
 ecma/extensions/15.1.2.1-1: FAIL_OK
@@ -674,6 +700,9 @@ js1_5/extensions/regress-365869: FAIL_OK
 js1_5/extensions/regress-367630: FAIL_OK
 js1_5/extensions/regress-367923: FAIL_OK
 js1_5/extensions/regress-368859: FAIL_OK
+js1_5/extensions/regress-369696-01: FAIL_OK
+js1_5/extensions/regress-369696-02: FAIL_OK
+js1_5/extensions/regress-369696-03: FAIL_OK
 js1_5/extensions/regress-374589: FAIL_OK
 js1_5/extensions/regress-375801: FAIL_OK
 js1_5/extensions/regress-376052: FAIL_OK
@@ -693,6 +722,11 @@ js1_5/extensions/regress-420612: FAIL_OK
 js1_5/extensions/regress-420869-01: FAIL_OK
 js1_5/extensions/regress-424257: FAIL_OK
 js1_5/extensions/regress-424683-01: FAIL_OK
+js1_5/extensions/regress-429739: FAIL_OK
+js1_5/extensions/regress-454142: FAIL_OK
+js1_5/extensions/regress-465145: FAIL_OK
+js1_5/extensions/regress-469625: FAIL_OK
+js1_5/extensions/regress-472787: FAIL_OK
 js1_5/extensions/regress-44009: FAIL_OK
 js1_5/extensions/regress-50447-1: FAIL_OK
 js1_5/extensions/regress-50447: FAIL_OK
@@ -771,7 +805,7 @@ js1_5/decompilation/regress-375882: PASS || FAIL
 js1_5/decompilation/regress-376564: PASS || FAIL
 js1_5/decompilation/regress-383721: PASS || FAIL
 js1_5/decompilation/regress-406555: PASS || FAIL
-
+js1_5/decompilation/regress-460870: PASS || FAIL
 
 # These tests take an unreasonable amount of time so we skip them
 # in fast mode.
index 14b2147..05cb762 100755 (executable)
@@ -34,8 +34,8 @@ The stats viewer reads counters from a binary file and displays them
 in a window, re-reading and re-displaying with regular intervals.
 """
 
-
 import mmap
+import optparse
 import os
 import re
 import struct
@@ -60,13 +60,15 @@ CHROME_COUNTERS_FILE_MAGIC_NUMBER = 0x13131313
 class StatsViewer(object):
   """The main class that keeps the data used by the stats viewer."""
 
-  def __init__(self, data_name):
+  def __init__(self, data_name, name_filter):
     """Creates a new instance.
 
     Args:
       data_name: the name of the file containing the counters.
+      name_filter: The regexp filter to apply to counter names.
     """
     self.data_name = data_name
+    self.name_filter = name_filter
 
     # The handle created by mmap.mmap to the counters file.  We need
     # this to clean it up on exit.
@@ -224,17 +226,19 @@ class StatsViewer(object):
     sorted_groups.sort()
     for counter_name in sorted_groups:
       counter_objs = groups[counter_name]
-      name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W,
-                           text=counter_name)
-      name.grid(row=index, column=0, padx=1, pady=1)
+      if self.name_filter.match(counter_name):
+        name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W,
+                             text=counter_name)
+        name.grid(row=index, column=0, padx=1, pady=1)
       count = len(counter_objs)
       for i in xrange(count):
         counter = counter_objs[i]
         name = counter.Name()
         var = Tkinter.StringVar()
-        value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W,
-                              textvariable=var)
-        value.grid(row=index, column=(1 + i), padx=1, pady=1)
+        if self.name_filter.match(name):
+          value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W,
+                                textvariable=var)
+          value.grid(row=index, column=(1 + i), padx=1, pady=1)
 
         # If we know how to interpret the prefix of this counter then
         # add an appropriate formatting to the variable
@@ -440,17 +444,25 @@ class ChromeCounterCollection(object):
                          self.counter_values_offset + i * self.max_threads * 4)
 
 
-def Main(data_file):
+def Main(data_file, name_filter):
   """Run the stats counter.
 
   Args:
     data_file: The counters file to monitor.
+    name_filter: The regexp filter to apply to counter names.
   """
-  StatsViewer(data_file).Run()
+  StatsViewer(data_file, name_filter).Run()
 
 
 if __name__ == "__main__":
-  if len(sys.argv) != 2:
-    print "Usage: stats-viewer.py <stats data>|<test_shell pid>"
+  parser = optparse.OptionParser("usage: %prog [--filter=re] "
+                                 "<stats data>|<test_shell pid>")
+  parser.add_option("--filter",
+                    default=".*",
+                    help=("regexp filter for counter names "
+                          "[default: %default]"))
+  (options, args) = parser.parse_args()
+  if len(args) != 1:
+    parser.print_help()
     sys.exit(1)
-  Main(sys.argv[1])
+  Main(args[0], re.compile(options.filter))