Diff
Modified: trunk/JSTests/ChangeLog (240113 => 240114)
--- trunk/JSTests/ChangeLog 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/JSTests/ChangeLog 2019-01-17 17:50:27 UTC (rev 240114)
@@ -1,3 +1,15 @@
+2019-01-17 Saam barati <[email protected]>
+
+ StringObjectUse should not be a structure check for the original string object structure
+ https://bugs.webkit.org/show_bug.cgi?id=193483
+ <rdar://problem/47280522>
+
+ Reviewed by Yusuke Suzuki.
+
+ * stress/cant-eliminate-string-object-structure-check-when-string-object-is-proven.js: Added.
+ (foo):
+ (a.valueOf.0):
+
2019-01-17 Yusuke Suzuki <[email protected]>
[JSC] ToThis omission in DFGByteCodeParser is wrong
Added: trunk/JSTests/stress/cant-eliminate-string-object-structure-check-when-string-object-is-proven.js (0 => 240114)
--- trunk/JSTests/stress/cant-eliminate-string-object-structure-check-when-string-object-is-proven.js (rev 0)
+++ trunk/JSTests/stress/cant-eliminate-string-object-structure-check-when-string-object-is-proven.js 2019-01-17 17:50:27 UTC (rev 240114)
@@ -0,0 +1,11 @@
+//@ runDefault("--forceEagerCompilation=1", "--useConcurrentJIT=0")
+
+function foo(x) {
+ x.toString();
+}
+
+var a = new String();
+a.valueOf = 0
+for (var i = 0; i < 5; i++) {
+ foo(a)
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (240113 => 240114)
--- trunk/Source/_javascript_Core/ChangeLog 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-01-17 17:50:27 UTC (rev 240114)
@@ -1,3 +1,105 @@
+2019-01-17 Saam barati <[email protected]>
+
+ StringObjectUse should not be a structure check for the original string object structure
+ https://bugs.webkit.org/show_bug.cgi?id=193483
+ <rdar://problem/47280522>
+
+ Reviewed by Yusuke Suzuki.
+
+ Prior to this patch, the use kind for StringObjectUse implied that we
+ do a StructureCheck on the input operand for the *original* StringObject
+ structure. This is generally not how we use UseKinds, so it's no surprise
+ that this is buggy. A UseKind should map to a set of SpeculatedTypes, not an
+ actual set of structures. This patch changes the meaning of StringObjectUse
+ to mean an object where jsDynamicCast<StringObject*> would succeed.
+
+ This patch also fixes a bug that was caused by the old and weird usage of the
+ UseKind to mean StructureCheck. Consider a program like this:
+ ```
+ S1 = Original StringObject structure
+ S2 = Original StringObject structure with the field "f" added
+
+ a: GetLocal()
+ b: CheckStructure(@a, {S2})
+ c: ToString(StringObject:@a)
+ ```
+
+ According to AI, in the above program, we would exit at @c, since
+ StringObject:@a implies a structure check of {S1}, and the intersection
+ of {S1} and {S2} is {}. So, we'd convert the program to be:
+ ```
+ a: GetLocal()
+ b: CheckStructure(@a, {S2})
+ c: Check(StringObject:@a)
+ d: Unreachable
+ ```
+
+ However, AI would set the proof status of the StringObject:@a edge
+ to be proven, since the SpeculatedType for @a is SpecStringObject.
+ This was incorrect of AI to do because the SpeculatedType itself
+ didn't capture the full power of StringObjectUse. However, having
+ a UseKind mean CheckStructure is weird precisely because what AI was
+ doing is a natural fit to how we typically we think about UseKinds.
+
+ So the above program would then incorrectly be converted to this, and
+ we'd crash when reaching the Unreachable node:
+ ```
+ a: GetLocal()
+ b: CheckStructure(@a, {S2})
+ d: Unreachable
+ ```
+
+ This patch makes it so that StringObjectUse just means that the object that
+ filters through a StringObjectUse check must !!jsDynamicCast<StringObject*>.
+ This is now in line with all other UseKinds. It also lets us simplify a bunch
+ of other code that had weird checks for the StringObjectUse UseKind.
+
+ This patch also makes it so that anywhere where we used to rely on
+ StringObjectUse implying a structure check we actually emit an explicit
+ CheckStructure node.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/ExitKind.cpp:
+ (JSC::exitKindToString):
+ * bytecode/ExitKind.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGCSEPhase.cpp:
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGEdgeUsesStructure.h: Removed.
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::attemptToForceStringArrayModeByToStringConversion):
+ (JSC::DFG::FixupPhase::addCheckStructureForOriginalStringObjectUse):
+ (JSC::DFG::FixupPhase::fixupToPrimitive):
+ (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
+ (JSC::DFG::FixupPhase::attemptToMakeFastStringAdd):
+ (JSC::DFG::FixupPhase::isStringObjectUse): Deleted.
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::canOptimizeStringObjectAccess):
+ * dfg/DFGMayExit.cpp:
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOrStringValueOf):
+ (JSC::DFG::SpeculativeJIT::speculateStringObject):
+ (JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
+ * dfg/DFGSpeculativeJIT.h:
+ (JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure): Deleted.
+ * dfg/DFGUseKind.h:
+ (JSC::DFG::alreadyChecked):
+ (JSC::DFG::usesStructure): Deleted.
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileToStringOrCallStringConstructorOrStringValueOf):
+ (JSC::FTL::DFG::LowerDFGToB3::speculateStringObject):
+ (JSC::FTL::DFG::LowerDFGToB3::speculateStringOrStringObject):
+ (JSC::FTL::DFG::LowerDFGToB3::speculateStringObjectForCell):
+ (JSC::FTL::DFG::LowerDFGToB3::speculateStringObjectForStructureID): Deleted.
+ * runtime/JSType.cpp:
+ (WTF::printInternal):
+ * runtime/JSType.h:
+ * runtime/StringObject.h:
+ (JSC::StringObject::createStructure):
+ * runtime/StringPrototype.h:
+
2019-01-17 Yusuke Suzuki <[email protected]>
[JSC] Add generateHeapSnapshotForGCDebugging function to dump GCDebugging data
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (240113 => 240114)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2019-01-17 17:50:27 UTC (rev 240114)
@@ -1464,7 +1464,6 @@
A78A9781179738D5009DF744 /* FTLJITFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = A78A977E179738D5009DF744 /* FTLJITFinalizer.h */; };
A790DD6E182F499700588807 /* SetIteratorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A790DD68182F499700588807 /* SetIteratorPrototype.h */; };
A790DD70182F499700588807 /* JSSetIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A790DD6A182F499700588807 /* JSSetIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
- A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */; };
A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */ = {isa = PBXBuildFile; fileRef = 000BEAF0DF604481AF6AB68C /* ModuleScopeData.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7A8AF3517ADB5F3005AB174 /* ArrayBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A8AF2617ADB5F3005AB174 /* ArrayBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7A8AF3717ADB5F3005AB174 /* ArrayBufferView.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A8AF2817ADB5F3005AB174 /* ArrayBufferView.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4268,7 +4267,6 @@
A790DD68182F499700588807 /* SetIteratorPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SetIteratorPrototype.h; sourceTree = "<group>"; };
A790DD69182F499700588807 /* JSSetIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSetIterator.cpp; sourceTree = "<group>"; };
A790DD6A182F499700588807 /* JSSetIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSetIterator.h; sourceTree = "<group>"; };
- A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdgeUsesStructure.h; path = dfg/DFGEdgeUsesStructure.h; sourceTree = "<group>"; };
A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedCodeBlock.cpp; sourceTree = "<group>"; };
A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedCodeBlock.h; sourceTree = "<group>"; };
A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRefPrivate.h; sourceTree = "<group>"; };
@@ -7369,7 +7367,6 @@
0FB4B51B16B62772003F696B /* DFGEdge.cpp */,
0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */,
A7D9A29117A0BC7400EE2618 /* DFGEdgeDominates.h */,
- A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */,
0F8F142F1ADF090100ED792C /* DFGEpoch.cpp */,
0F8F14301ADF090100ED792C /* DFGEpoch.h */,
A78A976C179738B8009DF744 /* DFGFailedFinalizer.cpp */,
@@ -8750,7 +8747,6 @@
0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */,
0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */,
A7D9A29617A0BC7400EE2618 /* DFGEdgeDominates.h in Headers */,
- A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */,
0F8F14341ADF090100ED792C /* DFGEpoch.h in Headers */,
0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
A78A9775179738B8009DF744 /* DFGFailedFinalizer.h in Headers */,
Modified: trunk/Source/_javascript_Core/bytecode/ExitKind.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/bytecode/ExitKind.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/bytecode/ExitKind.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -70,8 +70,6 @@
return "ArgumentsEscaped";
case ExoticObjectMode:
return "ExoticObjectMode";
- case NotStringObject:
- return "NotStringObject";
case VarargsOverflow:
return "VarargsOverflow";
case TDZFailure:
Modified: trunk/Source/_javascript_Core/bytecode/ExitKind.h (240113 => 240114)
--- trunk/Source/_javascript_Core/bytecode/ExitKind.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/bytecode/ExitKind.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -46,7 +46,6 @@
InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage.
ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to.
ExoticObjectMode, // We exited because some exotic object that we were accessing was in an exotic mode (like Arguments with slow arguments).
- NotStringObject, // We exited because we shouldn't have attempted to optimize string object access.
VarargsOverflow, // We exited because a varargs call passed more arguments than we expected.
TDZFailure, // We exited because we were in the TDZ and accessed the variable.
HoistingFailed, // Something that was hoisted exited. So, assume that hoisting is a bad idea.
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -2421,12 +2421,6 @@
case CallStringConstructor: {
switch (node->child1().useKind()) {
case StringObjectUse:
- // This also filters that the StringObject has the primordial StringObject
- // structure.
- filter(
- node->child1(),
- m_graph.registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()));
- break;
case StringOrStringObjectUse:
case Int32Use:
case Int52RepUse:
Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -33,7 +33,6 @@
#include "DFGClobberSet.h"
#include "DFGClobberize.h"
#include "DFGDominators.h"
-#include "DFGEdgeUsesStructure.h"
#include "DFGGraph.h"
#include "DFGPhase.h"
#include "JSCInlines.h"
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -28,7 +28,6 @@
#if ENABLE(DFG_JIT)
#include "DFGAbstractHeap.h"
-#include "DFGEdgeUsesStructure.h"
#include "DFGGraph.h"
#include "DFGHeapLocation.h"
#include "DFGLazyNode.h"
@@ -107,9 +106,6 @@
// information that clobberize() passes to write() and def(). Other clients of clobberize() can
// just ignore def() by using a NoOpClobberize functor.
- if (edgesUseStructure(graph, node))
- read(JSCell_structureID);
-
// We allow the runtime to perform a stack scan at any time. We don't model which nodes get implemented
// by calls into the runtime. For debugging we might replace the implementation of any node with a call
// to the runtime, and that call may walk stack. Therefore, each node must read() anything that a stack
@@ -1653,12 +1649,6 @@
case ToString:
case CallStringConstructor:
switch (node->child1().useKind()) {
- case StringObjectUse:
- case StringOrStringObjectUse:
- // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
- // now.
- return;
-
case CellUse:
case UntypedUse:
read(World);
@@ -1665,6 +1655,13 @@
write(Heap);
return;
+ case StringObjectUse:
+ case StringOrStringObjectUse:
+ // These two StringObjectUse's are pure because if we emit this node with either
+ // of these UseKinds, we'll first emit a StructureCheck ensuring that we're the
+ // original String or StringObject structure. Therefore, we don't have an overridden
+ // valueOf, etc.
+
case Int32Use:
case Int52RepUse:
case DoubleRepUse:
Deleted: trunk/Source/_javascript_Core/dfg/DFGEdgeUsesStructure.h (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGEdgeUsesStructure.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGEdgeUsesStructure.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2013 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. ``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
- * 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
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGGraph.h"
-
-namespace JSC { namespace DFG {
-
-class EdgeUsesStructure {
-public:
- EdgeUsesStructure()
- : m_result(false)
- {
- }
-
- void operator()(Node*, Edge edge)
- {
- m_result |= usesStructure(edge.useKind());
- }
-
- bool result() const { return m_result; }
-
-private:
- bool m_result;
-};
-
-inline bool edgesUseStructure(Graph& graph, Node* node)
-{
- EdgeUsesStructure edgeUsesStructure;
- DFG_NODE_DO_TO_CHILDREN(graph, node, edgeUsesStructure);
- return edgeUsesStructure.result();
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -2454,20 +2454,23 @@
if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
return;
+ addCheckStructureForOriginalStringObjectUse(useKind, node->origin, node->child1().node());
createToString<useKind>(node, node->child1());
arrayMode = ArrayMode(Array::String, Array::Read);
}
-
- template<UseKind useKind>
- bool isStringObjectUse()
+
+ void addCheckStructureForOriginalStringObjectUse(UseKind useKind, const NodeOrigin& origin, Node* node)
{
- switch (useKind) {
- case StringObjectUse:
- case StringOrStringObjectUse:
- return true;
- default:
- return false;
- }
+ RELEASE_ASSERT(useKind == StringObjectUse || StringOrStringObjectUse);
+
+ StructureSet set;
+ set.add(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
+ if (useKind == StringOrStringObjectUse)
+ set.add(vm().stringStructure.get());
+
+ m_insertionSet.insertNode(
+ m_indexInBlock, SpecNone, CheckStructure, origin,
+ OpInfo(m_graph.addStructureSet(set)), Edge(node, CellUse));
}
template<UseKind useKind>
@@ -2749,6 +2752,7 @@
if (node->child1()->shouldSpeculateStringObject()
&& m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
+ addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
fixEdge<StringObjectUse>(node->child1());
node->convertToToString();
return;
@@ -2756,6 +2760,7 @@
if (node->child1()->shouldSpeculateStringOrStringObject()
&& m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
+ addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
fixEdge<StringOrStringObjectUse>(node->child1());
node->convertToToString();
return;
@@ -2871,6 +2876,7 @@
if (node->child1()->shouldSpeculateStringObject()
&& m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
+ addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
fixEdge<StringObjectUse>(node->child1());
return;
}
@@ -2877,6 +2883,7 @@
if (node->child1()->shouldSpeculateStringOrStringObject()
&& m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
+ addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
fixEdge<StringOrStringObjectUse>(node->child1());
return;
}
@@ -2975,12 +2982,15 @@
convertStringAddUse<StringUse>(node, edge);
return;
}
- ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
+ if (!Options::useConcurrentJIT())
+ ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
if (edge->shouldSpeculateStringObject()) {
+ addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, edge.node());
convertStringAddUse<StringObjectUse>(node, edge);
return;
}
if (edge->shouldSpeculateStringOrStringObject()) {
+ addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, edge.node());
convertStringAddUse<StringOrStringObjectUse>(node, edge);
return;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -1690,7 +1690,7 @@
bool Graph::canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
{
- if (hasExitSite(codeOrigin, NotStringObject))
+ if (hasExitSite(codeOrigin, BadCache) || hasExitSite(codeOrigin, BadConstantCache))
return false;
JSGlobalObject* globalObject = globalObjectFor(codeOrigin);
Modified: trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGMayExit.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -175,13 +175,6 @@
result = Exits;
break;
- // These are shady because they check the structure even if the type of the child node
- // passes the StringObject type filter.
- case StringObjectUse:
- case StringOrStringObjectUse:
- result = Exits;
- break;
-
default:
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -9468,7 +9468,6 @@
GPRReg resultGPR = result.gpr();
speculateStringObject(node->child1(), op1GPR);
- m_interpreter.filter(node->child1(), SpecStringObject);
m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
cellResult(resultGPR, node);
@@ -9479,17 +9478,13 @@
GPRTemporary result(this);
GPRReg resultGPR = result.gpr();
- m_jit.load32(JITCompiler::Address(op1GPR, JSCell::structureIDOffset()), resultGPR);
- JITCompiler::Jump isString = m_jit.branchWeakStructure(
- JITCompiler::Equal,
- resultGPR,
- m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get()));
+ m_jit.load8(JITCompiler::Address(op1GPR, JSCell::typeInfoTypeOffset()), resultGPR);
+ JITCompiler::Jump isString = m_jit.branch32(JITCompiler::Equal, resultGPR, TrustedImm32(StringType));
- speculateStringObjectForStructure(node->child1(), resultGPR);
-
+ speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1().node(), m_jit.branch32(JITCompiler::NotEqual, resultGPR, TrustedImm32(StringObjectType)));
m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
-
JITCompiler::Jump done = m_jit.jump();
+
isString.link(&m_jit);
m_jit.move(op1GPR, resultGPR);
done.link(&m_jit);
@@ -10192,9 +10187,9 @@
speculateString(edge, operand.gpr());
}
-void SpeculativeJIT::speculateStringObject(Edge edge, GPRReg gpr)
+void SpeculativeJIT::speculateStringObject(Edge edge, GPRReg cellGPR)
{
- speculateStringObjectForStructure(edge, JITCompiler::Address(gpr, JSCell::structureIDOffset()));
+ DFG_TYPE_CHECK(JSValueSource::unboxedCell(cellGPR), edge, ~SpecCellCheck | SpecStringObject, m_jit.branchIfNotType(cellGPR, StringObjectType));
}
void SpeculativeJIT::speculateStringObject(Edge edge)
@@ -10204,11 +10199,7 @@
SpeculateCellOperand operand(this, edge);
GPRReg gpr = operand.gpr();
- if (!needsTypeCheck(edge, SpecStringObject))
- return;
-
speculateStringObject(edge, gpr);
- m_interpreter.filter(edge, SpecStringObject);
}
void SpeculativeJIT::speculateStringOrStringObject(Edge edge)
@@ -10221,17 +10212,13 @@
if (!needsTypeCheck(edge, SpecString | SpecStringObject))
return;
- GPRTemporary structureID(this);
- GPRReg structureIDGPR = structureID.gpr();
+ GPRTemporary typeTemp(this);
+ GPRReg typeGPR = typeTemp.gpr();
- m_jit.load32(JITCompiler::Address(gpr, JSCell::structureIDOffset()), structureIDGPR);
- JITCompiler::Jump isString = m_jit.branchWeakStructure(
- JITCompiler::Equal,
- structureIDGPR,
- m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get()));
-
- speculateStringObjectForStructure(edge, structureIDGPR);
-
+ m_jit.load8(JITCompiler::Address(gpr, JSCell::typeInfoTypeOffset()), typeGPR);
+
+ JITCompiler::Jump isString = m_jit.branch32(JITCompiler::Equal, typeGPR, TrustedImm32(StringType));
+ speculationCheck(BadType, JSValueSource::unboxedCell(gpr), edge.node(), m_jit.branch32(JITCompiler::NotEqual, typeGPR, TrustedImm32(StringObjectType)));
isString.link(&m_jit);
m_interpreter.filter(edge, SpecString | SpecStringObject);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -1631,8 +1631,6 @@
void speculateStringOrOther(Edge);
void speculateNotStringVar(Edge);
void speculateNotSymbol(Edge);
- template<typename StructureLocationType>
- void speculateStringObjectForStructure(Edge, StructureLocationType);
void speculateStringObject(Edge, GPRReg);
void speculateStringObject(Edge);
void speculateStringOrStringObject(Edge);
@@ -2604,20 +2602,6 @@
GPRReg m_gprOrInvalid;
};
-template<typename StructureLocationType>
-void SpeculativeJIT::speculateStringObjectForStructure(Edge edge, StructureLocationType structureLocation)
-{
- RegisteredStructure stringObjectStructure =
- m_jit.graph().registerStructure(m_jit.globalObjectFor(m_currentNode->origin.semantic)->stringObjectStructure());
-
- if (!m_state.forNode(edge).m_structure.isSubsetOf(RegisteredStructureSet(stringObjectStructure))) {
- speculationCheck(
- NotStringObject, JSValueRegs(), 0,
- m_jit.branchWeakStructure(
- JITCompiler::NotEqual, structureLocation, stringObjectStructure));
- }
-}
-
#define DFG_TYPE_CHECK_WITH_EXIT_KIND(exitKind, source, edge, typesPassedThrough, jumpToFail) do { \
JSValueSource _dtc_source = (source); \
Edge _dtc_edge = (edge); \
Modified: trunk/Source/_javascript_Core/dfg/DFGUseKind.h (240113 => 240114)
--- trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/dfg/DFGUseKind.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -268,27 +268,9 @@
}
}
-// Returns true if it uses structure in a way that could be clobbered by
-// things that change the structure.
-inline bool usesStructure(UseKind kind)
-{
- switch (kind) {
- case StringObjectUse:
- case StringOrStringObjectUse:
- return true;
- default:
- return false;
- }
-}
-
// Returns true if we've already guaranteed the type
inline bool alreadyChecked(UseKind kind, SpeculatedType type)
{
- // If the check involves the structure then we need to know more than just the type to be sure
- // that the check is done.
- if (usesStructure(kind))
- return false;
-
return !(type & ~typeFilterFor(kind));
}
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -6326,8 +6326,6 @@
case StringObjectUse: {
LValue cell = lowCell(m_node->child1());
speculateStringObjectForCell(m_node->child1(), cell);
- m_interpreter.filter(m_node->child1(), SpecStringObject);
-
setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
return;
}
@@ -6334,7 +6332,7 @@
case StringOrStringObjectUse: {
LValue cell = lowCell(m_node->child1());
- LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
+ LValue type = m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType);
LBasicBlock notString = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();
@@ -6341,11 +6339,13 @@
ValueFromBlock simpleResult = m_out.anchor(cell);
m_out.branch(
- m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
+ m_out.equal(type, m_out.constInt32(StringType)),
unsure(continuation), unsure(notString));
LBasicBlock lastNext = m_out.appendTo(notString, continuation);
- speculateStringObjectForStructureID(m_node->child1(), structureID);
+ speculate(
+ BadType, jsValueValue(cell), m_node->child1().node(),
+ m_out.notEqual(type, m_out.constInt32(StringObjectType)));
ValueFromBlock unboxedResult = m_out.anchor(
m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
m_out.jump(continuation);
@@ -16051,7 +16051,6 @@
return;
speculateStringObjectForCell(edge, lowCell(edge));
- m_interpreter.filter(edge, SpecStringObject);
}
void speculateStringOrStringObject(Edge edge)
@@ -16058,42 +16057,38 @@
{
if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
return;
+
+ LValue cellBase = lowCell(edge);
+ if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
+ return;
LBasicBlock notString = m_out.newBlock();
LBasicBlock continuation = m_out.newBlock();
- LValue structureID = m_out.load32(lowCell(edge), m_heaps.JSCell_structureID);
+ LValue type = m_out.load8ZeroExt32(cellBase, m_heaps.JSCell_typeInfoType);
m_out.branch(
- m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
+ m_out.equal(type, m_out.constInt32(StringType)),
unsure(continuation), unsure(notString));
LBasicBlock lastNext = m_out.appendTo(notString, continuation);
- speculateStringObjectForStructureID(edge, structureID);
+ speculate(
+ BadType, jsValueValue(cellBase), edge.node(),
+ m_out.notEqual(type, m_out.constInt32(StringObjectType)));
m_out.jump(continuation);
m_out.appendTo(continuation, lastNext);
-
m_interpreter.filter(edge, SpecString | SpecStringObject);
}
void speculateStringObjectForCell(Edge edge, LValue cell)
{
- speculateStringObjectForStructureID(edge, m_out.load32(cell, m_heaps.JSCell_structureID));
+ if (!m_interpreter.needsTypeCheck(edge, SpecStringObject))
+ return;
+
+ LValue type = m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType);
+ FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecStringObject, m_out.notEqual(type, m_out.constInt32(StringObjectType)));
}
- void speculateStringObjectForStructureID(Edge edge, LValue structureID)
- {
- RegisteredStructure stringObjectStructure =
- m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->stringObjectStructure());
-
- if (abstractStructure(edge).isSubsetOf(RegisteredStructureSet(stringObjectStructure)))
- return;
-
- speculate(
- NotStringObject, noValue(), 0,
- m_out.notEqual(structureID, weakStructureID(stringObjectStructure)));
- }
-
void speculateSymbol(Edge edge, LValue cell)
{
FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecSymbol, isNotSymbol(cell));
Modified: trunk/Source/_javascript_Core/runtime/JSType.cpp (240113 => 240114)
--- trunk/Source/_javascript_Core/runtime/JSType.cpp 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/runtime/JSType.cpp 2019-01-17 17:50:27 UTC (rev 240114)
@@ -100,6 +100,7 @@
CASE(JSWeakMapType)
CASE(JSWeakSetType)
CASE(WebAssemblyToJSCalleeType)
+ CASE(StringObjectType)
CASE(MaxJSType)
}
}
Modified: trunk/Source/_javascript_Core/runtime/JSType.h (240113 => 240114)
--- trunk/Source/_javascript_Core/runtime/JSType.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/runtime/JSType.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -110,10 +110,10 @@
JSSetType,
JSWeakMapType,
JSWeakSetType,
-
WebAssemblyToJSCalleeType,
+ StringObjectType,
- LastJSCObjectType = WebAssemblyToJSCalleeType, // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types.
+ LastJSCObjectType = StringObjectType, // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types.
MaxJSType = 0b11111111,
};
Modified: trunk/Source/_javascript_Core/runtime/StringObject.h (240113 => 240114)
--- trunk/Source/_javascript_Core/runtime/StringObject.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/runtime/StringObject.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -63,7 +63,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(StringObjectType, StructureFlags), info());
}
protected:
Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.h (240113 => 240114)
--- trunk/Source/_javascript_Core/runtime/StringPrototype.h 2019-01-17 17:32:38 UTC (rev 240113)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.h 2019-01-17 17:50:27 UTC (rev 240114)
@@ -41,7 +41,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(StringObjectType, StructureFlags), info());
}
DECLARE_INFO;