- Revision
- 229270
- Author
- [email protected]
- Date
- 2018-03-05 05:16:46 -0800 (Mon, 05 Mar 2018)
Log Message
We need to clear cached structures when having a bad time
https://bugs.webkit.org/show_bug.cgi?id=183256
<rdar://problem/36245022>
Reviewed by Mark Lam.
JSTests:
* stress/having-a-bad-time-with-derived-arrays.js: Added.
(assert):
(defineSetter):
(iterate):
(doSlice):
Source/_javascript_Core:
This patch makes both InternalFunctionAllocationProfile and the VM's
structure cache having-a-bad-time aware. For InternalFunctionAllocationProfile,
we clear them when they'd produce an object with a bad indexing type.
For the VM's Structure cache, we conservatively clear the entire cache
since it may be housing Structures with bad indexing types.
* runtime/FunctionRareData.h:
(JSC::FunctionRareData::clearInternalFunctionAllocationProfile):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::haveABadTime):
* runtime/StructureCache.h:
(JSC::StructureCache::clear):
Modified Paths
Added Paths
Diff
Modified: releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog (229269 => 229270)
--- releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog 2018-03-05 13:16:40 UTC (rev 229269)
+++ releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog 2018-03-05 13:16:46 UTC (rev 229270)
@@ -1,3 +1,17 @@
+2018-03-01 Saam Barati <[email protected]>
+
+ We need to clear cached structures when having a bad time
+ https://bugs.webkit.org/show_bug.cgi?id=183256
+ <rdar://problem/36245022>
+
+ Reviewed by Mark Lam.
+
+ * stress/having-a-bad-time-with-derived-arrays.js: Added.
+ (assert):
+ (defineSetter):
+ (iterate):
+ (doSlice):
+
2018-02-28 Yusuke Suzuki <[email protected]>
JSC crash with `import("")`
Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/having-a-bad-time-with-derived-arrays.js (0 => 229270)
--- releases/WebKitGTK/webkit-2.20/JSTests/stress/having-a-bad-time-with-derived-arrays.js (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/having-a-bad-time-with-derived-arrays.js 2018-03-05 13:16:46 UTC (rev 229270)
@@ -0,0 +1,48 @@
+function assert(b) {
+ if (!b)
+ throw new Error;
+}
+
+let called = false;
+function defineSetter() {
+ Array.prototype.__defineSetter__(0, function (x) {
+ assert(x === 42);
+ called = true;
+ });
+}
+
+class DerivedArray extends Array {
+ constructor(...args) {
+ super()
+ }
+}
+
+function iterate(a) {
+ for (let i = 0; i < a.length; i++) { }
+}
+
+let arr = [[[1, 2, 3, 4, 5], [ 2], 5], [[1, 2, 3], [ -4]]];
+let d = new DerivedArray();
+d[1] = 20;
+d[2] = 40;
+arr.push([d, [2] -9]);
+
+function doSlice(a) {
+ let r = a.slice();
+ defineSetter();
+ return r;
+}
+
+for (let i = 0; i < 10000; i++) {
+ for (let [a, b, ...c] of arr) {
+ let s = doSlice(a);
+ iterate(s);
+ delete s[0];
+ called = false;
+ s[0] = 42;
+ if (a === d) {
+ assert(called);
+ called = false;
+ }
+ }
+}
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog (229269 => 229270)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog 2018-03-05 13:16:40 UTC (rev 229269)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog 2018-03-05 13:16:46 UTC (rev 229270)
@@ -1,3 +1,24 @@
+2018-03-01 Saam Barati <[email protected]>
+
+ We need to clear cached structures when having a bad time
+ https://bugs.webkit.org/show_bug.cgi?id=183256
+ <rdar://problem/36245022>
+
+ Reviewed by Mark Lam.
+
+ This patch makes both InternalFunctionAllocationProfile and the VM's
+ structure cache having-a-bad-time aware. For InternalFunctionAllocationProfile,
+ we clear them when they'd produce an object with a bad indexing type.
+ For the VM's Structure cache, we conservatively clear the entire cache
+ since it may be housing Structures with bad indexing types.
+
+ * runtime/FunctionRareData.h:
+ (JSC::FunctionRareData::clearInternalFunctionAllocationProfile):
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::haveABadTime):
+ * runtime/StructureCache.h:
+ (JSC::StructureCache::clear):
+
2018-03-01 Yusuke Suzuki <[email protected]>
Unreviewed, fix exception check for ExceptionScope
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/FunctionRareData.h (229269 => 229270)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/FunctionRareData.h 2018-03-05 13:16:40 UTC (rev 229269)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/FunctionRareData.h 2018-03-05 13:16:46 UTC (rev 229270)
@@ -88,6 +88,10 @@
{
return m_internalFunctionAllocationProfile.createAllocationStructureFromBase(vm, globalObject, this, prototype, baseStructure);
}
+ void clearInternalFunctionAllocationProfile()
+ {
+ m_internalFunctionAllocationProfile.clear();
+ }
Structure* getBoundFunctionStructure() { return m_boundFunctionStructure.get(); }
void setBoundFunctionStructure(VM& vm, Structure* structure) { m_boundFunctionStructure.set(vm, this, structure); }
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/JSGlobalObject.cpp (229269 => 229270)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2018-03-05 13:16:40 UTC (rev 229269)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2018-03-05 13:16:46 UTC (rev 229270)
@@ -1170,10 +1170,15 @@
{
}
+inline bool hasBrokenIndexing(IndexingType type)
+{
+ return type && !hasSlowPutArrayStorage(type);
+}
+
inline bool hasBrokenIndexing(JSObject* object)
{
IndexingType type = object->indexingType();
- return type && !hasSlowPutArrayStorage(type);
+ return hasBrokenIndexing(type);
}
inline void ObjectsWithBrokenIndexingFinder::visit(JSCell* cell)
@@ -1181,32 +1186,48 @@
if (!cell->isObject())
return;
- JSObject* object = asObject(cell);
+ VM& vm = m_globalObject->vm();
- // Run this filter first, since it's cheap, and ought to filter out a lot of objects.
- if (!hasBrokenIndexing(object))
- return;
-
// We only want to have a bad time in the affected global object, not in the entire
// VM. But we have to be careful, since there may be objects that claim to belong to
// a different global object that have prototypes from our global object.
- bool foundGlobalObject = false;
- VM& vm = m_globalObject->vm();
- for (JSObject* current = object; ;) {
- if (current->globalObject() == m_globalObject) {
- foundGlobalObject = true;
- break;
+ auto isInEffectedGlobalObject = [&] (JSObject* object) {
+ for (JSObject* current = object; ;) {
+ if (current->globalObject() == m_globalObject)
+ return true;
+
+ JSValue prototypeValue = current->getPrototypeDirect(vm);
+ if (prototypeValue.isNull())
+ return false;
+ current = asObject(prototypeValue);
}
-
- JSValue prototypeValue = current->getPrototypeDirect(vm);
- if (prototypeValue.isNull())
- break;
- current = asObject(prototypeValue);
+ RELEASE_ASSERT_NOT_REACHED();
+ };
+
+ JSObject* object = asObject(cell);
+
+ if (JSFunction* function = jsDynamicCast<JSFunction*>(vm, object)) {
+ if (FunctionRareData* rareData = function->rareData()) {
+ // We only use this to cache JSFinalObjects. They do not start off with a broken indexing type.
+ ASSERT(!(rareData->objectAllocationStructure() && hasBrokenIndexing(rareData->objectAllocationStructure()->indexingType())));
+
+ if (Structure* structure = rareData->internalFunctionAllocationStructure()) {
+ if (hasBrokenIndexing(structure->indexingType())) {
+ bool isRelevantGlobalObject = (structure->globalObject() == m_globalObject)
+ || (structure->hasMonoProto() && !structure->storedPrototype().isNull() && isInEffectedGlobalObject(asObject(structure->storedPrototype())));
+ if (isRelevantGlobalObject)
+ rareData->clearInternalFunctionAllocationProfile();
+ }
+ }
+ }
}
- if (!foundGlobalObject)
+
+ // Run this filter first, since it's cheap, and ought to filter out a lot of objects.
+ if (!hasBrokenIndexing(object))
return;
- m_foundObjects.append(object);
+ if (isInEffectedGlobalObject(object))
+ m_foundObjects.append(object);
}
IterationStatus ObjectsWithBrokenIndexingFinder::operator()(HeapCell* cell, HeapCell::Kind kind) const
@@ -1227,7 +1248,9 @@
if (isHavingABadTime())
return;
-
+
+ vm.structureCache.clear(); // We may be caching array structures in here.
+
// Make sure that all allocations or indexed storage transitions that are inlining
// the assumption that it's safe to transition to a non-SlowPut array storage don't
// do so anymore.
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/StructureCache.h (229269 => 229270)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/StructureCache.h 2018-03-05 13:16:40 UTC (rev 229269)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/runtime/StructureCache.h 2018-03-05 13:16:46 UTC (rev 229270)
@@ -47,6 +47,8 @@
{
}
+ void clear() { m_structures.clear(); }
+
JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSGlobalObject*, JSObject*, unsigned inlineCapacity, bool makePolyProtoStructure = false, FunctionExecutable* = nullptr);
JS_EXPORT_PRIVATE Structure* emptyStructureForPrototypeFromBaseStructure(JSGlobalObject*, JSObject*, Structure*);