Diff
Modified: trunk/JSTests/ChangeLog (221853 => 221854)
--- trunk/JSTests/ChangeLog 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/JSTests/ChangeLog 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1,3 +1,15 @@
+2017-09-03 Yusuke Suzuki <[email protected]>
+
+ [DFG] Optimize WeakMap::get by adding intrinsic and fixup
+ https://bugs.webkit.org/show_bug.cgi?id=176010
+
+ Reviewed by Filip Pizlo.
+
+ * microbenchmarks/weak-map-key.js: Added.
+ (assert):
+ (objectKey):
+ (let.start.Date.now):
+
2017-09-09 Yusuke Suzuki <[email protected]>
[JSC] Optimize Object.keys by using careful array allocation
Added: trunk/JSTests/microbenchmarks/weak-map-key.js (0 => 221854)
--- trunk/JSTests/microbenchmarks/weak-map-key.js (rev 0)
+++ trunk/JSTests/microbenchmarks/weak-map-key.js 2017-09-11 08:19:33 UTC (rev 221854)
@@ -0,0 +1,34 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad!");
+}
+noInline(assert);
+
+let weakMap = new WeakMap;
+
+function objectKey(o) {
+ return weakMap.get(o);
+}
+noInline(objectKey);
+
+const iters = 300000;
+let start = Date.now();
+
+{
+ let o = {f: 20};
+ var array = [];
+ for (var i = 0; i < 10; i++) {
+ let newObject = { f: i };
+ weakMap.set(newObject, i);
+ array[i] = newObject;
+ }
+
+ for (var j = 0; j < iters; ++j) {
+ for (let i = 0; i < 10; i++)
+ assert(objectKey(array[i]) === i);
+ }
+}
+
+const verbose = false;
+if (verbose)
+ print(Date.now() - start);
Modified: trunk/Source/_javascript_Core/ChangeLog (221853 => 221854)
--- trunk/Source/_javascript_Core/ChangeLog 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1,3 +1,118 @@
+2017-09-03 Yusuke Suzuki <[email protected]>
+
+ [DFG] Optimize WeakMap::get by adding intrinsic and fixup
+ https://bugs.webkit.org/show_bug.cgi?id=176010
+
+ Reviewed by Filip Pizlo.
+
+ It reveals that Ember.js consumes 3.8% of execution time for WeakMap#get.
+ It is used for meta property for objects (see peekMeta function in Ember.js).
+
+ This patch optimizes WeakMap#get.
+
+ 1. We use inlineGet to inline WeakMap#get operation in the native function.
+ Since this native function itself is very small, we should inline HashMap#get
+ entirely in this function.
+
+ 2. We add JSWeakMapType and JSWeakSetType. This allows us to perform `isJSWeakMap()`
+ very fast. And this patch wires this to DFG and FTL to add WeakMapObjectUse and WeakSetObjectUse
+ to drop unnecessary type checking. We add fixup rules for WeakMapGet DFG node by using WeakMapObjectUse,
+ ObjectUse, and Int32Use.
+
+ 3. We add intrinsic for WeakMap#get, and handle it in DFG and FTL. We use MapHash to
+ calculate hash value for the key's Object and use this hash value to look up value from
+ JSWeakMap's HashMap. Currently, we just call the operationWeakMapGet function in DFG and FTL.
+ It is worth considering that implementing this operation entirely in JIT, like GetMapBucket.
+ But anyway, the current one already optimizes the performance, so we leave this for the subsequent
+ patches.
+
+ We currently do not implement any other intrinsics (like, WeakMap#has, WeakSet) because they are
+ not used in Ember.js right now.
+
+ This patch optimizes WeakMap#get by 50%.
+
+ baseline patched
+
+ weak-map-key 88.6456+-3.9564 ^ 59.1502+-2.2406 ^ definitely 1.4987x faster
+
+ * bytecode/DirectEvalCodeCache.h:
+ (JSC::DirectEvalCodeCache::tryGet):
+ * bytecode/SpeculatedType.cpp:
+ (JSC::dumpSpeculation):
+ (JSC::speculationFromClassInfo):
+ (JSC::speculationFromJSType):
+ (JSC::speculationFromString):
+ * bytecode/SpeculatedType.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGHeapLocation.cpp:
+ (WTF::printInternal):
+ * dfg/DFGHeapLocation.h:
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::hasHeapPrediction):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::SafeToExecuteEdge::operator()):
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::speculateWeakMapObject):
+ (JSC::DFG::SpeculativeJIT::speculateWeakSetObject):
+ (JSC::DFG::SpeculativeJIT::speculate):
+ (JSC::DFG::SpeculativeJIT::compileWeakMapGet):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::callOperation):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGUseKind.cpp:
+ (WTF::printInternal):
+ * dfg/DFGUseKind.h:
+ (JSC::DFG::typeFilterFor):
+ (JSC::DFG::isCell):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileWeakMapGet):
+ (JSC::FTL::DFG::LowerDFGToB3::lowWeakMapObject):
+ (JSC::FTL::DFG::LowerDFGToB3::lowWeakSetObject):
+ (JSC::FTL::DFG::LowerDFGToB3::speculate):
+ (JSC::FTL::DFG::LowerDFGToB3::speculateWeakMapObject):
+ (JSC::FTL::DFG::LowerDFGToB3::speculateWeakSetObject):
+ * jit/JITOperations.h:
+ * runtime/Intrinsic.cpp:
+ (JSC::intrinsicName):
+ * runtime/Intrinsic.h:
+ * runtime/JSType.h:
+ * runtime/JSWeakMap.h:
+ (JSC::isJSWeakMap):
+ * runtime/JSWeakSet.h:
+ (JSC::isJSWeakSet):
+ * runtime/WeakMapBase.cpp:
+ (JSC::WeakMapBase::get):
+ * runtime/WeakMapBase.h:
+ (JSC::WeakMapBase::HashTranslator::hash):
+ (JSC::WeakMapBase::HashTranslator::equal):
+ (JSC::WeakMapBase::inlineGet):
+ * runtime/WeakMapPrototype.cpp:
+ (JSC::WeakMapPrototype::finishCreation):
+ (JSC::getWeakMap):
+ (JSC::protoFuncWeakMapGet):
+ * runtime/WeakSetPrototype.cpp:
+ (JSC::getWeakSet):
+
2017-09-09 Yusuke Suzuki <[email protected]>
[JSC] Optimize Object.keys by using careful array allocation
Modified: trunk/Source/_javascript_Core/bytecode/DirectEvalCodeCache.h (221853 => 221854)
--- trunk/Source/_javascript_Core/bytecode/DirectEvalCodeCache.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/bytecode/DirectEvalCodeCache.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -86,7 +86,7 @@
DirectEvalExecutable* tryGet(const String& evalSource, CallSiteIndex callSiteIndex)
{
- return m_cacheMap.fastGet(CacheKey(evalSource, callSiteIndex)).get();
+ return m_cacheMap.inlineGet(CacheKey(evalSource, callSiteIndex)).get();
}
void set(ExecState* exec, JSCell* owner, const String& evalSource, CallSiteIndex callSiteIndex, DirectEvalExecutable* evalExecutable)
Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -35,6 +35,8 @@
#include "JSFunction.h"
#include "JSMap.h"
#include "JSSet.h"
+#include "JSWeakMap.h"
+#include "JSWeakSet.h"
#include "ProxyObject.h"
#include "RegExpObject.h"
#include "ScopedArguments.h"
@@ -180,6 +182,16 @@
else
isTop = false;
+ if (value & SpecWeakMapObject)
+ strOut.print("WeakMapObject");
+ else
+ isTop = false;
+
+ if (value & SpecWeakSetObject)
+ strOut.print("WeakSetObject");
+ else
+ isTop = false;
+
if (value & SpecProxyObject)
strOut.print("ProxyObject");
else
@@ -402,6 +414,12 @@
if (classInfo == JSSet::info())
return SpecSetObject;
+ if (classInfo == JSWeakMap::info())
+ return SpecWeakMapObject;
+
+ if (classInfo == JSWeakSet::info())
+ return SpecWeakSetObject;
+
if (classInfo == ProxyObject::info())
return SpecProxyObject;
@@ -520,6 +538,10 @@
return SpecMapObject;
case JSSetType:
return SpecSetObject;
+ case JSWeakMapType:
+ return SpecWeakMapObject;
+ case JSWeakSetType:
+ return SpecWeakSetObject;
default:
ASSERT_NOT_REACHED();
}
@@ -701,6 +723,10 @@
return SpecMapObject;
if (!strncmp(speculation, "SpecSetObject", strlen("SpecSetObject")))
return SpecSetObject;
+ if (!strncmp(speculation, "SpecWeakMapObject", strlen("SpecWeakMapObject")))
+ return SpecWeakMapObject;
+ if (!strncmp(speculation, "SpecWeakSetObject", strlen("SpecWeakSetObject")))
+ return SpecWeakSetObject;
if (!strncmp(speculation, "SpecProxyObject", strlen("SpecProxyObject")))
return SpecProxyObject;
if (!strncmp(speculation, "SpecDerivedArray", strlen("SpecDerivedArray")))
Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (221853 => 221854)
--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -58,26 +58,28 @@
static const SpeculatedType SpecRegExpObject = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
static const SpeculatedType SpecMapObject = 1ull << 16; // It's definitely a Map object or one of its subclasses.
static const SpeculatedType SpecSetObject = 1ull << 17; // It's definitely a Set object or one of its subclasses.
-static const SpeculatedType SpecProxyObject = 1ull << 18; // It's definitely a Proxy object or one of its subclasses.
-static const SpeculatedType SpecDerivedArray = 1ull << 19; // It's definitely a DerivedArray object.
-static const SpeculatedType SpecObjectOther = 1ull << 20; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
-static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
-static const SpeculatedType SpecStringIdent = 1ull << 21; // It's definitely a JSString, and it's an identifier.
-static const SpeculatedType SpecStringVar = 1ull << 22; // It's definitely a JSString, and it's not an identifier.
+static const SpeculatedType SpecWeakMapObject = 1ull << 18; // It's definitely a WeakMap object or one of its subclasses.
+static const SpeculatedType SpecWeakSetObject = 1ull << 19; // It's definitely a WeakSet object or one of its subclasses.
+static const SpeculatedType SpecProxyObject = 1ull << 20; // It's definitely a Proxy object or one of its subclasses.
+static const SpeculatedType SpecDerivedArray = 1ull << 21; // It's definitely a DerivedArray object.
+static const SpeculatedType SpecObjectOther = 1ull << 22; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
+static const SpeculatedType SpecStringIdent = 1ull << 23; // It's definitely a JSString, and it's an identifier.
+static const SpeculatedType SpecStringVar = 1ull << 24; // It's definitely a JSString, and it's not an identifier.
static const SpeculatedType SpecString = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
-static const SpeculatedType SpecSymbol = 1ull << 23; // It's definitely a Symbol.
-static const SpeculatedType SpecCellOther = 1ull << 24; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol.
+static const SpeculatedType SpecSymbol = 1ull << 25; // It's definitely a Symbol.
+static const SpeculatedType SpecCellOther = 1ull << 26; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol.
static const SpeculatedType SpecCell = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell.
-static const SpeculatedType SpecBoolInt32 = 1ull << 25; // It's definitely an Int32 with value 0 or 1.
-static const SpeculatedType SpecNonBoolInt32 = 1ull << 26; // It's definitely an Int32 with value other than 0 or 1.
+static const SpeculatedType SpecBoolInt32 = 1ull << 27; // It's definitely an Int32 with value 0 or 1.
+static const SpeculatedType SpecNonBoolInt32 = 1ull << 28; // It's definitely an Int32 with value other than 0 or 1.
static const SpeculatedType SpecInt32Only = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
-static const SpeculatedType SpecInt52Only = 1ull << 27; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
+static const SpeculatedType SpecInt52Only = 1ull << 29; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
static const SpeculatedType SpecAnyInt = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
-static const SpeculatedType SpecAnyIntAsDouble = 1ull << 28; // It's definitely an Int52 and it's inside a double.
-static const SpeculatedType SpecNonIntAsDouble = 1ull << 29; // It's definitely not an Int52 but it's a real number and it's a double.
+static const SpeculatedType SpecAnyIntAsDouble = 1ull << 30; // It's definitely an Int52 and it's inside a double.
+static const SpeculatedType SpecNonIntAsDouble = 1ull << 31; // It's definitely not an Int52 but it's a real number and it's a double.
static const SpeculatedType SpecDoubleReal = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
-static const SpeculatedType SpecDoublePureNaN = 1ull << 30; // It's definitely a NaN that is safe to tag (i.e. pure).
-static const SpeculatedType SpecDoubleImpureNaN = 1ull << 31; // It's definitely a NaN that is unsafe to tag (i.e. impure).
+static const SpeculatedType SpecDoublePureNaN = 1ull << 32; // It's definitely a NaN that is safe to tag (i.e. pure).
+static const SpeculatedType SpecDoubleImpureNaN = 1ull << 33; // It's definitely a NaN that is unsafe to tag (i.e. impure).
static const SpeculatedType SpecDoubleNaN = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
static const SpeculatedType SpecBytecodeDouble = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
static const SpeculatedType SpecFullDouble = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double.
@@ -85,12 +87,12 @@
static const SpeculatedType SpecFullRealNumber = SpecAnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or a Int52.
static const SpeculatedType SpecBytecodeNumber = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
static const SpeculatedType SpecFullNumber = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
-static const SpeculatedType SpecBoolean = 1ull << 32; // It's definitely a Boolean.
-static const SpeculatedType SpecOther = 1ull << 33; // It's definitely either Null or Undefined.
+static const SpeculatedType SpecBoolean = 1ull << 34; // It's definitely a Boolean.
+static const SpeculatedType SpecOther = 1ull << 35; // It's definitely either Null or Undefined.
static const SpeculatedType SpecMisc = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
static const SpeculatedType SpecHeapTop = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
static const SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc; // It's any non-Object JSValue.
-static const SpeculatedType SpecEmpty = 1ull << 34; // It's definitely an empty value marker.
+static const SpeculatedType SpecEmpty = 1ull << 36; // It's definitely an empty value marker.
static const SpeculatedType SpecBytecodeTop = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
static const SpeculatedType SpecFullTop = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1099,6 +1099,10 @@
}
break;
+ case WeakMapGet:
+ forNode(node).makeHeapTop();
+ break;
+
case IsEmpty:
case IsUndefined:
case IsBoolean:
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -2975,6 +2975,22 @@
return true;
}
+ case JSWeakMapGetIntrinsic: {
+ if (argumentCountIncludingThis != 2)
+ return false;
+
+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
+ return false;
+
+ insertChecks();
+ Node* map = get(virtualRegisterForArgument(0, registerOffset));
+ Node* key = get(virtualRegisterForArgument(1, registerOffset));
+ Node* hash = addToGraph(MapHash, key);
+ Node* result = addToGraph(WeakMapGet, OpInfo(), OpInfo(prediction), map, key, hash);
+ set(VirtualRegister(resultOperand), result);
+ return true;
+ }
+
case HasOwnPropertyIntrinsic: {
if (argumentCountIncludingThis != 2)
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1547,6 +1547,7 @@
case MapHash:
def(PureValue(node));
return;
+
case GetMapBucket: {
read(MiscFields);
Edge& mapEdge = node->child1();
@@ -1554,6 +1555,7 @@
def(HeapLocation(MapBucketLoc, MiscFields, mapEdge, keyEdge), LazyNode(node));
return;
}
+
case GetMapBucketHead: {
read(MiscFields);
Edge& mapEdge = node->child1();
@@ -1560,6 +1562,7 @@
def(HeapLocation(MapBucketHeadLoc, MiscFields, mapEdge), LazyNode(node));
return;
}
+
case GetMapBucketNext: {
read(MiscFields);
LocationKind locationKind = MapBucketMapNextLoc;
@@ -1569,6 +1572,7 @@
def(HeapLocation(locationKind, MiscFields, bucketEdge), LazyNode(node));
return;
}
+
case LoadKeyFromMapBucket: {
read(MiscFields);
Edge& bucketEdge = node->child1();
@@ -1575,6 +1579,7 @@
def(HeapLocation(MapBucketKeyLoc, MiscFields, bucketEdge), LazyNode(node));
return;
}
+
case LoadValueFromMapBucket: {
read(MiscFields);
Edge& bucketEdge = node->child1();
@@ -1582,6 +1587,14 @@
return;
}
+ case WeakMapGet: {
+ read(MiscFields);
+ Edge& mapEdge = node->child1();
+ Edge& keyEdge = node->child2();
+ def(HeapLocation(WeakMapGetLoc, MiscFields, mapEdge, keyEdge), LazyNode(node));
+ return;
+ }
+
case ToLowerCase:
def(PureValue(node));
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -203,6 +203,7 @@
case GetMapBucketNext:
case LoadKeyFromMapBucket:
case LoadValueFromMapBucket:
+ case WeakMapGet:
case Unreachable:
case ExtractCatchLocal:
case ExtractOSREntryLocal:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1900,6 +1900,13 @@
break;
}
+ case WeakMapGet: {
+ fixEdge<WeakMapObjectUse>(node->child1());
+ fixEdge<ObjectUse>(node->child2());
+ fixEdge<Int32Use>(node->child3());
+ break;
+ }
+
case DefineDataProperty: {
fixEdge<CellUse>(m_graph.varArgChild(node, 0));
Edge& propertyEdge = m_graph.varArgChild(node, 1);
Modified: trunk/Source/_javascript_Core/dfg/DFGHeapLocation.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGHeapLocation.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGHeapLocation.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -159,24 +159,35 @@
case RegExpObjectLastIndexLoc:
out.print("RegExpObjectLastIndexLoc");
return;
+
case MapBucketLoc:
out.print("MapBucketLoc");
return;
+
case MapBucketHeadLoc:
out.print("MapBucketHeadLoc");
return;
+
case MapBucketKeyLoc:
out.print("MapBucketKeyLoc");
return;
+
case MapBucketValueLoc:
out.print("MapBucketValueLoc");
return;
+
case MapBucketMapNextLoc:
out.print("MapBucketMapNextLoc");
return;
+
case MapBucketSetNextLoc:
out.print("MapBucketSetNextLoc");
return;
+
+ case WeakMapGetLoc:
+ out.print("WeakMapGetLoc");
+ return;
+
case DOMStateLoc:
out.print("DOMStateLoc");
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -68,6 +68,7 @@
MapBucketKeyLoc,
MapBucketMapNextLoc,
MapBucketSetNextLoc,
+ WeakMapGetLoc,
DOMStateLoc,
};
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1579,6 +1579,7 @@
case AtomicsSub:
case AtomicsXor:
case GetDynamicVar:
+ case WeakMapGet:
return true;
default:
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -437,6 +437,8 @@
macro(GetMapBucketNext, NodeResultJS) \
macro(LoadKeyFromMapBucket, NodeResultJS) \
macro(LoadValueFromMapBucket, NodeResultJS) \
+ /* Nodes for JSWeakMap and JSWeakSet */ \
+ macro(WeakMapGet, NodeResultJS) \
\
macro(ToLowerCase, NodeResultJS) \
/* Nodes for DOM JIT */\
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -55,6 +55,7 @@
#include "JSLexicalEnvironment.h"
#include "JSMap.h"
#include "JSSet.h"
+#include "JSWeakMap.h"
#include "ObjectConstructor.h"
#include "Operations.h"
#include "ParseInt.h"
@@ -944,6 +945,13 @@
return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
}
+EncodedJSValue JIT_OPERATION operationWeakMapGet(ExecState* exec, JSCell* weakMap, JSCell* object, int32_t hash)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ return JSValue::encode(jsCast<JSWeakMap*>(weakMap)->inlineGet(asObject(object), hash));
+}
+
EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(ExecState* exec, EncodedJSValue value)
{
VM& vm = exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -141,6 +141,7 @@
EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState*, JSGlobalObject*, RegExpObject*, JSString*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationWeakMapGet(ExecState*, JSCell*, JSCell*, int32_t) WTF_INTERNAL;
// These comparisons return a boolean within a size_t such that the value is zero extended to fill the register.
size_t JIT_OPERATION operationRegExpTestString(ExecState*, JSGlobalObject*, RegExpObject*, JSString*) WTF_INTERNAL;
size_t JIT_OPERATION operationRegExpTest(ExecState*, JSGlobalObject*, RegExpObject*, EncodedJSValue) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -722,7 +722,8 @@
case ToNumber:
case GetArgument:
case CallDOMGetter:
- case GetDynamicVar: {
+ case GetDynamicVar:
+ case WeakMapGet: {
setPrediction(m_currentNode->getHeapPrediction());
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -63,6 +63,8 @@
case DerivedArrayUse:
case MapObjectUse:
case SetObjectUse:
+ case WeakMapObjectUse:
+ case WeakSetObjectUse:
case ObjectOrOtherUse:
case StringIdentUse:
case StringUse:
@@ -412,6 +414,7 @@
case GetMapBucketNext:
case LoadKeyFromMapBucket:
case LoadValueFromMapBucket:
+ case WeakMapGet:
case AtomicsAdd:
case AtomicsAnd:
case AtomicsCompareExchange:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -8984,6 +8984,34 @@
speculateSetObject(edge, operand.gpr());
}
+void SpeculativeJIT::speculateWeakMapObject(Edge edge, GPRReg cell)
+{
+ speculateCellType(edge, cell, SpecWeakMapObject, JSWeakMapType);
+}
+
+void SpeculativeJIT::speculateWeakMapObject(Edge edge)
+{
+ if (!needsTypeCheck(edge, SpecWeakMapObject))
+ return;
+
+ SpeculateCellOperand operand(this, edge);
+ speculateWeakMapObject(edge, operand.gpr());
+}
+
+void SpeculativeJIT::speculateWeakSetObject(Edge edge, GPRReg cell)
+{
+ speculateCellType(edge, cell, SpecWeakSetObject, JSWeakSetType);
+}
+
+void SpeculativeJIT::speculateWeakSetObject(Edge edge)
+{
+ if (!needsTypeCheck(edge, SpecWeakSetObject))
+ return;
+
+ SpeculateCellOperand operand(this, edge);
+ speculateWeakSetObject(edge, operand.gpr());
+}
+
void SpeculativeJIT::speculateObjectOrOther(Edge edge)
{
if (!needsTypeCheck(edge, SpecObject | SpecOther))
@@ -9302,6 +9330,12 @@
case SetObjectUse:
speculateSetObject(edge);
break;
+ case WeakMapObjectUse:
+ speculateWeakMapObject(edge);
+ break;
+ case WeakSetObjectUse:
+ speculateWeakSetObject(edge);
+ break;
case ObjectOrOtherUse:
speculateObjectOrOther(edge);
break;
@@ -10407,6 +10441,28 @@
noResult(node);
}
+void SpeculativeJIT::compileWeakMapGet(Node* node)
+{
+ SpeculateCellOperand weakMap(this, node->child1());
+ SpeculateCellOperand object(this, node->child2());
+ SpeculateInt32Operand hash(this, node->child3());
+ JSValueRegsTemporary result(this);
+
+ GPRReg weakMapGPR = weakMap.gpr();
+ GPRReg objectGPR = object.gpr();
+ GPRReg hashGPR = hash.gpr();
+ JSValueRegs resultRegs = result.regs();
+
+ speculateWeakMapObject(node->child1(), weakMapGPR);
+ speculateObject(node->child2(), objectGPR);
+
+ flushRegisters();
+ callOperation(operationWeakMapGet, resultRegs, weakMapGPR, objectGPR, hashGPR);
+ m_jit.exceptionCheck();
+
+ jsValueResult(resultRegs, node);
+}
+
} } // namespace JSC::DFG
#endif
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1828,6 +1828,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result);
}
+ JITCompiler::Call callOperation(J_JITOperation_ECCZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result.payloadGPR());
+ }
JITCompiler::Call callOperation(J_JITOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
{
m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -2401,6 +2406,11 @@
m_jit.setupArgumentsWithExecState(arg1, arg2);
return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
}
+ JITCompiler::Call callOperation(J_JITOperation_ECCZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+ {
+ m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+ return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+ }
JITCompiler::Call callOperation(V_JITOperation_EOZD operation, GPRReg arg1, GPRReg arg2, FPRReg arg3)
{
@@ -2801,6 +2811,7 @@
void compileCheckSubClass(Node*);
void compileGetMapBucketHead(Node*);
void compileGetMapBucketNext(Node*);
+ void compileWeakMapGet(Node*);
void compileLoadKeyFromMapBucket(Node*);
void compileLoadValueFromMapBucket(Node*);
@@ -3062,6 +3073,10 @@
void speculateMapObject(Edge, GPRReg cell);
void speculateSetObject(Edge);
void speculateSetObject(Edge, GPRReg cell);
+ void speculateWeakMapObject(Edge);
+ void speculateWeakMapObject(Edge, GPRReg cell);
+ void speculateWeakSetObject(Edge);
+ void speculateWeakSetObject(Edge, GPRReg cell);
void speculateObjectOrOther(Edge);
void speculateString(Edge edge, GPRReg cell);
void speculateStringIdentAndLoadStorage(Edge edge, GPRReg string, GPRReg storage);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -4964,6 +4964,10 @@
compileLoadValueFromMapBucket(node);
break;
+ case WeakMapGet:
+ compileWeakMapGet(node);
+ break;
+
case Flush:
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -5334,6 +5334,10 @@
compileLoadValueFromMapBucket(node);
break;
+ case WeakMapGet:
+ compileWeakMapGet(node);
+ break;
+
case ToLowerCase: {
compileToLowerCase(node);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -109,6 +109,12 @@
case SetObjectUse:
out.print("SetObjectUse");
return;
+ case WeakMapObjectUse:
+ out.print("WeakMapObjectUse");
+ return;
+ case WeakSetObjectUse:
+ out.print("WeakSetObjectUse");
+ return;
case ObjectOrOtherUse:
out.print("ObjectOrOther");
return;
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.h (221853 => 221854)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -67,6 +67,8 @@
SymbolUse,
MapObjectUse,
SetObjectUse,
+ WeakMapObjectUse,
+ WeakSetObjectUse,
StringObjectUse,
StringOrStringObjectUse,
NotStringVarUse,
@@ -149,6 +151,10 @@
return SpecMapObject;
case SetObjectUse:
return SpecSetObject;
+ case WeakMapObjectUse:
+ return SpecWeakMapObject;
+ case WeakSetObjectUse:
+ return SpecWeakSetObject;
case StringObjectUse:
return SpecStringObject;
case StringOrStringObjectUse:
@@ -241,6 +247,8 @@
case StringOrStringObjectUse:
case MapObjectUse:
case SetObjectUse:
+ case WeakMapObjectUse:
+ case WeakSetObjectUse:
return true;
default:
return false;
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -201,6 +201,7 @@
case GetMapBucketNext:
case LoadKeyFromMapBucket:
case LoadValueFromMapBucket:
+ case WeakMapGet:
case IsEmpty:
case IsUndefined:
case IsBoolean:
@@ -491,6 +492,8 @@
case SymbolUse:
case MapObjectUse:
case SetObjectUse:
+ case WeakMapObjectUse:
+ case WeakSetObjectUse:
case FinalObjectUse:
case RegExpObjectUse:
case ProxyObjectUse:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1028,6 +1028,9 @@
case LoadValueFromMapBucket:
compileLoadValueFromMapBucket();
break;
+ case WeakMapGet:
+ compileWeakMapGet();
+ break;
case IsObject:
compileIsObject();
break;
@@ -8471,6 +8474,15 @@
setJSValue(m_out.load64(mapBucket, m_heaps.HashMapBucket_key));
}
+ void compileWeakMapGet()
+ {
+ LValue weakMap = lowWeakMapObject(m_node->child1());
+ LValue object = lowObject(m_node->child2());
+ LValue hash = lowInt32(m_node->child3());
+
+ setJSValue(vmCall(Int64, m_out.operation(operationWeakMapGet), m_callFrame, weakMap, object, hash));
+ }
+
void compileIsObjectOrNull()
{
JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
@@ -12952,6 +12964,20 @@
speculateSetObject(edge, result);
return result;
}
+
+ LValue lowWeakMapObject(Edge edge)
+ {
+ LValue result = lowCell(edge);
+ speculateWeakMapObject(edge, result);
+ return result;
+ }
+
+ LValue lowWeakSetObject(Edge edge)
+ {
+ LValue result = lowCell(edge);
+ speculateWeakSetObject(edge, result);
+ return result;
+ }
LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
{
@@ -13405,6 +13431,12 @@
case SetObjectUse:
speculateSetObject(edge);
break;
+ case WeakMapObjectUse:
+ speculateWeakMapObject(edge);
+ break;
+ case WeakSetObjectUse:
+ speculateWeakSetObject(edge);
+ break;
case StringUse:
speculateString(edge);
break;
@@ -13800,6 +13832,28 @@
{
speculateSetObject(edge, lowCell(edge));
}
+
+ void speculateWeakMapObject(Edge edge, LValue cell)
+ {
+ FTL_TYPE_CHECK(
+ jsValueValue(cell), edge, SpecWeakMapObject, isNotType(cell, JSWeakMapType));
+ }
+
+ void speculateWeakMapObject(Edge edge)
+ {
+ speculateWeakMapObject(edge, lowCell(edge));
+ }
+
+ void speculateWeakSetObject(Edge edge, LValue cell)
+ {
+ FTL_TYPE_CHECK(
+ jsValueValue(cell), edge, SpecWeakSetObject, isNotType(cell, JSWeakSetType));
+ }
+
+ void speculateWeakSetObject(Edge edge)
+ {
+ speculateWeakSetObject(edge, lowCell(edge));
+ }
void speculateString(Edge edge, LValue cell)
{
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (221853 => 221854)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -126,6 +126,7 @@
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EAapJcpZ)(ExecState*, ArrayAllocationProfile*, const JSValue*, int32_t);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EC)(ExecState*, JSCell*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ECCZ)(ExecState*, JSCell*, JSCell*, int32_t);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ECI)(ExecState*, JSCell*, UniquedStringImpl*);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -153,6 +153,8 @@
return "JSSetBucketNextIntrinsic";
case JSSetBucketKeyIntrinsic:
return "JSSetBucketKeyIntrinsic";
+ case JSWeakMapGetIntrinsic:
+ return "JSWeakMapGetIntrinsic";
case HasOwnPropertyIntrinsic:
return "HasOwnPropertyIntrinsic";
case AtomicsAddIntrinsic:
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -89,6 +89,7 @@
JSSetBucketHeadIntrinsic,
JSSetBucketNextIntrinsic,
JSSetBucketKeyIntrinsic,
+ JSWeakMapGetIntrinsic,
HasOwnPropertyIntrinsic,
AtomicsAddIntrinsic,
AtomicsAndIntrinsic,
Modified: trunk/Source/_javascript_Core/runtime/JSType.h (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/JSType.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/JSType.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -94,6 +94,8 @@
ProxyObjectType,
JSMapType,
JSSetType,
+ JSWeakMapType,
+ JSWeakSetType,
WebAssemblyFunctionType,
Modified: trunk/Source/_javascript_Core/runtime/JSWeakMap.h (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/JSWeakMap.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/JSWeakMap.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -38,7 +38,7 @@
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ return Structure::create(vm, globalObject, prototype, TypeInfo(JSWeakMapType, StructureFlags), info());
}
static JSWeakMap* create(VM& vm, Structure* structure)
@@ -62,4 +62,16 @@
static String toStringName(const JSObject*, ExecState*);
};
+inline bool isJSWeakMap(JSCell* from)
+{
+ static_assert(std::is_final<JSWeakMap>::value, "");
+ return from->type() == JSWeakMapType;
+}
+
+inline bool isJSWeakMap(JSValue from)
+{
+ static_assert(std::is_final<JSWeakMap>::value, "");
+ return from.isCell() && from.asCell()->type() == JSWeakMapType;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSWeakSet.h (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/JSWeakSet.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/JSWeakSet.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -38,7 +38,7 @@
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
- return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ return Structure::create(vm, globalObject, prototype, TypeInfo(JSWeakSetType, StructureFlags), info());
}
static JSWeakSet* create(VM& vm, Structure* structure)
@@ -62,4 +62,16 @@
static String toStringName(const JSObject*, ExecState*);
};
+inline bool isJSWeakSet(JSCell* from)
+{
+ static_assert(std::is_final<JSWeakSet>::value, "");
+ return from->type() == JSWeakSetType;
+}
+
+inline bool isJSWeakSet(JSValue from)
+{
+ static_assert(std::is_final<JSWeakSet>::value, "");
+ return from.isCell() && from.asCell()->type() == JSWeakSetType;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/WeakMapBase.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/WeakMapBase.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/WeakMapBase.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -65,6 +65,11 @@
visitor.reportExtraMemoryVisited(thisObj->m_map.capacity() * (sizeof(JSObject*) + sizeof(WriteBarrier<Unknown>)));
}
+JSValue WeakMapBase::get(JSObject* key)
+{
+ return inlineGet(key);
+}
+
void WeakMapBase::set(VM& vm, JSObject* key, JSValue value)
{
// Here we force the write barrier on the key.
@@ -72,14 +77,6 @@
result.iterator->value.set(vm, this, value);
}
-JSValue WeakMapBase::get(JSObject* key)
-{
- auto iter = m_map.find(key);
- if (iter == m_map.end())
- return jsUndefined();
- return iter->value.get();
-}
-
bool WeakMapBase::remove(JSObject* key)
{
return m_map.remove(key);
Modified: trunk/Source/_javascript_Core/runtime/WeakMapBase.h (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/WeakMapBase.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/WeakMapBase.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -38,6 +38,8 @@
void set(VM&, JSObject*, JSValue);
JSValue get(JSObject*);
+ JSValue inlineGet(JSObject*);
+ JSValue inlineGet(JSObject*, int32_t hash);
bool remove(JSObject*);
bool contains(JSObject*);
void clear();
@@ -57,6 +59,19 @@
WeakMapBase(VM&, Structure*);
static void destroy(JSCell*);
+ using KeyWithHash = std::pair<JSObject*, unsigned>;
+ struct HashTranslator {
+ static inline unsigned hash(const KeyWithHash& keyWithHash)
+ {
+ return keyWithHash.second;
+ }
+
+ static inline bool equal(JSObject* key, const KeyWithHash& keyWithHash)
+ {
+ return key == keyWithHash.first;
+ }
+ };
+
class DeadKeyCleaner : public UnconditionalFinalizer, public WeakReferenceHarvester {
public:
WeakMapBase* target();
@@ -70,4 +85,19 @@
MapType m_map;
};
+ALWAYS_INLINE JSValue WeakMapBase::inlineGet(JSObject* key)
+{
+ if (auto result = m_map.inlineGet(key))
+ return result.get();
+ return jsUndefined();
+}
+
+ALWAYS_INLINE JSValue WeakMapBase::inlineGet(JSObject* key, int32_t hash)
+{
+ KeyWithHash keyWithHash { key, hash };
+ if (auto result = m_map.inlineGet<HashTranslator>(keyWithHash))
+ return result.get();
+ return jsUndefined();
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/WeakMapPrototype.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/WeakMapPrototype.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/WeakMapPrototype.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -46,7 +46,7 @@
vm.prototypeMap.addPrototype(this);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, protoFuncWeakMapDelete, DontEnum, 1);
- JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, protoFuncWeakMapGet, DontEnum, 1);
+ JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, protoFuncWeakMapGet, DontEnum, 1, JSWeakMapGetIntrinsic);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, protoFuncWeakMapHas, DontEnum, 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, protoFuncWeakMapSet, DontEnum, 2);
@@ -53,18 +53,18 @@
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "WeakMap"), DontEnum | ReadOnly);
}
-static JSWeakMap* getWeakMap(CallFrame* callFrame, JSValue value)
+ALWAYS_INLINE static JSWeakMap* getWeakMap(CallFrame* callFrame, JSValue value)
{
VM& vm = callFrame->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- if (!value.isObject()) {
+ if (UNLIKELY(!value.isObject())) {
throwTypeError(callFrame, scope, WTF::ASCIILiteral("Called WeakMap function on non-object"));
return nullptr;
}
- if (JSWeakMap* weakMap = jsDynamicCast<JSWeakMap*>(vm, value))
- return weakMap;
+ if (LIKELY(isJSWeakMap(asObject(value))))
+ return jsCast<JSWeakMap*>(value);
throwTypeError(callFrame, scope, WTF::ASCIILiteral("Called WeakMap function on a non-WeakMap object"));
return nullptr;
@@ -87,7 +87,7 @@
JSValue key = callFrame->argument(0);
if (!key.isObject())
return JSValue::encode(jsUndefined());
- return JSValue::encode(map->get(asObject(key)));
+ return JSValue::encode(map->inlineGet(asObject(key)));
}
EncodedJSValue JSC_HOST_CALL protoFuncWeakMapHas(CallFrame* callFrame)
Modified: trunk/Source/_javascript_Core/runtime/WeakSetPrototype.cpp (221853 => 221854)
--- trunk/Source/_javascript_Core/runtime/WeakSetPrototype.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/_javascript_Core/runtime/WeakSetPrototype.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -51,18 +51,18 @@
putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "WeakSet"), DontEnum | ReadOnly);
}
-static JSWeakSet* getWeakSet(CallFrame* callFrame, JSValue value)
+ALWAYS_INLINE static JSWeakSet* getWeakSet(CallFrame* callFrame, JSValue value)
{
VM& vm = callFrame->vm();
auto scope = DECLARE_THROW_SCOPE(vm);
- if (!value.isObject()) {
+ if (UNLIKELY(!value.isObject())) {
throwTypeError(callFrame, scope, WTF::ASCIILiteral("Called WeakSet function on non-object"));
return nullptr;
}
- if (JSWeakSet* weakSet = jsDynamicCast<JSWeakSet*>(vm, value))
- return weakSet;
+ if (LIKELY(isJSWeakSet(asObject(value))))
+ return jsCast<JSWeakSet*>(value);
throwTypeError(callFrame, scope, WTF::ASCIILiteral("Called WeakSet function on a non-WeakSet object"));
return nullptr;
Modified: trunk/Source/WTF/ChangeLog (221853 => 221854)
--- trunk/Source/WTF/ChangeLog 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/WTF/ChangeLog 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1,3 +1,18 @@
+2017-09-03 Yusuke Suzuki <[email protected]>
+
+ [DFG] Optimize WeakMap::get by adding intrinsic and fixup
+ https://bugs.webkit.org/show_bug.cgi?id=176010
+
+ Reviewed by Filip Pizlo.
+
+ Add inlineGet method with HashTranslator.
+
+ * wtf/HashMap.h:
+ (WTF::X>::inlineGet const):
+ (WTF::MappedTraits>::inlineGet const):
+ (WTF::MappedTraits>::fastGet const): Deleted.
+ * wtf/LoggingHashMap.h:
+
2017-09-07 Myles C. Maxfield <[email protected]>
[PAL] Unify PlatformUserPreferredLanguages.h with Language.h
Modified: trunk/Source/WTF/wtf/HashMap.h (221853 => 221854)
--- trunk/Source/WTF/wtf/HashMap.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/WTF/wtf/HashMap.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -106,7 +106,7 @@
MappedPeekType get(const KeyType&) const;
// Same as get(), but aggressively inlined.
- MappedPeekType fastGet(const KeyType&) const;
+ MappedPeekType inlineGet(const KeyType&) const;
// Replaces the value but not the key if the key is already present.
// Return value includes both an iterator to the key location,
@@ -144,6 +144,7 @@
template<typename HashTranslator, typename T> const_iterator find(const T&) const;
template<typename HashTranslator, typename T> bool contains(const T&) const;
template<typename HashTranslator, typename T> MappedPeekType get(const T&) const;
+ template<typename HashTranslator, typename T> MappedPeekType inlineGet(const T&) const;
// An alternate version of add() that finds the object by hashing and comparing
// with some other type, to avoid the cost of type conversion if the object is already
@@ -306,6 +307,16 @@
template<typename T, typename U, typename V, typename W, typename X>
template<typename HashTranslator, typename TYPE>
+auto HashMap<T, U, V, W, X>::inlineGet(const TYPE& value) const -> MappedPeekType
+{
+ auto* entry = const_cast<HashTableType&>(m_impl).template inlineLookup<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
+ if (!entry)
+ return MappedTraits::peek(MappedTraits::emptyValue());
+ return MappedTraits::peek(entry->value);
+}
+
+template<typename T, typename U, typename V, typename W, typename X>
+template<typename HashTranslator, typename TYPE>
inline bool HashMap<T, U, V, W, X>::contains(const TYPE& value) const
{
return m_impl.template contains<HashMapTranslatorAdapter<KeyValuePairTraits, HashTranslator>>(value);
@@ -407,7 +418,7 @@
}
template<typename T, typename U, typename V, typename W, typename MappedTraits>
-ALWAYS_INLINE auto HashMap<T, U, V, W, MappedTraits>::fastGet(const KeyType& key) const -> MappedPeekType
+ALWAYS_INLINE auto HashMap<T, U, V, W, MappedTraits>::inlineGet(const KeyType& key) const -> MappedPeekType
{
KeyValuePairType* entry = const_cast<HashTableType&>(m_impl).template inlineLookup<IdentityTranslatorType>(key);
if (!entry)
Modified: trunk/Source/WTF/wtf/LoggingHashMap.h (221853 => 221854)
--- trunk/Source/WTF/wtf/LoggingHashMap.h 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/WTF/wtf/LoggingHashMap.h 2017-09-11 08:19:33 UTC (rev 221854)
@@ -152,10 +152,10 @@
return m_map.get(key);
}
- MappedPeekType fastGet(const KeyType& key) const
+ MappedPeekType inlineGet(const KeyType& key) const
{
find(key);
- return m_map.fastGet(key);
+ return m_map.inlineGet(key);
}
template<typename PassedType>
Modified: trunk/Source/WebCore/ChangeLog (221853 => 221854)
--- trunk/Source/WebCore/ChangeLog 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/WebCore/ChangeLog 2017-09-11 08:19:33 UTC (rev 221854)
@@ -1,3 +1,13 @@
+2017-09-03 Yusuke Suzuki <[email protected]>
+
+ [DFG] Optimize WeakMap::get by adding intrinsic and fixup
+ https://bugs.webkit.org/show_bug.cgi?id=176010
+
+ Reviewed by Filip Pizlo.
+
+ * platform/network/curl/CurlJobManager.cpp:
+ (WebCore::CurlJobList::finishJobs):
+
2017-09-10 Zan Dobersek <[email protected]>
[GStreamer] Drop libgcrypt initialization in webkit_media_clear_key_decrypt_init()
Modified: trunk/Source/WebCore/platform/network/curl/CurlJobManager.cpp (221853 => 221854)
--- trunk/Source/WebCore/platform/network/curl/CurlJobManager.cpp 2017-09-11 08:10:06 UTC (rev 221853)
+++ trunk/Source/WebCore/platform/network/curl/CurlJobManager.cpp 2017-09-11 08:19:33 UTC (rev 221854)
@@ -65,7 +65,7 @@
if (!m_activeJobs.contains(ticket))
continue;
removeHandle(ticket);
- notifyResult(m_activeJobs.fastGet(ticket), result);
+ notifyResult(m_activeJobs.inlineGet(ticket), result);
m_activeJobs.remove(ticket);
}
}