summaryrefslogtreecommitdiffstats
path: root/js/src
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-11-07 12:47:12 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-11-07 12:47:12 +0100
commit8240fb9c736f91044cabbdde8c537b179fc4921e (patch)
tree49a4cc8dc683cf955d61b6618ad471860554ccb5 /js/src
parentf9e04b54c2ccbc1f8e24b511003de09b4565193c (diff)
parent5c83a18cde404b5c0c9fba1d35f003d951ea32e2 (diff)
downloadUXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar.gz
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar.lz
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.tar.xz
UXP-8240fb9c736f91044cabbdde8c537b179fc4921e.zip
Merge branch 'master' into Pale_Moon-release
# Conflicts: # application/palemoon/config/version.txt
Diffstat (limited to 'js/src')
-rw-r--r--js/src/jit-test/tests/ion/bug1493900-1.js17
-rw-r--r--js/src/jit-test/tests/ion/bug1493900-2.js7
-rw-r--r--js/src/jit/BacktrackingAllocator.cpp33
-rw-r--r--js/src/jit/BacktrackingAllocator.h30
-rw-r--r--js/src/jit/MIR.h5
-rw-r--r--js/src/jit/x86/Assembler-x86.h13
-rw-r--r--js/src/jit/x86/BaseAssembler-x86.h8
-rw-r--r--js/src/jit/x86/MacroAssembler-x86.cpp31
-rw-r--r--js/src/jsapi.cpp18
-rw-r--r--js/src/jsapi.h6
-rw-r--r--js/src/vm/ArrayBufferObject.h9
-rw-r--r--js/src/vm/TypeInference.cpp15
-rw-r--r--js/src/vm/TypeInference.h5
-rw-r--r--js/src/vm/TypedArrayCommon.h21
14 files changed, 144 insertions, 74 deletions
diff --git a/js/src/jit-test/tests/ion/bug1493900-1.js b/js/src/jit-test/tests/ion/bug1493900-1.js
new file mode 100644
index 000000000..643c1943d
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1493900-1.js
@@ -0,0 +1,17 @@
+function f() {
+ var objs = [];
+ for (var i = 0; i < 100; i++) {
+ objs[i] = {};
+ }
+ var o = objs[0];
+ var a = new Float64Array(1024);
+ function g(a, b) {
+ let p = b;
+ for (; p.x < 0; p = p.x) {
+ while (p === p) {}
+ }
+ for (var i = 0; i < 10000; ++i) {}
+ }
+ g(a, o);
+}
+f();
diff --git a/js/src/jit-test/tests/ion/bug1493900-2.js b/js/src/jit-test/tests/ion/bug1493900-2.js
new file mode 100644
index 000000000..7e7f5fdec
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1493900-2.js
@@ -0,0 +1,7 @@
+function f(a, b) {
+ for (; b.x < 0; b = b.x) {
+ while (b === b) {};
+ }
+ for (var i = 0; i < 99999; ++i) {}
+}
+f(0, 0);
diff --git a/js/src/jit/BacktrackingAllocator.cpp b/js/src/jit/BacktrackingAllocator.cpp
index 73aceeccb..645aefc4f 100644
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -1736,6 +1736,18 @@ BacktrackingAllocator::deadRange(LiveRange* range)
}
bool
+BacktrackingAllocator::moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from,
+ LiveRange* to, LDefinition::Type type)
+{
+ if (successor->mir()->numPredecessors() > 1) {
+ MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
+ return moveAtExit(predecessor, from, to, type);
+ }
+
+ return moveAtEntry(successor, from, to, type);
+}
+
+bool
BacktrackingAllocator::resolveControlFlow()
{
// Add moves to handle changing assignments for vregs over their lifetime.
@@ -1843,10 +1855,15 @@ BacktrackingAllocator::resolveControlFlow()
LiveRange* from = vreg(input).rangeFor(exitOf(predecessor), /* preferRegister = */ true);
MOZ_ASSERT(from);
- if (!alloc().ensureBallast())
+ if (!alloc().ensureBallast()) {
return false;
- if (!moveAtExit(predecessor, from, to, def->type()))
+ }
+
+ // Note: we have to use moveAtEdge both here and below (for edge
+ // resolution) to avoid conflicting moves. See bug 1493900.
+ if (!moveAtEdge(predecessor, successor, from, to, def->type())) {
return false;
+ }
}
}
}
@@ -1875,16 +1892,12 @@ BacktrackingAllocator::resolveControlFlow()
if (targetRange->covers(exitOf(predecessor)))
continue;
- if (!alloc().ensureBallast())
+ if (!alloc().ensureBallast()) {
return false;
+ }
LiveRange* from = reg.rangeFor(exitOf(predecessor), true);
- if (successor->mir()->numPredecessors() > 1) {
- MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
- if (!moveAtExit(predecessor, from, targetRange, reg.type()))
- return false;
- } else {
- if (!moveAtEntry(successor, from, targetRange, reg.type()))
- return false;
+ if (!moveAtEdge(predecessor, successor, from, targetRange, reg.type())) {
+ return false;
}
}
}
diff --git a/js/src/jit/BacktrackingAllocator.h b/js/src/jit/BacktrackingAllocator.h
index 9910498fb..c6cf26695 100644
--- a/js/src/jit/BacktrackingAllocator.h
+++ b/js/src/jit/BacktrackingAllocator.h
@@ -108,8 +108,9 @@ class Requirement
}
MOZ_ASSERT(newRequirement.kind() == Requirement::REGISTER);
- if (kind() == Requirement::FIXED)
+ if (kind() == Requirement::FIXED) {
return allocation().isRegister();
+ }
*this = newRequirement;
return true;
@@ -353,10 +354,12 @@ class LiveRange : public TempObject
// Comparator for use in range splay trees.
static int compare(LiveRange* v0, LiveRange* v1) {
// LiveRange includes 'from' but excludes 'to'.
- if (v0->to() <= v1->from())
+ if (v0->to() <= v1->from()) {
return -1;
- if (v0->from() >= v1->to())
+ }
+ if (v0->from() >= v1->to()) {
return 1;
+ }
return 0;
}
};
@@ -642,10 +645,12 @@ class BacktrackingAllocator : protected RegisterAllocator
// Comparator for use in splay tree.
static int compare(CallRange* v0, CallRange* v1) {
- if (v0->range.to <= v1->range.from)
+ if (v0->range.to <= v1->range.from) {
return -1;
- if (v0->range.from >= v1->range.to)
+ }
+ if (v0->range.from >= v1->range.to) {
return 1;
+ }
return 0;
}
};
@@ -744,36 +749,43 @@ class BacktrackingAllocator : protected RegisterAllocator
MOZ_MUST_USE bool moveInput(LInstruction* ins, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = getInputMoveGroup(ins);
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAfter(LInstruction* ins, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = getMoveGroupAfter(ins);
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAtExit(LBlock* block, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = block->getExitMoveGroup(alloc());
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAtEntry(LBlock* block, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = block->getEntryMoveGroup(alloc());
return addMove(moves, from, to, type);
}
+ MOZ_MUST_USE bool moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from,
+ LiveRange* to, LDefinition::Type type);
+
// Debugging methods.
void dumpAllocations();
diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
index 6ec05af76..b2e84322f 100644
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -8272,7 +8272,10 @@ class MGetFirstDollarIndex
: MUnaryInstruction(str)
{
setResultType(MIRType::Int32);
- setMovable();
+
+ // Codegen assumes string length > 0 but that's not guaranteed in RegExp.
+ // Don't allow LICM to move this.
+ MOZ_ASSERT(!isMovable());
}
public:
diff --git a/js/src/jit/x86/Assembler-x86.h b/js/src/jit/x86/Assembler-x86.h
index 3fb5efaff..5939583d9 100644
--- a/js/src/jit/x86/Assembler-x86.h
+++ b/js/src/jit/x86/Assembler-x86.h
@@ -421,20 +421,11 @@ class Assembler : public AssemblerX86Shared
MOZ_ASSERT(dest.size() == 16);
masm.vhaddpd_rr(src.encoding(), dest.encoding());
}
- void vsubpd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
+ void vsubpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
MOZ_ASSERT(src0.size() == 16);
MOZ_ASSERT(dest.size() == 16);
- switch (src1.kind()) {
- case Operand::MEM_REG_DISP:
- masm.vsubpd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
- break;
- case Operand::MEM_ADDRESS32:
- masm.vsubpd_mr(src1.address(), src0.encoding(), dest.encoding());
- break;
- default:
- MOZ_CRASH("unexpected operand kind");
- }
+ masm.vsubpd_rr(src1.encoding(), src0.encoding(), dest.encoding());
}
void vpunpckldq(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
diff --git a/js/src/jit/x86/BaseAssembler-x86.h b/js/src/jit/x86/BaseAssembler-x86.h
index 5b16311d0..caaef3f82 100644
--- a/js/src/jit/x86/BaseAssembler-x86.h
+++ b/js/src/jit/x86/BaseAssembler-x86.h
@@ -152,14 +152,6 @@ class BaseAssemblerX86 : public BaseAssembler
{
twoByteOpSimd("vsubpd", VEX_PD, OP2_SUBPS_VpsWps, src1, src0, dst);
}
- void vsubpd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
- {
- twoByteOpSimd("vsubpd", VEX_PD, OP2_SUBPS_VpsWps, offset, base, src0, dst);
- }
- void vsubpd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
- {
- twoByteOpSimd("vsubpd", VEX_PD, OP2_SUBPS_VpsWps, address, src0, dst);
- }
void vpunpckldq_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) {
twoByteOpSimd("vpunpckldq", VEX_PD, OP2_PUNPCKLDQ, src1, src0, dst);
diff --git a/js/src/jit/x86/MacroAssembler-x86.cpp b/js/src/jit/x86/MacroAssembler-x86.cpp
index dc97b5b5b..429a71fa9 100644
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -21,15 +21,6 @@
using namespace js;
using namespace js::jit;
-// vpunpckldq requires 16-byte boundary for memory operand.
-// See convertUInt64ToDouble for the details.
-MOZ_ALIGNED_DECL(static const uint64_t, 16) TO_DOUBLE[4] = {
- 0x4530000043300000LL,
- 0x0LL,
- 0x4330000000000000LL,
- 0x4530000000000000LL
-};
-
static const double TO_DOUBLE_HIGH_SCALE = 0x100000000;
bool
@@ -90,8 +81,16 @@ MacroAssemblerX86::convertUInt64ToDouble(Register64 src, FloatRegister dest, Reg
// here, each 64-bit part of dest represents following double:
// HI(dest) = 0x 1.00000HHHHHHHH * 2**84 == 2**84 + 0x HHHHHHHH 00000000
// LO(dest) = 0x 1.00000LLLLLLLL * 2**52 == 2**52 + 0x 00000000 LLLLLLLL
- movePtr(ImmWord((uintptr_t)TO_DOUBLE), temp);
- vpunpckldq(Operand(temp, 0), dest128, dest128);
+ // See convertUInt64ToDouble for the details.
+ static const int32_t CST1[4] = {
+ 0x43300000,
+ 0x45300000,
+ 0x0,
+ 0x0,
+ };
+
+ loadConstantSimd128Int(SimdConstant::CreateX4(CST1), ScratchSimd128Reg);
+ vpunpckldq(ScratchSimd128Reg, dest128, dest128);
// Subtract a constant C2 from dest, for each 64-bit part:
// C2 = 0x 45300000 00000000 43300000 00000000
@@ -101,7 +100,15 @@ MacroAssemblerX86::convertUInt64ToDouble(Register64 src, FloatRegister dest, Reg
// after the operation each 64-bit part of dest represents following:
// HI(dest) = double(0x HHHHHHHH 00000000)
// LO(dest) = double(0x 00000000 LLLLLLLL)
- vsubpd(Operand(temp, sizeof(uint64_t) * 2), dest128, dest128);
+ static const int32_t CST2[4] = {
+ 0x0,
+ 0x43300000,
+ 0x0,
+ 0x45300000,
+ };
+
+ loadConstantSimd128Int(SimdConstant::CreateX4(CST2), ScratchSimd128Reg);
+ vsubpd(ScratchSimd128Reg, dest128, dest128);
// Add HI(dest) and LO(dest) in double and store it into LO(dest),
// LO(dest) = double(0x HHHHHHHH 00000000) + double(0x 00000000 LLLLLLLL)
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index 85a38bba4..37d023bd4 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2003,10 +2003,10 @@ JS_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
}
JS_PUBLIC_API(bool)
-JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name,
+JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
MutableHandle<PropertyDescriptor> desc)
{
- JSAtom* atom = AtomizeChars(cx, name, js_strlen(name));
+ JSAtom* atom = AtomizeChars(cx, name, namelen);
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
@@ -2028,7 +2028,19 @@ JS_GetPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name,
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
- return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc);
+ return JS_GetPropertyDescriptorById(cx, obj, id, desc);
+}
+
+JS_PUBLIC_API(bool)
+JS_GetUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen,
+ MutableHandle<PropertyDescriptor> desc)
+{
+ JSAtom* atom = AtomizeChars(cx, name, namelen);
+ if (!atom) {
+ return false;
+ }
+ RootedId id(cx, AtomToId(atom));
+ return JS_GetPropertyDescriptorById(cx, obj, id, desc);
}
static bool
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index c1195cc00..30c4a835a 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2917,7 +2917,7 @@ JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* nam
JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
-JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name,
+JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
@@ -2934,6 +2934,10 @@ extern JS_PUBLIC_API(bool)
JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name,
JS::MutableHandle<JS::PropertyDescriptor> desc);
+extern JS_PUBLIC_API(bool)
+JS_GetUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
+ JS::MutableHandle<JS::PropertyDescriptor> desc);
+
/**
* Define a property on obj.
*
diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h
index 6614f5220..e9c9bc0e0 100644
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -457,8 +457,8 @@ ClampDoubleToUint8(const double x);
struct uint8_clamped {
uint8_t val;
- uint8_clamped() { }
- uint8_clamped(const uint8_clamped& other) : val(other.val) { }
+ uint8_clamped() = default;
+ uint8_clamped(const uint8_clamped& other) = default;
// invoke our assignment helpers for constructor conversion
explicit uint8_clamped(uint8_t x) { *this = x; }
@@ -469,10 +469,7 @@ struct uint8_clamped {
explicit uint8_clamped(int32_t x) { *this = x; }
explicit uint8_clamped(double x) { *this = x; }
- uint8_clamped& operator=(const uint8_clamped& x) {
- val = x.val;
- return *this;
- }
+ uint8_clamped& operator=(const uint8_clamped& x) = default;
uint8_clamped& operator=(uint8_t x) {
val = x;
diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
index 3d09c7464..c86345d9c 100644
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -12,6 +12,8 @@
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/Sprintf.h"
+#include <new>
+
#include "jsapi.h"
#include "jscntxt.h"
#include "jsgc.h"
@@ -859,10 +861,8 @@ TypeSet::IsTypeAboutToBeFinalized(TypeSet::Type* v)
}
bool
-TypeSet::clone(LifoAlloc* alloc, TemporaryTypeSet* result) const
+TypeSet::cloneIntoUninitialized(LifoAlloc* alloc, TemporaryTypeSet* result) const
{
- MOZ_ASSERT(result->empty());
-
unsigned objectCount = baseObjectCount();
unsigned capacity = (objectCount >= 2) ? TypeHashSet::Capacity(objectCount) : 0;
@@ -874,15 +874,15 @@ TypeSet::clone(LifoAlloc* alloc, TemporaryTypeSet* result) const
PodCopy(newSet, objectSet, capacity);
}
- new(result) TemporaryTypeSet(flags, capacity ? newSet : objectSet);
+ new (result) TemporaryTypeSet(flags, capacity ? newSet : objectSet);
return true;
}
TemporaryTypeSet*
TypeSet::clone(LifoAlloc* alloc) const
{
- TemporaryTypeSet* res = alloc->new_<TemporaryTypeSet>();
- if (!res || !clone(alloc, res))
+ TemporaryTypeSet* res = alloc->pod_malloc<TemporaryTypeSet>();
+ if (!res || !cloneIntoUninitialized(alloc, res))
return nullptr;
return res;
}
@@ -1150,10 +1150,9 @@ TypeScript::FreezeTypeSets(CompilerConstraintList* constraints, JSScript* script
TemporaryTypeSet* types = alloc->newArrayUninitialized<TemporaryTypeSet>(count);
if (!types)
return false;
- PodZero(types, count);
for (size_t i = 0; i < count; i++) {
- if (!existing[i].clone(alloc, &types[i]))
+ if (!existing[i].cloneIntoUninitialized(alloc, &types[i]))
return false;
}
diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
index 0e737bad7..0f1cd4936 100644
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -498,7 +498,10 @@ class TypeSet
// Clone a type set into an arbitrary allocator.
TemporaryTypeSet* clone(LifoAlloc* alloc) const;
- bool clone(LifoAlloc* alloc, TemporaryTypeSet* result) const;
+
+ // |*result| is not even partly initialized when this function is called:
+ // this function placement-new's its contents into existence.
+ bool cloneIntoUninitialized(LifoAlloc* alloc, TemporaryTypeSet* result) const;
// Create a new TemporaryTypeSet where undefined and/or null has been filtered out.
TemporaryTypeSet* filter(LifoAlloc* alloc, bool filterUndefined, bool filterNull) const;
diff --git a/js/src/vm/TypedArrayCommon.h b/js/src/vm/TypedArrayCommon.h
index d29c93a65..f59419b28 100644
--- a/js/src/vm/TypedArrayCommon.h
+++ b/js/src/vm/TypedArrayCommon.h
@@ -11,7 +11,8 @@
#include "mozilla/Assertions.h"
#include "mozilla/FloatingPoint.h"
-#include "mozilla/PodOperations.h"
+
+#include <algorithm>
#include "jsarray.h"
#include "jscntxt.h"
@@ -245,12 +246,24 @@ class UnsharedOps
template<typename T>
static void podCopy(SharedMem<T*> dest, SharedMem<T*> src, size_t nelem) {
- mozilla::PodCopy(dest.unwrapUnshared(), src.unwrapUnshared(), nelem);
+ // std::copy_n better matches the argument values/types of this
+ // function, but as noted below it allows the input/output ranges to
+ // overlap. std::copy does not, so use it so the compiler has extra
+ // ability to optimize.
+ const auto* first = src.unwrapUnshared();
+ const auto* last = first + nelem;
+ auto* result = dest.unwrapUnshared();
+ std::copy(first, last, result);
}
template<typename T>
- static void podMove(SharedMem<T*> dest, SharedMem<T*> src, size_t nelem) {
- mozilla::PodMove(dest.unwrapUnshared(), src.unwrapUnshared(), nelem);
+ static void podMove(SharedMem<T*> dest, SharedMem<T*> src, size_t n) {
+ // std::copy_n copies from |src| to |dest| starting from |src|, so
+ // input/output ranges *may* permissibly overlap, as this function
+ // allows.
+ const auto* start = src.unwrapUnshared();
+ auto* result = dest.unwrapUnshared();
+ std::copy_n(start, n, result);
}
static SharedMem<void*> extract(TypedArrayObject* obj) {