mirror of https://github.com/nodejs/node.git
Upgrade V8 to 2.2.21
This commit is contained in:
parent
94cd83ef34
commit
2072925f12
|
@ -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).
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
]);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(); })
|
||||
]);
|
||||
|
|
|
@ -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)
|
||||
]);
|
||||
|
||||
|
|
|
@ -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)
|
||||
]);
|
||||
|
||||
|
|
|
@ -22,10 +22,15 @@ the benchmark suite.
|
|||
|
||||
<div class="subtitle"><h3>Version 6 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v6/run.html">link</a>)</h3></div>
|
||||
|
||||
<p>Removed dead code from the RayTrace benchmark and changed the Splay
|
||||
benchmark to avoid converting the same numeric key to a string over
|
||||
and over again.
|
||||
</p>
|
||||
<p>Removed dead code from the RayTrace benchmark and fixed a couple of
|
||||
typos in the DeltaBlue implementation. Changed the Splay benchmark to
|
||||
avoid converting the same numeric key to a string over and over again
|
||||
and to avoid inserting and removing the same element repeatedly thus
|
||||
increasing pressure on the memory subsystem.</p>
|
||||
|
||||
<p>Furthermore, the benchmark runner was changed to run the benchmarks
|
||||
for at least a few times to stabilize the reported numbers on slower
|
||||
machines.</p>
|
||||
|
||||
<div class="subtitle"><h3>Version 5 (<a href="http://v8.googlecode.com/svn/data/benchmarks/v5/run.html">link</a>)</h3></div>
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// Martin Richards.
|
||||
|
||||
|
||||
var Richards = new BenchmarkSuite('Richards', 34886, [
|
||||
var Richards = new BenchmarkSuite('Richards', 20687, [
|
||||
new Benchmark("Richards", runRichards)
|
||||
]);
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ higher scores means better performance: <em>Bigger is better!</em>
|
|||
<li><b>RegExp</b><br>Regular expression benchmark generated by extracting regular expression operations from 50 of the most popular web pages
|
||||
(<i>1614 lines</i>).
|
||||
</li>
|
||||
<li><b>Splay</b><br>Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (<i>379 lines</i>).</li>
|
||||
<li><b>Splay</b><br>Data manipulation benchmark that deals with splay trees and exercises the automatic memory management subsystem (<i>394 lines</i>).</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4279,22 +4279,147 @@ void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
|
|||
}
|
||||
|
||||
|
||||
// Generates the Math.pow method - currently just calls runtime.
|
||||
// Generates the Math.pow method.
|
||||
void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
|
||||
ASSERT(args->length() == 2);
|
||||
Load(args->at(0));
|
||||
Load(args->at(1));
|
||||
frame_->CallRuntime(Runtime::kMath_pow, 2);
|
||||
frame_->EmitPush(r0);
|
||||
|
||||
if (!CpuFeatures::IsSupported(VFP3)) {
|
||||
frame_->CallRuntime(Runtime::kMath_pow, 2);
|
||||
frame_->EmitPush(r0);
|
||||
} else {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
JumpTarget runtime, done;
|
||||
Label not_minus_half, allocate_return;
|
||||
|
||||
Register scratch1 = VirtualFrame::scratch0();
|
||||
Register scratch2 = VirtualFrame::scratch1();
|
||||
|
||||
// Get base and exponent to registers.
|
||||
Register exponent = frame_->PopToRegister();
|
||||
Register base = frame_->PopToRegister(exponent);
|
||||
|
||||
// Set the frame for the runtime jump target. The code below jumps to the
|
||||
// jump target label so the frame needs to be established before that.
|
||||
ASSERT(runtime.entry_frame() == NULL);
|
||||
runtime.set_entry_frame(frame_);
|
||||
|
||||
__ BranchOnSmi(exponent, runtime.entry_label());
|
||||
|
||||
// Special handling of raising to the power of -0.5 and 0.5. First check
|
||||
// that the value is a heap number and that the lower bits (which for both
|
||||
// values are zero).
|
||||
Register heap_number_map = r6;
|
||||
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
||||
__ ldr(scratch1, FieldMemOperand(exponent, HeapObject::kMapOffset));
|
||||
__ ldr(scratch2, FieldMemOperand(exponent, HeapNumber::kMantissaOffset));
|
||||
__ cmp(scratch1, heap_number_map);
|
||||
runtime.Branch(ne);
|
||||
__ tst(scratch2, scratch2);
|
||||
runtime.Branch(ne);
|
||||
|
||||
// Load the e
|
||||
__ ldr(scratch1, FieldMemOperand(exponent, HeapNumber::kExponentOffset));
|
||||
|
||||
// Compare exponent with -0.5.
|
||||
__ cmp(scratch1, Operand(0xbfe00000));
|
||||
__ b(ne, ¬_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<Expression*>* args) {
|
||||
ASSERT(args->length() == 1);
|
||||
Load(args->at(0));
|
||||
frame_->CallRuntime(Runtime::kMath_sqrt, 1);
|
||||
frame_->EmitPush(r0);
|
||||
|
||||
if (!CpuFeatures::IsSupported(VFP3)) {
|
||||
frame_->CallRuntime(Runtime::kMath_sqrt, 1);
|
||||
frame_->EmitPush(r0);
|
||||
} else {
|
||||
CpuFeatures::Scope scope(VFP3);
|
||||
JumpTarget runtime, done;
|
||||
|
||||
Register scratch1 = VirtualFrame::scratch0();
|
||||
Register scratch2 = VirtualFrame::scratch1();
|
||||
|
||||
// Get the value from the frame.
|
||||
Register tos = frame_->PopToRegister();
|
||||
|
||||
// Set the frame for the runtime jump target. The code below jumps to the
|
||||
// jump target label so the frame needs to be established before that.
|
||||
ASSERT(runtime.entry_frame() == NULL);
|
||||
runtime.set_entry_frame(frame_);
|
||||
|
||||
Register heap_number_map = r6;
|
||||
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
|
||||
|
||||
// Get the double value from the heap number into vfp register d0.
|
||||
__ ObjectToDoubleVFPRegister(tos, d0,
|
||||
scratch1, scratch2, heap_number_map, s0,
|
||||
runtime.entry_label());
|
||||
|
||||
// Calculate the square root of d0 and place result in a heap number object.
|
||||
__ vsqrt(d0, d0);
|
||||
__ AllocateHeapNumberWithValue(
|
||||
tos, d0, scratch1, scratch2, heap_number_map, runtime.entry_label());
|
||||
done.Jump();
|
||||
|
||||
runtime.Bind();
|
||||
// Push back the argument again for the runtime call.
|
||||
frame_->EmitPush(tos);
|
||||
frame_->CallRuntime(Runtime::kMath_sqrt, 1);
|
||||
__ Move(tos, r0);
|
||||
|
||||
done.Bind();
|
||||
frame_->EmitPush(tos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6257,7 +6382,6 @@ bool CodeGenerator::HasValidEntryRegisters() { return true; }
|
|||
#undef __
|
||||
#define __ ACCESS_MASM(masm)
|
||||
|
||||
|
||||
Handle<String> Reference::GetName() {
|
||||
ASSERT(type_ == NAMED);
|
||||
Property* property = expression_->AsProperty();
|
||||
|
@ -6621,7 +6745,7 @@ void ConvertToDoubleStub::Generate(MacroAssembler* masm) {
|
|||
__ bind(¬_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(
|
||||
|
|
|
@ -881,6 +881,102 @@ class StringCompareStub: public CodeStub {
|
|||
};
|
||||
|
||||
|
||||
// This stub can do a fast mod operation without using fp.
|
||||
// It is tail called from the GenericBinaryOpStub and it always
|
||||
// returns an answer. It never causes GC so it doesn't need a real frame.
|
||||
//
|
||||
// The inputs are always positive Smis. This is never called
|
||||
// where the denominator is a power of 2. We handle that separately.
|
||||
//
|
||||
// If we consider the denominator as an odd number multiplied by a power of 2,
|
||||
// then:
|
||||
// * The exponent (power of 2) is in the shift_distance register.
|
||||
// * The odd number is in the odd_number register. It is always in the range
|
||||
// of 3 to 25.
|
||||
// * The bits from the numerator that are to be copied to the answer (there are
|
||||
// shift_distance of them) are in the mask_bits register.
|
||||
// * The other bits of the numerator have been shifted down and are in the lhs
|
||||
// register.
|
||||
class IntegerModStub : public CodeStub {
|
||||
public:
|
||||
IntegerModStub(Register result,
|
||||
Register shift_distance,
|
||||
Register odd_number,
|
||||
Register mask_bits,
|
||||
Register lhs,
|
||||
Register scratch)
|
||||
: result_(result),
|
||||
shift_distance_(shift_distance),
|
||||
odd_number_(odd_number),
|
||||
mask_bits_(mask_bits),
|
||||
lhs_(lhs),
|
||||
scratch_(scratch) {
|
||||
// We don't code these in the minor key, so they should always be the same.
|
||||
// We don't really want to fix that since this stub is rather large and we
|
||||
// don't want many copies of it.
|
||||
ASSERT(shift_distance_.is(r9));
|
||||
ASSERT(odd_number_.is(r4));
|
||||
ASSERT(mask_bits_.is(r3));
|
||||
ASSERT(scratch_.is(r5));
|
||||
}
|
||||
|
||||
private:
|
||||
Register result_;
|
||||
Register shift_distance_;
|
||||
Register odd_number_;
|
||||
Register mask_bits_;
|
||||
Register lhs_;
|
||||
Register scratch_;
|
||||
|
||||
// Minor key encoding in 16 bits.
|
||||
class ResultRegisterBits: public BitField<int, 0, 4> {};
|
||||
class LhsRegisterBits: public BitField<int, 4, 4> {};
|
||||
|
||||
Major MajorKey() { return IntegerMod; }
|
||||
int MinorKey() {
|
||||
// Encode the parameters in a unique 16 bit value.
|
||||
return ResultRegisterBits::encode(result_.code())
|
||||
| LhsRegisterBits::encode(lhs_.code());
|
||||
}
|
||||
|
||||
void Generate(MacroAssembler* masm);
|
||||
|
||||
const char* GetName() { return "IntegerModStub"; }
|
||||
|
||||
// Utility functions.
|
||||
void DigitSum(MacroAssembler* masm,
|
||||
Register lhs,
|
||||
int mask,
|
||||
int shift,
|
||||
Label* entry);
|
||||
void DigitSum(MacroAssembler* masm,
|
||||
Register lhs,
|
||||
Register scratch,
|
||||
int mask,
|
||||
int shift1,
|
||||
int shift2,
|
||||
Label* entry);
|
||||
void ModGetInRangeBySubtraction(MacroAssembler* masm,
|
||||
Register lhs,
|
||||
int shift,
|
||||
int rhs);
|
||||
void ModReduce(MacroAssembler* masm,
|
||||
Register lhs,
|
||||
int max,
|
||||
int denominator);
|
||||
void ModAnswer(MacroAssembler* masm,
|
||||
Register result,
|
||||
Register shift_distance,
|
||||
Register mask_bits,
|
||||
Register sum_of_digits);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void Print() { PrintF("IntegerModStub\n"); }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
// This stub can convert a signed int32 to a heap number (double). It does
|
||||
// not work for int32s that are in Smi range! No GC occurs during this stub
|
||||
// so you don't have to set up the frame.
|
||||
|
|
|
@ -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)];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <cstdarg>
|
||||
#include "v8.h"
|
||||
|
||||
|
@ -2262,7 +2263,8 @@ static int GlueRegCode(bool last_bit, int vm, int m) {
|
|||
// Dd = vmul(Dn, Dm)
|
||||
// Dd = vdiv(Dn, Dm)
|
||||
// vcmp(Dd, Dm)
|
||||
// VMRS
|
||||
// vmrs
|
||||
// Dd = vsqrt(Dm)
|
||||
void Simulator::DecodeTypeVFP(Instr* instr) {
|
||||
ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) );
|
||||
ASSERT(instr->Bits(11, 9) == 0x5);
|
||||
|
@ -2284,6 +2286,11 @@ void Simulator::DecodeTypeVFP(Instr* instr) {
|
|||
} else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) &&
|
||||
(instr->Opc3Field() & 0x1)) {
|
||||
DecodeVCMP(instr);
|
||||
} else if (((instr->Opc2Field() == 0x1)) && (instr->Opc3Field() == 0x3)) {
|
||||
// vsqrt
|
||||
double dm_value = get_double_from_d_register(vm);
|
||||
double dd_value = sqrt(dm_value);
|
||||
set_d_register_from_double(vd, dd_value);
|
||||
} else {
|
||||
UNREACHABLE(); // Not used by V8.
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace internal {
|
|||
V(RecordWrite) \
|
||||
V(ConvertToDouble) \
|
||||
V(WriteInt32ToHeapNumber) \
|
||||
V(IntegerMod) \
|
||||
V(StackCheck) \
|
||||
V(FastNewClosure) \
|
||||
V(FastNewContext) \
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -197,7 +197,17 @@ void TransformToFastProperties(Handle<JSObject> object,
|
|||
|
||||
void FlattenString(Handle<String> string) {
|
||||
CALL_HEAP_FUNCTION_VOID(string->TryFlatten());
|
||||
}
|
||||
|
||||
|
||||
Handle<String> FlattenGetString(Handle<String> string) {
|
||||
Handle<String> result;
|
||||
CALL_AND_RETRY(string->TryFlatten(),
|
||||
{ result = Handle<String>(String::cast(__object__));
|
||||
break; },
|
||||
return Handle<String>());
|
||||
ASSERT(string->IsFlat());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -193,8 +193,14 @@ void NormalizeProperties(Handle<JSObject> object,
|
|||
void NormalizeElements(Handle<JSObject> object);
|
||||
void TransformToFastProperties(Handle<JSObject> object,
|
||||
int unused_property_fields);
|
||||
|
||||
// Flattens a string.
|
||||
void FlattenString(Handle<String> str);
|
||||
|
||||
// Flattens a string and returns the underlying external or sequential
|
||||
// string.
|
||||
Handle<String> FlattenGetString(Handle<String> str);
|
||||
|
||||
Handle<Object> SetProperty(Handle<JSObject> object,
|
||||
Handle<String> key,
|
||||
Handle<Object> value,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 += " ";
|
||||
|
|
|
@ -356,7 +356,16 @@ int RegExpImpl::IrregexpPrepare(Handle<JSRegExp> regexp,
|
|||
if (!subject->IsFlat()) {
|
||||
FlattenString(subject);
|
||||
}
|
||||
bool is_ascii = subject->IsAsciiRepresentation();
|
||||
// Check the asciiness of the underlying storage.
|
||||
bool is_ascii;
|
||||
{
|
||||
AssertNoAllocation no_gc;
|
||||
String* sequential_string = *subject;
|
||||
if (subject->IsConsString()) {
|
||||
sequential_string = ConsString::cast(*subject)->first();
|
||||
}
|
||||
is_ascii = sequential_string->IsAsciiRepresentation();
|
||||
}
|
||||
if (!EnsureCompiledIrregexp(regexp, is_ascii)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -381,6 +390,11 @@ RegExpImpl::IrregexpResult RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
|
|||
ASSERT(index <= subject->length());
|
||||
ASSERT(subject->IsFlat());
|
||||
|
||||
// A flat ASCII string might have a two-byte first part.
|
||||
if (subject->IsConsString()) {
|
||||
subject = Handle<String>(ConsString::cast(*subject)->first());
|
||||
}
|
||||
|
||||
#ifndef V8_INTERPRETED_REGEXP
|
||||
ASSERT(output.length() >=
|
||||
(IrregexpNumberOfCaptures(*irregexp) + 1) * 2);
|
||||
|
@ -407,7 +421,7 @@ RegExpImpl::IrregexpResult RegExpImpl::IrregexpExecOnce(Handle<JSRegExp> regexp,
|
|||
// If result is RETRY, the string has changed representation, and we
|
||||
// must restart from scratch.
|
||||
// In this case, it means we must make sure we are prepared to handle
|
||||
// the, potentially, differen subject (the string can switch between
|
||||
// the, potentially, different subject (the string can switch between
|
||||
// being internal and external, and even between being ASCII and UC16,
|
||||
// but the characters are always the same).
|
||||
IrregexpPrepare(regexp, subject);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -2782,13 +2782,17 @@ int Runtime::StringMatch(Handle<String> sub,
|
|||
// algorithm is unnecessary overhead.
|
||||
if (pattern_length == 1) {
|
||||
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
|
||||
if (sub->IsAsciiRepresentation()) {
|
||||
String* seq_sub = *sub;
|
||||
if (seq_sub->IsConsString()) {
|
||||
seq_sub = ConsString::cast(seq_sub)->first();
|
||||
}
|
||||
if (seq_sub->IsAsciiRepresentation()) {
|
||||
uc16 pchar = pat->Get(0);
|
||||
if (pchar > String::kMaxAsciiCharCode) {
|
||||
return -1;
|
||||
}
|
||||
Vector<const char> ascii_vector =
|
||||
sub->ToAsciiVector().SubVector(start_index, subject_length);
|
||||
seq_sub->ToAsciiVector().SubVector(start_index, subject_length);
|
||||
const void* pos = memchr(ascii_vector.start(),
|
||||
static_cast<const char>(pchar),
|
||||
static_cast<size_t>(ascii_vector.length()));
|
||||
|
@ -2798,7 +2802,9 @@ int Runtime::StringMatch(Handle<String> sub,
|
|||
return static_cast<int>(reinterpret_cast<const char*>(pos)
|
||||
- ascii_vector.start() + start_index);
|
||||
}
|
||||
return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
|
||||
return SingleCharIndexOf(seq_sub->ToUC16Vector(),
|
||||
pat->Get(0),
|
||||
start_index);
|
||||
}
|
||||
|
||||
if (!pat->IsFlat()) {
|
||||
|
@ -2806,19 +2812,29 @@ int Runtime::StringMatch(Handle<String> sub,
|
|||
}
|
||||
|
||||
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
|
||||
// Extract flattened substrings of cons strings before determining asciiness.
|
||||
String* seq_sub = *sub;
|
||||
if (seq_sub->IsConsString()) {
|
||||
seq_sub = ConsString::cast(seq_sub)->first();
|
||||
}
|
||||
String* seq_pat = *pat;
|
||||
if (seq_pat->IsConsString()) {
|
||||
seq_pat = ConsString::cast(seq_pat)->first();
|
||||
}
|
||||
|
||||
// dispatch on type of strings
|
||||
if (pat->IsAsciiRepresentation()) {
|
||||
Vector<const char> pat_vector = pat->ToAsciiVector();
|
||||
if (sub->IsAsciiRepresentation()) {
|
||||
return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
|
||||
if (seq_pat->IsAsciiRepresentation()) {
|
||||
Vector<const char> pat_vector = seq_pat->ToAsciiVector();
|
||||
if (seq_sub->IsAsciiRepresentation()) {
|
||||
return StringSearch(seq_sub->ToAsciiVector(), pat_vector, start_index);
|
||||
}
|
||||
return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
|
||||
return StringSearch(seq_sub->ToUC16Vector(), pat_vector, start_index);
|
||||
}
|
||||
Vector<const uc16> pat_vector = pat->ToUC16Vector();
|
||||
if (sub->IsAsciiRepresentation()) {
|
||||
return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
|
||||
Vector<const uc16> pat_vector = seq_pat->ToUC16Vector();
|
||||
if (seq_sub->IsAsciiRepresentation()) {
|
||||
return StringSearch(seq_sub->ToAsciiVector(), pat_vector, start_index);
|
||||
}
|
||||
return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
|
||||
return StringSearch(seq_sub->ToUC16Vector(), pat_vector, start_index);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9063,7 +9079,7 @@ static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
|
|||
// Set break point.
|
||||
Debug::SetBreakPoint(shared, break_point_object_arg, &source_position);
|
||||
|
||||
return Heap::undefined_value();
|
||||
return Smi::FromInt(source_position);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -79,7 +79,7 @@ class TypeInfo {
|
|||
|
||||
// Decode compact representation. Very sensitive to enum values below!
|
||||
static TypeInfo ExpandedRepresentation(int three_bit_representation) {
|
||||
Type t = static_cast<Type>(three_bit_representation >= 6 ?
|
||||
Type t = static_cast<Type>(three_bit_representation > 4 ?
|
||||
three_bit_representation + 2 :
|
||||
three_bit_representation);
|
||||
t = (t == kUnknownType) ? t : static_cast<Type>(t | kPrimitiveType);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1563,7 +1563,7 @@ void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
|
|||
void Assembler::movsxbq(Register dst, const Operand& src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
emit_rex_32(dst, src);
|
||||
emit_rex_64(dst, src);
|
||||
emit(0x0F);
|
||||
emit(0xBE);
|
||||
emit_operand(dst, src);
|
||||
|
@ -1601,7 +1601,7 @@ void Assembler::movsxlq(Register dst, const Operand& src) {
|
|||
void Assembler::movzxbq(Register dst, const Operand& src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
emit_rex_64(dst, src);
|
||||
emit_optional_rex_32(dst, src);
|
||||
emit(0x0F);
|
||||
emit(0xB6);
|
||||
emit_operand(dst, src);
|
||||
|
@ -1621,7 +1621,7 @@ void Assembler::movzxbl(Register dst, const Operand& src) {
|
|||
void Assembler::movzxwq(Register dst, const Operand& src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
last_pc_ = pc_;
|
||||
emit_rex_64(dst, src);
|
||||
emit_optional_rex_32(dst, src);
|
||||
emit(0x0F);
|
||||
emit(0xB7);
|
||||
emit_operand(dst, src);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -468,20 +468,20 @@ int DisassemblerX64::PrintRightOperandHelper(
|
|||
if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
|
||||
// index == rsp means no index. Only use sib byte with no index for
|
||||
// rsp and r12 base.
|
||||
AppendToBuffer("[%s]", (this->*register_name)(base));
|
||||
AppendToBuffer("[%s]", NameOfCPURegister(base));
|
||||
return 2;
|
||||
} else if (base == 5) {
|
||||
// base == rbp means no base register (when mod == 0).
|
||||
int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2);
|
||||
AppendToBuffer("[%s*%d+0x%x]",
|
||||
(this->*register_name)(index),
|
||||
NameOfCPURegister(index),
|
||||
1 << scale, disp);
|
||||
return 6;
|
||||
} else if (index != 4 && base != 5) {
|
||||
// [base+index*scale]
|
||||
AppendToBuffer("[%s+%s*%d]",
|
||||
(this->*register_name)(base),
|
||||
(this->*register_name)(index),
|
||||
NameOfCPURegister(base),
|
||||
NameOfCPURegister(index),
|
||||
1 << scale);
|
||||
return 2;
|
||||
} else {
|
||||
|
@ -489,7 +489,7 @@ int DisassemblerX64::PrintRightOperandHelper(
|
|||
return 1;
|
||||
}
|
||||
} else {
|
||||
AppendToBuffer("[%s]", (this->*register_name)(rm));
|
||||
AppendToBuffer("[%s]", NameOfCPURegister(rm));
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
@ -503,21 +503,21 @@ int DisassemblerX64::PrintRightOperandHelper(
|
|||
: *reinterpret_cast<char*>(modrmp + 2);
|
||||
if (index == 4 && (base & 7) == 4 && scale == 0 /*times_1*/) {
|
||||
if (-disp > 0) {
|
||||
AppendToBuffer("[%s-0x%x]", (this->*register_name)(base), -disp);
|
||||
AppendToBuffer("[%s-0x%x]", NameOfCPURegister(base), -disp);
|
||||
} else {
|
||||
AppendToBuffer("[%s+0x%x]", (this->*register_name)(base), disp);
|
||||
AppendToBuffer("[%s+0x%x]", NameOfCPURegister(base), disp);
|
||||
}
|
||||
} else {
|
||||
if (-disp > 0) {
|
||||
AppendToBuffer("[%s+%s*%d-0x%x]",
|
||||
(this->*register_name)(base),
|
||||
(this->*register_name)(index),
|
||||
NameOfCPURegister(base),
|
||||
NameOfCPURegister(index),
|
||||
1 << scale,
|
||||
-disp);
|
||||
} else {
|
||||
AppendToBuffer("[%s+%s*%d+0x%x]",
|
||||
(this->*register_name)(base),
|
||||
(this->*register_name)(index),
|
||||
NameOfCPURegister(base),
|
||||
NameOfCPURegister(index),
|
||||
1 << scale,
|
||||
disp);
|
||||
}
|
||||
|
@ -528,9 +528,9 @@ int DisassemblerX64::PrintRightOperandHelper(
|
|||
int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1)
|
||||
: *reinterpret_cast<char*>(modrmp + 1);
|
||||
if (-disp > 0) {
|
||||
AppendToBuffer("[%s-0x%x]", (this->*register_name)(rm), -disp);
|
||||
AppendToBuffer("[%s-0x%x]", NameOfCPURegister(rm), -disp);
|
||||
} else {
|
||||
AppendToBuffer("[%s+0x%x]", (this->*register_name)(rm), disp);
|
||||
AppendToBuffer("[%s+0x%x]", NameOfCPURegister(rm), disp);
|
||||
}
|
||||
return (mod == 2) ? 5 : 2;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -58,7 +58,7 @@ using ::v8::Function;
|
|||
using ::v8::AccessorInfo;
|
||||
using ::v8::Extension;
|
||||
|
||||
namespace i = ::v8::internal;
|
||||
namespace i = ::i;
|
||||
|
||||
|
||||
static void ExpectString(const char* code, const char* expected) {
|
||||
|
@ -381,11 +381,11 @@ THREADED_TEST(ScriptUsingStringResource) {
|
|||
CHECK(source->IsExternal());
|
||||
CHECK_EQ(resource,
|
||||
static_cast<TestResource*>(source->GetExternalStringResource()));
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(0, TestResource::dispose_count);
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(1, TestResource::dispose_count);
|
||||
}
|
||||
|
||||
|
@ -402,11 +402,11 @@ THREADED_TEST(ScriptUsingAsciiStringResource) {
|
|||
Local<Value> value = script->Run();
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(7, value->Int32Value());
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(0, TestAsciiResource::dispose_count);
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(1, TestAsciiResource::dispose_count);
|
||||
}
|
||||
|
||||
|
@ -427,11 +427,11 @@ THREADED_TEST(ScriptMakingExternalString) {
|
|||
Local<Value> value = script->Run();
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(7, value->Int32Value());
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(0, TestResource::dispose_count);
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(1, TestResource::dispose_count);
|
||||
}
|
||||
|
||||
|
@ -453,11 +453,11 @@ THREADED_TEST(ScriptMakingExternalAsciiString) {
|
|||
Local<Value> value = script->Run();
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(7, value->Int32Value());
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(0, TestAsciiResource::dispose_count);
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(1, TestAsciiResource::dispose_count);
|
||||
}
|
||||
|
||||
|
@ -645,11 +645,11 @@ TEST(ExternalStringWithDisposeHandling) {
|
|||
Local<Value> value = script->Run();
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(7, value->Int32Value());
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(0, TestAsciiResource::dispose_count);
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
|
||||
CHECK_EQ(0, TestAsciiResource::dispose_count);
|
||||
|
||||
|
@ -666,11 +666,11 @@ TEST(ExternalStringWithDisposeHandling) {
|
|||
Local<Value> value = script->Run();
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(7, value->Int32Value());
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(0, TestAsciiResource::dispose_count);
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
|
||||
CHECK_EQ(1, TestAsciiResource::dispose_count);
|
||||
}
|
||||
|
@ -708,7 +708,7 @@ THREADED_TEST(StringConcat) {
|
|||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(68, value->Int32Value());
|
||||
}
|
||||
v8::internal::CompilationCache::Clear();
|
||||
i::CompilationCache::Clear();
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
}
|
||||
|
@ -1881,7 +1881,7 @@ static const char* js_code_causing_out_of_memory =
|
|||
// that come after them so they cannot run in parallel.
|
||||
TEST(OutOfMemory) {
|
||||
// It's not possible to read a snapshot into a heap with different dimensions.
|
||||
if (v8::internal::Snapshot::IsEnabled()) return;
|
||||
if (i::Snapshot::IsEnabled()) return;
|
||||
// Set heap limits.
|
||||
static const int K = 1024;
|
||||
v8::ResourceConstraints constraints;
|
||||
|
@ -1922,7 +1922,7 @@ v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
|
|||
|
||||
TEST(OutOfMemoryNested) {
|
||||
// It's not possible to read a snapshot into a heap with different dimensions.
|
||||
if (v8::internal::Snapshot::IsEnabled()) return;
|
||||
if (i::Snapshot::IsEnabled()) return;
|
||||
// Set heap limits.
|
||||
static const int K = 1024;
|
||||
v8::ResourceConstraints constraints;
|
||||
|
@ -1951,7 +1951,7 @@ TEST(OutOfMemoryNested) {
|
|||
|
||||
TEST(HugeConsStringOutOfMemory) {
|
||||
// It's not possible to read a snapshot into a heap with different dimensions.
|
||||
if (v8::internal::Snapshot::IsEnabled()) return;
|
||||
if (i::Snapshot::IsEnabled()) return;
|
||||
v8::HandleScope scope;
|
||||
LocalContext context;
|
||||
// Set heap limits.
|
||||
|
@ -6811,7 +6811,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
|
|||
int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
|
||||
++(*call_count);
|
||||
if ((*call_count) % 20 == 0) {
|
||||
v8::internal::Heap::CollectAllGarbage(true);
|
||||
i::Heap::CollectAllGarbage(true);
|
||||
}
|
||||
return v8::Handle<Value>();
|
||||
}
|
||||
|
@ -7620,8 +7620,8 @@ THREADED_TEST(ObjectProtoToString) {
|
|||
|
||||
|
||||
bool ApiTestFuzzer::fuzzing_ = false;
|
||||
v8::internal::Semaphore* ApiTestFuzzer::all_tests_done_=
|
||||
v8::internal::OS::CreateSemaphore(0);
|
||||
i::Semaphore* ApiTestFuzzer::all_tests_done_=
|
||||
i::OS::CreateSemaphore(0);
|
||||
int ApiTestFuzzer::active_tests_;
|
||||
int ApiTestFuzzer::tests_being_run_;
|
||||
int ApiTestFuzzer::current_;
|
||||
|
@ -7899,7 +7899,7 @@ THREADED_TEST(LockUnlockLock) {
|
|||
|
||||
static int GetGlobalObjectsCount() {
|
||||
int count = 0;
|
||||
v8::internal::HeapIterator it;
|
||||
i::HeapIterator it;
|
||||
for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
|
||||
if (object->IsJSGlobalObject()) count++;
|
||||
return count;
|
||||
|
@ -7912,11 +7912,11 @@ static int GetSurvivingGlobalObjectsCount() {
|
|||
// the first garbage collection but some of the maps have already
|
||||
// been marked at that point. Therefore some of the maps are not
|
||||
// collected until the second garbage collection.
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
int count = GetGlobalObjectsCount();
|
||||
#ifdef DEBUG
|
||||
if (count > 0) v8::internal::Heap::TracePathToGlobal();
|
||||
if (count > 0) i::Heap::TracePathToGlobal();
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
@ -10021,7 +10021,7 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
|
|||
|
||||
|
||||
THREADED_TEST(ExternalByteArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalByteArray, int8_t>(
|
||||
ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
|
||||
v8::kExternalByteArray,
|
||||
-128,
|
||||
127);
|
||||
|
@ -10029,7 +10029,7 @@ THREADED_TEST(ExternalByteArray) {
|
|||
|
||||
|
||||
THREADED_TEST(ExternalUnsignedByteArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalUnsignedByteArray, uint8_t>(
|
||||
ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
|
||||
v8::kExternalUnsignedByteArray,
|
||||
0,
|
||||
255);
|
||||
|
@ -10037,7 +10037,7 @@ THREADED_TEST(ExternalUnsignedByteArray) {
|
|||
|
||||
|
||||
THREADED_TEST(ExternalShortArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalShortArray, int16_t>(
|
||||
ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
|
||||
v8::kExternalShortArray,
|
||||
-32768,
|
||||
32767);
|
||||
|
@ -10045,7 +10045,7 @@ THREADED_TEST(ExternalShortArray) {
|
|||
|
||||
|
||||
THREADED_TEST(ExternalUnsignedShortArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalUnsignedShortArray, uint16_t>(
|
||||
ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
|
||||
v8::kExternalUnsignedShortArray,
|
||||
0,
|
||||
65535);
|
||||
|
@ -10053,7 +10053,7 @@ THREADED_TEST(ExternalUnsignedShortArray) {
|
|||
|
||||
|
||||
THREADED_TEST(ExternalIntArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalIntArray, int32_t>(
|
||||
ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
|
||||
v8::kExternalIntArray,
|
||||
INT_MIN, // -2147483648
|
||||
INT_MAX); // 2147483647
|
||||
|
@ -10061,7 +10061,7 @@ THREADED_TEST(ExternalIntArray) {
|
|||
|
||||
|
||||
THREADED_TEST(ExternalUnsignedIntArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalUnsignedIntArray, uint32_t>(
|
||||
ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
|
||||
v8::kExternalUnsignedIntArray,
|
||||
0,
|
||||
UINT_MAX); // 4294967295
|
||||
|
@ -10069,7 +10069,7 @@ THREADED_TEST(ExternalUnsignedIntArray) {
|
|||
|
||||
|
||||
THREADED_TEST(ExternalFloatArray) {
|
||||
ExternalArrayTestHelper<v8::internal::ExternalFloatArray, float>(
|
||||
ExternalArrayTestHelper<i::ExternalFloatArray, float>(
|
||||
v8::kExternalFloatArray,
|
||||
-500,
|
||||
500);
|
||||
|
@ -10547,7 +10547,7 @@ TEST(Regress528) {
|
|||
other_context->Enter();
|
||||
CompileRun(source_simple);
|
||||
other_context->Exit();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
if (GetGlobalObjectsCount() == 1) break;
|
||||
}
|
||||
CHECK_GE(2, gc_count);
|
||||
|
@ -10569,7 +10569,7 @@ TEST(Regress528) {
|
|||
other_context->Enter();
|
||||
CompileRun(source_eval);
|
||||
other_context->Exit();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
if (GetGlobalObjectsCount() == 1) break;
|
||||
}
|
||||
CHECK_GE(2, gc_count);
|
||||
|
@ -10596,7 +10596,7 @@ TEST(Regress528) {
|
|||
other_context->Enter();
|
||||
CompileRun(source_exception);
|
||||
other_context->Exit();
|
||||
v8::internal::Heap::CollectAllGarbage(false);
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
if (GetGlobalObjectsCount() == 1) break;
|
||||
}
|
||||
CHECK_GE(2, gc_count);
|
||||
|
@ -10859,7 +10859,7 @@ THREADED_TEST(AddToJSFunctionResultCache) {
|
|||
" return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
|
||||
" return 'PASSED';"
|
||||
"})()";
|
||||
v8::internal::Heap::ClearJSFunctionResultCaches();
|
||||
i::Heap::ClearJSFunctionResultCaches();
|
||||
ExpectString(code, "PASSED");
|
||||
}
|
||||
|
||||
|
@ -10883,7 +10883,7 @@ THREADED_TEST(FillJSFunctionResultCache) {
|
|||
" return 'FAILED: k0CacheSize is too small';"
|
||||
" return 'PASSED';"
|
||||
"})()";
|
||||
v8::internal::Heap::ClearJSFunctionResultCaches();
|
||||
i::Heap::ClearJSFunctionResultCaches();
|
||||
ExpectString(code, "PASSED");
|
||||
}
|
||||
|
||||
|
@ -10908,7 +10908,7 @@ THREADED_TEST(RoundRobinGetFromCache) {
|
|||
" };"
|
||||
" return 'PASSED';"
|
||||
"})()";
|
||||
v8::internal::Heap::ClearJSFunctionResultCaches();
|
||||
i::Heap::ClearJSFunctionResultCaches();
|
||||
ExpectString(code, "PASSED");
|
||||
}
|
||||
|
||||
|
@ -10933,7 +10933,7 @@ THREADED_TEST(ReverseGetFromCache) {
|
|||
" };"
|
||||
" return 'PASSED';"
|
||||
"})()";
|
||||
v8::internal::Heap::ClearJSFunctionResultCaches();
|
||||
i::Heap::ClearJSFunctionResultCaches();
|
||||
ExpectString(code, "PASSED");
|
||||
}
|
||||
|
||||
|
@ -10951,6 +10951,87 @@ THREADED_TEST(TestEviction) {
|
|||
" };"
|
||||
" return 'PASSED';"
|
||||
"})()";
|
||||
v8::internal::Heap::ClearJSFunctionResultCaches();
|
||||
i::Heap::ClearJSFunctionResultCaches();
|
||||
ExpectString(code, "PASSED");
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(TwoByteStringInAsciiCons) {
|
||||
// See Chromium issue 47824.
|
||||
v8::HandleScope scope;
|
||||
|
||||
LocalContext context;
|
||||
const char* init_code =
|
||||
"var str1 = 'abelspendabel';"
|
||||
"var str2 = str1 + str1 + str1;"
|
||||
"str2;";
|
||||
Local<Value> result = CompileRun(init_code);
|
||||
|
||||
CHECK(result->IsString());
|
||||
i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
|
||||
int length = string->length();
|
||||
CHECK(string->IsAsciiRepresentation());
|
||||
|
||||
FlattenString(string);
|
||||
i::Handle<i::String> flat_string = FlattenGetString(string);
|
||||
|
||||
CHECK(string->IsAsciiRepresentation());
|
||||
CHECK(flat_string->IsAsciiRepresentation());
|
||||
|
||||
// Create external resource.
|
||||
uint16_t* uc16_buffer = new uint16_t[length + 1];
|
||||
|
||||
i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
|
||||
uc16_buffer[length] = 0;
|
||||
|
||||
TestResource resource(uc16_buffer);
|
||||
|
||||
flat_string->MakeExternal(&resource);
|
||||
|
||||
CHECK(flat_string->IsTwoByteRepresentation());
|
||||
|
||||
// At this point, we should have a Cons string which is flat and ASCII,
|
||||
// with a first half that is a two-byte string (although it only contains
|
||||
// ASCII characters). This is a valid sequence of steps, and it can happen
|
||||
// in real pages.
|
||||
|
||||
CHECK(string->IsAsciiRepresentation());
|
||||
i::ConsString* cons = i::ConsString::cast(*string);
|
||||
CHECK_EQ(0, cons->second()->length());
|
||||
CHECK(cons->first()->IsTwoByteRepresentation());
|
||||
|
||||
// Check that some string operations work.
|
||||
|
||||
// Atom RegExp.
|
||||
Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
|
||||
CHECK_EQ(6, reresult->Int32Value());
|
||||
|
||||
// Nonatom RegExp.
|
||||
reresult = CompileRun("str2.match(/abe./g).length;");
|
||||
CHECK_EQ(6, reresult->Int32Value());
|
||||
|
||||
reresult = CompileRun("str2.search(/bel/g);");
|
||||
CHECK_EQ(1, reresult->Int32Value());
|
||||
|
||||
reresult = CompileRun("str2.search(/be./g);");
|
||||
CHECK_EQ(1, reresult->Int32Value());
|
||||
|
||||
ExpectTrue("/bel/g.test(str2);");
|
||||
|
||||
ExpectTrue("/be./g.test(str2);");
|
||||
|
||||
reresult = CompileRun("/bel/g.exec(str2);");
|
||||
CHECK(!reresult->IsNull());
|
||||
|
||||
reresult = CompileRun("/be./g.exec(str2);");
|
||||
CHECK(!reresult->IsNull());
|
||||
|
||||
ExpectString("str2.substring(2, 10);", "elspenda");
|
||||
|
||||
ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
|
||||
|
||||
ExpectString("str2.charAt(2);", "e");
|
||||
|
||||
reresult = CompileRun("str2.charCodeAt(2);");
|
||||
CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
# 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
|
||||
|
||||
chapter15/15.3: UNIMPLEMENTED
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# 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 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
|
||||
|
||||
chapter15/15.5: UNIMPLEMENTED
|
||||
chapter15/15.6: UNIMPLEMENTED
|
||||
chapter15/15.7: UNIMPLEMENTED
|
||||
chapter15/15.9: UNIMPLEMENTED
|
||||
chapter15/15.10: UNIMPLEMENTED
|
||||
chapter15/15.12: UNIMPLEMENTED
|
||||
# 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 ]
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
|
@ -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));
|
||||
|
|
@ -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");
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -34,8 +34,8 @@ The stats viewer reads counters from a binary file and displays them
|
|||
in a window, re-reading and re-displaying with regular intervals.
|
||||
"""
|
||||
|
||||
|
||||
import mmap
|
||||
import optparse
|
||||
import os
|
||||
import re
|
||||
import struct
|
||||
|
@ -60,13 +60,15 @@ CHROME_COUNTERS_FILE_MAGIC_NUMBER = 0x13131313
|
|||
class StatsViewer(object):
|
||||
"""The main class that keeps the data used by the stats viewer."""
|
||||
|
||||
def __init__(self, data_name):
|
||||
def __init__(self, data_name, name_filter):
|
||||
"""Creates a new instance.
|
||||
|
||||
Args:
|
||||
data_name: the name of the file containing the counters.
|
||||
name_filter: The regexp filter to apply to counter names.
|
||||
"""
|
||||
self.data_name = data_name
|
||||
self.name_filter = name_filter
|
||||
|
||||
# The handle created by mmap.mmap to the counters file. We need
|
||||
# this to clean it up on exit.
|
||||
|
@ -224,17 +226,19 @@ class StatsViewer(object):
|
|||
sorted_groups.sort()
|
||||
for counter_name in sorted_groups:
|
||||
counter_objs = groups[counter_name]
|
||||
name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W,
|
||||
text=counter_name)
|
||||
name.grid(row=index, column=0, padx=1, pady=1)
|
||||
if self.name_filter.match(counter_name):
|
||||
name = Tkinter.Label(self.root, width=50, anchor=Tkinter.W,
|
||||
text=counter_name)
|
||||
name.grid(row=index, column=0, padx=1, pady=1)
|
||||
count = len(counter_objs)
|
||||
for i in xrange(count):
|
||||
counter = counter_objs[i]
|
||||
name = counter.Name()
|
||||
var = Tkinter.StringVar()
|
||||
value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W,
|
||||
textvariable=var)
|
||||
value.grid(row=index, column=(1 + i), padx=1, pady=1)
|
||||
if self.name_filter.match(name):
|
||||
value = Tkinter.Label(self.root, width=15, anchor=Tkinter.W,
|
||||
textvariable=var)
|
||||
value.grid(row=index, column=(1 + i), padx=1, pady=1)
|
||||
|
||||
# If we know how to interpret the prefix of this counter then
|
||||
# add an appropriate formatting to the variable
|
||||
|
@ -440,17 +444,25 @@ class ChromeCounterCollection(object):
|
|||
self.counter_values_offset + i * self.max_threads * 4)
|
||||
|
||||
|
||||
def Main(data_file):
|
||||
def Main(data_file, name_filter):
|
||||
"""Run the stats counter.
|
||||
|
||||
Args:
|
||||
data_file: The counters file to monitor.
|
||||
name_filter: The regexp filter to apply to counter names.
|
||||
"""
|
||||
StatsViewer(data_file).Run()
|
||||
StatsViewer(data_file, name_filter).Run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print "Usage: stats-viewer.py <stats data>|<test_shell pid>"
|
||||
parser = optparse.OptionParser("usage: %prog [--filter=re] "
|
||||
"<stats data>|<test_shell pid>")
|
||||
parser.add_option("--filter",
|
||||
default=".*",
|
||||
help=("regexp filter for counter names "
|
||||
"[default: %default]"))
|
||||
(options, args) = parser.parse_args()
|
||||
if len(args) != 1:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
Main(sys.argv[1])
|
||||
Main(args[0], re.compile(options.filter))
|
||||
|
|
Loading…
Reference in New Issue