Title: [266107] trunk/Source/_javascript_Core
Revision
266107
Author
[email protected]
Date
2020-08-25 01:06:48 -0700 (Tue, 25 Aug 2020)

Log Message

[JSC] Add concurrency-aware version of isCallable / isConstructor to make it usable in DFG compiler
https://bugs.webkit.org/show_bug.cgi?id=215746

Reviewed by Saam Barati.

This patch adds isCallableWithConcurrency and isConstructorWithConcurrency to JSCell, JSValue etc.
This can work even if it is called from concurrent compiler threads. We also add jsTypeStringForValueWithConcurrency
and jsTypeofIsFunctionWithConcurrency which are using the above WithConcurrency functionalities.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* runtime/Concurrency.h: Added.
(WTF::printInternal):
* runtime/InternalFunction.cpp:
(JSC::InternalFunction::finishCreation):
(JSC::InternalFunction::getCallData):
(JSC::InternalFunction::getConstructData):
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::isCallableWithConcurrency const):
(JSC::JSValue::isConstructorWithConcurrency const):
* runtime/JSCell.h:
* runtime/JSCellInlines.h:
(JSC::JSCell::isCallableWithConcurrency):
(JSC::JSCell::isConstructorWithConcurrency):
(JSC::JSCell::isCallable):
(JSC::JSCell::isConstructor):
* runtime/JSFunction.cpp:
(JSC::JSFunction::finishCreation):
(JSC::JSFunction::getCallData):
(JSC::JSFunction::getConstructData):
* runtime/NumberPrototype.cpp:
(JSC::throwVMToThisNumberError):
* runtime/Operations.cpp:
(JSC::jsTypeStringForValueWithConcurrency):
(JSC::jsTypeStringForValue): Deleted.
* runtime/Operations.h:
(JSC::jsTypeofIsFunctionWithConcurrency):
(JSC::jsTypeStringForValue):
(JSC::jsTypeofIsFunction):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (266106 => 266107)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2020-08-25 08:06:48 UTC (rev 266107)
@@ -818,6 +818,7 @@
     runtime/CommonIdentifiers.h
     runtime/CompilationResult.h
     runtime/Completion.h
+    runtime/Concurrency.h
     runtime/ConcurrentJSLock.h
     runtime/ConfigFile.h
     runtime/ConsoleClient.h

Modified: trunk/Source/_javascript_Core/ChangeLog (266106 => 266107)


--- trunk/Source/_javascript_Core/ChangeLog	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-08-25 08:06:48 UTC (rev 266107)
@@ -1,3 +1,48 @@
+2020-08-25  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Add concurrency-aware version of isCallable / isConstructor to make it usable in DFG compiler
+        https://bugs.webkit.org/show_bug.cgi?id=215746
+
+        Reviewed by Saam Barati.
+
+        This patch adds isCallableWithConcurrency and isConstructorWithConcurrency to JSCell, JSValue etc.
+        This can work even if it is called from concurrent compiler threads. We also add jsTypeStringForValueWithConcurrency
+        and jsTypeofIsFunctionWithConcurrency which are using the above WithConcurrency functionalities.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * runtime/Concurrency.h: Added.
+        (WTF::printInternal):
+        * runtime/InternalFunction.cpp:
+        (JSC::InternalFunction::finishCreation):
+        (JSC::InternalFunction::getCallData):
+        (JSC::InternalFunction::getConstructData):
+        * runtime/JSCJSValue.h:
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::isCallableWithConcurrency const):
+        (JSC::JSValue::isConstructorWithConcurrency const):
+        * runtime/JSCell.h:
+        * runtime/JSCellInlines.h:
+        (JSC::JSCell::isCallableWithConcurrency):
+        (JSC::JSCell::isConstructorWithConcurrency):
+        (JSC::JSCell::isCallable):
+        (JSC::JSCell::isConstructor):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::finishCreation):
+        (JSC::JSFunction::getCallData):
+        (JSC::JSFunction::getConstructData):
+        * runtime/NumberPrototype.cpp:
+        (JSC::throwVMToThisNumberError):
+        * runtime/Operations.cpp:
+        (JSC::jsTypeStringForValueWithConcurrency):
+        (JSC::jsTypeStringForValue): Deleted.
+        * runtime/Operations.h:
+        (JSC::jsTypeofIsFunctionWithConcurrency):
+        (JSC::jsTypeStringForValue):
+        (JSC::jsTypeofIsFunction):
+
 2020-08-25  Alexey Shvayka  <[email protected]>
 
         Implementation of the class "extends" clause incorrectly uses __proto__ for setting prototypes

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (266106 => 266107)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2020-08-25 08:06:48 UTC (rev 266107)
@@ -1848,6 +1848,7 @@
 		E365F33B24AA623B00C991B2 /* IntlDisplayNamesPrototype.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E365F33824AA621100C991B2 /* IntlDisplayNamesPrototype.lut.h */; };
 		E36B767022F8D61900D09818 /* WasmOMGForOSREntryPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */; };
 		E36CC9472086314F0051FFD6 /* WasmCreationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E36CC9462086314F0051FFD6 /* WasmCreationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		E36EDCE524F0975700E60DA2 /* Concurrency.h in Headers */ = {isa = PBXBuildFile; fileRef = E36EDCE424F0975700E60DA2 /* Concurrency.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		E383500A2390D93B0036316D /* WasmGlobal.h in Headers */ = {isa = PBXBuildFile; fileRef = E38350092390D9370036316D /* WasmGlobal.h */; };
 		E3850B15226ED641009ABF9C /* DFGMinifiedIDInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3850B14226ED63E009ABF9C /* DFGMinifiedIDInlines.h */; };
@@ -5047,6 +5048,7 @@
 		E36B766E22F8D61100D09818 /* WasmOMGForOSREntryPlan.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOMGForOSREntryPlan.cpp; sourceTree = "<group>"; };
 		E36B766F22F8D61100D09818 /* WasmOMGForOSREntryPlan.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WasmOMGForOSREntryPlan.h; sourceTree = "<group>"; };
 		E36CC9462086314F0051FFD6 /* WasmCreationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCreationMode.h; sourceTree = "<group>"; };
+		E36EDCE424F0975700E60DA2 /* Concurrency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Concurrency.h; sourceTree = "<group>"; };
 		E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; };
 		E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = "<group>"; };
 		E37CFB2D22F27C57009A7B38 /* WasmCompilationMode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WasmCompilationMode.cpp; sourceTree = "<group>"; };
@@ -7155,6 +7157,7 @@
 				A7E5A3A61797432D00E893C0 /* CompilationResult.h */,
 				969A09220ED1E09C00F1F681 /* Completion.cpp */,
 				F5BB2BC5030F772101FCFE1D /* Completion.h */,
+				E36EDCE424F0975700E60DA2 /* Concurrency.h */,
 				0FDB2CE9174896C7007B3C1B /* ConcurrentJSLock.h */,
 				658824B01E5CFDF400FB7359 /* ConfigFile.cpp */,
 				658824AE1E5CFDB000FB7359 /* ConfigFile.h */,
@@ -9316,6 +9319,7 @@
 				0FD2FD9420B52BDE00F09441 /* CompleteSubspaceInlines.h in Headers */,
 				BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */,
 				0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */,
+				E36EDCE524F0975700E60DA2 /* Concurrency.h in Headers */,
 				0FDB2CEA174896C7007B3C1B /* ConcurrentJSLock.h in Headers */,
 				BC18C3F50E16F5CD00B34460 /* config.h in Headers */,
 				658824AF1E5CFDB000FB7359 /* ConfigFile.h in Headers */,

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (266106 => 266107)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -1491,9 +1491,14 @@
                 } else
                     setConstant(node, jsBoolean(child.value().isNull()));
                 break;
-            case TypeOfIsFunction:
-                setConstant(node, jsBoolean(jsTypeofIsFunction(m_codeBlock->globalObjectFor(node->origin.semantic), child.value())));
+            case TypeOfIsFunction: {
+                TriState result = jsTypeofIsFunctionWithConcurrency<Concurrency::ConcurrentThread>(m_codeBlock->globalObjectFor(node->origin.semantic), child.value());
+                if (result != TriState::Indeterminate)
+                    setConstant(node, jsBoolean(result == TriState::True));
+                else
+                    constantWasSet = false;
                 break;
+            }
             case IsUndefinedOrNull:
                 setConstant(node, jsBoolean(child.value().isUndefinedOrNull()));
                 break;
@@ -1512,12 +1517,22 @@
             case IsObject:
                 setConstant(node, jsBoolean(child.value().isObject()));
                 break;
-            case IsCallable:
-                setConstant(node, jsBoolean(child.value().isCallable(m_vm)));
+            case IsCallable: {
+                TriState result = child.value().isCallableWithConcurrency<Concurrency::ConcurrentThread>(m_vm);
+                if (result != TriState::Indeterminate)
+                    setConstant(node, jsBoolean(result == TriState::True));
+                else
+                    constantWasSet = false;
                 break;
-            case IsConstructor:
-                setConstant(node, jsBoolean(child.value().isConstructor(m_vm)));
+            }
+            case IsConstructor: {
+                TriState result = child.value().isConstructorWithConcurrency<Concurrency::ConcurrentThread>(m_vm);
+                if (result != TriState::Indeterminate)
+                    setConstant(node, jsBoolean(result == TriState::True));
+                else
+                    constantWasSet = false;
                 break;
+            }
             case IsEmpty:
                 setConstant(node, jsBoolean(child.value().isEmpty()));
                 break;
@@ -1782,9 +1797,10 @@
         JSValue child = forNode(node->child1()).value();
         AbstractValue& abstractChild = forNode(node->child1());
         if (child) {
-            JSValue typeString = jsTypeStringForValue(m_vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
-            setConstant(node, *m_graph.freeze(typeString));
-            break;
+            if (JSString* typeString = jsTypeStringForValueWithConcurrency(m_vm, m_codeBlock->globalObjectFor(node->origin.semantic), child, Concurrency::ConcurrentThread)) {
+                setConstant(node, *m_graph.freeze(typeString));
+                break;
+            }
         }
         
         if (isFullNumberSpeculation(abstractChild.m_type)) {

Added: trunk/Source/_javascript_Core/runtime/Concurrency.h (0 => 266107)


--- trunk/Source/_javascript_Core/runtime/Concurrency.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/Concurrency.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+enum class Concurrency : uint8_t {
+    MainThread,
+    ConcurrentThread,
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+inline void printInternal(PrintStream& out, JSC::Concurrency concurrency)
+{
+    switch (concurrency) {
+    case JSC::Concurrency::MainThread:
+        out.print("MainThread");
+        return;
+    case JSC::Concurrency::ConcurrentThread:
+        out.print("ConcurrentThread");
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+

Modified: trunk/Source/_javascript_Core/runtime/InternalFunction.cpp (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/InternalFunction.cpp	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/InternalFunction.cpp	2020-08-25 08:06:48 UTC (rev 266107)
@@ -47,6 +47,7 @@
 {
     Base::finishCreation(vm);
     ASSERT(jsDynamicCast<InternalFunction*>(vm, this));
+    // JSCell::{getCallData,getConstructData} relies on the following conditions.
     ASSERT(methodTable(vm)->getCallData == InternalFunction::info()->methodTable.getCallData);
     ASSERT(methodTable(vm)->getConstructData == InternalFunction::info()->methodTable.getConstructData);
     ASSERT(type() == InternalFunctionType || type() == NullSetterFunctionType);
@@ -86,6 +87,7 @@
 
 CallData InternalFunction::getCallData(JSCell* cell)
 {
+    // Keep this function OK for invocation from concurrent compilers.
     auto* function = jsCast<InternalFunction*>(cell);
     ASSERT(function->m_functionForCall);
 
@@ -97,6 +99,7 @@
 
 CallData InternalFunction::getConstructData(JSCell* cell)
 {
+    // Keep this function OK for invocation from concurrent compilers.
     CallData constructData;
     auto* function = jsCast<InternalFunction*>(cell);
     if (function->m_functionForConstruct != callHostFunctionAsConstructor) {

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValue.h (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include "Concurrency.h"
 #include "ECMAMode.h"
 #include "JSExportMacros.h"
 #include "PureNaN.h"
@@ -233,7 +234,9 @@
     // Querying the type.
     bool isEmpty() const;
     bool isCallable(VM&) const;
+    template<Concurrency> TriState isCallableWithConcurrency(VM&) const;
     bool isConstructor(VM&) const;
+    template<Concurrency> TriState isConstructorWithConcurrency(VM&) const;
     bool isUndefined() const;
     bool isNull() const;
     bool isUndefinedOrNull() const;

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -920,11 +920,27 @@
     return isCell() && asCell()->isCallable(vm);
 }
 
+template<Concurrency concurrency>
+inline TriState JSValue::isCallableWithConcurrency(VM& vm) const
+{
+    if (!isCell())
+        return TriState::False;
+    return asCell()->isCallableWithConcurrency<concurrency>(vm);
+}
+
 inline bool JSValue::isConstructor(VM& vm) const
 {
     return isCell() && asCell()->isConstructor(vm);
 }
 
+template<Concurrency concurrency>
+inline TriState JSValue::isConstructorWithConcurrency(VM& vm) const
+{
+    if (!isCell())
+        return TriState::False;
+    return asCell()->isConstructorWithConcurrency<concurrency>(vm);
+}
+
 // this method is here to be after the inline declaration of JSCell::inherits
 inline bool JSValue::inherits(VM& vm, const ClassInfo* classInfo) const
 {

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -109,6 +109,8 @@
     bool isProxy() const;
     bool isCallable(VM&);
     bool isConstructor(VM&);
+    template<Concurrency> TriState isCallableWithConcurrency(VM&);
+    template<Concurrency> TriState isConstructorWithConcurrency(VM&);
     bool inherits(VM&, const ClassInfo*) const;
     template<typename Target> bool inherits(VM&) const;
     bool isAPIValueWrapper() const;

Modified: trunk/Source/_javascript_Core/runtime/JSCellInlines.h (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/JSCellInlines.h	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/JSCellInlines.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -241,20 +241,55 @@
     return m_type == ImpureProxyType || m_type == PureForwardingProxyType || m_type == ProxyObjectType;
 }
 
-ALWAYS_INLINE bool JSCell::isCallable(VM& vm)
+// FIXME: Consider making getCallData concurrency-safe once NPAPI support is removed.
+// https://bugs.webkit.org/show_bug.cgi?id=215801
+template<Concurrency concurrency>
+ALWAYS_INLINE TriState JSCell::isCallableWithConcurrency(VM& vm)
 {
+    if (!isObject())
+        return TriState::False;
     if (type() == JSFunctionType)
-        return true;
-    if (inlineTypeFlags() & OverridesGetCallData)
-        return methodTable(vm)->getCallData(this).type != CallData::Type::None;
-    return false;
+        return TriState::True;
+    if (inlineTypeFlags() & OverridesGetCallData) {
+        if constexpr (concurrency == Concurrency::MainThread)
+            return (methodTable(vm)->getCallData(this).type != CallData::Type::None) ? TriState::True : TriState::False;
+        // We know that InternalFunction::getCallData is concurrency aware. Plus, derived classes of InternalFunction never
+        // override getCallData (this is ensured by ASSERT in InternalFunction).
+        if (type() == InternalFunctionType)
+            return (methodTable(vm)->getCallData(this).type != CallData::Type::None) ? TriState::True : TriState::False;
+        return TriState::Indeterminate;
+    }
+    return TriState::False;
 }
 
-inline bool JSCell::isConstructor(VM& vm)
+template<Concurrency concurrency>
+inline TriState JSCell::isConstructorWithConcurrency(VM& vm)
 {
-    return methodTable(vm)->getConstructData(this).type != CallData::Type::None;
+    if (!isObject())
+        return TriState::False;
+    if constexpr (concurrency == Concurrency::MainThread)
+        return (methodTable(vm)->getConstructData(this).type != CallData::Type::None) ? TriState::True : TriState::False;
+    // We know that both getConstructData of both types are concurrency aware. Plus, derived classes of JSFunction and InternalFunction
+    // never override getConstructData (this is ensured by ASSERT in JSFunction and InternalFunction).
+    if (type() == JSFunctionType || type() == InternalFunctionType)
+        return (methodTable(vm)->getConstructData(this).type != CallData::Type::None) ? TriState::True : TriState::False;
+    return TriState::Indeterminate;
 }
 
+ALWAYS_INLINE bool JSCell::isCallable(VM& vm)
+{
+    auto result = isCallableWithConcurrency<Concurrency::MainThread>(vm);
+    ASSERT(result != TriState::Indeterminate);
+    return result == TriState::True;
+}
+
+ALWAYS_INLINE bool JSCell::isConstructor(VM& vm)
+{
+    auto result = isConstructorWithConcurrency<Concurrency::MainThread>(vm);
+    ASSERT(result != TriState::Indeterminate);
+    return result == TriState::True;
+}
+
 inline bool JSCell::isAPIValueWrapper() const
 {
     return m_type == APIValueWrapperType;

Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp	2020-08-25 08:06:48 UTC (rev 266107)
@@ -109,6 +109,7 @@
     Base::finishCreation(vm);
     ASSERT(jsDynamicCast<JSFunction*>(vm, this));
     ASSERT(type() == JSFunctionType);
+    // JSCell::{getCallData,getConstructData} relies on the following conditions.
     ASSERT(methodTable(vm)->getConstructData == &JSFunction::getConstructData);
     ASSERT(methodTable(vm)->getCallData == &JSFunction::getCallData);
 }
@@ -118,6 +119,7 @@
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
     ASSERT(type() == JSFunctionType);
+    // JSCell::{getCallData,getConstructData} relies on the following conditions.
     ASSERT(methodTable(vm)->getConstructData == &JSFunction::getConstructData);
     ASSERT(methodTable(vm)->getCallData == &JSFunction::getCallData);
 
@@ -258,6 +260,7 @@
 
 CallData JSFunction::getCallData(JSCell* cell)
 {
+    // Keep this function OK for invocation from concurrent compilers.
     CallData callData;
 
     JSFunction* thisObject = jsCast<JSFunction*>(cell);
@@ -682,6 +685,7 @@
 // ECMA 13.2.2 [[Construct]]
 CallData JSFunction::getConstructData(JSCell* cell)
 {
+    // Keep this function OK for invocation from concurrent compilers.
     CallData constructData;
 
     JSFunction* thisObject = jsCast<JSFunction*>(cell);

Modified: trunk/Source/_javascript_Core/runtime/NumberPrototype.cpp (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/NumberPrototype.cpp	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/NumberPrototype.cpp	2020-08-25 08:06:48 UTC (rev 266107)
@@ -104,7 +104,7 @@
 
 static ALWAYS_INLINE EncodedJSValue throwVMToThisNumberError(JSGlobalObject* globalObject, ThrowScope& scope, JSValue thisValue)
 {
-    auto typeString = asString(jsTypeStringForValue(globalObject->vm(), globalObject, thisValue))->value(globalObject);
+    auto typeString = jsTypeStringForValue(globalObject, thisValue)->value(globalObject);
     scope.assertNoException();
     return throwVMTypeError(globalObject, scope, WTF::makeString("thisNumberValue called on incompatible ", typeString));
 }

Modified: trunk/Source/_javascript_Core/runtime/Operations.cpp (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/Operations.cpp	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/Operations.cpp	2020-08-25 08:06:48 UTC (rev 266107)
@@ -75,7 +75,7 @@
     RELEASE_AND_RETURN(scope, arithmeticBinaryOp(globalObject, p1, p2, doubleOp, bigIntOp, "Invalid mix of BigInt and other type in addition."_s));
 }
 
-JSValue jsTypeStringForValue(VM& vm, JSGlobalObject* globalObject, JSValue v)
+JSString* jsTypeStringForValueWithConcurrency(VM& vm, JSGlobalObject* globalObject, JSValue v, Concurrency concurrency)
 {
     if (v.isUndefined())
         return vm.smallStrings.undefinedString();
@@ -95,17 +95,24 @@
         // as null when doing comparisons.
         if (object->structure(vm)->masqueradesAsUndefined(globalObject))
             return vm.smallStrings.undefinedString();
-        if (object->isCallable(vm))
+        if (LIKELY(concurrency == Concurrency::MainThread)) {
+            if (object->isCallable(vm))
+                return vm.smallStrings.functionString();
+            return vm.smallStrings.objectString();
+        }
+
+        switch (object->isCallableWithConcurrency<Concurrency::ConcurrentThread>(vm)) {
+        case TriState::True:
             return vm.smallStrings.functionString();
+        case TriState::False:
+            return vm.smallStrings.objectString();
+        case TriState::Indeterminate:
+            return nullptr;
+        }
     }
     return vm.smallStrings.objectString();
 }
 
-JSValue jsTypeStringForValue(JSGlobalObject* globalObject, JSValue v)
-{
-    return jsTypeStringForValue(globalObject->vm(), globalObject, v);
-}
-
 bool jsTypeofIsObject(JSGlobalObject* globalObject, JSValue v)
 {
     VM& vm = globalObject->vm();

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (266106 => 266107)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2020-08-25 07:45:00 UTC (rev 266106)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2020-08-25 08:06:48 UTC (rev 266107)
@@ -31,24 +31,34 @@
 #define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
 
 NEVER_INLINE JSValue jsAddSlowCase(JSGlobalObject*, JSValue, JSValue);
-JSValue jsTypeStringForValue(JSGlobalObject*, JSValue);
-JSValue jsTypeStringForValue(VM&, JSGlobalObject*, JSValue);
+JSString* jsTypeStringForValueWithConcurrency(VM&, JSGlobalObject*, JSValue, Concurrency);
 bool jsTypeofIsObject(JSGlobalObject*, JSValue);
 size_t normalizePrototypeChain(JSGlobalObject*, JSCell*, bool& sawPolyProto);
 
-ALWAYS_INLINE bool jsTypeofIsFunction(JSGlobalObject* globalObject, JSValue value)
+template<Concurrency concurrency>
+ALWAYS_INLINE TriState jsTypeofIsFunctionWithConcurrency(JSGlobalObject* globalObject, JSValue value)
 {
     VM& vm = globalObject->vm();
-    if (value.isObject()) {
-        JSObject* object = asObject(value);
-        if (object->structure(vm)->masqueradesAsUndefined(globalObject))
-            return false;
-        if (object->isCallable(vm))
-            return true;
-    }
-    return false;
+    if (!value.isObject())
+        return TriState::False;
+    JSObject* object = asObject(value);
+    if (object->structure(vm)->masqueradesAsUndefined(globalObject))
+        return TriState::False;
+    return object->isCallableWithConcurrency<concurrency>(vm);
 }
 
+inline JSString* jsTypeStringForValue(JSGlobalObject* globalObject, JSValue value)
+{
+    return jsTypeStringForValueWithConcurrency(getVM(globalObject), globalObject, value, Concurrency::MainThread);
+}
+
+ALWAYS_INLINE bool jsTypeofIsFunction(JSGlobalObject* globalObject, JSValue value)
+{
+    auto result = jsTypeofIsFunctionWithConcurrency<Concurrency::MainThread>(globalObject, value);
+    ASSERT(result != TriState::Indeterminate);
+    return result == TriState::True;
+}
+
 ALWAYS_INLINE JSString* jsString(JSGlobalObject* globalObject, const String& u1, JSString* s2)
 {
     VM& vm = getVM(globalObject);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to