diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index a8c6186e47..8b58faa183 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -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).
diff --git a/deps/v8/benchmarks/README.txt b/deps/v8/benchmarks/README.txt
index 8e08159da8..800b4f5185 100644
--- a/deps/v8/benchmarks/README.txt
+++ b/deps/v8/benchmarks/README.txt
@@ -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.
diff --git a/deps/v8/benchmarks/base.js b/deps/v8/benchmarks/base.js
index ce308419ed..0388da6844 100644
--- a/deps/v8/benchmarks/base.js
+++ b/deps/v8/benchmarks/base.js
@@ -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() {
diff --git a/deps/v8/benchmarks/crypto.js b/deps/v8/benchmarks/crypto.js
index 12b88ef294..7e9829dc22 100644
--- a/deps/v8/benchmarks/crypto.js
+++ b/deps/v8/benchmarks/crypto.js
@@ -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)
]);
diff --git a/deps/v8/benchmarks/deltablue.js b/deps/v8/benchmarks/deltablue.js
index 7e25d2e13f..4af8387a1c 100644
--- a/deps/v8/benchmarks/deltablue.js
+++ b/deps/v8/benchmarks/deltablue.js
@@ -23,13 +23,13 @@
// 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;
}
diff --git a/deps/v8/benchmarks/earley-boyer.js b/deps/v8/benchmarks/earley-boyer.js
index 3c7f922c4d..b1efe4addd 100644
--- a/deps/v8/benchmarks/earley-boyer.js
+++ b/deps/v8/benchmarks/earley-boyer.js
@@ -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(); })
]);
diff --git a/deps/v8/benchmarks/raytrace.js b/deps/v8/benchmarks/raytrace.js
index da4d5924aa..eaf61a123b 100644
--- a/deps/v8/benchmarks/raytrace.js
+++ b/deps/v8/benchmarks/raytrace.js
@@ -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)
]);
diff --git a/deps/v8/benchmarks/regexp.js b/deps/v8/benchmarks/regexp.js
index dce15b8e37..f9f816c7bd 100644
--- a/deps/v8/benchmarks/regexp.js
+++ b/deps/v8/benchmarks/regexp.js
@@ -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)
]);
diff --git a/deps/v8/benchmarks/revisions.html b/deps/v8/benchmarks/revisions.html
index b03aa126d6..1c54f63462 100644
--- a/deps/v8/benchmarks/revisions.html
+++ b/deps/v8/benchmarks/revisions.html
@@ -22,10 +22,15 @@ the benchmark suite.
-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.
diff --git a/deps/v8/benchmarks/richards.js b/deps/v8/benchmarks/richards.js
index c9368eff91..b5736f7a21 100644
--- a/deps/v8/benchmarks/richards.js
+++ b/deps/v8/benchmarks/richards.js
@@ -35,7 +35,7 @@
// Martin Richards.
-var Richards = new BenchmarkSuite('Richards', 34886, [
+var Richards = new BenchmarkSuite('Richards', 20687, [
new Benchmark("Richards", runRichards)
]);
diff --git a/deps/v8/benchmarks/run.html b/deps/v8/benchmarks/run.html
index 30036b7843..05bfffee02 100644
--- a/deps/v8/benchmarks/run.html
+++ b/deps/v8/benchmarks/run.html
@@ -116,7 +116,7 @@ higher scores means better performance: Bigger is better!
RegExp Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages
(1614 lines ).
-Splay Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (379 lines ).
+Splay Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (394 lines ).
diff --git a/deps/v8/benchmarks/splay.js b/deps/v8/benchmarks/splay.js
index d8c8f04271..d63ab8b82f 100644
--- a/deps/v8/benchmarks/splay.js
+++ b/deps/v8/benchmarks/splay.js
@@ -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)
]);
@@ -230,9 +230,24 @@ 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);
diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc
index f8d98db926..c8170b3d55 100644
--- a/deps/v8/src/arm/assembler-arm.cc
+++ b/deps/v8/src/arm/assembler-arm.cc
@@ -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.
diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h
index 54b584ae46..8a4173d837 100644
--- a/deps/v8/src/arm/assembler-arm.h
+++ b/deps/v8/src/arm/assembler-arm.h
@@ -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);
diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index b6639ae670..f923c092d1 100644
--- a/deps/v8/src/arm/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -4279,22 +4279,147 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList* args) {
}
-// Generates the Math.pow method - currently just calls runtime.
+// Generates the Math.pow method.
void CodeGenerator::GenerateMathPow(ZoneList* 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, ¬_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(¬_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* 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 Reference::GetName() {
ASSERT(type_ == NAMED);
Property* property = expression_->AsProperty();
@@ -6621,7 +6745,7 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
__ bind(¬_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, ¬_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, ¬_power_of_2);
// Calculate power of two modulus.
__ and_(result, lhs, Operand(scratch));
__ Ret();
+
+ __ bind(¬_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(
diff --git a/deps/v8/src/arm/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h
index 925d2675e1..2d8a935203 100644
--- a/deps/v8/src/arm/codegen-arm.h
+++ b/deps/v8/src/arm/codegen-arm.h
@@ -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 {};
+ class LhsRegisterBits: public BitField {};
+
+ 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.
diff --git a/deps/v8/src/arm/constants-arm.cc b/deps/v8/src/arm/constants-arm.cc
index 4e186d1382..002e4c1368 100644
--- a/deps/v8/src/arm/constants-arm.cc
+++ b/deps/v8/src/arm/constants-arm.cc
@@ -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)];
}
diff --git a/deps/v8/src/arm/disasm-arm.cc b/deps/v8/src/arm/disasm-arm.cc
index 400536993a..fb17d45d5a 100644
--- a/deps/v8/src/arm/disasm-arm.cc
+++ b/deps/v8/src/arm/disasm-arm.cc
@@ -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.
}
diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc
index 134dfa3952..0af10362f0 100644
--- a/deps/v8/src/arm/ic-arm.cc
+++ b/deps/v8/src/arm/ic-arm.cc
@@ -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,
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index df7565f135..630e0b80ac 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -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, ¬_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(¬_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);
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index e02a6c8a3e..c3f45a632e 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -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
diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index 77776c2b6d..6240cd4787 100644
--- a/deps/v8/src/arm/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -26,6 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include
+#include
#include
#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.
}
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
index de2ad56cc6..e5a222fcda 100644
--- a/deps/v8/src/code-stubs.h
+++ b/deps/v8/src/code-stubs.h
@@ -46,6 +46,7 @@ namespace internal {
V(RecordWrite) \
V(ConvertToDouble) \
V(WriteInt32ToHeapNumber) \
+ V(IntegerMod) \
V(StackCheck) \
V(FastNewClosure) \
V(FastNewContext) \
diff --git a/deps/v8/src/debug-debugger.js b/deps/v8/src/debug-debugger.js
index d5e91cbdd2..c808c87b8e 100644
--- a/deps/v8/src/debug-debugger.js
+++ b/deps/v8/src/debug-debugger.js
@@ -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) {
diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc
index c90365c31a..f2adab7567 100644
--- a/deps/v8/src/handles.cc
+++ b/deps/v8/src/handles.cc
@@ -197,7 +197,17 @@ void TransformToFastProperties(Handle object,
void FlattenString(Handle string) {
CALL_HEAP_FUNCTION_VOID(string->TryFlatten());
+}
+
+
+Handle FlattenGetString(Handle string) {
+ Handle result;
+ CALL_AND_RETRY(string->TryFlatten(),
+ { result = Handle(String::cast(__object__));
+ break; },
+ return Handle());
ASSERT(string->IsFlat());
+ return result;
}
diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h
index 96b17a653c..1e14daf9a9 100644
--- a/deps/v8/src/handles.h
+++ b/deps/v8/src/handles.h
@@ -193,8 +193,14 @@ void NormalizeProperties(Handle object,
void NormalizeElements(Handle object);
void TransformToFastProperties(Handle object,
int unused_property_fields);
+
+// Flattens a string.
void FlattenString(Handle str);
+// Flattens a string and returns the underlying external or sequential
+// string.
+Handle FlattenGetString(Handle str);
+
Handle SetProperty(Handle object,
Handle key,
Handle value,
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index c0c54426a3..1a847c1681 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -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, ¬_identical);
+ }
__ bind(&heap_number);
// It is a heap number, so return non-equal if it's NaN and equal if
// it's not NaN.
diff --git a/deps/v8/src/json.js b/deps/v8/src/json.js
index e5ee03d31d..cdb10be1aa 100644
--- a/deps/v8/src/json.js
+++ b/deps/v8/src/json.js
@@ -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 += " ";
diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc
index 3e9c5eab9a..9f98782bbc 100644
--- a/deps/v8/src/jsregexp.cc
+++ b/deps/v8/src/jsregexp.cc
@@ -356,7 +356,16 @@ int RegExpImpl::IrregexpPrepare(Handle 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 regexp,
ASSERT(index <= subject->length());
ASSERT(subject->IsFlat());
+ // A flat ASCII string might have a two-byte first part.
+ if (subject->IsConsString()) {
+ subject = Handle(ConsString::cast(*subject)->first());
+ }
+
#ifndef V8_INTERPRETED_REGEXP
ASSERT(output.length() >=
(IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
@@ -407,7 +421,7 @@ RegExpImpl::IrregexpResult RegExpImpl::IrregexpExecOnce(Handle 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);
diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc
index 5a057e1643..883b28ef42 100644
--- a/deps/v8/src/objects.cc
+++ b/deps/v8/src/objects.cc
@@ -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
diff --git a/deps/v8/src/regexp-macro-assembler.cc b/deps/v8/src/regexp-macro-assembler.cc
index fc6594759c..09797ca2a4 100644
--- a/deps/v8/src/regexp-macro-assembler.cc
+++ b/deps/v8/src/regexp-macro-assembler.cc
@@ -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;
diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js
index f0945b3459..58e620d9ab 100644
--- a/deps/v8/src/regexp.js
+++ b/deps/v8/src/regexp.js
@@ -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;
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 8625053894..22e80b33e0 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -2782,13 +2782,17 @@ int Runtime::StringMatch(Handle 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 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(pchar),
static_cast(ascii_vector.length()));
@@ -2798,7 +2802,9 @@ int Runtime::StringMatch(Handle sub,
return static_cast(reinterpret_cast(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 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 pat_vector = pat->ToAsciiVector();
- if (sub->IsAsciiRepresentation()) {
- return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
+ if (seq_pat->IsAsciiRepresentation()) {
+ Vector 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 pat_vector = pat->ToUC16Vector();
- if (sub->IsAsciiRepresentation()) {
- return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
+ Vector 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);
}
diff --git a/deps/v8/src/runtime.js b/deps/v8/src/runtime.js
index 3e4d473c27..ab6e3e9df1 100644
--- a/deps/v8/src/runtime.js
+++ b/deps/v8/src/runtime.js
@@ -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 {
diff --git a/deps/v8/src/type-info.h b/deps/v8/src/type-info.h
index 9d20bc19df..91ecab8f5b 100644
--- a/deps/v8/src/type-info.h
+++ b/deps/v8/src/type-info.h
@@ -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(three_bit_representation >= 6 ?
+ Type t = static_cast(three_bit_representation > 4 ?
three_bit_representation + 2 :
three_bit_representation);
t = (t == kUnknownType) ? t : static_cast(t | kPrimitiveType);
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 4cc7e1be49..68c2e7320b 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -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
diff --git a/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc
index 2bb92d7e25..c19e2ba130 100644
--- a/deps/v8/src/x64/assembler-x64.cc
+++ b/deps/v8/src/x64/assembler-x64.cc
@@ -1563,7 +1563,7 @@ void Assembler::movq(Register dst, Handle 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);
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index 0c4cd16cee..a6d31be79f 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -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, ¬_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.
diff --git a/deps/v8/src/x64/disasm-x64.cc b/deps/v8/src/x64/disasm-x64.cc
index 002a5ebc7b..06a8c79629 100644
--- a/deps/v8/src/x64/disasm-x64.cc
+++ b/deps/v8/src/x64/disasm-x64.cc
@@ -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(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(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(modrmp + 1)
: *reinterpret_cast(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;
}
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index 32cd2dbc13..3b2c789d1b 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -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.
diff --git a/deps/v8/src/x64/virtual-frame-x64.cc b/deps/v8/src/x64/virtual-frame-x64.cc
index f5e17fd18f..3a0b72fc6c 100644
--- a/deps/v8/src/x64/virtual-frame-x64.cc
+++ b/deps/v8/src/x64/virtual-frame-x64.cc
@@ -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();
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
index 876c104bca..18388c0273 100644
--- a/deps/v8/test/cctest/SConscript
+++ b/deps/v8/test/cctest/SConscript
@@ -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'
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 0cf3f7ba41..be5ecba688 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -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(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 = 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 = 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 = 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 = 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 = 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 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 InterceptorCallICFastApi(Local name,
int* call_count = reinterpret_cast(v8::External::Unwrap(info.Data()));
++(*call_count);
if ((*call_count) % 20 == 0) {
- v8::internal::Heap::CollectAllGarbage(true);
+ i::Heap::CollectAllGarbage(true);
}
return v8::Handle();
}
@@ -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(
+ ExternalArrayTestHelper(
v8::kExternalByteArray,
-128,
127);
@@ -10029,7 +10029,7 @@ THREADED_TEST(ExternalByteArray) {
THREADED_TEST(ExternalUnsignedByteArray) {
- ExternalArrayTestHelper(
+ ExternalArrayTestHelper(
v8::kExternalUnsignedByteArray,
0,
255);
@@ -10037,7 +10037,7 @@ THREADED_TEST(ExternalUnsignedByteArray) {
THREADED_TEST(ExternalShortArray) {
- ExternalArrayTestHelper(
+ ExternalArrayTestHelper(
v8::kExternalShortArray,
-32768,
32767);
@@ -10045,7 +10045,7 @@ THREADED_TEST(ExternalShortArray) {
THREADED_TEST(ExternalUnsignedShortArray) {
- ExternalArrayTestHelper(
+ ExternalArrayTestHelper(
v8::kExternalUnsignedShortArray,
0,
65535);
@@ -10053,7 +10053,7 @@ THREADED_TEST(ExternalUnsignedShortArray) {
THREADED_TEST(ExternalIntArray) {
- ExternalArrayTestHelper(
+ ExternalArrayTestHelper(
v8::kExternalIntArray,
INT_MIN, // -2147483648
INT_MAX); // 2147483647
@@ -10061,7 +10061,7 @@ THREADED_TEST(ExternalIntArray) {
THREADED_TEST(ExternalUnsignedIntArray) {
- ExternalArrayTestHelper(
+ ExternalArrayTestHelper(
v8::kExternalUnsignedIntArray,
0,
UINT_MAX); // 4294967295
@@ -10069,7 +10069,7 @@ THREADED_TEST(ExternalUnsignedIntArray) {
THREADED_TEST(ExternalFloatArray) {
- ExternalArrayTestHelper(
+ ExternalArrayTestHelper(
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 result = CompileRun(init_code);
+
+ CHECK(result->IsString());
+ i::Handle string = v8::Utils::OpenHandle(String::Cast(*result));
+ int length = string->length();
+ CHECK(string->IsAsciiRepresentation());
+
+ FlattenString(string);
+ i::Handle 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 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('e'), reresult->Int32Value());
+}
diff --git a/deps/v8/test/cctest/test-disasm-arm.cc b/deps/v8/test/cctest/test-disasm-arm.cc
index 5903fe650b..18e641d6a3 100644
--- a/deps/v8/test/cctest/test-disasm-arm.cc
+++ b/deps/v8/test/cctest/test-disasm-arm.cc
@@ -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
index 0000000000..59dd83d1f7
--- /dev/null
+++ b/deps/v8/test/cctest/test-type-info.cc
@@ -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
diff --git a/deps/v8/test/es5conform/README b/deps/v8/test/es5conform/README
index 9cfc92b4b9..675249e0f1 100644
--- a/deps/v8/test/es5conform/README
+++ b/deps/v8/test/es5conform/README
@@ -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.
diff --git a/deps/v8/test/es5conform/es5conform.status b/deps/v8/test/es5conform/es5conform.status
index 9d9dc3cd5f..8e1e941e02 100644
--- a/deps/v8/test/es5conform/es5conform.status
+++ b/deps/v8/test/es5conform/es5conform.status
@@ -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 ]
diff --git a/deps/v8/test/mjsunit/debug-setbreakpoint.js b/deps/v8/test/mjsunit/debug-setbreakpoint.js
index 9661c95a4e..8201d6394a 100644
--- a/deps/v8/test/mjsunit/debug-setbreakpoint.js
+++ b/deps/v8/test/mjsunit/debug-setbreakpoint.js
@@ -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);
diff --git a/deps/v8/test/mjsunit/math-sqrt.js b/deps/v8/test/mjsunit/math-sqrt.js
index ae29b74381..fb00d5ba8a 100644
--- a/deps/v8/test/mjsunit/math-sqrt.js
+++ b/deps/v8/test/mjsunit/math-sqrt.js
@@ -27,18 +27,23 @@
// 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
index 0000000000..8ad98fa7ec
--- /dev/null
+++ b/deps/v8/test/mjsunit/mod.js
@@ -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
index 0000000000..6a6d87bb0e
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-753.js
@@ -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));
+
diff --git a/deps/v8/test/mjsunit/to_number_order.js b/deps/v8/test/mjsunit/to_number_order.js
index 1329bad2ca..d17e600050 100644
--- a/deps/v8/test/mjsunit/to_number_order.js
+++ b/deps/v8/test/mjsunit/to_number_order.js
@@ -39,6 +39,14 @@ x = "";
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.
@@ -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");
diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status
index b4ec444784..28fc063154 100644
--- a/deps/v8/test/mozilla/mozilla.status
+++ b/deps/v8/test/mozilla/mozilla.status
@@ -26,13 +26,13 @@
# 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.
diff --git a/deps/v8/tools/stats-viewer.py b/deps/v8/tools/stats-viewer.py
index 14b214768f..05cb762882 100755
--- a/deps/v8/tools/stats-viewer.py
+++ b/deps/v8/tools/stats-viewer.py
@@ -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 |"
+ parser = optparse.OptionParser("usage: %prog [--filter=re] "
+ "|")
+ 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))