| Differences between
and this patch
- Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +8 lines
Lines 295-300 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec1
295
		0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */; settings = {ATTRIBUTES = (Private, ); }; };
295
		0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */; settings = {ATTRIBUTES = (Private, ); }; };
296
		0F3B7E2A19A11B8000D9BC56 /* CallVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */; };
296
		0F3B7E2A19A11B8000D9BC56 /* CallVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */; };
297
		0F3B7E2B19A11B8000D9BC56 /* CallVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2519A11B8000D9BC56 /* CallVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
297
		0F3B7E2B19A11B8000D9BC56 /* CallVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B7E2519A11B8000D9BC56 /* CallVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
298
		0F3C1F1A1B868E7900ABB08B /* DFGClobbersExitState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3C1F181B868E7900ABB08B /* DFGClobbersExitState.cpp */; };
299
		0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3C1F191B868E7900ABB08B /* DFGClobbersExitState.h */; settings = {ATTRIBUTES = (Private, ); }; };
298
		0F3BD1B71B896A0700598AA6 /* DFGInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3BD1B61B896A0700598AA6 /* DFGInsertionSet.cpp */; };
300
		0F3BD1B71B896A0700598AA6 /* DFGInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3BD1B61B896A0700598AA6 /* DFGInsertionSet.cpp */; };
299
		0F3E01AA19D353A500F61B7F /* DFGPrePostNumbering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3E01A819D353A500F61B7F /* DFGPrePostNumbering.cpp */; };
301
		0F3E01AA19D353A500F61B7F /* DFGPrePostNumbering.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3E01A819D353A500F61B7F /* DFGPrePostNumbering.cpp */; };
300
		0F3E01AB19D353A500F61B7F /* DFGPrePostNumbering.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */; settings = {ATTRIBUTES = (Private, ); }; };
302
		0F3E01AB19D353A500F61B7F /* DFGPrePostNumbering.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 2107-2112 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec2
2107
		0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGValidate.h; path = dfg/DFGValidate.h; sourceTree = "<group>"; };
2109
		0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGValidate.h; path = dfg/DFGValidate.h; sourceTree = "<group>"; };
2108
		0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallVariant.cpp; sourceTree = "<group>"; };
2110
		0F3B7E2419A11B8000D9BC56 /* CallVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallVariant.cpp; sourceTree = "<group>"; };
2109
		0F3B7E2519A11B8000D9BC56 /* CallVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallVariant.h; sourceTree = "<group>"; };
2111
		0F3B7E2519A11B8000D9BC56 /* CallVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallVariant.h; sourceTree = "<group>"; };
2112
		0F3C1F181B868E7900ABB08B /* DFGClobbersExitState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGClobbersExitState.cpp; path = dfg/DFGClobbersExitState.cpp; sourceTree = "<group>"; };
2113
		0F3C1F191B868E7900ABB08B /* DFGClobbersExitState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGClobbersExitState.h; path = dfg/DFGClobbersExitState.h; sourceTree = "<group>"; };
2110
		0F3BD1B61B896A0700598AA6 /* DFGInsertionSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInsertionSet.cpp; path = dfg/DFGInsertionSet.cpp; sourceTree = "<group>"; };
2114
		0F3BD1B61B896A0700598AA6 /* DFGInsertionSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInsertionSet.cpp; path = dfg/DFGInsertionSet.cpp; sourceTree = "<group>"; };
2111
		0F3E01A819D353A500F61B7F /* DFGPrePostNumbering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPrePostNumbering.cpp; path = dfg/DFGPrePostNumbering.cpp; sourceTree = "<group>"; };
2115
		0F3E01A819D353A500F61B7F /* DFGPrePostNumbering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPrePostNumbering.cpp; path = dfg/DFGPrePostNumbering.cpp; sourceTree = "<group>"; };
2112
		0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPrePostNumbering.h; path = dfg/DFGPrePostNumbering.h; sourceTree = "<group>"; };
2116
		0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPrePostNumbering.h; path = dfg/DFGPrePostNumbering.h; sourceTree = "<group>"; };
Lines 5119-5124 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec3
5119
				A77A423917A0BBFD00A8DB81 /* DFGClobberize.h */,
5123
				A77A423917A0BBFD00A8DB81 /* DFGClobberize.h */,
5120
				A77A423A17A0BBFD00A8DB81 /* DFGClobberSet.cpp */,
5124
				A77A423A17A0BBFD00A8DB81 /* DFGClobberSet.cpp */,
5121
				A77A423B17A0BBFD00A8DB81 /* DFGClobberSet.h */,
5125
				A77A423B17A0BBFD00A8DB81 /* DFGClobberSet.h */,
5126
				0F3C1F181B868E7900ABB08B /* DFGClobbersExitState.cpp */,
5127
				0F3C1F191B868E7900ABB08B /* DFGClobbersExitState.h */,
5122
				0F04396B1B03DC0B009598B7 /* DFGCombinedLiveness.cpp */,
5128
				0F04396B1B03DC0B009598B7 /* DFGCombinedLiveness.cpp */,
5123
				0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */,
5129
				0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */,
5124
				0FB4B51A16B62772003F696B /* DFGCommon.cpp */,
5130
				0FB4B51A16B62772003F696B /* DFGCommon.cpp */,
Lines 6148-6153 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec4
6148
				0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */,
6154
				0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */,
6149
				86EC9DD11328DF82002B2AD7 /* DFGRegisterBank.h in Headers */,
6155
				86EC9DD11328DF82002B2AD7 /* DFGRegisterBank.h in Headers */,
6150
				0F2FCCFC18A60070001A27F8 /* DFGSafepoint.h in Headers */,
6156
				0F2FCCFC18A60070001A27F8 /* DFGSafepoint.h in Headers */,
6157
				0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */,
6151
				A77A424317A0BBFD00A8DB81 /* DFGSafeToExecute.h in Headers */,
6158
				A77A424317A0BBFD00A8DB81 /* DFGSafeToExecute.h in Headers */,
6152
				A741017F179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h in Headers */,
6159
				A741017F179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h in Headers */,
6153
				0F2FCCFD18A60070001A27F8 /* DFGScannable.h in Headers */,
6160
				0F2FCCFD18A60070001A27F8 /* DFGScannable.h in Headers */,
Lines 7381-7386 Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj_sec5
7381
				149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */,
7388
				149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */,
7382
				2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */,
7389
				2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */,
7383
				0FC712DE17CD8779008CC93C /* DeferredCompilationCallback.cpp in Sources */,
7390
				0FC712DE17CD8779008CC93C /* DeferredCompilationCallback.cpp in Sources */,
7391
				0F3C1F1A1B868E7900ABB08B /* DFGClobbersExitState.cpp in Sources */,
7384
				A77A423D17A0BBFD00A8DB81 /* DFGAbstractHeap.cpp in Sources */,
7392
				A77A423D17A0BBFD00A8DB81 /* DFGAbstractHeap.cpp in Sources */,
7385
				0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */,
7393
				0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */,
7386
				0F485321187750560083B687 /* DFGArithMode.cpp in Sources */,
7394
				0F485321187750560083B687 /* DFGArithMode.cpp in Sources */,
- Source/JavaScriptCore/dfg/DFGAbstractHeap.h +1 lines
Lines 39-44 namespace JSC { namespace DFG { Source/JavaScriptCore/dfg/DFGAbstractHeap.h_sec1
39
// - Stack with a TOP payload is a direct subtype of World
39
// - Stack with a TOP payload is a direct subtype of World
40
// - Stack with a non-TOP payload is a direct subtype of Stack with a TOP payload.
40
// - Stack with a non-TOP payload is a direct subtype of Stack with a TOP payload.
41
// - Heap is a direct subtype of World.
41
// - Heap is a direct subtype of World.
42
// - SideState is a direct subtype of World.
42
// - Any other kind with TOP payload is the direct subtype of Heap.
43
// - Any other kind with TOP payload is the direct subtype of Heap.
43
// - Any other kind with non-TOP payload is the direct subtype of the same kind with a TOP payload.
44
// - Any other kind with non-TOP payload is the direct subtype of the same kind with a TOP payload.
44
45
- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp -7 / +41 lines
Lines 35-40 Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec1
35
#include "CodeBlockWithJITType.h"
35
#include "CodeBlockWithJITType.h"
36
#include "DFGArrayMode.h"
36
#include "DFGArrayMode.h"
37
#include "DFGCapabilities.h"
37
#include "DFGCapabilities.h"
38
#include "DFGClobberize.h"
38
#include "DFGGraph.h"
39
#include "DFGGraph.h"
39
#include "DFGJITCode.h"
40
#include "DFGJITCode.h"
40
#include "GetByIdStatus.h"
41
#include "GetByIdStatus.h"
Lines 362-367 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec2
362
    {
363
    {
363
        addToGraph(MovHint, OpInfo(operand.offset()), value);
364
        addToGraph(MovHint, OpInfo(operand.offset()), value);
364
365
366
        // We can't exit anymore because our OSR exit state has changed.
367
        m_exitOK = false;
368
365
        DelayedSetLocal delayed(currentCodeOrigin(), operand, value);
369
        DelayedSetLocal delayed(currentCodeOrigin(), operand, value);
366
        
370
        
367
        if (setMode == NormalSet) {
371
        if (setMode == NormalSet) {
Lines 374-381 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec3
374
    
378
    
375
    void processSetLocalQueue()
379
    void processSetLocalQueue()
376
    {
380
    {
377
        for (unsigned i = 0; i < m_setLocalQueue.size(); ++i)
381
        // We play hacks with m_exitOK here. We know that the SetLocals we are emitting are already
382
        // recorded in OSR exit state, so they aren't real effects. So, we don't want them to have any
383
        // effect on m_exitOK.
384
        bool exitOKBefore = m_exitOK;
385
        for (unsigned i = 0; i < m_setLocalQueue.size(); ++i) {
378
            m_setLocalQueue[i].execute(this);
386
            m_setLocalQueue[i].execute(this);
387
            m_exitOK = exitOKBefore;
388
        }
379
        m_setLocalQueue.resize(0);
389
        m_setLocalQueue.resize(0);
380
    }
390
    }
381
391
Lines 651-665 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec4
651
661
652
    NodeOrigin currentNodeOrigin()
662
    NodeOrigin currentNodeOrigin()
653
    {
663
    {
654
        // FIXME: We should set the forExit origin only on those nodes that can exit.
655
        // https://bugs.webkit.org/show_bug.cgi?id=145204
656
        CodeOrigin semantic;
664
        CodeOrigin semantic;
665
        CodeOrigin forExit;
666
657
        if (m_currentSemanticOrigin.isSet())
667
        if (m_currentSemanticOrigin.isSet())
658
            semantic = m_currentSemanticOrigin;
668
            semantic = m_currentSemanticOrigin;
659
        else
669
        else
660
            semantic = currentCodeOrigin();
670
            semantic = currentCodeOrigin();
661
        
671
662
        return NodeOrigin(semantic, currentCodeOrigin(), true);
672
        forExit = currentCodeOrigin();
673
674
        return NodeOrigin(semantic, forExit, m_exitOK);
663
    }
675
    }
664
    
676
    
665
    BranchData* branchData(unsigned taken, unsigned notTaken)
677
    BranchData* branchData(unsigned taken, unsigned notTaken)
Lines 677-682 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec5
677
        if (Options::verboseDFGByteCodeParsing())
689
        if (Options::verboseDFGByteCodeParsing())
678
            dataLog("        appended ", node, " ", Graph::opName(node->op()), "\n");
690
            dataLog("        appended ", node, " ", Graph::opName(node->op()), "\n");
679
        m_currentBlock->append(node);
691
        m_currentBlock->append(node);
692
        clobberize(
693
            m_graph, node, NoOpClobberize(),
694
            [&] (const AbstractHeap& heap) {
695
                // Writes to SideState are not observable.
696
                if (heap.isSubtypeOf(SideState))
697
                    return;
698
699
                // We assume all other writes are observable, and so if we tried to exit after them
700
                // with the same origin then we'd cause that effect to repeat.
701
                m_exitOK = false;
702
            },
703
            NoOpClobberize());
680
        return node;
704
        return node;
681
    }
705
    }
682
    
706
    
Lines 900-905 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec6
900
    unsigned m_currentIndex;
924
    unsigned m_currentIndex;
901
    // The semantic origin of the current node if different from the current Index.
925
    // The semantic origin of the current node if different from the current Index.
902
    CodeOrigin m_currentSemanticOrigin;
926
    CodeOrigin m_currentSemanticOrigin;
927
    // True if it's OK to OSR exit right now.
928
    bool m_exitOK { false };
903
929
904
    FrozenValue* m_constantUndefined;
930
    FrozenValue* m_constantUndefined;
905
    FrozenValue* m_constantNull;
931
    FrozenValue* m_constantNull;
Lines 1053-1058 private: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec7
1053
1079
1054
#define LAST_OPCODE(name) \
1080
#define LAST_OPCODE(name) \
1055
    m_currentIndex += OPCODE_LENGTH(name); \
1081
    m_currentIndex += OPCODE_LENGTH(name); \
1082
    m_exitOK = false; \
1056
    return shouldContinueParsing
1083
    return shouldContinueParsing
1057
1084
1058
void ByteCodeParser::handleCall(Instruction* pc, NodeType op, CodeSpecializationKind kind)
1085
void ByteCodeParser::handleCall(Instruction* pc, NodeType op, CodeSpecializationKind kind)
Lines 1356-1361 void ByteCodeParser::inlineCall(Node* ca Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec8
1356
    clearCaches(); // Reset our state now that we're back to the outer code.
1383
    clearCaches(); // Reset our state now that we're back to the outer code.
1357
    
1384
    
1358
    m_currentIndex = oldIndex;
1385
    m_currentIndex = oldIndex;
1386
    m_exitOK = false;
1359
    
1387
    
1360
    // If the inlined code created some new basic blocks, then we have linking to do.
1388
    // If the inlined code created some new basic blocks, then we have linking to do.
1361
    if (inlineStackEntry.m_callsiteBlockHead != m_graph.lastBlock()) {
1389
    if (inlineStackEntry.m_callsiteBlockHead != m_graph.lastBlock()) {
Lines 2901-2912 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec9
2901
    Interpreter* interpreter = m_vm->interpreter;
2929
    Interpreter* interpreter = m_vm->interpreter;
2902
    Instruction* instructionsBegin = m_inlineStackTop->m_codeBlock->instructions().begin();
2930
    Instruction* instructionsBegin = m_inlineStackTop->m_codeBlock->instructions().begin();
2903
    unsigned blockBegin = m_currentIndex;
2931
    unsigned blockBegin = m_currentIndex;
2904
    
2932
2905
    // If we are the first basic block, introduce markers for arguments. This allows
2933
    // If we are the first basic block, introduce markers for arguments. This allows
2906
    // us to track if a use of an argument may use the actual argument passed, as
2934
    // us to track if a use of an argument may use the actual argument passed, as
2907
    // opposed to using a value we set explicitly.
2935
    // opposed to using a value we set explicitly.
2908
    if (m_currentBlock == m_graph.block(0) && !inlineCallFrame()) {
2936
    if (m_currentBlock == m_graph.block(0) && !inlineCallFrame()) {
2909
        m_graph.m_arguments.resize(m_numArguments);
2937
        m_graph.m_arguments.resize(m_numArguments);
2938
        // We will emit SetArgument nodes. They don't exit, but we're at the top of an op_enter so
2939
        // exitOK = true.
2940
        m_exitOK = true;
2910
        for (unsigned argument = 0; argument < m_numArguments; ++argument) {
2941
        for (unsigned argument = 0; argument < m_numArguments; ++argument) {
2911
            VariableAccessData* variable = newVariableAccessData(
2942
            VariableAccessData* variable = newVariableAccessData(
2912
                virtualRegisterForArgument(argument));
2943
                virtualRegisterForArgument(argument));
Lines 2922-2927 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec10
2922
    }
2953
    }
2923
2954
2924
    while (true) {
2955
    while (true) {
2956
        // We're staring a new bytecode instruction. Hence, we once again have a place that we can exit
2957
        // to.
2958
        m_exitOK = true;
2959
        
2925
        processSetLocalQueue();
2960
        processSetLocalQueue();
2926
        
2961
        
2927
        // Don't extend over jump destinations.
2962
        // Don't extend over jump destinations.
Lines 2998-3004 bool ByteCodeParser::parseBlock(unsigned Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp_sec11
2998
3033
2999
                    FrozenValue* frozen = m_graph.freeze(cachedFunction);
3034
                    FrozenValue* frozen = m_graph.freeze(cachedFunction);
3000
                    addToGraph(CheckCell, OpInfo(frozen), callee);
3035
                    addToGraph(CheckCell, OpInfo(frozen), callee);
3001
                    set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(JSConstant, OpInfo(frozen)));
3002
3036
3003
                    function = static_cast<JSFunction*>(cachedFunction);
3037
                    function = static_cast<JSFunction*>(cachedFunction);
3004
                }
3038
                }
- Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp +77 lines
Line 0 Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#include "config.h"
27
#include "DFGClobbersExitState.h"
28
29
#if ENABLE(DFG_JIT)
30
31
#include "DFGClobberize.h"
32
#include "DFGGraph.h"
33
#include "DFGNode.h"
34
#include "JSCInlines.h"
35
36
namespace JSC { namespace DFG {
37
38
bool clobbersExitState(Graph& graph, Node* node)
39
{
40
    // There are certain nodes whose effect on the exit state has nothing to do with what they
41
    // normally clobber.
42
    switch (node->op()) {
43
    case MovHint:
44
    case ZombieHint:
45
    case PutHint:
46
    case KillStack:
47
        // These nodes all write to the exit state, so obviously, they clobber it.
48
        return true;
49
50
    case SetLocal:
51
    case PutStack:
52
        // These nodes write to the stack, but they may only do so after we have already had a MovHint
53
        // for the exact same value and the same stack location. Hence, they have no further effect on
54
        // exit state.
55
        return false;
56
57
    default:
58
        // For all other nodes, we just care about whether they write to something other than SideState.
59
        bool result = false;
60
        clobberize(
61
            graph, node, NoOpClobberize(),
62
            [&] (const AbstractHeap& heap) {
63
                // There shouldn't be such a thing as a strict subtype of SideState. That's what allows
64
                // us to use a fast != check, below.
65
                ASSERT(!heap.isStrictSubtypeOf(SideState));
66
67
                if (heap != SideState)
68
                    result = true;
69
            },
70
            NoOpClobberize());
71
        return result;
72
    }
73
}
74
75
} } // namespace JSC::DFG
76
77
#endif // ENABLE(DFG_JIT)
- Source/JavaScriptCore/dfg/DFGClobbersExitState.h +46 lines
Line 0 Source/JavaScriptCore/dfg/DFGClobbersExitState.h_sec1
1
/*
2
 * Copyright (C) 2015 Apple Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24
 */
25
26
#ifndef DFGClobbersExitState_h
27
#define DFGClobbersExitState_h
28
29
#if ENABLE(DFG_JIT)
30
31
namespace JSC { namespace DFG {
32
33
class Graph;
34
struct Node;
35
36
// A conservative approximation of whether the node will perform an effect that means that we can no
37
// longer exit to this node's exit origin.
38
39
bool clobbersExitState(Graph&, Node*);
40
41
} } // namespace JSC::DFG
42
43
#endif // ENABLE(DFG_JIT)
44
45
#endif // DFGClobbersExitState_h
46
- Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp -1 / +3 lines
Lines 667-672 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec1
667
        
667
        
668
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
668
        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
669
669
670
        node->child1().setUseKind(KnownCellUse);
670
        childEdge.setUseKind(KnownCellUse);
671
        childEdge.setUseKind(KnownCellUse);
671
672
672
        Transition* transition = 0;
673
        Transition* transition = 0;
Lines 713-719 private: Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp_sec2
713
            // https://bugs.webkit.org/show_bug.cgi?id=142921 or
714
            // https://bugs.webkit.org/show_bug.cgi?id=142921 or
714
            // https://bugs.webkit.org/show_bug.cgi?id=142924.
715
            // https://bugs.webkit.org/show_bug.cgi?id=142924.
715
            m_insertionSet.insertNode(
716
            m_insertionSet.insertNode(
716
                indexInBlock + 1, SpecNone, PutStructure, origin, OpInfo(transition), childEdge);
717
                indexInBlock + 1, SpecNone, PutStructure, origin.withInvalidExit(), OpInfo(transition),
718
                childEdge);
717
        }
719
        }
718
    }
720
    }
719
    
721
    
- Source/JavaScriptCore/dfg/DFGFixupPhase.cpp -18 / +65 lines
Lines 1637-1642 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec1
1637
                break;
1637
                break;
1638
                
1638
                
1639
            case SetLocal:
1639
            case SetLocal:
1640
                // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
1641
                // add new type checking use kind for SetLocals, we need to modify that code as well.
1642
                
1640
                switch (variable->flushFormat()) {
1643
                switch (variable->flushFormat()) {
1641
                case FlushedJSValue:
1644
                case FlushedJSValue:
1642
                    break;
1645
                    break;
Lines 2110-2117 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec2
2110
            return;
2113
            return;
2111
        ASSERT(block->isReachable);
2114
        ASSERT(block->isReachable);
2112
        m_block = block;
2115
        m_block = block;
2113
        for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
2116
        unsigned indexForChecks = UINT_MAX;
2114
            Node* node = block->at(m_indexInBlock);
2117
        NodeOrigin originForChecks;
2118
        for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
2119
            Node* node = block->at(indexInBlock);
2120
2121
            // If this is a node at which we could exit, then save its index. If nodes after this one
2122
            // cannot exit, then we will hoist checks to here.
2123
            if (node->origin.exitOK) {
2124
                indexForChecks = indexInBlock;
2125
                originForChecks = node->origin;
2126
            }
2115
2127
2116
            // First, try to relax the representational demands of each node, in order to have
2128
            // First, try to relax the representational demands of each node, in order to have
2117
            // fewer conversions.
2129
            // fewer conversions.
Lines 2175-2195 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec3
2175
                node,
2187
                node,
2176
                [&] (Edge& edge) {
2188
                [&] (Edge& edge) {
2177
                    Node* result = nullptr;
2189
                    Node* result = nullptr;
2178
        
2190
2179
                    switch (edge.useKind()) {
2191
                    switch (edge.useKind()) {
2180
                    case DoubleRepUse:
2192
                    case DoubleRepUse:
2181
                    case DoubleRepRealUse:
2193
                    case DoubleRepRealUse:
2182
                    case DoubleRepMachineIntUse: {
2194
                    case DoubleRepMachineIntUse: {
2183
                        if (edge->hasDoubleResult())
2195
                        if (edge->hasDoubleResult())
2184
                            return;
2196
                            break;
2185
            
2197
            
2186
                        if (edge->isNumberConstant()) {
2198
                        if (edge->isNumberConstant()) {
2187
                            result = m_insertionSet.insertNode(
2199
                            result = m_insertionSet.insertNode(
2188
                                m_indexInBlock, SpecBytecodeDouble, DoubleConstant, node->origin,
2200
                                indexForChecks, SpecBytecodeDouble, DoubleConstant, node->origin,
2189
                                OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
2201
                                OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
2190
                        } else if (edge->hasInt52Result()) {
2202
                        } else if (edge->hasInt52Result()) {
2191
                            result = m_insertionSet.insertNode(
2203
                            result = m_insertionSet.insertNode(
2192
                                m_indexInBlock, SpecInt52AsDouble, DoubleRep, node->origin,
2204
                                indexForChecks, SpecInt52AsDouble, DoubleRep, node->origin,
2193
                                Edge(edge.node(), Int52RepUse));
2205
                                Edge(edge.node(), Int52RepUse));
2194
                        } else {
2206
                        } else {
2195
                            UseKind useKind;
2207
                            UseKind useKind;
Lines 2201-2253 private: Source/JavaScriptCore/dfg/DFGFixupPhase.cpp_sec4
2201
                                useKind = NotCellUse;
2213
                                useKind = NotCellUse;
2202
2214
2203
                            result = m_insertionSet.insertNode(
2215
                            result = m_insertionSet.insertNode(
2204
                                m_indexInBlock, SpecBytecodeDouble, DoubleRep, node->origin,
2216
                                indexForChecks, SpecBytecodeDouble, DoubleRep, node->origin,
2205
                                Edge(edge.node(), useKind));
2217
                                Edge(edge.node(), useKind));
2206
                        }
2218
                        }
2219
2220
                        edge.setNode(result);
2207
                        break;
2221
                        break;
2208
                    }
2222
                    }
2209
            
2223
            
2210
                    case Int52RepUse: {
2224
                    case Int52RepUse: {
2211
                        if (edge->hasInt52Result())
2225
                        if (edge->hasInt52Result())
2212
                            return;
2226
                            break;
2213
            
2227
            
2214
                        if (edge->isMachineIntConstant()) {
2228
                        if (edge->isMachineIntConstant()) {
2215
                            result = m_insertionSet.insertNode(
2229
                            result = m_insertionSet.insertNode(
2216
                                m_indexInBlock, SpecMachineInt, Int52Constant, node->origin,
2230
                                indexForChecks, SpecMachineInt, Int52Constant, node->origin,
2217
                                OpInfo(edge->constant()));
2231
                                OpInfo(edge->constant()));
2218
                        } else if (edge->hasDoubleResult()) {
2232
                        } else if (edge->hasDoubleResult()) {
2219
                            result = m_insertionSet.insertNode(
2233
                            result = m_insertionSet.insertNode(
2220
                                m_indexInBlock, SpecMachineInt, Int52Rep, node->origin,
2234
                                indexForChecks, SpecMachineInt, Int52Rep, node->origin,
2221
                                Edge(edge.node(), DoubleRepMachineIntUse));
2235
                                Edge(edge.node(), DoubleRepMachineIntUse));
2222
                        } else if (edge->shouldSpeculateInt32ForArithmetic()) {
2236
                        } else if (edge->shouldSpeculateInt32ForArithmetic()) {
2223
                            result = m_insertionSet.insertNode(
2237
                            result = m_insertionSet.insertNode(
2224
                                m_indexInBlock, SpecInt32, Int52Rep, node->origin,
2238
                                indexForChecks, SpecInt32, Int52Rep, node->origin,
2225
                                Edge(edge.node(), Int32Use));
2239
                                Edge(edge.node(), Int32Use));
2226
                        } else {
2240
                        } else {
2227
                            result = m_insertionSet.insertNode(
2241
                            result = m_insertionSet.insertNode(
2228
                                m_indexInBlock, SpecMachineInt, Int52Rep, node->origin,
2242
                                indexForChecks, SpecMachineInt, Int52Rep, node->origin,
2229
                                Edge(edge.node(), MachineIntUse));
2243
                                Edge(edge.node(), MachineIntUse));
2230
                        }
2244
                        }
2245
2246
                        edge.setNode(result);
2231
                        break;
2247
                        break;
2232
                    }
2248
                    }
2233
            
2249
2234
                    default: {
2250
                    default: {
2235
                        if (!edge->hasDoubleResult() && !edge->hasInt52Result())
2251
                        if (!edge->hasDoubleResult() && !edge->hasInt52Result())
2236
                            return;
2252
                            break;
2237
            
2253
            
2238
                        if (edge->hasDoubleResult()) {
2254
                        if (edge->hasDoubleResult()) {
2239
                            result = m_insertionSet.insertNode(
2255
                            result = m_insertionSet.insertNode(
2240
                                m_indexInBlock, SpecBytecodeDouble, ValueRep, node->origin,
2256
                                indexForChecks, SpecBytecodeDouble, ValueRep, node->origin,
2241
                                Edge(edge.node(), DoubleRepUse));
2257
                                Edge(edge.node(), DoubleRepUse));
2242
                        } else {
2258
                        } else {
2243
                            result = m_insertionSet.insertNode(
2259
                            result = m_insertionSet.insertNode(
2244
                                m_indexInBlock, SpecInt32 | SpecInt52AsDouble, ValueRep,
2260
                                indexForChecks, SpecInt32 | SpecInt52AsDouble, ValueRep,
2245
                                node->origin, Edge(edge.node(), Int52RepUse));
2261
                                node->origin, Edge(edge.node(), Int52RepUse));
2246
                        }
2262
                        }
2263
2264
                        edge.setNode(result);
2247
                        break;
2265
                        break;
2248
                    } }
2266
                    } }
2249
                    
2267
2250
                    edge.setNode(result);
2268
                    // It's remotely possible that this node cannot do type checks, but we now have a
2269
                    // type check on this node. We don't have to handle the general form of this
2270
                    // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
2271
                    // than a delayed one. So, we only worry about those checks that we may have put on
2272
                    // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
2273
                    // saying "!node->origin.exitOK".
2274
                    if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
2275
                        UseKind knownUseKind = UntypedUse;
2276
                        
2277
                        switch (edge.useKind()) {
2278
                        case Int32Use:
2279
                            knownUseKind = KnownInt32Use;
2280
                            break;
2281
                        case CellUse:
2282
                            knownUseKind = KnownCellUse;
2283
                            break;
2284
                        case BooleanUse:
2285
                            knownUseKind = KnownBooleanUse;
2286
                            break;
2287
                        default:
2288
                            DFG_CRASH(m_graph, node, "Bad use kind");
2289
                            break;
2290
                        }
2291
2292
                        m_insertionSet.insertNode(
2293
                            indexForChecks, SpecNone, Check,
2294
                            originForChecks.withSemantic(node->origin.semantic), edge);
2295
2296
                        edge.setUseKind(knownUseKind);
2297
                    }
2251
                });
2298
                });
2252
        }
2299
        }
2253
        
2300
        
- Source/JavaScriptCore/dfg/DFGFlushFormat.h +22 lines
Lines 90-95 inline UseKind useKindFor(FlushFormat fo Source/JavaScriptCore/dfg/DFGFlushFormat.h_sec1
90
    return UntypedUse;
90
    return UntypedUse;
91
}
91
}
92
92
93
inline UseKind uncheckedUseKindFor(FlushFormat format)
94
{
95
    switch (format) {
96
    case DeadFlush:
97
    case FlushedJSValue:
98
    case ConflictingFlush:
99
        return UntypedUse;
100
    case FlushedCell:
101
        return KnownCellUse;
102
    case FlushedInt32:
103
        return KnownInt32Use;
104
    case FlushedInt52:
105
        return Int52RepUse;
106
    case FlushedDouble:
107
        return DoubleRepUse;
108
    case FlushedBoolean:
109
        return KnownBooleanUse;
110
    }
111
    RELEASE_ASSERT_NOT_REACHED();
112
    return UntypedUse;
113
}
114
93
inline SpeculatedType typeFilterFor(FlushFormat format)
115
inline SpeculatedType typeFilterFor(FlushFormat format)
94
{
116
{
95
    return typeFilterFor(useKindFor(format));
117
    return typeFilterFor(useKindFor(format));
- Source/JavaScriptCore/dfg/DFGGraph.cpp -5 / +18 lines
Lines 34-40 Source/JavaScriptCore/dfg/DFGGraph.cpp_sec1
34
#include "CodeBlockWithJITType.h"
34
#include "CodeBlockWithJITType.h"
35
#include "DFGBlockWorklist.h"
35
#include "DFGBlockWorklist.h"
36
#include "DFGClobberSet.h"
36
#include "DFGClobberSet.h"
37
#include "DFGClobbersExitState.h"
37
#include "DFGJITCode.h"
38
#include "DFGJITCode.h"
39
#include "DFGMayExit.h"
38
#include "DFGVariableAccessDataDump.h"
40
#include "DFGVariableAccessDataDump.h"
39
#include "FullBytecodeLiveness.h"
41
#include "FullBytecodeLiveness.h"
40
#include "FunctionExecutableDump.h"
42
#include "FunctionExecutableDump.h"
Lines 101-108 static void printWhiteSpace(PrintStream& Source/JavaScriptCore/dfg/DFGGraph.cpp_sec2
101
        out.print(" ");
103
        out.print(" ");
102
}
104
}
103
105
104
bool Graph::dumpCodeOrigin(PrintStream& out, const char* prefix, Node* previousNode, Node* currentNode, DumpContext* context)
106
bool Graph::dumpCodeOrigin(PrintStream& out, const char* prefix, Node*& previousNodeRef, Node* currentNode, DumpContext* context)
105
{
107
{
108
    if (!currentNode->origin.semantic)
109
        return false;
110
    
111
    Node* previousNode = previousNodeRef;
112
    previousNodeRef = currentNode;
113
106
    if (!previousNode)
114
    if (!previousNode)
107
        return false;
115
        return false;
108
    
116
    
Lines 345-356 void Graph::dump(PrintStream& out, const Source/JavaScriptCore/dfg/DFGGraph.cpp_sec3
345
        out.print(comma, "R:", sortedListDump(reads.direct(), ","));
353
        out.print(comma, "R:", sortedListDump(reads.direct(), ","));
346
    if (!writes.isEmpty())
354
    if (!writes.isEmpty())
347
        out.print(comma, "W:", sortedListDump(writes.direct(), ","));
355
        out.print(comma, "W:", sortedListDump(writes.direct(), ","));
356
    ExitMode exitMode = mayExit(*this, node);
357
    if (exitMode != DoesNotExit)
358
        out.print(comma, exitMode);
359
    if (clobbersExitState(*this, node))
360
        out.print(comma, "ClobbersExit");
348
    if (node->origin.isSet()) {
361
    if (node->origin.isSet()) {
349
        out.print(comma, "bc#", node->origin.semantic.bytecodeIndex);
362
        out.print(comma, "bc#", node->origin.semantic.bytecodeIndex);
350
        if (node->origin.semantic != node->origin.forExit)
363
        if (node->origin.semantic != node->origin.forExit && node->origin.forExit.isSet())
351
            out.print(comma, "exit: ", node->origin.forExit);
364
            out.print(comma, "exit: ", node->origin.forExit);
352
    }
365
    }
353
    
366
    if (!node->origin.exitOK)
367
        out.print(comma, "ExitInvalid");
354
    out.print(")");
368
    out.print(")");
355
369
356
    if (node->hasVariableAccessData(*this) && node->tryGetVariableAccessData())
370
    if (node->hasVariableAccessData(*this) && node->tryGetVariableAccessData())
Lines 455-461 void Graph::dump(PrintStream& out, DumpC Source/JavaScriptCore/dfg/DFGGraph.cpp_sec4
455
        out.print("  Arguments: ", listDump(m_arguments), "\n");
469
        out.print("  Arguments: ", listDump(m_arguments), "\n");
456
    out.print("\n");
470
    out.print("\n");
457
    
471
    
458
    Node* lastNode = 0;
472
    Node* lastNode = nullptr;
459
    for (size_t b = 0; b < m_blocks.size(); ++b) {
473
    for (size_t b = 0; b < m_blocks.size(); ++b) {
460
        BasicBlock* block = m_blocks[b].get();
474
        BasicBlock* block = m_blocks[b].get();
461
        if (!block)
475
        if (!block)
Lines 496-502 void Graph::dump(PrintStream& out, DumpC Source/JavaScriptCore/dfg/DFGGraph.cpp_sec5
496
        for (size_t i = 0; i < block->size(); ++i) {
510
        for (size_t i = 0; i < block->size(); ++i) {
497
            dumpCodeOrigin(out, "", lastNode, block->at(i), context);
511
            dumpCodeOrigin(out, "", lastNode, block->at(i), context);
498
            dump(out, "", block->at(i), context);
512
            dump(out, "", block->at(i), context);
499
            lastNode = block->at(i);
500
        }
513
        }
501
        out.print("  States: ", block->cfaBranchDirection, ", ", block->cfaStructureClobberStateAtTail);
514
        out.print("  States: ", block->cfaBranchDirection, ", ", block->cfaStructureClobberStateAtTail);
502
        if (!block->cfaDidFinish)
515
        if (!block->cfaDidFinish)
- Source/JavaScriptCore/dfg/DFGGraph.h -1 / +1 lines
Lines 210-216 public: Source/JavaScriptCore/dfg/DFGGraph.h_sec1
210
210
211
    // Dump the code origin of the given node as a diff from the code origin of the
211
    // Dump the code origin of the given node as a diff from the code origin of the
212
    // preceding node. Returns true if anything was printed.
212
    // preceding node. Returns true if anything was printed.
213
    bool dumpCodeOrigin(PrintStream&, const char* prefix, Node* previousNode, Node* currentNode, DumpContext*);
213
    bool dumpCodeOrigin(PrintStream&, const char* prefix, Node*& previousNode, Node* currentNode, DumpContext*);
214
214
215
    AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
215
    AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
216
    {
216
    {
- Source/JavaScriptCore/dfg/DFGMayExit.cpp -4 / +39 lines
Lines 79-86 private: Source/JavaScriptCore/dfg/DFGMayExit.cpp_sec1
79
79
80
} // anonymous namespace
80
} // anonymous namespace
81
81
82
bool mayExit(Graph& graph, Node* node)
82
ExitMode mayExit(Graph& graph, Node* node)
83
{
83
{
84
    ExitMode result = DoesNotExit;
85
    
84
    switch (node->op()) {
86
    switch (node->op()) {
85
    // This is a carefully curated list of nodes that definitely do not exit. We try to be very
87
    // This is a carefully curated list of nodes that definitely do not exit. We try to be very
86
    // conservative when maintaining this list, because adding new node types to it doesn't
88
    // conservative when maintaining this list, because adding new node types to it doesn't
Lines 116-133 bool mayExit(Graph& graph, Node* node) Source/JavaScriptCore/dfg/DFGMayExit.cpp_sec2
116
    case DoubleRep:
118
    case DoubleRep:
117
    case Int52Rep:
119
    case Int52Rep:
118
    case ValueRep:
120
    case ValueRep:
121
    case ExtractOSREntryLocal:
122
    case LogicalNot:
123
    case NotifyWrite:
124
    case PutStructure:
119
        break;
125
        break;
120
        
126
127
    case StrCat:
128
        result = ExitsForExceptions;
129
        break;
130
121
    default:
131
    default:
122
        // If in doubt, return true.
132
        // If in doubt, return true.
123
        return true;
133
        return Exits;
124
    }
134
    }
125
135
126
    EdgeMayExit functor;
136
    EdgeMayExit functor;
127
    DFG_NODE_DO_TO_CHILDREN(graph, node, functor);
137
    DFG_NODE_DO_TO_CHILDREN(graph, node, functor);
128
    return functor.result();
138
    if (functor.result())
139
        result = Exits;
140
    
141
    return result;
129
}
142
}
130
143
131
} } // namespace JSC::DFG
144
} } // namespace JSC::DFG
132
145
146
namespace WTF {
147
148
using namespace JSC::DFG;
149
150
void printInternal(PrintStream& out, ExitMode mode)
151
{
152
    switch (mode) {
153
    case DoesNotExit:
154
        out.print("DoesNotExit");
155
        return;
156
    case ExitsForExceptions:
157
        out.print("ExitsForExceptions");
158
        return;
159
    case Exits:
160
        out.print("Exits");
161
        return;
162
    }
163
    RELEASE_ASSERT_NOT_REACHED();
164
}
165
166
} // namespace WTF
167
133
#endif // ENABLE(DFG_JIT)
168
#endif // ENABLE(DFG_JIT)
- Source/JavaScriptCore/dfg/DFGMayExit.h -2 / +40 lines
Lines 1-5 Source/JavaScriptCore/dfg/DFGMayExit.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
2
 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 36-45 struct Node; Source/JavaScriptCore/dfg/DFGMayExit.h_sec2
36
// A *very* conservative approximation of whether or not a node could possibly exit. Usually
36
// A *very* conservative approximation of whether or not a node could possibly exit. Usually
37
// returns true except in cases where we obviously don't expect an exit.
37
// returns true except in cases where we obviously don't expect an exit.
38
38
39
bool mayExit(Graph&, Node*);
39
enum ExitMode {
40
    // The node does not exit at all. This means that it's legal to eliminate the first store in a
41
    // program like:
42
    //
43
    // global = 1 // first store
44
    // DoesNotExit(); // let's assume that this also doesn't read "global"
45
    // global = 2 // second store
46
    //
47
    // It's legal to eliminate the first one since nobody will see it; the second store is always
48
    // executed right after.
49
    DoesNotExit,
50
51
    // The node will exit, but only by properly throwing exceptions. A proper exception throw will
52
    // divert execution to the matching op_catch and will not reexecute the exit origin. This means
53
    // that the store elimination optimization above would be illegal, but the following would be OK:
54
    //
55
    // SideEffect(..., exit: bc#42)
56
    // ExitsForExceptions(..., exit: #bc42, ExitInvalid)
57
    //
58
    // In particular, it's OK for a node that reports ExitsForExceptions to be executed in a context
59
    // where !Node::origin.exitOK. That's because this node will not exit in a manner that could lead
60
    // to the reexecution of SideEffect().
61
    ExitsForExceptions,
62
63
    // The node will exit to the exit origin. This means that we cannot do store elimination like for
64
    // DoesNotExit and also we cannot place this node in an ExitInvalid context, since this will exit
65
    // in a manner that will cause the reexecution of all previous operations within this exit origin.
66
    Exits
67
};
68
69
ExitMode mayExit(Graph&, Node*);
40
70
41
} } // namespace JSC::DFG
71
} } // namespace JSC::DFG
42
72
73
namespace WTF {
74
75
class PrintStream;
76
77
void printInternal(PrintStream&, JSC::DFG::ExitMode);
78
79
} // namespace WTF
80
43
#endif // ENABLE(DFG_JIT)
81
#endif // ENABLE(DFG_JIT)
44
82
45
#endif // DFGMayExit_h
83
#endif // DFGMayExit_h
- Source/JavaScriptCore/dfg/DFGMovHintRemovalPhase.cpp -1 / +1 lines
Lines 108-114 private: Source/JavaScriptCore/dfg/DFGMovHintRemovalPhase.cpp_sec1
108
                m_state.operand(node->unlinkedLocal()) = Epoch();
108
                m_state.operand(node->unlinkedLocal()) = Epoch();
109
            }
109
            }
110
            
110
            
111
            if (mayExit(m_graph, node))
111
            if (mayExit(m_graph, node) != DoesNotExit)
112
                currentEpoch.bump();
112
                currentEpoch.bump();
113
            
113
            
114
            if (nodeIndex) {
114
            if (nodeIndex) {
- Source/JavaScriptCore/dfg/DFGNodeOrigin.h -2 / +21 lines
Lines 1-5 Source/JavaScriptCore/dfg/DFGNodeOrigin.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2014 Apple Inc. All rights reserved.
2
 * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 29-37 Source/JavaScriptCore/dfg/DFGNodeOrigin.h_sec2
29
#if ENABLE(DFG_JIT)
29
#if ENABLE(DFG_JIT)
30
30
31
#include "CodeOrigin.h"
31
#include "CodeOrigin.h"
32
#include "DFGClobbersExitState.h"
32
33
33
namespace JSC { namespace DFG {
34
namespace JSC { namespace DFG {
34
35
36
class Graph;
37
struct Node;
38
35
struct NodeOrigin {
39
struct NodeOrigin {
36
    NodeOrigin() { }
40
    NodeOrigin() { }
37
    
41
    
Lines 48-54 struct NodeOrigin { Source/JavaScriptCore/dfg/DFGNodeOrigin.h_sec3
48
        return semantic.isSet();
52
        return semantic.isSet();
49
    }
53
    }
50
    
54
    
51
    NodeOrigin withSemantic(CodeOrigin semantic)
55
    NodeOrigin withSemantic(CodeOrigin semantic) const
52
    {
56
    {
53
        if (!isSet())
57
        if (!isSet())
54
            return NodeOrigin();
58
            return NodeOrigin();
Lines 58-64 struct NodeOrigin { Source/JavaScriptCore/dfg/DFGNodeOrigin.h_sec4
58
            result.semantic = semantic;
62
            result.semantic = semantic;
59
        return result;
63
        return result;
60
    }
64
    }
65
66
    NodeOrigin withInvalidExit() const
67
    {
68
        NodeOrigin result = *this;
69
        result.exitOK = false;
70
        return result;
71
    }
61
    
72
    
73
    NodeOrigin forInsertingAfter(Graph& graph, Node* node) const
74
    {
75
        NodeOrigin result = *this;
76
        if (result.exitOK && clobbersExitState(graph, node))
77
            result.exitOK = false;
78
        return result;
79
    }
80
62
    // Used for determining what bytecode this came from. This is important for
81
    // Used for determining what bytecode this came from. This is important for
63
    // debugging, exceptions, and even basic execution semantics.
82
    // debugging, exceptions, and even basic execution semantics.
64
    CodeOrigin semantic;
83
    CodeOrigin semantic;
- Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp -3 / +9 lines
Lines 1-5 Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 89-95 public: Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp_sec2
89
        // executionCount to use best judgement - but that seems unnecessary since we know for
89
        // executionCount to use best judgement - but that seems unnecessary since we know for
90
        // sure what the executionCount should be in this case.
90
        // sure what the executionCount should be in this case.
91
        BasicBlock* newRoot = insertionSet.insert(0, 1);
91
        BasicBlock* newRoot = insertionSet.insert(0, 1);
92
        NodeOrigin origin = target->at(0)->origin;
92
93
        // We'd really like to use an unset origin, but ThreadedCPS won't allow that.
94
        NodeOrigin origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), false);
93
        
95
        
94
        Vector<Node*> locals(baseline->m_numCalleeRegisters);
96
        Vector<Node*> locals(baseline->m_numCalleeRegisters);
95
        for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
97
        for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
Lines 106-111 public: Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp_sec3
106
                Edge(locals[local]));
108
                Edge(locals[local]));
107
        }
109
        }
108
110
111
        // Now use the origin of the target, since it's not OK to exit, and we will probably hoist
112
        // type checks to here.
113
        origin = target->at(0)->origin;
114
        
109
        for (int argument = 0; argument < baseline->numParameters(); ++argument) {
115
        for (int argument = 0; argument < baseline->numParameters(); ++argument) {
110
            Node* oldNode = target->variablesAtHead.argument(argument);
116
            Node* oldNode = target->variablesAtHead.argument(argument);
111
            if (!oldNode) {
117
            if (!oldNode) {
Lines 117-123 public: Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp_sec4
117
                OpInfo(oldNode->variableAccessData()));
123
                OpInfo(oldNode->variableAccessData()));
118
            m_graph.m_arguments[argument] = node;
124
            m_graph.m_arguments[argument] = node;
119
        }
125
        }
120
        
126
121
        for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
127
        for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
122
            Node* previousHead = target->variablesAtHead.local(local);
128
            Node* previousHead = target->variablesAtHead.local(local);
123
            if (!previousHead)
129
            if (!previousHead)
- Source/JavaScriptCore/dfg/DFGOSRExit.cpp -2 / +2 lines
Lines 36-49 Source/JavaScriptCore/dfg/DFGOSRExit.cpp_sec1
36
namespace JSC { namespace DFG {
36
namespace JSC { namespace DFG {
37
37
38
OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAValueProfile valueProfile, SpeculativeJIT* jit, unsigned streamIndex, unsigned recoveryIndex)
38
OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAValueProfile valueProfile, SpeculativeJIT* jit, unsigned streamIndex, unsigned recoveryIndex)
39
    : OSRExitBase(kind, jit->m_codeOriginForExitTarget, jit->m_codeOriginForExitProfile)
39
    : OSRExitBase(kind, jit->m_origin.forExit, jit->m_origin.semantic)
40
    , m_jsValueSource(jsValueSource)
40
    , m_jsValueSource(jsValueSource)
41
    , m_valueProfile(valueProfile)
41
    , m_valueProfile(valueProfile)
42
    , m_patchableCodeOffset(0)
42
    , m_patchableCodeOffset(0)
43
    , m_recoveryIndex(recoveryIndex)
43
    , m_recoveryIndex(recoveryIndex)
44
    , m_streamIndex(streamIndex)
44
    , m_streamIndex(streamIndex)
45
{
45
{
46
    ASSERT(m_codeOrigin.isSet());
46
    DFG_ASSERT(jit->m_jit.graph(), jit->m_currentNode, jit->m_origin.exitOK);
47
}
47
}
48
48
49
void OSRExit::setPatchableCodeOffset(MacroAssembler::PatchableJump check)
49
void OSRExit::setPatchableCodeOffset(MacroAssembler::PatchableJump check)
- Source/JavaScriptCore/dfg/DFGOSRExitBase.h -1 / +1 lines
Lines 1-5 Source/JavaScriptCore/dfg/DFGOSRExitBase.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2013 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
- Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp -4 / +5 lines
Lines 1697-1703 private: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp_sec1
1697
                    if (m_sinkCandidates.contains(node)) {
1697
                    if (m_sinkCandidates.contains(node)) {
1698
                        m_insertionSet.insert(
1698
                        m_insertionSet.insert(
1699
                            nodeIndex + 1,
1699
                            nodeIndex + 1,
1700
                            location.createHint(m_graph, node->origin, m_bottom));
1700
                            location.createHint(m_graph, node->origin.withInvalidExit(), m_bottom));
1701
                    }
1701
                    }
1702
                }
1702
                }
1703
1703
Lines 1750-1757 private: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp_sec2
1750
1750
1751
                        doLower = true;
1751
                        doLower = true;
1752
1752
1753
                        m_insertionSet.insert(nodeIndex + 1,
1753
                        m_insertionSet.insert(
1754
                            location.createHint(m_graph, node->origin, nodeValue));
1754
                            nodeIndex + 1,
1755
                            location.createHint(m_graph, node->origin.withInvalidExit(), nodeValue));
1755
                    },
1756
                    },
1756
                    [&] (PromotedHeapLocation location) -> Node* {
1757
                    [&] (PromotedHeapLocation location) -> Node* {
1757
                        return resolve(block, location);
1758
                        return resolve(block, location);
Lines 1905-1911 private: Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp_sec3
1905
                continue;
1906
                continue;
1906
1907
1907
            m_insertionSet.insert(
1908
            m_insertionSet.insert(
1908
                nodeIndex, entry.key.createHint(m_graph, origin, materialization));
1909
                nodeIndex, entry.key.createHint(m_graph, origin.withInvalidExit(), materialization));
1909
        }
1910
        }
1910
1911
1911
        for (unsigned i = availability.m_locals.size(); i--;) {
1912
        for (unsigned i = availability.m_locals.size(); i--;) {
- Source/JavaScriptCore/dfg/DFGPhantomInsertionPhase.cpp -2 / +5 lines
Lines 123-129 private: Source/JavaScriptCore/dfg/DFGPhantomInsertionPhase.cpp_sec1
123
                break;
123
                break;
124
            }
124
            }
125
            
125
            
126
            if (mayExit(m_graph, node)) {
126
            if (mayExit(m_graph, node) != DoesNotExit) {
127
                currentEpoch.bump();
127
                currentEpoch.bump();
128
                lastExitingIndex = nodeIndex;
128
                lastExitingIndex = nodeIndex;
129
            }
129
            }
Lines 160-169 private: Source/JavaScriptCore/dfg/DFGPhantomInsertionPhase.cpp_sec2
160
                    // We have exact ref counts, so creating a new use means that we have to
160
                    // We have exact ref counts, so creating a new use means that we have to
161
                    // increment the ref count.
161
                    // increment the ref count.
162
                    killedNode->postfixRef();
162
                    killedNode->postfixRef();
163
164
                    Node* lastExitingNode = block->at(lastExitingIndex);
163
                    
165
                    
164
                    m_insertionSet.insertNode(
166
                    m_insertionSet.insertNode(
165
                        lastExitingIndex + 1, SpecNone, Phantom,
167
                        lastExitingIndex + 1, SpecNone, Phantom,
166
                        block->at(lastExitingIndex)->origin, killedNode->defaultEdge());
168
                        lastExitingNode->origin.forInsertingAfter(m_graph, lastExitingNode),
169
                        killedNode->defaultEdge());
167
            });
170
            });
168
        }
171
        }
169
        
172
        
- Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp -1 / +6 lines
Lines 271-276 public: Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp_sec1
271
                    m_insertionSet.insertNode(
271
                    m_insertionSet.insertNode(
272
                        nodeIndex, SpecNone, KillStack, node->origin,
272
                        nodeIndex, SpecNone, KillStack, node->origin,
273
                        OpInfo(node->unlinkedLocal().offset()));
273
                        OpInfo(node->unlinkedLocal().offset()));
274
                    node->origin.exitOK = false; // KillStack clobbers exit.
274
                    break;
275
                    break;
275
                }
276
                }
276
                    
277
                    
Lines 346-352 public: Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp_sec2
346
                    SSACalculator::Variable* ssaVariable = phiDef->variable();
347
                    SSACalculator::Variable* ssaVariable = phiDef->variable();
347
                    VariableAccessData* variable = m_variableForSSAIndex[ssaVariable->index()];
348
                    VariableAccessData* variable = m_variableForSSAIndex[ssaVariable->index()];
348
                    FlushFormat format = variable->flushFormat();
349
                    FlushFormat format = variable->flushFormat();
349
                    UseKind useKind = useKindFor(format);
350
351
                    // We can use an unchecked use kind because the SetLocal was turned into a Check.
352
                    // We have to use an unchecked use because at least sometimes, the end of the block
353
                    // is not exitOK.
354
                    UseKind useKind = uncheckedUseKindFor(format);
350
                    
355
                    
351
                    m_insertionSet.insertNode(
356
                    m_insertionSet.insertNode(
352
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
357
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp -26 / +8 lines
Lines 61-67 SpeculativeJIT::SpeculativeJIT(JITCompil Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec1
61
    , m_interpreter(m_jit.graph(), m_state)
61
    , m_interpreter(m_jit.graph(), m_state)
62
    , m_stream(&jit.jitCode()->variableEventStream)
62
    , m_stream(&jit.jitCode()->variableEventStream)
63
    , m_minifiedGraph(&jit.jitCode()->minifiedDFG)
63
    , m_minifiedGraph(&jit.jitCode()->minifiedDFG)
64
    , m_isCheckingArgumentTypes(false)
65
{
64
{
66
}
65
}
67
66
Lines 196-202 void SpeculativeJIT::speculationCheck(Ex Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec2
196
{
195
{
197
    if (!m_compileOkay)
196
    if (!m_compileOkay)
198
        return;
197
        return;
199
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
200
    JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
198
    JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
201
    if (fuzzJump.isSet()) {
199
    if (fuzzJump.isSet()) {
202
        JITCompiler::JumpList jumpsToFail;
200
        JITCompiler::JumpList jumpsToFail;
Lines 212-218 void SpeculativeJIT::speculationCheck(Ex Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec3
212
{
210
{
213
    if (!m_compileOkay)
211
    if (!m_compileOkay)
214
        return;
212
        return;
215
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
216
    JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
213
    JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
217
    if (fuzzJump.isSet()) {
214
    if (fuzzJump.isSet()) {
218
        JITCompiler::JumpList myJumpsToFail;
215
        JITCompiler::JumpList myJumpsToFail;
Lines 228-234 OSRExitJumpPlaceholder SpeculativeJIT::s Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec4
228
{
225
{
229
    if (!m_compileOkay)
226
    if (!m_compileOkay)
230
        return OSRExitJumpPlaceholder();
227
        return OSRExitJumpPlaceholder();
231
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
232
    unsigned index = m_jit.jitCode()->osrExit.size();
228
    unsigned index = m_jit.jitCode()->osrExit.size();
233
    m_jit.appendExitInfo();
229
    m_jit.appendExitInfo();
234
    m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
230
    m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
Lines 237-255 OSRExitJumpPlaceholder SpeculativeJIT::s Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec5
237
233
238
OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
234
OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
239
{
235
{
240
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
241
    return speculationCheck(kind, jsValueSource, nodeUse.node());
236
    return speculationCheck(kind, jsValueSource, nodeUse.node());
242
}
237
}
243
238
244
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
239
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
245
{
240
{
246
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
247
    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
241
    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
248
}
242
}
249
243
250
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
244
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
251
{
245
{
252
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
253
    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
246
    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
254
}
247
}
255
248
Lines 257-263 void SpeculativeJIT::speculationCheck(Ex Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec6
257
{
250
{
258
    if (!m_compileOkay)
251
    if (!m_compileOkay)
259
        return;
252
        return;
260
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
261
    unsigned recoveryIndex = m_jit.jitCode()->appendSpeculationRecovery(recovery);
253
    unsigned recoveryIndex = m_jit.jitCode()->appendSpeculationRecovery(recovery);
262
    m_jit.appendExitInfo(jumpToFail);
254
    m_jit.appendExitInfo(jumpToFail);
263
    m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size(), recoveryIndex));
255
    m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size(), recoveryIndex));
Lines 265-271 void SpeculativeJIT::speculationCheck(Ex Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec7
265
257
266
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
258
void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
267
{
259
{
268
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
269
    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
260
    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
270
}
261
}
271
262
Lines 273-279 void SpeculativeJIT::emitInvalidationPoi Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec8
273
{
264
{
274
    if (!m_compileOkay)
265
    if (!m_compileOkay)
275
        return;
266
        return;
276
    ASSERT(m_canExit);
277
    OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList());
267
    OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList());
278
    m_jit.jitCode()->appendOSRExit(OSRExit(
268
    m_jit.jitCode()->appendOSRExit(OSRExit(
279
        UncountableInvalidation, JSValueSource(),
269
        UncountableInvalidation, JSValueSource(),
Lines 286-292 void SpeculativeJIT::emitInvalidationPoi Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec9
286
276
287
void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
277
void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
288
{
278
{
289
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
290
    if (!m_compileOkay)
279
    if (!m_compileOkay)
291
        return;
280
        return;
292
    speculationCheck(kind, jsValueRegs, node, m_jit.jump());
281
    speculationCheck(kind, jsValueRegs, node, m_jit.jump());
Lines 297-303 void SpeculativeJIT::terminateSpeculativ Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec10
297
286
298
void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
287
void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
299
{
288
{
300
    ASSERT(m_isCheckingArgumentTypes || m_canExit);
301
    terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
289
    terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
302
}
290
}
303
291
Lines 1467-1475 void SpeculativeJIT::compileCurrentBlock Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec11
1467
                variable->machineLocal(),
1455
                variable->machineLocal(),
1468
                format));
1456
                format));
1469
    }
1457
    }
1470
    
1458
1471
    m_codeOriginForExitTarget = CodeOrigin();
1459
    m_origin = NodeOrigin();
1472
    m_codeOriginForExitProfile = CodeOrigin();
1473
    
1460
    
1474
    for (m_indexInBlock = 0; m_indexInBlock < m_block->size(); ++m_indexInBlock) {
1461
    for (m_indexInBlock = 0; m_indexInBlock < m_block->size(); ++m_indexInBlock) {
1475
        m_currentNode = m_block->at(m_indexInBlock);
1462
        m_currentNode = m_block->at(m_indexInBlock);
Lines 1481-1495 void SpeculativeJIT::compileCurrentBlock Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec12
1481
            return;
1468
            return;
1482
        }
1469
        }
1483
1470
1484
        if (ASSERT_DISABLED)
1485
            m_canExit = true; // Essentially disable the assertions.
1486
        else
1487
            m_canExit = mayExit(m_jit.graph(), m_currentNode);
1488
        
1489
        m_interpreter.startExecuting();
1471
        m_interpreter.startExecuting();
1490
        m_jit.setForNode(m_currentNode);
1472
        m_jit.setForNode(m_currentNode);
1491
        m_codeOriginForExitTarget = m_currentNode->origin.forExit;
1473
        m_origin = m_currentNode->origin;
1492
        m_codeOriginForExitProfile = m_currentNode->origin.semantic;
1474
        if (validationEnabled())
1475
            m_origin.exitOK &= mayExit(m_jit.graph(), m_currentNode) == Exits;
1493
        m_lastGeneratedNode = m_currentNode->op();
1476
        m_lastGeneratedNode = m_currentNode->op();
1494
        
1477
        
1495
        ASSERT(m_currentNode->shouldGenerate());
1478
        ASSERT(m_currentNode->shouldGenerate());
Lines 1536-1544 void SpeculativeJIT::compileCurrentBlock Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec13
1536
void SpeculativeJIT::checkArgumentTypes()
1519
void SpeculativeJIT::checkArgumentTypes()
1537
{
1520
{
1538
    ASSERT(!m_currentNode);
1521
    ASSERT(!m_currentNode);
1539
    m_isCheckingArgumentTypes = true;
1522
    m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
1540
    m_codeOriginForExitTarget = CodeOrigin(0);
1541
    m_codeOriginForExitProfile = CodeOrigin(0);
1542
1523
1543
    for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1524
    for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1544
        Node* node = m_jit.graph().m_arguments[i];
1525
        Node* node = m_jit.graph().m_arguments[i];
Lines 1601-1607 void SpeculativeJIT::checkArgumentTypes( Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp_sec14
1601
        }
1582
        }
1602
#endif
1583
#endif
1603
    }
1584
    }
1604
    m_isCheckingArgumentTypes = false;
1585
1586
    m_origin = NodeOrigin();
1605
}
1587
}
1606
1588
1607
bool SpeculativeJIT::compile()
1589
bool SpeculativeJIT::compile()
- Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h -5 / +1 lines
Lines 2458-2464 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec1
2458
    BasicBlock* m_block;
2458
    BasicBlock* m_block;
2459
    Node* m_currentNode;
2459
    Node* m_currentNode;
2460
    NodeType m_lastGeneratedNode;
2460
    NodeType m_lastGeneratedNode;
2461
    bool m_canExit;
2462
    unsigned m_indexInBlock;
2461
    unsigned m_indexInBlock;
2463
    // Virtual and physical register maps.
2462
    // Virtual and physical register maps.
2464
    Vector<GenerationInfo, 32> m_generationInfo;
2463
    Vector<GenerationInfo, 32> m_generationInfo;
Lines 2479-2486 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec2
2479
    };
2478
    };
2480
    Vector<BranchRecord, 8> m_branches;
2479
    Vector<BranchRecord, 8> m_branches;
2481
2480
2482
    CodeOrigin m_codeOriginForExitTarget;
2481
    NodeOrigin m_origin;
2483
    CodeOrigin m_codeOriginForExitProfile;
2484
    
2482
    
2485
    InPlaceAbstractState m_state;
2483
    InPlaceAbstractState m_state;
2486
    AbstractInterpreter<InPlaceAbstractState> m_interpreter;
2484
    AbstractInterpreter<InPlaceAbstractState> m_interpreter;
Lines 2488-2495 public: Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h_sec3
2488
    VariableEventStream* m_stream;
2486
    VariableEventStream* m_stream;
2489
    MinifiedGraph* m_minifiedGraph;
2487
    MinifiedGraph* m_minifiedGraph;
2490
    
2488
    
2491
    bool m_isCheckingArgumentTypes;
2492
    
2493
    Vector<std::unique_ptr<SlowPathGenerator>, 8> m_slowPathGenerators;
2489
    Vector<std::unique_ptr<SlowPathGenerator>, 8> m_slowPathGenerators;
2494
    Vector<SilentRegisterSavePlan> m_plans;
2490
    Vector<SilentRegisterSavePlan> m_plans;
2495
};
2491
};
- Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp -2 / +12 lines
Lines 108-115 public: Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp_sec1
108
            BasicBlock* block = m_graph.block(blockIndex);
108
            BasicBlock* block = m_graph.block(blockIndex);
109
            if (!block)
109
            if (!block)
110
                continue;
110
                continue;
111
            unsigned indexForChecks = UINT_MAX;
112
            NodeOrigin originForChecks;
111
            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
113
            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
112
                Node* node = block->at(indexInBlock);
114
                Node* node = block->at(indexInBlock);
115
                
116
                if (node->origin.exitOK) {
117
                    indexForChecks = indexInBlock;
118
                    originForChecks = node->origin;
119
                }
120
                
113
                // Be careful not to use 'node' after appending to the graph. In those switch
121
                // Be careful not to use 'node' after appending to the graph. In those switch
114
                // cases where we need to append, we first carefully extract everything we need
122
                // cases where we need to append, we first carefully extract everything we need
115
                // from the node, before doing any appending.
123
                // from the node, before doing any appending.
Lines 170-182 public: Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp_sec2
170
                    
178
                    
171
                    if (iter->value.m_structure) {
179
                    if (iter->value.m_structure) {
172
                        insertionSet.insertNode(
180
                        insertionSet.insertNode(
173
                            indexInBlock, SpecNone, CheckStructure, origin,
181
                            indexForChecks, SpecNone, CheckStructure,
182
                            originForChecks.withSemantic(origin.semantic),
174
                            OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
183
                            OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
175
                            Edge(child1.node(), CellUse));
184
                            Edge(child1.node(), CellUse));
176
                    } else if (iter->value.m_arrayModeIsValid) {
185
                    } else if (iter->value.m_arrayModeIsValid) {
177
                        ASSERT(iter->value.m_arrayModeHoistingOkay);
186
                        ASSERT(iter->value.m_arrayModeHoistingOkay);
178
                        insertionSet.insertNode(
187
                        insertionSet.insertNode(
179
                            indexInBlock, SpecNone, CheckArray, origin,
188
                            indexForChecks, SpecNone, CheckArray,
189
                            originForChecks.withSemantic(origin.semantic),
180
                            OpInfo(iter->value.m_arrayMode.asWord()),
190
                            OpInfo(iter->value.m_arrayMode.asWord()),
181
                            Edge(child1.node(), CellUse));
191
                            Edge(child1.node(), CellUse));
182
                    } else
192
                    } else
- Source/JavaScriptCore/dfg/DFGValidate.cpp -3 / +22 lines
Lines 29-34 Source/JavaScriptCore/dfg/DFGValidate.cpp_sec1
29
#if ENABLE(DFG_JIT)
29
#if ENABLE(DFG_JIT)
30
30
31
#include "CodeBlockWithJITType.h"
31
#include "CodeBlockWithJITType.h"
32
#include "DFGClobbersExitState.h"
32
#include "DFGMayExit.h"
33
#include "DFGMayExit.h"
33
#include "JSCInlines.h"
34
#include "JSCInlines.h"
34
#include <wtf/Assertions.h>
35
#include <wtf/Assertions.h>
Lines 185-197 public: Source/JavaScriptCore/dfg/DFGValidate.cpp_sec2
185
            
186
            
186
            for (size_t i = 0; i < block->size(); ++i) {
187
            for (size_t i = 0; i < block->size(); ++i) {
187
                Node* node = block->at(i);
188
                Node* node = block->at(i);
188
                
189
189
                VALIDATE((node), node->origin.semantic.isSet() == node->origin.forExit.isSet());
190
                VALIDATE((node), node->origin.semantic.isSet() == node->origin.forExit.isSet());
190
                VALIDATE((node), !mayExit(m_graph, node) || node->origin.forExit.isSet());
191
                VALIDATE((node), !(!node->origin.forExit.isSet() && node->origin.exitOK));
192
                VALIDATE((node), !(mayExit(m_graph, node) == Exits && !node->origin.exitOK));
193
194
                if (i) {
195
                    Node* previousNode = block->at(i - 1);
196
                    VALIDATE(
197
                        (node),
198
                        !clobbersExitState(m_graph, previousNode)
199
                        || !node->origin.exitOK
200
                        || node->origin.forExit != previousNode->origin.forExit);
201
                    VALIDATE(
202
                        (node),
203
                        !(!previousNode->origin.exitOK && node->origin.exitOK)
204
                        || node->origin.forExit != previousNode->origin.forExit);
205
                }
206
                
191
                VALIDATE((node), !node->hasStructure() || !!node->structure());
207
                VALIDATE((node), !node->hasStructure() || !!node->structure());
192
                VALIDATE((node), !node->hasCellOperand() || node->cellOperand()->value().isCell());
208
                VALIDATE((node), !node->hasCellOperand() || node->cellOperand()->value().isCell());
193
                VALIDATE((node), !node->hasCellOperand() || !!node->cellOperand()->value());
209
                VALIDATE((node), !node->hasCellOperand() || !!node->cellOperand()->value());
194
                 
210
                
195
                if (!(node->flags() & NodeHasVarArgs)) {
211
                if (!(node->flags() & NodeHasVarArgs)) {
196
                    if (!node->child2())
212
                    if (!node->child2())
197
                        VALIDATE((node), !node->child3());
213
                        VALIDATE((node), !node->child3());
Lines 210-219 public: Source/JavaScriptCore/dfg/DFGValidate.cpp_sec3
210
                    switch (node->child1().useKind()) {
226
                    switch (node->child1().useKind()) {
211
                    case UntypedUse:
227
                    case UntypedUse:
212
                    case CellUse:
228
                    case CellUse:
229
                    case KnownCellUse:
213
                    case Int32Use:
230
                    case Int32Use:
231
                    case KnownInt32Use:
214
                    case Int52RepUse:
232
                    case Int52RepUse:
215
                    case DoubleRepUse:
233
                    case DoubleRepUse:
216
                    case BooleanUse:
234
                    case BooleanUse:
235
                    case KnownBooleanUse:
217
                        break;
236
                        break;
218
                    default:
237
                    default:
219
                        VALIDATE((node), !"Bad use kind");
238
                        VALIDATE((node), !"Bad use kind");
- Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp -9 / +13 lines
Lines 227-235 public: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
227
            availabilityMap().m_locals.argument(i) =
227
            availabilityMap().m_locals.argument(i) =
228
                Availability(FlushedAt(FlushedJSValue, virtualRegisterForArgument(i)));
228
                Availability(FlushedAt(FlushedJSValue, virtualRegisterForArgument(i)));
229
        }
229
        }
230
        m_codeOriginForExitTarget = CodeOrigin(0);
231
        m_codeOriginForExitProfile = CodeOrigin(0);
232
        m_node = nullptr;
230
        m_node = nullptr;
231
        m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
233
        for (unsigned i = codeBlock()->numParameters(); i--;) {
232
        for (unsigned i = codeBlock()->numParameters(); i--;) {
234
            Node* node = m_graph.m_arguments[i];
233
            Node* node = m_graph.m_arguments[i];
235
            VirtualRegister operand = virtualRegisterForArgument(i);
234
            VirtualRegister operand = virtualRegisterForArgument(i);
Lines 393-400 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
393
        }
392
        }
394
        
393
        
395
        m_node = m_highBlock->at(nodeIndex);
394
        m_node = m_highBlock->at(nodeIndex);
396
        m_codeOriginForExitProfile = m_node->origin.semantic;
395
        m_origin = m_node->origin;
397
        m_codeOriginForExitTarget = m_node->origin.forExit;
398
        
396
        
399
        if (verboseCompilationEnabled())
397
        if (verboseCompilationEnabled())
400
            dataLog("Lowering ", m_node, "\n");
398
            dataLog("Lowering ", m_node, "\n");
Lines 878-892 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
878
            m_out.set(lowDouble(m_node->child1()), destination);
876
            m_out.set(lowDouble(m_node->child1()), destination);
879
            break;
877
            break;
880
        case Int32Use:
878
        case Int32Use:
879
        case KnownInt32Use:
881
            m_out.set(lowInt32(m_node->child1()), destination);
880
            m_out.set(lowInt32(m_node->child1()), destination);
882
            break;
881
            break;
883
        case Int52RepUse:
882
        case Int52RepUse:
884
            m_out.set(lowInt52(m_node->child1()), destination);
883
            m_out.set(lowInt52(m_node->child1()), destination);
885
            break;
884
            break;
886
        case BooleanUse:
885
        case BooleanUse:
886
        case KnownBooleanUse:
887
            m_out.set(lowBoolean(m_node->child1()), destination);
887
            m_out.set(lowBoolean(m_node->child1()), destination);
888
            break;
888
            break;
889
        case CellUse:
889
        case CellUse:
890
        case KnownCellUse:
890
            m_out.set(lowCell(m_node->child1()), destination);
891
            m_out.set(lowCell(m_node->child1()), destination);
891
            break;
892
            break;
892
        case UntypedUse:
893
        case UntypedUse:
Lines 4752-4761 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
4752
    {
4753
    {
4753
        if (verboseCompilationEnabled())
4754
        if (verboseCompilationEnabled())
4754
            dataLog("    Invalidation point with availability: ", availabilityMap(), "\n");
4755
            dataLog("    Invalidation point with availability: ", availabilityMap(), "\n");
4756
4757
        DFG_ASSERT(m_graph, m_node, m_origin.exitOK);
4755
        
4758
        
4756
        m_ftlState.jitCode->osrExit.append(OSRExit(
4759
        m_ftlState.jitCode->osrExit.append(OSRExit(
4757
            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
4760
            UncountableInvalidation, InvalidValueFormat, MethodOfGettingAValueProfile(),
4758
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
4761
            m_origin.forExit, m_origin.semantic,
4759
            availabilityMap().m_locals.numberOfArguments(),
4762
            availabilityMap().m_locals.numberOfArguments(),
4760
            availabilityMap().m_locals.numberOfLocals()));
4763
            availabilityMap().m_locals.numberOfLocals()));
4761
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
4764
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
Lines 8093-8098 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
8093
            if (!m_availableRecoveries.isEmpty())
8096
            if (!m_availableRecoveries.isEmpty())
8094
                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
8097
                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
8095
        }
8098
        }
8099
8100
        DFG_ASSERT(m_graph, m_node, m_origin.exitOK);
8096
        
8101
        
8097
        if (doOSRExitFuzzing()) {
8102
        if (doOSRExitFuzzing()) {
8098
            LValue numberOfFuzzChecks = m_out.add(
8103
            LValue numberOfFuzzChecks = m_out.add(
Lines 8117-8123 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
8117
        
8122
        
8118
        m_ftlState.jitCode->osrExit.append(OSRExit(
8123
        m_ftlState.jitCode->osrExit.append(OSRExit(
8119
            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
8124
            kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue),
8120
            m_codeOriginForExitTarget, m_codeOriginForExitProfile,
8125
            m_origin.forExit, m_origin.semantic,
8121
            availabilityMap().m_locals.numberOfArguments(),
8126
            availabilityMap().m_locals.numberOfArguments(),
8122
            availabilityMap().m_locals.numberOfLocals()));
8127
            availabilityMap().m_locals.numberOfLocals()));
8123
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
8128
        m_ftlState.finalizer->osrExit.append(OSRExitCompilationInfo());
Lines 8612-8620 private: Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
8612
    BasicBlock* m_highBlock;
8617
    BasicBlock* m_highBlock;
8613
    BasicBlock* m_nextHighBlock;
8618
    BasicBlock* m_nextHighBlock;
8614
    LBasicBlock m_nextLowBlock;
8619
    LBasicBlock m_nextLowBlock;
8615
    
8620
8616
    CodeOrigin m_codeOriginForExitTarget;
8621
    NodeOrigin m_origin;
8617
    CodeOrigin m_codeOriginForExitProfile;
8618
    unsigned m_nodeIndex;
8622
    unsigned m_nodeIndex;
8619
    Node* m_node;
8623
    Node* m_node;
8620
    
8624
    
- Source/WTF/wtf/Insertion.h -1 / +3 lines
Lines 1-5 Source/WTF/wtf/Insertion.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2013 Apple Inc. All rights reserved.
2
 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 59-66 void executeInsertions(TargetVectorType& Source/WTF/wtf/Insertion.h_sec2
59
        return;
59
        return;
60
    target.grow(target.size() + insertions.size());
60
    target.grow(target.size() + insertions.size());
61
    size_t lastIndex = target.size();
61
    size_t lastIndex = target.size();
62
    size_t originalTargetSize = target.size();
62
    for (size_t indexInInsertions = insertions.size(); indexInInsertions--;) {
63
    for (size_t indexInInsertions = insertions.size(); indexInInsertions--;) {
63
        ASSERT(!indexInInsertions || insertions[indexInInsertions].index() >= insertions[indexInInsertions - 1].index());
64
        ASSERT(!indexInInsertions || insertions[indexInInsertions].index() >= insertions[indexInInsertions - 1].index());
65
        ASSERT_UNUSED(originalTargetSize, insertions[indexInInsertions].index() < originalTargetSize);
64
        size_t firstIndex = insertions[indexInInsertions].index() + indexInInsertions;
66
        size_t firstIndex = insertions[indexInInsertions].index() + indexInInsertions;
65
        size_t indexOffset = indexInInsertions + 1;
67
        size_t indexOffset = indexInInsertions + 1;
66
        for (size_t i = lastIndex; --i > firstIndex;)
68
        for (size_t i = lastIndex; --i > firstIndex;)

Return to Bug 145204