Changeset 240114 in webkit


Ignore:
Timestamp:
Jan 17, 2019 9:50:27 AM (5 years ago)
Author:
sbarati@apple.com
Message:

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.

JSTests:

  • stress/cant-eliminate-string-object-structure-check-when-string-object-is-proven.js: Added.

(foo):
(a.valueOf.0):

Source/JavaScriptCore:

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.

(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:
Location:
trunk
Files:
1 added
1 deleted
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r240106 r240114  
     12019-01-17  Saam barati  <sbarati@apple.com>
     2
     3        StringObjectUse should not be a structure check for the original string object structure
     4        https://bugs.webkit.org/show_bug.cgi?id=193483
     5        <rdar://problem/47280522>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        * stress/cant-eliminate-string-object-structure-check-when-string-object-is-proven.js: Added.
     10        (foo):
     11        (a.valueOf.0):
     12
    1132019-01-17  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
    214
  • trunk/Source/JavaScriptCore/ChangeLog

    r240113 r240114  
     12019-01-17  Saam barati  <sbarati@apple.com>
     2
     3        StringObjectUse should not be a structure check for the original string object structure
     4        https://bugs.webkit.org/show_bug.cgi?id=193483
     5        <rdar://problem/47280522>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        Prior to this patch, the use kind for StringObjectUse implied that we
     10        do a StructureCheck on the input operand for the *original* StringObject
     11        structure. This is generally not how we use UseKinds, so it's no surprise
     12        that this is buggy. A UseKind should map to a set of SpeculatedTypes, not an
     13        actual set of structures. This patch changes the meaning of StringObjectUse
     14        to mean an object where jsDynamicCast<StringObject*> would succeed.
     15       
     16        This patch also fixes a bug that was caused by the old and weird usage of the
     17        UseKind to mean StructureCheck. Consider a program like this:
     18        ```
     19        S1 = Original StringObject structure
     20        S2 = Original StringObject structure with the field "f" added
     21       
     22        a: GetLocal()
     23        b: CheckStructure(@a, {S2})
     24        c: ToString(StringObject:@a)
     25        ```
     26       
     27        According to AI, in the above program, we would exit at @c, since
     28        StringObject:@a implies a structure check of {S1}, and the intersection
     29        of {S1} and {S2} is {}. So, we'd convert the program to be:
     30        ```
     31        a: GetLocal()
     32        b: CheckStructure(@a, {S2})
     33        c: Check(StringObject:@a)
     34        d: Unreachable
     35        ```
     36       
     37        However, AI would set the proof status of the StringObject:@a edge
     38        to be proven, since the SpeculatedType for @a is SpecStringObject.
     39        This was incorrect of AI to do because the SpeculatedType itself
     40        didn't capture the full power of StringObjectUse. However, having
     41        a UseKind mean CheckStructure is weird precisely because what AI was
     42        doing is a natural fit to how we typically we think about UseKinds.
     43       
     44        So the above program would then incorrectly be converted to this, and
     45        we'd crash when reaching the Unreachable node:
     46        ```
     47        a: GetLocal()
     48        b: CheckStructure(@a, {S2})
     49        d: Unreachable
     50        ```
     51       
     52        This patch makes it so that StringObjectUse just means that the object that
     53        filters through a StringObjectUse check must !!jsDynamicCast<StringObject*>.
     54        This is now in line with all other UseKinds. It also lets us simplify a bunch
     55        of other code that had weird checks for the StringObjectUse UseKind.
     56       
     57        This patch also makes it so that anywhere where we used to rely on
     58        StringObjectUse implying a structure check we actually emit an explicit
     59        CheckStructure node.
     60
     61        * JavaScriptCore.xcodeproj/project.pbxproj:
     62        * bytecode/ExitKind.cpp:
     63        (JSC::exitKindToString):
     64        * bytecode/ExitKind.h:
     65        * dfg/DFGAbstractInterpreterInlines.h:
     66        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     67        * dfg/DFGCSEPhase.cpp:
     68        * dfg/DFGClobberize.h:
     69        (JSC::DFG::clobberize):
     70        * dfg/DFGEdgeUsesStructure.h: Removed.
     71        * dfg/DFGFixupPhase.cpp:
     72        (JSC::DFG::FixupPhase::attemptToForceStringArrayModeByToStringConversion):
     73        (JSC::DFG::FixupPhase::addCheckStructureForOriginalStringObjectUse):
     74        (JSC::DFG::FixupPhase::fixupToPrimitive):
     75        (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
     76        (JSC::DFG::FixupPhase::attemptToMakeFastStringAdd):
     77        (JSC::DFG::FixupPhase::isStringObjectUse): Deleted.
     78        * dfg/DFGGraph.cpp:
     79        (JSC::DFG::Graph::canOptimizeStringObjectAccess):
     80        * dfg/DFGMayExit.cpp:
     81        * dfg/DFGSpeculativeJIT.cpp:
     82        (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOrStringValueOf):
     83        (JSC::DFG::SpeculativeJIT::speculateStringObject):
     84        (JSC::DFG::SpeculativeJIT::speculateStringOrStringObject):
     85        * dfg/DFGSpeculativeJIT.h:
     86        (JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure): Deleted.
     87        * dfg/DFGUseKind.h:
     88        (JSC::DFG::alreadyChecked):
     89        (JSC::DFG::usesStructure): Deleted.
     90        * ftl/FTLLowerDFGToB3.cpp:
     91        (JSC::FTL::DFG::LowerDFGToB3::compileToStringOrCallStringConstructorOrStringValueOf):
     92        (JSC::FTL::DFG::LowerDFGToB3::speculateStringObject):
     93        (JSC::FTL::DFG::LowerDFGToB3::speculateStringOrStringObject):
     94        (JSC::FTL::DFG::LowerDFGToB3::speculateStringObjectForCell):
     95        (JSC::FTL::DFG::LowerDFGToB3::speculateStringObjectForStructureID): Deleted.
     96        * runtime/JSType.cpp:
     97        (WTF::printInternal):
     98        * runtime/JSType.h:
     99        * runtime/StringObject.h:
     100        (JSC::StringObject::createStructure):
     101        * runtime/StringPrototype.h:
     102
    11032019-01-17  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
    2104
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r240023 r240114  
    14651465                A790DD6E182F499700588807 /* SetIteratorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A790DD68182F499700588807 /* SetIteratorPrototype.h */; };
    14661466                A790DD70182F499700588807 /* JSSetIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A790DD6A182F499700588807 /* JSSetIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    1467                 A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */; };
    14681467                A79D3ED9C5064DD0A8466A3A /* ModuleScopeData.h in Headers */ = {isa = PBXBuildFile; fileRef = 000BEAF0DF604481AF6AB68C /* ModuleScopeData.h */; settings = {ATTRIBUTES = (Private, ); }; };
    14691468                A7A8AF3517ADB5F3005AB174 /* ArrayBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A8AF2617ADB5F3005AB174 /* ArrayBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    42694268                A790DD69182F499700588807 /* JSSetIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSetIterator.cpp; sourceTree = "<group>"; };
    42704269                A790DD6A182F499700588807 /* JSSetIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSetIterator.h; sourceTree = "<group>"; };
    4271                 A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdgeUsesStructure.h; path = dfg/DFGEdgeUsesStructure.h; sourceTree = "<group>"; };
    42724270                A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UnlinkedCodeBlock.cpp; sourceTree = "<group>"; };
    42734271                A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedCodeBlock.h; sourceTree = "<group>"; };
     
    73707368                                0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */,
    73717369                                A7D9A29117A0BC7400EE2618 /* DFGEdgeDominates.h */,
    7372                                 A7986D5617A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h */,
    73737370                                0F8F142F1ADF090100ED792C /* DFGEpoch.cpp */,
    73747371                                0F8F14301ADF090100ED792C /* DFGEpoch.h */,
     
    87518748                                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */,
    87528749                                A7D9A29617A0BC7400EE2618 /* DFGEdgeDominates.h in Headers */,
    8753                                 A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */,
    87548750                                0F8F14341ADF090100ED792C /* DFGEpoch.h in Headers */,
    87558751                                0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */,
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp

    r231607 r240114  
    7171    case ExoticObjectMode:
    7272        return "ExoticObjectMode";
    73     case NotStringObject:
    74         return "NotStringObject";
    7573    case VarargsOverflow:
    7674        return "VarargsOverflow";
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.h

    r221341 r240114  
    4747    ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to.
    4848    ExoticObjectMode, // We exited because some exotic object that we were accessing was in an exotic mode (like Arguments with slow arguments).
    49     NotStringObject, // We exited because we shouldn't have attempted to optimize string object access.
    5049    VarargsOverflow, // We exited because a varargs call passed more arguments than we expected.
    5150    TDZFailure, // We exited because we were in the TDZ and accessed the variable.
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r240106 r240114  
    24222422        switch (node->child1().useKind()) {
    24232423        case StringObjectUse:
    2424             // This also filters that the StringObject has the primordial StringObject
    2425             // structure.
    2426             filter(
    2427                 node->child1(),
    2428                 m_graph.registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()));
    2429             break;
    24302424        case StringOrStringObjectUse:
    24312425        case Int32Use:
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp

    r230287 r240114  
    3434#include "DFGClobberize.h"
    3535#include "DFGDominators.h"
    36 #include "DFGEdgeUsesStructure.h"
    3736#include "DFGGraph.h"
    3837#include "DFGPhase.h"
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r239761 r240114  
    2929
    3030#include "DFGAbstractHeap.h"
    31 #include "DFGEdgeUsesStructure.h"
    3231#include "DFGGraph.h"
    3332#include "DFGHeapLocation.h"
     
    108107    // just ignore def() by using a NoOpClobberize functor.
    109108
    110     if (edgesUseStructure(graph, node))
    111         read(JSCell_structureID);
    112    
    113109    // We allow the runtime to perform a stack scan at any time. We don't model which nodes get implemented
    114110    // by calls into the runtime. For debugging we might replace the implementation of any node with a call
     
    16541650    case CallStringConstructor:
    16551651        switch (node->child1().useKind()) {
     1652        case CellUse:
     1653        case UntypedUse:
     1654            read(World);
     1655            write(Heap);
     1656            return;
     1657
    16561658        case StringObjectUse:
    16571659        case StringOrStringObjectUse:
    1658             // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
    1659             // now.
    1660             return;
    1661            
    1662         case CellUse:
    1663         case UntypedUse:
    1664             read(World);
    1665             write(Heap);
    1666             return;
     1660            // These two StringObjectUse's are pure because if we emit this node with either
     1661            // of these UseKinds, we'll first emit a StructureCheck ensuring that we're the
     1662            // original String or StringObject structure. Therefore, we don't have an overridden
     1663            // valueOf, etc.
    16671664
    16681665        case Int32Use:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r240024 r240114  
    24552455            return;
    24562456       
     2457        addCheckStructureForOriginalStringObjectUse(useKind, node->origin, node->child1().node());
    24572458        createToString<useKind>(node, node->child1());
    24582459        arrayMode = ArrayMode(Array::String, Array::Read);
    24592460    }
    2460    
    2461     template<UseKind useKind>
    2462     bool isStringObjectUse()
    2463     {
    2464         switch (useKind) {
    2465         case StringObjectUse:
    2466         case StringOrStringObjectUse:
    2467             return true;
    2468         default:
    2469             return false;
    2470         }
     2461
     2462    void addCheckStructureForOriginalStringObjectUse(UseKind useKind, const NodeOrigin& origin, Node* node)
     2463    {
     2464        RELEASE_ASSERT(useKind == StringObjectUse || StringOrStringObjectUse);
     2465
     2466        StructureSet set;
     2467        set.add(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
     2468        if (useKind == StringOrStringObjectUse)
     2469            set.add(vm().stringStructure.get());
     2470
     2471        m_insertionSet.insertNode(
     2472            m_indexInBlock, SpecNone, CheckStructure, origin,
     2473            OpInfo(m_graph.addStructureSet(set)), Edge(node, CellUse));
    24712474    }
    24722475   
     
    27502753        if (node->child1()->shouldSpeculateStringObject()
    27512754            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
     2755            addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
    27522756            fixEdge<StringObjectUse>(node->child1());
    27532757            node->convertToToString();
     
    27572761        if (node->child1()->shouldSpeculateStringOrStringObject()
    27582762            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
     2763            addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
    27592764            fixEdge<StringOrStringObjectUse>(node->child1());
    27602765            node->convertToToString();
     
    28722877        if (node->child1()->shouldSpeculateStringObject()
    28732878            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
     2879            addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
    28742880            fixEdge<StringObjectUse>(node->child1());
    28752881            return;
     
    28782884        if (node->child1()->shouldSpeculateStringOrStringObject()
    28792885            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
     2886            addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
    28802887            fixEdge<StringOrStringObjectUse>(node->child1());
    28812888            return;
     
    29762983                    return;
    29772984                }
    2978                 ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
     2985                if (!Options::useConcurrentJIT())
     2986                    ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
    29792987                if (edge->shouldSpeculateStringObject()) {
     2988                    addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, edge.node());
    29802989                    convertStringAddUse<StringObjectUse>(node, edge);
    29812990                    return;
    29822991                }
    29832992                if (edge->shouldSpeculateStringOrStringObject()) {
     2993                    addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, edge.node());
    29842994                    convertStringAddUse<StringOrStringObjectUse>(node, edge);
    29852995                    return;
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r240023 r240114  
    16911691bool Graph::canOptimizeStringObjectAccess(const CodeOrigin& codeOrigin)
    16921692{
    1693     if (hasExitSite(codeOrigin, NotStringObject))
     1693    if (hasExitSite(codeOrigin, BadCache) || hasExitSite(codeOrigin, BadConstantCache))
    16941694        return false;
    16951695
  • trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp

    r239142 r240114  
    176176                break;
    177177               
    178             // These are shady because they check the structure even if the type of the child node
    179             // passes the StringObject type filter.
    180             case StringObjectUse:
    181             case StringOrStringObjectUse:
    182                 result = Exits;
    183                 break;
    184                
    185178            default:
    186179                break;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r239612 r240114  
    94699469       
    94709470        speculateStringObject(node->child1(), op1GPR);
    9471         m_interpreter.filter(node->child1(), SpecStringObject);
    94729471
    94739472        m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
     
    94809479        GPRReg resultGPR = result.gpr();
    94819480
    9482         m_jit.load32(JITCompiler::Address(op1GPR, JSCell::structureIDOffset()), resultGPR);
    9483         JITCompiler::Jump isString = m_jit.branchWeakStructure(
    9484             JITCompiler::Equal,
    9485             resultGPR,
    9486             m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get()));
    9487 
    9488         speculateStringObjectForStructure(node->child1(), resultGPR);
    9489        
     9481        m_jit.load8(JITCompiler::Address(op1GPR, JSCell::typeInfoTypeOffset()), resultGPR);
     9482        JITCompiler::Jump isString = m_jit.branch32(JITCompiler::Equal, resultGPR, TrustedImm32(StringType));
     9483
     9484        speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1().node(), m_jit.branch32(JITCompiler::NotEqual, resultGPR, TrustedImm32(StringObjectType)));
    94909485        m_jit.loadPtr(JITCompiler::Address(op1GPR, JSWrapperObject::internalValueCellOffset()), resultGPR);
    9491        
    94929486        JITCompiler::Jump done = m_jit.jump();
     9487
    94939488        isString.link(&m_jit);
    94949489        m_jit.move(op1GPR, resultGPR);
     
    1019310188}
    1019410189
    10195 void SpeculativeJIT::speculateStringObject(Edge edge, GPRReg gpr)
    10196 {
    10197     speculateStringObjectForStructure(edge, JITCompiler::Address(gpr, JSCell::structureIDOffset()));
     10190void SpeculativeJIT::speculateStringObject(Edge edge, GPRReg cellGPR)
     10191{
     10192    DFG_TYPE_CHECK(JSValueSource::unboxedCell(cellGPR), edge, ~SpecCellCheck | SpecStringObject, m_jit.branchIfNotType(cellGPR, StringObjectType));
    1019810193}
    1019910194
     
    1020510200    SpeculateCellOperand operand(this, edge);
    1020610201    GPRReg gpr = operand.gpr();
    10207     if (!needsTypeCheck(edge, SpecStringObject))
    10208         return;
    10209    
    1021010202    speculateStringObject(edge, gpr);
    10211     m_interpreter.filter(edge, SpecStringObject);
    1021210203}
    1021310204
     
    1022210213        return;
    1022310214
    10224     GPRTemporary structureID(this);
    10225     GPRReg structureIDGPR = structureID.gpr();
    10226 
    10227     m_jit.load32(JITCompiler::Address(gpr, JSCell::structureIDOffset()), structureIDGPR);
    10228     JITCompiler::Jump isString = m_jit.branchWeakStructure(
    10229         JITCompiler::Equal,
    10230         structureIDGPR,
    10231         m_jit.graph().registerStructure(m_jit.vm()->stringStructure.get()));
    10232    
    10233     speculateStringObjectForStructure(edge, structureIDGPR);
    10234    
     10215    GPRTemporary typeTemp(this);
     10216    GPRReg typeGPR = typeTemp.gpr();
     10217
     10218    m_jit.load8(JITCompiler::Address(gpr, JSCell::typeInfoTypeOffset()), typeGPR);
     10219
     10220    JITCompiler::Jump isString = m_jit.branch32(JITCompiler::Equal, typeGPR, TrustedImm32(StringType));
     10221    speculationCheck(BadType, JSValueSource::unboxedCell(gpr), edge.node(), m_jit.branch32(JITCompiler::NotEqual, typeGPR, TrustedImm32(StringObjectType)));
    1023510222    isString.link(&m_jit);
    1023610223   
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r239612 r240114  
    16321632    void speculateNotStringVar(Edge);
    16331633    void speculateNotSymbol(Edge);
    1634     template<typename StructureLocationType>
    1635     void speculateStringObjectForStructure(Edge, StructureLocationType);
    16361634    void speculateStringObject(Edge, GPRReg);
    16371635    void speculateStringObject(Edge);
     
    26052603};
    26062604
    2607 template<typename StructureLocationType>
    2608 void SpeculativeJIT::speculateStringObjectForStructure(Edge edge, StructureLocationType structureLocation)
    2609 {
    2610     RegisteredStructure stringObjectStructure =
    2611         m_jit.graph().registerStructure(m_jit.globalObjectFor(m_currentNode->origin.semantic)->stringObjectStructure());
    2612    
    2613     if (!m_state.forNode(edge).m_structure.isSubsetOf(RegisteredStructureSet(stringObjectStructure))) {
    2614         speculationCheck(
    2615             NotStringObject, JSValueRegs(), 0,
    2616             m_jit.branchWeakStructure(
    2617                 JITCompiler::NotEqual, structureLocation, stringObjectStructure));
    2618     }
    2619 }
    2620 
    26212605#define DFG_TYPE_CHECK_WITH_EXIT_KIND(exitKind, source, edge, typesPassedThrough, jumpToFail) do { \
    26222606        JSValueSource _dtc_source = (source);                           \
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.h

    r238297 r240114  
    269269}
    270270
    271 // Returns true if it uses structure in a way that could be clobbered by
    272 // things that change the structure.
    273 inline bool usesStructure(UseKind kind)
    274 {
    275     switch (kind) {
    276     case StringObjectUse:
    277     case StringOrStringObjectUse:
    278         return true;
    279     default:
    280         return false;
    281     }
    282 }
    283 
    284271// Returns true if we've already guaranteed the type
    285272inline bool alreadyChecked(UseKind kind, SpeculatedType type)
    286273{
    287     // If the check involves the structure then we need to know more than just the type to be sure
    288     // that the check is done.
    289     if (usesStructure(kind))
    290         return false;
    291    
    292274    return !(type & ~typeFilterFor(kind));
    293275}
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r240024 r240114  
    63276327            LValue cell = lowCell(m_node->child1());
    63286328            speculateStringObjectForCell(m_node->child1(), cell);
    6329             m_interpreter.filter(m_node->child1(), SpecStringObject);
    6330            
    63316329            setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
    63326330            return;
     
    63356333        case StringOrStringObjectUse: {
    63366334            LValue cell = lowCell(m_node->child1());
    6337             LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
     6335            LValue type = m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType);
    63386336           
    63396337            LBasicBlock notString = m_out.newBlock();
     
    63426340            ValueFromBlock simpleResult = m_out.anchor(cell);
    63436341            m_out.branch(
    6344                 m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
     6342                m_out.equal(type, m_out.constInt32(StringType)),
    63456343                unsure(continuation), unsure(notString));
    63466344           
    63476345            LBasicBlock lastNext = m_out.appendTo(notString, continuation);
    6348             speculateStringObjectForStructureID(m_node->child1(), structureID);
     6346            speculate(
     6347                BadType, jsValueValue(cell), m_node->child1().node(),
     6348                m_out.notEqual(type, m_out.constInt32(StringObjectType)));
    63496349            ValueFromBlock unboxedResult = m_out.anchor(
    63506350                m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
     
    1605216052       
    1605316053        speculateStringObjectForCell(edge, lowCell(edge));
    16054         m_interpreter.filter(edge, SpecStringObject);
    1605516054    }
    1605616055   
    1605716056    void speculateStringOrStringObject(Edge edge)
    1605816057    {
     16058        if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
     16059            return;
     16060
     16061        LValue cellBase = lowCell(edge);
    1605916062        if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
    1606016063            return;
     
    1606316066        LBasicBlock continuation = m_out.newBlock();
    1606416067       
    16065         LValue structureID = m_out.load32(lowCell(edge), m_heaps.JSCell_structureID);
     16068        LValue type = m_out.load8ZeroExt32(cellBase, m_heaps.JSCell_typeInfoType);
    1606616069        m_out.branch(
    16067             m_out.equal(structureID, m_out.constInt32(vm().stringStructure->id())),
     16070            m_out.equal(type, m_out.constInt32(StringType)),
    1606816071            unsure(continuation), unsure(notString));
    1606916072       
    1607016073        LBasicBlock lastNext = m_out.appendTo(notString, continuation);
    16071         speculateStringObjectForStructureID(edge, structureID);
     16074        speculate(
     16075            BadType, jsValueValue(cellBase), edge.node(),
     16076            m_out.notEqual(type, m_out.constInt32(StringObjectType)));
    1607216077        m_out.jump(continuation);
    1607316078       
    1607416079        m_out.appendTo(continuation, lastNext);
    16075        
    1607616080        m_interpreter.filter(edge, SpecString | SpecStringObject);
    1607716081    }
     
    1607916083    void speculateStringObjectForCell(Edge edge, LValue cell)
    1608016084    {
    16081         speculateStringObjectForStructureID(edge, m_out.load32(cell, m_heaps.JSCell_structureID));
    16082     }
    16083    
    16084     void speculateStringObjectForStructureID(Edge edge, LValue structureID)
    16085     {
    16086         RegisteredStructure stringObjectStructure =
    16087             m_graph.registerStructure(m_graph.globalObjectFor(m_node->origin.semantic)->stringObjectStructure());
    16088 
    16089         if (abstractStructure(edge).isSubsetOf(RegisteredStructureSet(stringObjectStructure)))
    16090             return;
    16091        
    16092         speculate(
    16093             NotStringObject, noValue(), 0,
    16094             m_out.notEqual(structureID, weakStructureID(stringObjectStructure)));
    16095     }
    16096 
     16085        if (!m_interpreter.needsTypeCheck(edge, SpecStringObject))
     16086            return;
     16087
     16088        LValue type = m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType);
     16089        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecStringObject, m_out.notEqual(type, m_out.constInt32(StringObjectType)));
     16090    }
     16091   
    1609716092    void speculateSymbol(Edge edge, LValue cell)
    1609816093    {
  • trunk/Source/JavaScriptCore/runtime/JSType.cpp

    r237547 r240114  
    101101    CASE(JSWeakSetType)
    102102    CASE(WebAssemblyToJSCalleeType)
     103    CASE(StringObjectType)
    103104    CASE(MaxJSType)
    104105    }
  • trunk/Source/JavaScriptCore/runtime/JSType.h

    r239951 r240114  
    111111    JSWeakMapType,
    112112    JSWeakSetType,
     113    WebAssemblyToJSCalleeType,
     114    StringObjectType,
    113115
    114     WebAssemblyToJSCalleeType,
    115 
    116     LastJSCObjectType = WebAssemblyToJSCalleeType, // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types.
     116    LastJSCObjectType = StringObjectType, // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types.
    117117    MaxJSType = 0b11111111,
    118118};
  • trunk/Source/JavaScriptCore/runtime/StringObject.h

    r229410 r240114  
    6464    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    6565    {
    66         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     66        return Structure::create(vm, globalObject, prototype, TypeInfo(StringObjectType, StructureFlags), info());
    6767    }
    6868
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.h

    r239191 r240114  
    4242    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    4343    {
    44         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     44        return Structure::create(vm, globalObject, prototype, TypeInfo(StringObjectType, StructureFlags), info());
    4545    }
    4646
Note: See TracChangeset for help on using the changeset viewer.