Modified: trunk/Source/_javascript_Core/ChangeLog (194399 => 194400)
--- trunk/Source/_javascript_Core/ChangeLog 2015-12-23 23:31:44 UTC (rev 194399)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-12-23 23:45:17 UTC (rev 194400)
@@ -1,3 +1,20 @@
+2015-12-23 Keith Miller <[email protected]>
+
+ [JSC] Bugfix for intrinsic getters with dictionary structures.
+ https://bugs.webkit.org/show_bug.cgi?id=152538
+
+ Reviewed by Mark Lam.
+
+ Intrinsic getters did not check if an object was a dictionary. This meant, if a property on
+ the prototype chain of a dictionary was an intrinsic getter we would IC it. Later, if a
+ property is added to the dictionary the IC would still return the result of the intrinsic.
+ The fix is to no longer IC intrinsic getters if the base object is a dictionary.
+
+ * jit/Repatch.cpp:
+ (JSC::tryCacheGetByID):
+ * tests/stress/typedarray-length-dictionary.js: Added.
+ (len):
+
2015-12-23 Andy VanWagoner <[email protected]>
[INTL] Implement DateTime Format Functions
Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (194399 => 194400)
--- trunk/Source/_javascript_Core/jit/Repatch.cpp 2015-12-23 23:31:44 UTC (rev 194399)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp 2015-12-23 23:45:17 UTC (rev 194400)
@@ -224,31 +224,19 @@
VM& vm = exec->vm();
std::unique_ptr<AccessCase> newCase;
- JSFunction* getter = nullptr;
- ObjectPropertyConditionSet conditionSet;
- JSCell* baseCell = baseValue.asCell();
- Structure* structure = baseCell->structure(vm);
- if (slot.isCacheableGetter())
- getter = jsDynamicCast<JSFunction*>(slot.getterSetter()->getter());
-
if (isJSArray(baseValue) && propertyName == exec->propertyNames().length)
newCase = AccessCase::getLength(vm, codeBlock, AccessCase::ArrayLength);
else if (isJSString(baseValue) && propertyName == exec->propertyNames().length)
newCase = AccessCase::getLength(vm, codeBlock, AccessCase::StringLength);
- else if (getter && AccessCase::canEmitIntrinsicGetter(getter, structure)) {
- if (slot.slotBase() != baseValue) {
- conditionSet = generateConditionsForPrototypePropertyHit(vm, codeBlock->ownerExecutable(), exec, structure, slot.slotBase(), propertyName.impl());
- if (!conditionSet.isValid())
- return GiveUpOnCache;
- }
-
- newCase = AccessCase::getIntrinsic(vm, codeBlock, getter, slot.cachedOffset(), structure, conditionSet);
-
- } else {
+ else {
if (!slot.isCacheable() && !slot.isUnset())
return GiveUpOnCache;
+ ObjectPropertyConditionSet conditionSet;
+ JSCell* baseCell = baseValue.asCell();
+ Structure* structure = baseCell->structure(vm);
+
bool loadTargetFromProxy = false;
if (baseCell->type() == PureForwardingProxyType) {
baseValue = jsCast<JSProxy*>(baseCell)->target();
@@ -297,24 +285,32 @@
if (!conditionSet.isValid())
return GiveUpOnCache;
-
+
offset = slot.isUnset() ? invalidOffset : conditionSet.slotBaseCondition().offset();
}
- AccessCase::AccessType type;
- if (slot.isCacheableValue())
- type = AccessCase::Load;
- else if (slot.isUnset())
- type = AccessCase::Miss;
- else if (slot.isCacheableGetter())
- type = AccessCase::Getter;
- else
- type = AccessCase::CustomGetter;
+ JSFunction* getter = nullptr;
+ if (slot.isCacheableGetter())
+ getter = jsDynamicCast<JSFunction*>(slot.getterSetter()->getter());
- newCase = AccessCase::get(
- vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy,
- slot.watchpointSet(), slot.isCacheableCustom() ? slot.customGetter() : nullptr,
- slot.isCacheableCustom() ? slot.slotBase() : nullptr);
+ if (!loadTargetFromProxy && getter && AccessCase::canEmitIntrinsicGetter(getter, structure))
+ newCase = AccessCase::getIntrinsic(vm, codeBlock, getter, slot.cachedOffset(), structure, conditionSet);
+ else {
+ AccessCase::AccessType type;
+ if (slot.isCacheableValue())
+ type = AccessCase::Load;
+ else if (slot.isUnset())
+ type = AccessCase::Miss;
+ else if (slot.isCacheableGetter())
+ type = AccessCase::Getter;
+ else
+ type = AccessCase::CustomGetter;
+
+ newCase = AccessCase::get(
+ vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy,
+ slot.watchpointSet(), slot.isCacheableCustom() ? slot.customGetter() : nullptr,
+ slot.isCacheableCustom() ? slot.slotBase() : nullptr);
+ }
}
MacroAssemblerCodePtr codePtr =
Added: trunk/Source/_javascript_Core/tests/stress/typedarray-length-dictionary.js (0 => 194400)
--- trunk/Source/_javascript_Core/tests/stress/typedarray-length-dictionary.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/typedarray-length-dictionary.js 2015-12-23 23:45:17 UTC (rev 194400)
@@ -0,0 +1,19 @@
+// This tests that we do not inline cache intrinsic getters when the base structure is a dictionary.
+
+foo = new Int32Array(10);
+
+function len() {
+ return foo.length;
+}
+noInline(len);
+
+foo.bar = 1;
+foo.baz = 2;
+delete foo.bar;
+
+for (i = 0; i < 1000; i++)
+ len()
+
+Object.defineProperty(foo, "length", { value: 1 });
+if (len() !== 1)
+ throw "bad result";