Title: [210866] branches/safari-603-branch/Source/_javascript_Core

Diff

Modified: branches/safari-603-branch/Source/_javascript_Core/ChangeLog (210865 => 210866)


--- branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-01-18 20:42:19 UTC (rev 210865)
+++ branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-01-18 20:42:24 UTC (rev 210866)
@@ -1,5 +1,45 @@
 2017-01-18  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r210745. rdar://problem/30019309
+
+    2017-01-13  Saam Barati  <sbar...@apple.com>
+
+            Initialize the ArraySpecies watchpoint as Clear and transition to IsWatched once slice is called for the first time
+            https://bugs.webkit.org/show_bug.cgi?id=167017
+            <rdar://problem/30019309>
+
+            Reviewed by Keith Miller and Filip Pizlo.
+
+            This patch is to reverse the JSBench regression from r210695.
+
+            The new state diagram for the array species watchpoint is as
+            follows:
+
+            1. On GlobalObject construction, it starts life out as ClearWatchpoint.
+            2. When slice is called for the first time, we observe the state
+            of the world, and either transition it to IsWatched if we were able
+            to set up the object property conditions, or to IsInvalidated if we
+            were not.
+            3. The DFG compiler will now only lower slice as an intrinsic if
+            it observed the speciesWatchpoint.state() as IsWatched.
+            4. The IsWatched => IsInvalidated transition happens only when
+            one of the object property condition watchpoints fire.
+
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+            * runtime/ArrayPrototype.cpp:
+            (JSC::speciesWatchpointIsValid):
+            (JSC::speciesConstructArray):
+            (JSC::arrayProtoPrivateFuncConcatMemcpy):
+            (JSC::ArrayPrototype::tryInitializeSpeciesWatchpoint):
+            (JSC::ArrayPrototype::initializeSpeciesWatchpoint): Deleted.
+            * runtime/ArrayPrototype.h:
+            * runtime/JSGlobalObject.cpp:
+            (JSC::JSGlobalObject::JSGlobalObject):
+            (JSC::JSGlobalObject::init):
+
+2017-01-18  Matthew Hanson  <matthew_han...@apple.com>
+
         Merge r210695. rdar://problem/29913445
 
     2017-01-12  Saam Barati  <sbar...@apple.com>

Modified: branches/safari-603-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (210865 => 210866)


--- branches/safari-603-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-01-18 20:42:19 UTC (rev 210865)
+++ branches/safari-603-branch/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-01-18 20:42:24 UTC (rev 210866)
@@ -2278,7 +2278,7 @@
             InlineWatchpointSet& arrayPrototypeTransition = globalObject->arrayPrototype()->structure()->transitionWatchpointSet();
 
             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
-            if (globalObject->arraySpeciesWatchpoint().isStillValid()
+            if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
                 && globalObject->havingABadTimeWatchpoint()->isStillValid()
                 && arrayPrototypeTransition.isStillValid()
                 && objectPrototypeTransition.isStillValid()

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/ArrayPrototype.cpp (210865 => 210866)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2017-01-18 20:42:19 UTC (rev 210865)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2017-01-18 20:42:24 UTC (rev 210866)
@@ -191,12 +191,19 @@
         throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
 }
 
-inline bool speciesWatchpointIsValid(JSObject* thisObject)
+ALWAYS_INLINE bool speciesWatchpointIsValid(ExecState* exec, JSObject* thisObject)
 {
-    ArrayPrototype* arrayPrototype = thisObject->globalObject()->arrayPrototype();
+    JSGlobalObject* globalObject = thisObject->globalObject();
+    ArrayPrototype* arrayPrototype = globalObject->arrayPrototype();
+
+    if (globalObject->arraySpeciesWatchpoint().stateOnJSThread() == ClearWatchpoint) {
+        arrayPrototype->tryInitializeSpeciesWatchpoint(exec);
+        ASSERT(globalObject->arraySpeciesWatchpoint().stateOnJSThread() != ClearWatchpoint);
+    }
+
     return !thisObject->hasCustomProperties()
         && arrayPrototype == thisObject->getPrototypeDirect()
-        && arrayPrototype->globalObject()->arraySpeciesWatchpoint().isStillValid();
+        && globalObject->arraySpeciesWatchpoint().stateOnJSThread() == IsWatched;
 }
 
 enum class SpeciesConstructResult {
@@ -221,7 +228,7 @@
     if (LIKELY(thisIsArray)) {
         // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal.
         // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default.
-        bool isValid = speciesWatchpointIsValid(thisObject);
+        bool isValid = speciesWatchpointIsValid(exec, thisObject);
         if (LIKELY(isValid))
             return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
 
@@ -1239,7 +1246,7 @@
         return JSValue::encode(jsNull());
 
     // We need to check the species constructor here since checking it in the JS wrapper is too expensive for the non-optimizing tiers.
-    bool isValid = speciesWatchpointIsValid(firstArray);
+    bool isValid = speciesWatchpointIsValid(exec, firstArray);
     if (UNLIKELY(!isValid))
         return JSValue::encode(jsNull());
 
@@ -1331,7 +1338,7 @@
     ArrayPrototype* m_arrayPrototype;
 };
 
-void ArrayPrototype::initializeSpeciesWatchpoint(ExecState* exec)
+void ArrayPrototype::tryInitializeSpeciesWatchpoint(ExecState* exec)
 {
     VM& vm = exec->vm();
 
@@ -1339,7 +1346,6 @@
     RELEASE_ASSERT(!m_constructorSpeciesWatchpoint);
 
     auto scope = DECLARE_THROW_SCOPE(vm);
-    UNUSED_PARAM(scope);
 
     if (verbose)
         dataLog("Initializing Array species watchpoints for Array.prototype: ", pointerDump(this), " with structure: ", pointerDump(this->structure()), "\nand Array: ", pointerDump(this->globalObject()->arrayConstructor()), " with structure: ", pointerDump(this->globalObject()->arrayConstructor()->structure()), "\n");
@@ -1355,12 +1361,19 @@
     JSGlobalObject* globalObject = this->globalObject();
     ArrayConstructor* arrayConstructor = globalObject->arrayConstructor();
 
+    auto invalidateWatchpoint = [&] {
+        globalObject->arraySpeciesWatchpoint().invalidate(vm, StringFireDetail("Was not able to set up array species watchpoint."));
+    };
+
     PropertySlot constructorSlot(this, PropertySlot::InternalMethodType::VMInquiry);
     this->getOwnPropertySlot(this, exec, vm.propertyNames->constructor, constructorSlot);
-    ASSERT(!scope.exception());
-    ASSERT(constructorSlot.slotBase() == this);
-    ASSERT(constructorSlot.isCacheableValue());
-    RELEASE_ASSERT(constructorSlot.getValue(exec, vm.propertyNames->constructor) == arrayConstructor);
+    ASSERT_UNUSED(scope, !scope.exception());
+    if (constructorSlot.slotBase() != this
+        || !constructorSlot.isCacheableValue()
+        || constructorSlot.getValue(exec, vm.propertyNames->constructor) != arrayConstructor) {
+        invalidateWatchpoint();
+        return;
+    }
 
     Structure* constructorStructure = arrayConstructor->structure(vm);
     if (constructorStructure->isDictionary())
@@ -1368,10 +1381,13 @@
 
     PropertySlot speciesSlot(arrayConstructor, PropertySlot::InternalMethodType::VMInquiry);
     arrayConstructor->getOwnPropertySlot(arrayConstructor, exec, vm.propertyNames->speciesSymbol, speciesSlot);
-    ASSERT(!scope.exception());
-    ASSERT(speciesSlot.slotBase() == arrayConstructor);
-    ASSERT(speciesSlot.isCacheableGetter());
-    RELEASE_ASSERT(speciesSlot.getterSetter() == globalObject->speciesGetterSetter());
+    ASSERT_UNUSED(scope, !scope.exception());
+    if (speciesSlot.slotBase() != arrayConstructor
+        || !speciesSlot.isCacheableGetter()
+        || speciesSlot.getterSetter() != globalObject->speciesGetterSetter()) {
+        invalidateWatchpoint();
+        return;
+    }
 
     // Now we need to setup the watchpoints to make sure these conditions remain valid.
     prototypeStructure->startWatchingPropertyForReplacements(vm, constructorSlot.cachedOffset());
@@ -1380,8 +1396,10 @@
     ObjectPropertyCondition constructorCondition = ObjectPropertyCondition::equivalence(vm, this, this, vm.propertyNames->constructor.impl(), arrayConstructor);
     ObjectPropertyCondition speciesCondition = ObjectPropertyCondition::equivalence(vm, this, arrayConstructor, vm.propertyNames->speciesSymbol.impl(), globalObject->speciesGetterSetter());
 
-    RELEASE_ASSERT(constructorCondition.isWatchable());
-    RELEASE_ASSERT(speciesCondition.isWatchable());
+    if (!constructorCondition.isWatchable() || !speciesCondition.isWatchable()) {
+        invalidateWatchpoint();
+        return;
+    }
 
     m_constructorWatchpoint = std::make_unique<ArrayPrototypeAdaptiveInferredPropertyWatchpoint>(constructorCondition, this);
     m_constructorWatchpoint->install();
@@ -1388,6 +1406,10 @@
 
     m_constructorSpeciesWatchpoint = std::make_unique<ArrayPrototypeAdaptiveInferredPropertyWatchpoint>(speciesCondition, this);
     m_constructorSpeciesWatchpoint->install();
+
+    // We only watch this from the DFG, and the DFG makes sure to only start watching if the watchpoint is in the IsWatched state.
+    RELEASE_ASSERT(!globalObject->arraySpeciesWatchpoint().isBeingWatched()); 
+    globalObject->arraySpeciesWatchpoint().touch(vm, "Set up array species watchpoint.");
 }
 
 ArrayPrototypeAdaptiveInferredPropertyWatchpoint::ArrayPrototypeAdaptiveInferredPropertyWatchpoint(const ObjectPropertyCondition& key, ArrayPrototype* prototype)

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/ArrayPrototype.h (210865 => 210866)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/ArrayPrototype.h	2017-01-18 20:42:19 UTC (rev 210865)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/ArrayPrototype.h	2017-01-18 20:42:24 UTC (rev 210866)
@@ -49,7 +49,7 @@
         return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
     }
 
-    void initializeSpeciesWatchpoint(ExecState*);
+    void tryInitializeSpeciesWatchpoint(ExecState*);
 
     static const bool needsDestruction = false;
     // We don't need destruction since we use a finalizer.

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/JSGlobalObject.cpp (210865 => 210866)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2017-01-18 20:42:19 UTC (rev 210865)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2017-01-18 20:42:24 UTC (rev 210866)
@@ -331,7 +331,7 @@
     , m_varInjectionWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
     , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
     , m_arrayIteratorProtocolWatchpoint(IsWatched)
-    , m_arraySpeciesWatchpoint(IsWatched)
+    , m_arraySpeciesWatchpoint(ClearWatchpoint)
     , m_templateRegistry(vm)
     , m_evalEnabled(true)
     , m_runtimeFlags()
@@ -944,8 +944,6 @@
             m_arrayPrototypeSymbolIteratorWatchpoint = std::make_unique<ArrayIteratorAdaptiveWatchpoint>(condition, this);
             m_arrayPrototypeSymbolIteratorWatchpoint->install();
         }
-
-        this->arrayPrototype()->initializeSpeciesWatchpoint(exec);
     }
 
     resetPrototype(vm, getPrototypeDirect());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to