Title: [264857] trunk
Revision
264857
Author
[email protected]
Date
2020-07-24 14:29:40 -0700 (Fri, 24 Jul 2020)

Log Message

[JSC] DFG::AbstractValue::filterByValue should re-filter configured m_value via m_type
https://bugs.webkit.org/show_bug.cgi?id=214721
<rdar://problem/65882837>

Reviewed by Mark Lam.

JSTests:

* stress/speculation-from-structure-and-classinfo-should-agree.js: Added.
(bar):
(foo):

Source/_javascript_Core:

Let's consider the following case.

    1. Input AbstractValue is saying SpecObjectOther.
    2. We have CheckIsConstant with StringPrototype (which is SpecObjectOther | SpecStringObject in the current SpeculatedType).
    3. We call filterByValue, which filters m_type by SpecObjectOther | SpecStringObject. But the filtered m_type is SpecObjectOther since (2)'s SpeculatedType is broader.
    4. We store the given constant (StringPrototype) to m_value.
    5. This AbstractValue's m_type is SpecObjectOther while its m_value's SpeculatedType is SpecObjectOther | SpecStringObject. Contradiction!

When setting m_value by filterByValue, we should filter m_value with m_type to ensure that m_value is the expected one.
This patch also avoid using SpecObjectOther | SpecStringObject for StringPrototype since we can return narrower type for that.

* bytecode/SpeculatedType.cpp:
(JSC::speculationFromStructure):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::filterByValue):
(JSC::DFG::AbstractValue::filter):
* dfg/DFGPredictionPropagationPhase.cpp:
* runtime/StringObject.cpp:
(JSC::StringObject::finishCreation):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (264856 => 264857)


--- trunk/JSTests/ChangeLog	2020-07-24 21:03:23 UTC (rev 264856)
+++ trunk/JSTests/ChangeLog	2020-07-24 21:29:40 UTC (rev 264857)
@@ -1,3 +1,15 @@
+2020-07-24  Yusuke Suzuki  <[email protected]>
+
+        [JSC] DFG::AbstractValue::filterByValue should re-filter configured m_value via m_type
+        https://bugs.webkit.org/show_bug.cgi?id=214721
+        <rdar://problem/65882837>
+
+        Reviewed by Mark Lam.
+
+        * stress/speculation-from-structure-and-classinfo-should-agree.js: Added.
+        (bar):
+        (foo):
+
 2020-07-24  Alexey Shvayka  <[email protected]>
 
         JSON.parse should not modify non-configurable properties.

Added: trunk/JSTests/stress/speculation-from-structure-and-classinfo-should-agree.js (0 => 264857)


--- trunk/JSTests/stress/speculation-from-structure-and-classinfo-should-agree.js	                        (rev 0)
+++ trunk/JSTests/stress/speculation-from-structure-and-classinfo-should-agree.js	2020-07-24 21:29:40 UTC (rev 264857)
@@ -0,0 +1,14 @@
+//@ runDefault("--forceEagerCompilation=1", "--minimumOptimizationDelay=10", "--maximumOptimizationDelay=10", "--useConcurrentJIT=0")
+
+function bar(a0) {
+    '' instanceof a0;
+}
+
+function foo() {
+    optimizeNextInvocation(foo);
+    bar(String);
+    bar(Symbol);
+}
+
+for (let i=0; i<11; i++)
+    foo();

Modified: trunk/Source/_javascript_Core/ChangeLog (264856 => 264857)


--- trunk/Source/_javascript_Core/ChangeLog	2020-07-24 21:03:23 UTC (rev 264856)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-07-24 21:29:40 UTC (rev 264857)
@@ -1,3 +1,31 @@
+2020-07-24  Yusuke Suzuki  <[email protected]>
+
+        [JSC] DFG::AbstractValue::filterByValue should re-filter configured m_value via m_type
+        https://bugs.webkit.org/show_bug.cgi?id=214721
+        <rdar://problem/65882837>
+
+        Reviewed by Mark Lam.
+
+        Let's consider the following case.
+
+            1. Input AbstractValue is saying SpecObjectOther.
+            2. We have CheckIsConstant with StringPrototype (which is SpecObjectOther | SpecStringObject in the current SpeculatedType).
+            3. We call filterByValue, which filters m_type by SpecObjectOther | SpecStringObject. But the filtered m_type is SpecObjectOther since (2)'s SpeculatedType is broader.
+            4. We store the given constant (StringPrototype) to m_value.
+            5. This AbstractValue's m_type is SpecObjectOther while its m_value's SpeculatedType is SpecObjectOther | SpecStringObject. Contradiction!
+
+        When setting m_value by filterByValue, we should filter m_value with m_type to ensure that m_value is the expected one.
+        This patch also avoid using SpecObjectOther | SpecStringObject for StringPrototype since we can return narrower type for that.
+
+        * bytecode/SpeculatedType.cpp:
+        (JSC::speculationFromStructure):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::filterByValue):
+        (JSC::DFG::AbstractValue::filter):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * runtime/StringObject.cpp:
+        (JSC::StringObject::finishCreation):
+
 2020-07-24  Alexey Shvayka  <[email protected]>
 
         JSON.parse should not modify non-configurable properties.

Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (264856 => 264857)


--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2020-07-24 21:03:23 UTC (rev 264856)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp	2020-07-24 21:29:40 UTC (rev 264857)
@@ -517,21 +517,32 @@
 SpeculatedType speculationFromStructure(Structure* structure)
 {
     SpeculatedType filteredResult = SpecNone;
-    if (structure->typeInfo().type() == StringType)
+    switch (structure->typeInfo().type()) {
+    case StringType:
         filteredResult = SpecString;
-    else if (structure->typeInfo().type() == SymbolType)
+        break;
+    case SymbolType:
         filteredResult = SpecSymbol;
-    else if (structure->typeInfo().type() == HeapBigIntType)
+        break;
+    case HeapBigIntType:
         filteredResult = SpecHeapBigInt;
-    else if (structure->typeInfo().type() == DerivedArrayType)
+        break;
+    case DerivedArrayType:
         filteredResult = SpecDerivedArray;
-    else if (structure->typeInfo().type() == ArrayType)
+        break;
+    case ArrayType:
         filteredResult = SpecArray;
-    else if (structure->typeInfo().type() == StringObjectType)
+        break;
+    case StringObjectType:
         filteredResult = SpecStringObject;
-    else
+        break;
+    // We do not want to accept String.prototype in StringObjectUse, so that we do not include it as SpecStringObject.
+    case DerivedStringObjectType:
+        filteredResult = SpecObjectOther;
+        break;
+    default:
         return speculationFromClassInfoInheritance(structure->classInfo());
-
+    }
     ASSERT(filteredResult);
     ASSERT(isSubtypeSpeculation(filteredResult, speculationFromClassInfoInheritance(structure->classInfo())));
     return filteredResult;

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractValue.cpp (264856 => 264857)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractValue.cpp	2020-07-24 21:03:23 UTC (rev 264856)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractValue.cpp	2020-07-24 21:29:40 UTC (rev 264857)
@@ -321,8 +321,15 @@
 FiltrationResult AbstractValue::filterByValue(const FrozenValue& value)
 {
     FiltrationResult result = filter(speculationFromValue(value.value()));
-    if (m_type)
+    if (m_type) {
         m_value = value.value();
+        // It is possible that SpeculatedType from value is broader than original m_type.
+        // The filter operation can only keep m_type as is or make it narrower.
+        // As a result, the SpeculatedType from m_value can become broader than m_type. This breaks an invariant.
+        // When setting m_value after filtering, we should filter m_value with m_type.
+        filterValueByType();
+    }
+    checkConsistency();
     return result;
 }
 
@@ -353,6 +360,11 @@
     if (!m_value) {
         // We previously didn't prove a value but now we have done so.
         m_value = other.m_value; 
+        // It is possible that SpeculatedType from other.m_value is broader than original m_type.
+        // The filter operation can only keep m_type as is or make it narrower.
+        // As a result, the SpeculatedType from m_value can become broader than m_type. This breaks an invariant.
+        // When setting m_value after filtering, we should filter m_value with m_type.
+        filterValueByType();
         return FiltrationOK;
     }
     

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (264856 => 264857)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2020-07-24 21:03:23 UTC (rev 264856)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2020-07-24 21:29:40 UTC (rev 264857)
@@ -588,9 +588,12 @@
             if (isStrictMode)
                 changed |= mergePrediction(node->getHeapPrediction());
             else if (prediction) {
+                SpeculatedType originalPrediction = prediction;
                 if (prediction & ~SpecObject) {
                     // Wrapper objects are created only in sloppy mode.
                     prediction &= SpecObject;
+                    if (originalPrediction & SpecString)
+                        prediction = mergeSpeculations(prediction, SpecStringObject);
                     prediction = mergeSpeculations(prediction, SpecObjectOther);
                 }
                 changed |= mergePrediction(prediction);

Modified: trunk/Source/_javascript_Core/runtime/StringObject.cpp (264856 => 264857)


--- trunk/Source/_javascript_Core/runtime/StringObject.cpp	2020-07-24 21:03:23 UTC (rev 264856)
+++ trunk/Source/_javascript_Core/runtime/StringObject.cpp	2020-07-24 21:29:40 UTC (rev 264857)
@@ -41,6 +41,7 @@
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
     setInternalValue(vm, string);
+    ASSERT_WITH_MESSAGE(type() == StringObjectType || type() == DerivedStringObjectType, "Instance inheriting StringObject should have DerivedStringObjectType");
 }
 
 bool StringObject::getOwnPropertySlot(JSObject* cell, JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to