Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (177379 => 177380)
--- trunk/Source/_javascript_Core/ChangeLog 2014-12-16 19:55:54 UTC (rev 177379)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-12-16 20:11:00 UTC (rev 177380)
@@ -1,3 +1,24 @@
+2014-12-16 Matthew Mirman <mmir...@apple.com>
+
+ Fixes operationPutByIdOptimizes such that they check that the put didn't
+ change the structure of the object who's property access is being
+ cached.
+ https://bugs.webkit.org/show_bug.cgi?id=139500
+
+ Reviewed by Geoffrey Garen.
+
+ * jit/JITOperations.cpp:
+ (JSC::operationPutByIdStrictOptimize): saved the structure before the put.
+ (JSC::operationPutByIdNonStrictOptimize): ditto.
+ (JSC::operationPutByIdDirectStrictOptimize): ditto.
+ (JSC::operationPutByIdDirectNonStrictOptimize): ditto.
+ * jit/Repatch.cpp:
+ (JSC::tryCachePutByID): Added argument for the old structure
+ (JSC::repatchPutByID): Added argument for the old structure
+ * jit/Repatch.h:
+ * tests/stress/put-by-id-build-list-order-recurse.js:
+ Added test that fails without this patch.
+
2014-12-15 Chris Dumez <cdu...@apple.com>
[iOS] Add feature counting support
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (177379 => 177380)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2014-12-16 19:55:54 UTC (rev 177379)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2014-12-16 20:11:00 UTC (rev 177380)
@@ -273,14 +273,15 @@
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
-
+
+ Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
baseValue.put(exec, ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
+ repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
else
stubInfo->seen = true;
}
@@ -296,14 +297,15 @@
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
-
+
+ Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
baseValue.put(exec, ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
+ repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
else
stubInfo->seen = true;
}
@@ -320,13 +322,14 @@
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
+ Structure* structure = baseObject->structure(*vm);
baseObject->putDirect(exec->vm(), ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
+ repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
else
stubInfo->seen = true;
}
@@ -343,13 +346,14 @@
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
+ Structure* structure = baseObject->structure(*vm);
baseObject->putDirect(exec->vm(), ident, value, slot);
if (accessType != static_cast<AccessType>(stubInfo->accessType))
return;
if (stubInfo->seen)
- repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
+ repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
else
stubInfo->seen = true;
}
Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (177379 => 177380)
--- trunk/Source/_javascript_Core/jit/Repatch.cpp 2014-12-16 19:55:54 UTC (rev 177379)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp 2014-12-16 20:11:00 UTC (rev 177380)
@@ -1224,7 +1224,7 @@
structure);
}
-static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier& ident, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Structure* structure, const Identifier& ident, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
{
if (Options::forceICFailure())
return GiveUpOnCache;
@@ -1235,7 +1235,10 @@
if (!baseValue.isCell())
return GiveUpOnCache;
JSCell* baseCell = baseValue.asCell();
- Structure* structure = baseCell->structure(*vm);
+
+ if (baseCell->structure(*vm)->id() != structure->id())
+ return GiveUpOnCache;
+
Structure* oldStructure = structure->previousID();
if (!slot.isCacheablePut() && !slot.isCacheableCustom() && !slot.isCacheableSetter())
@@ -1333,11 +1336,11 @@
return GiveUpOnCache;
}
-void repatchPutByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+void repatchPutByID(ExecState* exec, JSValue baseValue, Structure* structure, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
{
GCSafeConcurrentJITLocker locker(exec->codeBlock()->m_lock, exec->vm().heap);
- if (tryCachePutByID(exec, baseValue, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
+ if (tryCachePutByID(exec, baseValue, structure, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
repatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
}
Modified: trunk/Source/_javascript_Core/jit/Repatch.h (177379 => 177380)
--- trunk/Source/_javascript_Core/jit/Repatch.h 2014-12-16 19:55:54 UTC (rev 177379)
+++ trunk/Source/_javascript_Core/jit/Repatch.h 2014-12-16 20:11:00 UTC (rev 177380)
@@ -36,7 +36,7 @@
void repatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
void buildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
void buildGetByIDProtoList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
-void repatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
+void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
void buildPutByIdList(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
void repatchIn(ExecState*, JSCell*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&);
void linkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind, RegisterPreservationMode);
Added: trunk/Source/_javascript_Core/tests/stress/put-by-id-build-list-order-recurse.js (0 => 177380)
--- trunk/Source/_javascript_Core/tests/stress/put-by-id-build-list-order-recurse.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/put-by-id-build-list-order-recurse.js 2014-12-16 20:11:00 UTC (rev 177380)
@@ -0,0 +1,35 @@
+var count = 0;
+
+function setter(value) {
+ Object.defineProperty(
+ this, "f", {
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: 32
+ });
+ var o = Object.create(this);
+ var currentCount = count++;
+ var str = "for (var i = " + currentCount + "; i < " + (100 + currentCount) + "; ++i)\n"
+ + " o.f\n";
+ eval(str);
+}
+
+function foo(o) {
+ o.f = 42;
+}
+
+noInline(foo);
+
+for (var i = 0; i < 1000; ++i) {
+ var o = {};
+ o.__defineSetter__("f", setter);
+
+ foo(o);
+ if (o.f != 32)
+ throw ("Error 1: "+o.f);
+
+ foo(o);
+ if (o.f != 42)
+ throw ("Error 2: "+o.f);
+}
\ No newline at end of file