Changeset 230488 in webkit


Ignore:
Timestamp:
Apr 10, 2018 12:45:54 PM (6 years ago)
Author:
fpizlo@apple.com
Message:

DFG AI and clobberize should agree with each other
https://bugs.webkit.org/show_bug.cgi?id=184440

Reviewed by Saam Barati.

JSTests:

Add tests for all of the bugs I fixed.

  • stress/direct-arguments-out-of-bounds-change-structure.js: Added.

(foo):

  • stress/new-typed-array-cse-effects.js: Added.

(foo):

  • stress/scoped-arguments-out-of-bounds-change-structure.js: Added.

(foo.theO):
(foo):

  • stress/string-from-char-code-change-structure-not-dead.js: Added.

(foo):
(i.valueOf):
(weirdValue.valueOf):

  • stress/string-from-char-code-change-structure.js: Added.

(foo):
(i.valueOf):
(weirdValue.valueOf):

Source/JavaScriptCore:

One way to fix bugs involving underapproximation in AI or clobberize is to assert that they
agree with each other. That's what this patch does: it adds an assertion that AI's structure
state tracking must be equivalent to JSCell_structureID being clobbered.

One subtlety is that AI sometimes folds away structure clobbering using information that
clobberize doesn't have. So, we track this wuth special kinds of AI states (FoldedClobber and
ObservedTransitions).

This fixes a bunch of cases of AI missing clobberStructures/clobberWorld and one case of
clobberize missing a write(Heap).

This also makes some cases more precise in order to appease the assertion. Making things more
precise might make things faster, but I didn't measure it because that wasn't the goal.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • dfg/DFGAbstractInterpreter.h:
  • dfg/DFGAbstractInterpreterClobberState.cpp: Added.

(WTF::printInternal):

  • dfg/DFGAbstractInterpreterClobberState.h: Added.

(JSC::DFG::mergeClobberStates):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::startExecuting):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::didFoldClobberWorld):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberStructures):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::didFoldClobberStructures):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::setDidClobber): Deleted.

  • dfg/DFGAtTailAbstractState.h:

(JSC::DFG::AtTailAbstractState::setClobberState):
(JSC::DFG::AtTailAbstractState::mergeClobberState):
(JSC::DFG::AtTailAbstractState::setDidClobber): Deleted.

  • dfg/DFGCFAPhase.cpp:

(JSC::DFG::CFAPhase::performBlockCFA):

  • dfg/DFGClobberSet.cpp:

(JSC::DFG::writeSet):

  • dfg/DFGClobberSet.h:
  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGInPlaceAbstractState.h:

(JSC::DFG::InPlaceAbstractState::clobberState const):
(JSC::DFG::InPlaceAbstractState::didClobberOrFolded const):
(JSC::DFG::InPlaceAbstractState::didClobber const):
(JSC::DFG::InPlaceAbstractState::setClobberState):
(JSC::DFG::InPlaceAbstractState::mergeClobberState):
(JSC::DFG::InPlaceAbstractState::setDidClobber): Deleted.

Location:
trunk
Files:
7 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r230457 r230488  
     12018-04-10  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG AI and clobberize should agree with each other
     4        https://bugs.webkit.org/show_bug.cgi?id=184440
     5
     6        Reviewed by Saam Barati.
     7       
     8        Add tests for all of the bugs I fixed.
     9
     10        * stress/direct-arguments-out-of-bounds-change-structure.js: Added.
     11        (foo):
     12        * stress/new-typed-array-cse-effects.js: Added.
     13        (foo):
     14        * stress/scoped-arguments-out-of-bounds-change-structure.js: Added.
     15        (foo.theO):
     16        (foo):
     17        * stress/string-from-char-code-change-structure-not-dead.js: Added.
     18        (foo):
     19        (i.valueOf):
     20        (weirdValue.valueOf):
     21        * stress/string-from-char-code-change-structure.js: Added.
     22        (foo):
     23        (i.valueOf):
     24        (weirdValue.valueOf):
     25
    1262018-04-09  Leo Balter  <leonardo.balter@gmail.com>
    227
  • trunk/Source/JavaScriptCore/ChangeLog

    r230486 r230488  
     12018-04-09  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG AI and clobberize should agree with each other
     4        https://bugs.webkit.org/show_bug.cgi?id=184440
     5
     6        Reviewed by Saam Barati.
     7       
     8        One way to fix bugs involving underapproximation in AI or clobberize is to assert that they
     9        agree with each other. That's what this patch does: it adds an assertion that AI's structure
     10        state tracking must be equivalent to JSCell_structureID being clobbered.
     11       
     12        One subtlety is that AI sometimes folds away structure clobbering using information that
     13        clobberize doesn't have. So, we track this wuth special kinds of AI states (FoldedClobber and
     14        ObservedTransitions).
     15       
     16        This fixes a bunch of cases of AI missing clobberStructures/clobberWorld and one case of
     17        clobberize missing a write(Heap).
     18       
     19        This also makes some cases more precise in order to appease the assertion. Making things more
     20        precise might make things faster, but I didn't measure it because that wasn't the goal.
     21
     22        * JavaScriptCore.xcodeproj/project.pbxproj:
     23        * Sources.txt:
     24        * dfg/DFGAbstractInterpreter.h:
     25        * dfg/DFGAbstractInterpreterClobberState.cpp: Added.
     26        (WTF::printInternal):
     27        * dfg/DFGAbstractInterpreterClobberState.h: Added.
     28        (JSC::DFG::mergeClobberStates):
     29        * dfg/DFGAbstractInterpreterInlines.h:
     30        (JSC::DFG::AbstractInterpreter<AbstractStateType>::startExecuting):
     31        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     32        (JSC::DFG::AbstractInterpreter<AbstractStateType>::didFoldClobberWorld):
     33        (JSC::DFG::AbstractInterpreter<AbstractStateType>::clobberStructures):
     34        (JSC::DFG::AbstractInterpreter<AbstractStateType>::didFoldClobberStructures):
     35        (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
     36        (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
     37        (JSC::DFG::AbstractInterpreter<AbstractStateType>::setDidClobber): Deleted.
     38        * dfg/DFGAtTailAbstractState.h:
     39        (JSC::DFG::AtTailAbstractState::setClobberState):
     40        (JSC::DFG::AtTailAbstractState::mergeClobberState):
     41        (JSC::DFG::AtTailAbstractState::setDidClobber): Deleted.
     42        * dfg/DFGCFAPhase.cpp:
     43        (JSC::DFG::CFAPhase::performBlockCFA):
     44        * dfg/DFGClobberSet.cpp:
     45        (JSC::DFG::writeSet):
     46        * dfg/DFGClobberSet.h:
     47        * dfg/DFGClobberize.h:
     48        (JSC::DFG::clobberize):
     49        * dfg/DFGConstantFoldingPhase.cpp:
     50        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     51        * dfg/DFGInPlaceAbstractState.h:
     52        (JSC::DFG::InPlaceAbstractState::clobberState const):
     53        (JSC::DFG::InPlaceAbstractState::didClobberOrFolded const):
     54        (JSC::DFG::InPlaceAbstractState::didClobber const):
     55        (JSC::DFG::InPlaceAbstractState::setClobberState):
     56        (JSC::DFG::InPlaceAbstractState::mergeClobberState):
     57        (JSC::DFG::InPlaceAbstractState::setDidClobber): Deleted.
     58
    1592018-04-10  Filip Pizlo  <fpizlo@apple.com>
    260
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r230294 r230488  
    343343                0F5CF9841E9D537700C18692 /* AirLowerStackArgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9831E9D537500C18692 /* AirLowerStackArgs.h */; };
    344344                0F5CF9891E9ED65200C18692 /* AirStackAllocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */; };
     345                0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */; };
    345346                0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
    346347                0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    23472348                0F5CF9871E9ED64E00C18692 /* AirStackAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirStackAllocation.h; path = b3/air/AirStackAllocation.h; sourceTree = "<group>"; };
    23482349                0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeOrigin.cpp; path = dfg/DFGNodeOrigin.cpp; sourceTree = "<group>"; };
     2350                0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractInterpreterClobberState.h; path = dfg/DFGAbstractInterpreterClobberState.h; sourceTree = "<group>"; };
     2351                0F5E0FD7207C72710097F0DE /* DFGAbstractInterpreterClobberState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractInterpreterClobberState.cpp; path = dfg/DFGAbstractInterpreterClobberState.cpp; sourceTree = "<group>"; };
    23492352                0F5EF91B16878F78003E5C25 /* JITThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITThunks.cpp; sourceTree = "<group>"; };
    23502353                0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; };
     
    70927095                                A77A423717A0BBFD00A8DB81 /* DFGAbstractHeap.h */,
    70937096                                A704D8FE17A0BAA8006BA554 /* DFGAbstractInterpreter.h */,
     7097                                0F5E0FD7207C72710097F0DE /* DFGAbstractInterpreterClobberState.cpp */,
     7098                                0F5E0FD6207C72710097F0DE /* DFGAbstractInterpreterClobberState.h */,
    70947099                                A704D8FF17A0BAA8006BA554 /* DFGAbstractInterpreterInlines.h */,
    70957100                                0F55C19317276E4600CEABFD /* DFGAbstractValue.cpp */,
     
    82168221                                8B3BF5E41E3D368B0076A87A /* AsyncGeneratorPrototype.lut.h in Headers */,
    82178222                                8BC064961E1D845C00B2B8CA /* AsyncIteratorPrototype.h in Headers */,
     8223                                0F5E0FD8207C72730097F0DE /* DFGAbstractInterpreterClobberState.h in Headers */,
    82188224                                6A38CFAA1E32B5AB0060206F /* AsyncStackTrace.h in Headers */,
    82198225                                0F7CF9571DC125900098CC12 /* AtomicsObject.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r230294 r230488  
    275275
    276276dfg/DFGAbstractHeap.cpp
     277dfg/DFGAbstractInterpreterClobberState.cpp
    277278dfg/DFGAbstractValue.cpp
    278279dfg/DFGAdaptiveInferredPropertyValueWatchpoint.cpp
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h

    r227341 r230488  
    151151private:
    152152    void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
     153    void didFoldClobberWorld();
    153154   
    154155    template<typename Functor>
     
    156157   
    157158    void clobberStructures(unsigned indexInBlock);
     159    void didFoldClobberStructures();
     160   
    158161    void observeTransition(unsigned indexInBlock, RegisteredStructure from, RegisteredStructure to);
    159162    void observeTransitions(unsigned indexInBlock, const TransitionVector&);
    160     void setDidClobber();
    161163   
    162164    enum BooleanResult {
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r230485 r230488  
    3030#include "ArrayConstructor.h"
    3131#include "DFGAbstractInterpreter.h"
     32#include "DFGAbstractInterpreterClobberState.h"
    3233#include "DOMJITGetterSetter.h"
    3334#include "DOMJITSignature.h"
     
    9899    ASSERT(m_state.isValid());
    99100   
    100     m_state.setDidClobber(false);
     101    m_state.setClobberState(AbstractInterpreterClobberState::NotClobbered);
    101102}
    102103
     
    330331        // itself into a straight-line sequence of GetStack/PutStack.
    331332        // https://bugs.webkit.org/show_bug.cgi?id=143071
    332         clobberWorld(node->origin.semantic, clobberLimit);
     333        switch (node->op()) {
     334        case LoadVarargs:
     335            clobberWorld(node->origin.semantic, clobberLimit);
     336            break;
     337        case ForwardVarargs:
     338            break;
     339        default:
     340            DFG_CRASH(m_graph, node, "Bad opcode");
     341            break;
     342        }
    333343        LoadVarargsData* data = node->loadVarargsData();
    334344        m_state.variables().operand(data->count).setType(SpecInt32Only);
     
    610620        JSValue operand = forNode(node->child1()).value();
    611621        if (std::optional<double> number = operand.toNumberFromPrimitive()) {
     622            switch (node->child1().useKind()) {
     623            case Int32Use:
     624            case KnownInt32Use:
     625                break;
     626            default:
     627                didFoldClobberWorld();
     628                break;
     629            }
    612630            uint32_t value = toUInt32(*number);
    613631            setConstant(node, jsNumber(clz32(value)));
     
    10171035        JSValue operand = forNode(node->child1()).value();
    10181036        if (std::optional<double> number = operand.toNumberFromPrimitive()) {
     1037            if (node->child1().useKind() != DoubleRepUse)
     1038                didFoldClobberWorld();
     1039           
    10191040            double roundedValue = 0;
    10201041            if (node->op() == ArithRound)
     
    15161537    case CompareGreaterEq:
    15171538    case CompareEq: {
     1539        bool isClobbering = node->isBinaryUseKind(UntypedUse);
     1540       
     1541        if (isClobbering)
     1542            didFoldClobberWorld();
     1543       
    15181544        JSValue leftConst = forNode(node->child1()).value();
    15191545        JSValue rightConst = forNode(node->child2()).value();
     
    16371663        }
    16381664
    1639         if (node->isBinaryUseKind(UntypedUse))
     1665        if (isClobbering)
    16401666            clobberWorld(node->origin.semantic, clobberLimit);
    16411667        forNode(node).setType(SpecBoolean);
     
    17241750       
    17251751    case StringFromCharCode:
     1752        switch (node->child1().useKind()) {
     1753        case Int32Use:
     1754            break;
     1755        case UntypedUse:
     1756            clobberWorld(node->origin.semantic, clobberLimit);
     1757            break;
     1758        default:
     1759            DFG_CRASH(m_graph, node, "Bad use kind");
     1760            break;
     1761        }
    17261762        forNode(node).setType(m_graph, SpecString);
    17271763        break;
     
    17841820        case Array::DirectArguments:
    17851821        case Array::ScopedArguments:
     1822            if (node->arrayMode().isOutOfBounds())
     1823                clobberWorld(node->origin.semantic, clobberLimit);
    17861824            forNode(node).makeHeapTop();
    17871825            break;
     
    20702108        JSValue childConst = forNode(node->child1()).value();
    20712109        if (childConst && childConst.isNumber()) {
     2110            didFoldClobberWorld();
    20722111            setConstant(node, childConst);
    20732112            break;
     
    20782117        if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) {
    20792118            m_state.setFoundConstants(true);
     2119            didFoldClobberWorld();
    20802120            forNode(node) = forNode(node->child1());
    20812121            break;
     
    20912131        JSValue childConst = forNode(node->child1()).value();
    20922132        if (childConst && childConst.isNumber()) {
     2133            didFoldClobberWorld();
    20932134            setConstant(node, childConst);
    20942135            break;
     
    20992140        if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
    21002141            m_state.setFoundConstants(true);
     2142            didFoldClobberWorld();
    21012143            forNode(node) = forNode(node->child1());
    21022144            break;
     
    21422184            if (2 <= radix && radix <= 36) {
    21432185                m_state.setFoundConstants(true);
     2186                didFoldClobberWorld();
    21442187                forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
    21452188                break;
     
    21852228
    21862229    case Spread:
    2187         if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
    2188             clobberWorld(node->origin.semantic, clobberLimit);
     2230        switch (node->child1()->op()) {
     2231        case PhantomNewArrayBuffer:
     2232        case PhantomCreateRest:
     2233            break;
     2234        default:
     2235            if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
     2236                clobberWorld(node->origin.semantic, clobberLimit);
     2237            else
     2238                didFoldClobberWorld();
     2239            break;
     2240        }
    21892241
    21902242        forNode(node).set(
     
    22682320                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
    22692321                            m_state.setFoundConstants(true);
     2322                            didFoldClobberWorld();
    22702323                            forNode(node).set(m_graph, structure);
    22712324                            break;
     
    22922345        if (!(source.m_type & ~SpecObject)) {
    22932346            m_state.setFoundConstants(true);
     2347            if (node->op() == ToObject)
     2348                didFoldClobberWorld();
    22942349            destination = source;
    22952350            break;
     
    23162371    case PhantomNewRegexp:
    23172372    case BottomValue:
    2318         m_state.setDidClobber(true); // Prevent constant folding.
    23192373        // This claims to return bottom.
    23202374        break;
     
    25212575    case GetById:
    25222576    case GetByIdFlush: {
    2523         if (!node->prediction()) {
    2524             m_state.setIsValid(false);
    2525             break;
    2526         }
    2527        
    25282577        AbstractValue& value = forNode(node->child1());
    25292578        if (value.m_structure.isFinite()
     
    25452594                }
    25462595                m_state.setFoundConstants(true);
     2596                didFoldClobberWorld();
    25472597                forNode(node) = result;
    25482598                break;
     
    26742724    case PutStructure:
    26752725        if (!forNode(node->child1()).m_structure.isClear()) {
    2676             if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
     2726            if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) {
     2727                didFoldClobberStructures();
    26772728                m_state.setFoundConstants(true);
    2678             else {
     2729            } else {
    26792730                observeTransition(
    26802731                    clobberLimit, node->transition()->previous, node->transition()->next);
     
    26892740        // FIXME: We don't model the fact that the structureID is nuked, simply because currently
    26902741        // nobody would currently benefit from having that information. But it's a bug nonetheless.
     2742        if (node->op() == NukeStructureAndSetButterfly)
     2743            didFoldClobberStructures();
    26912744        forNode(node).clear(); // The result is not a JS value.
    26922745        break;
     
    27882841    case Arrayify: {
    27892842        if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
     2843            didFoldClobberStructures();
    27902844            m_state.setFoundConstants(true);
    27912845            break;
     
    28792933
    28802934            if (prototype && canFold) {
     2935                switch (node->child1().useKind()) {
     2936                case ArrayUse:
     2937                case FunctionUse:
     2938                case FinalObjectUse:
     2939                    break;
     2940                default:
     2941                    didFoldClobberWorld();
     2942                    break;
     2943                }
    28812944                setConstant(node, *m_graph.freeze(prototype));
    28822945                break;
     
    30103073        AbstractValue resultingValue;
    30113074       
     3075        if (node->multiPutByOffsetData().writesStructures())
     3076            didFoldClobberStructures();
     3077           
    30123078        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
    30133079            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
     
    31403206                    m_state.setFoundConstants(true);
    31413207               
     3208                didFoldClobberWorld();
    31423209                observeTransitions(clobberLimit, transitions);
    31433210                if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
     
    33673434                && (radix.asNumber() == 0 || radix.asNumber() == 10)) {
    33683435                m_state.setFoundConstants(true);
     3436                if (node->child1().useKind() == UntypedUse)
     3437                    didFoldClobberWorld();
    33693438                forNode(node).setType(SpecInt32Only);
    33703439                break;
     
    34673536{
    34683537    clobberStructures(clobberLimit);
     3538}
     3539
     3540template<typename AbstractStateType>
     3541void AbstractInterpreter<AbstractStateType>::didFoldClobberWorld()
     3542{
     3543    didFoldClobberStructures();
    34693544}
    34703545
     
    35023577{
    35033578    forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
    3504     setDidClobber();
     3579    m_state.mergeClobberState(AbstractInterpreterClobberState::ClobberedStructures);
     3580    m_state.setStructureClobberState(StructuresAreClobbered);
     3581}
     3582
     3583template<typename AbstractStateType>
     3584void AbstractInterpreter<AbstractStateType>::didFoldClobberStructures()
     3585{
     3586    m_state.mergeClobberState(AbstractInterpreterClobberState::FoldedClobber);
    35053587}
    35063588
     
    35133595   
    35143596    ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
     3597   
     3598    m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
    35153599}
    35163600
     
    35193603    unsigned clobberLimit, const TransitionVector& vector)
    35203604{
     3605    if (vector.isEmpty())
     3606        return;
     3607   
    35213608    AbstractValue::TransitionsObserver transitionsObserver(vector);
    35223609    forAllValues(clobberLimit, transitionsObserver);
     
    35273614            ASSERT(!vector[i].previous->dfgShouldWatch());
    35283615    }
    3529 }
    3530 
    3531 template<typename AbstractStateType>
    3532 void AbstractInterpreter<AbstractStateType>::setDidClobber()
    3533 {
    3534     m_state.setDidClobber(true);
    3535     m_state.setStructureClobberState(StructuresAreClobbered);
     3616
     3617    m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
    35363618}
    35373619
     
    36333715    JSValue child = forNode(node->child1()).value();
    36343716    if (std::optional<double> number = child.toNumberFromPrimitive()) {
     3717        if (node->child1().useKind() != DoubleRepUse)
     3718            didFoldClobberWorld();
    36353719        setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
    36363720        return;
  • trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h

    r225966 r230488  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(DFG_JIT)
    2929
     30#include "DFGAbstractInterpreterClobberState.h"
    3031#include "DFGAbstractValue.h"
    3132#include "DFGBasicBlock.h"
     
    6061    StructureClobberState structureClobberState() const { return m_block->cfaStructureClobberStateAtTail; }
    6162   
    62     void setDidClobber(bool) { }
     63    void setClobberState(AbstractInterpreterClobberState) { }
     64    void mergeClobberState(AbstractInterpreterClobberState) { }
    6365    void setStructureClobberState(StructureClobberState state) { RELEASE_ASSERT(state == m_block->cfaStructureClobberStateAtTail); }
    6466    void setIsValid(bool isValid) { m_block->cfaDidFinish = isValid; }
  • trunk/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp

    r204130 r230488  
    11/*
    2  * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3030
    3131#include "DFGAbstractInterpreterInlines.h"
     32#include "DFGClobberSet.h"
    3233#include "DFGGraph.h"
    3334#include "DFGInPlaceAbstractState.h"
     
    164165        }
    165166        for (unsigned i = 0; i < block->size(); ++i) {
     167            Node* node = block->at(i);
    166168            if (m_verbose) {
    167                 Node* node = block->at(i);
    168169                dataLogF("      %s @%u: ", Graph::opName(node->op()), node->index());
    169170               
     
    180181                break;
    181182            }
     183           
     184            if (m_state.didClobberOrFolded() != writesOverlap(m_graph, node, JSCell_structureID))
     185                DFG_CRASH(m_graph, node, toCString("AI-clobberize disagreement; AI says ", m_state.clobberState(), " while clobberize says ", writeSet(m_graph, node)).data());
    182186        }
    183187        if (m_verbose) {
  • trunk/Source/JavaScriptCore/dfg/DFGClobberSet.cpp

    r210023 r230488  
    11/*
    2  * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    159159}
    160160
     161ClobberSet writeSet(Graph& graph, Node* node)
     162{
     163    ClobberSet result;
     164    addWrites(graph, node, result);
     165    return result;
     166}
     167
    161168bool readsOverlap(Graph& graph, Node* node, ClobberSet& readSet)
    162169{
  • trunk/Source/JavaScriptCore/dfg/DFGClobberSet.h

    r207787 r230488  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    114114void addReadsAndWrites(Graph&, Node*, ClobberSet& reads, ClobberSet& writes);
    115115
     116ClobberSet writeSet(Graph&, Node*);
     117
    116118bool readsOverlap(Graph&, Node*, ClobberSet&);
    117119bool writesOverlap(Graph&, Node*, ClobberSet&);
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r230485 r230488  
    955955           
    956956        case Array::ArrayStorage:
     957            if (node->arrayMode().isOutOfBounds()) {
     958                read(World);
     959                write(Heap);
     960                return;
     961            }
     962            read(Butterfly_publicLength);
     963            read(Butterfly_vectorLength);
     964            read(ArrayStorageProperties);
     965            write(ArrayStorageProperties);
     966            if (node->arrayMode().mayStoreToHole())
     967                write(Butterfly_publicLength);
     968            return;
     969
    957970        case Array::SlowPutArrayStorage:
    958             // Give up on life for now.
    959             read(World);
    960             write(Heap);
     971            if (node->arrayMode().mayStoreToHole()) {
     972                read(World);
     973                write(Heap);
     974                return;
     975            }
     976            read(Butterfly_publicLength);
     977            read(Butterfly_vectorLength);
     978            read(ArrayStorageProperties);
     979            write(ArrayStorageProperties);
    961980            return;
    962981
     
    12971316
    12981317    case NewArrayWithSize:
    1299     case NewTypedArray:
    13001318        read(HeapObjectCount);
    13011319        write(HeapObjectCount);
    13021320        return;
     1321
     1322    case NewTypedArray:
     1323        switch (node->child1().useKind()) {
     1324        case Int32Use:
     1325            read(HeapObjectCount);
     1326            write(HeapObjectCount);
     1327            return;
     1328        case UntypedUse:
     1329            read(World);
     1330            write(Heap);
     1331            return;
     1332        default:
     1333            DFG_CRASH(graph, node, "Bad use kind");
     1334        }
     1335        break;
    13031336
    13041337    case NewArrayWithSpread: {
     
    15381571            return;
    15391572        }
    1540        
     1573
    15411574        if (node->isBinaryUseKind(UntypedUse)) {
    15421575            read(World);
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r230376 r230488  
    784784            }
    785785               
     786            case PhantomNewObject:
     787            case PhantomNewFunction:
     788            case PhantomNewGeneratorFunction:
     789            case PhantomNewAsyncGeneratorFunction:
     790            case PhantomNewAsyncFunction:
     791            case PhantomCreateActivation:
     792            case PhantomDirectArguments:
     793            case PhantomClonedArguments:
     794            case PhantomCreateRest:
     795            case PhantomSpread:
     796            case PhantomNewArrayWithSpread:
     797            case PhantomNewArrayBuffer:
     798            case PhantomNewRegexp:
     799            case BottomValue:
     800                alreadyHandled = true;
     801                break;
     802
    786803            default:
    787804                break;
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r230376 r230488  
    686686           
    687687        case StringFromCharCode:
    688             if (node->child1()->shouldSpeculateInt32())
     688            if (node->child1()->shouldSpeculateInt32()) {
    689689                fixEdge<Int32Use>(node->child1());
    690             else
     690                node->clearFlags(NodeMustGenerate);
     691            } else
    691692                fixEdge<UntypedUse>(node->child1());
    692693            break;
  • trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h

    r225966 r230488  
    11/*
    2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828#if ENABLE(DFG_JIT)
    2929
     30#include "DFGAbstractInterpreterClobberState.h"
    3031#include "DFGAbstractValue.h"
    3132#include "DFGBranchDirection.h"
     
    9192    void reset();
    9293   
     94    AbstractInterpreterClobberState clobberState() const { return m_clobberState; }
     95   
     96    // Would have the last executed node clobbered things had we not found a way to fold it?
     97    bool didClobberOrFolded() const { return clobberState() != AbstractInterpreterClobberState::NotClobbered; }
     98   
    9399    // Did the last executed node clobber the world?
    94     bool didClobber() const { return m_didClobber; }
     100    bool didClobber() const { return clobberState() == AbstractInterpreterClobberState::ClobberedStructures; }
    95101   
    96102    // Are structures currently clobbered?
     
    115121   
    116122    // Methods intended to be called from AbstractInterpreter.
    117     void setDidClobber(bool didClobber) { m_didClobber = didClobber; }
     123    void setClobberState(AbstractInterpreterClobberState state) { m_clobberState = state; }
     124    void mergeClobberState(AbstractInterpreterClobberState state) { m_clobberState = mergeClobberStates(m_clobberState, state); }
    118125    void setStructureClobberState(StructureClobberState value) { m_structureClobberState = value; }
    119126    void setIsValid(bool isValid) { m_isValid = isValid; }
     
    146153   
    147154    bool m_isValid;
    148     bool m_didClobber;
     155    AbstractInterpreterClobberState m_clobberState;
    149156    StructureClobberState m_structureClobberState;
    150157   
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r230376 r230488  
    283283    macro(StringCharCodeAt, NodeResultInt32) \
    284284    macro(StringCharAt, NodeResultJS) \
    285     macro(StringFromCharCode, NodeResultJS) \
     285    macro(StringFromCharCode, NodeResultJS | NodeMustGenerate) \
    286286    \
    287287    /* Nodes for comparison operations. */\
Note: See TracChangeset for help on using the changeset viewer.