Rename StructureCheckHoistingPhase to TypeCheckHoistingPhase
authormhahnenberg@apple.com <mhahnenberg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 May 2013 23:15:07 +0000 (23:15 +0000)
committermhahnenberg@apple.com <mhahnenberg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 10 May 2013 23:15:07 +0000 (23:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=115938

We're going to add some more types of check hoisting soon, so let's have the right name here.

Rubber stamped by Filip Pizlo.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGStructureCheckHoistingPhase.cpp: Removed.
* dfg/DFGStructureCheckHoistingPhase.h: Removed.
* dfg/DFGTypeCheckHoistingPhase.cpp: Copied from Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp.
(JSC::DFG::TypeCheckHoistingPhase::TypeCheckHoistingPhase):
(JSC::DFG::performTypeCheckHoisting):
* dfg/DFGTypeCheckHoistingPhase.h: Copied from Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@149911 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.h [new file with mode: 0644]

index 9a0c1ee..fe97b6d 100644 (file)
@@ -112,7 +112,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGSpeculativeJIT.cpp
     dfg/DFGSpeculativeJIT32_64.cpp
     dfg/DFGSpeculativeJIT64.cpp
-    dfg/DFGStructureCheckHoistingPhase.cpp
+    dfg/DFGTypeCheckHoistingPhase.cpp
     dfg/DFGThunks.cpp
     dfg/DFGUnificationPhase.cpp
     dfg/DFGUseKind.cpp
index 072e9b2..9c41dc4 100644 (file)
@@ -1,3 +1,25 @@
+2013-05-10  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        Rename StructureCheckHoistingPhase to TypeCheckHoistingPhase
+        https://bugs.webkit.org/show_bug.cgi?id=115938
+
+        We're going to add some more types of check hoisting soon, so let's have the right name here.
+
+        Rubber stamped by Filip Pizlo.
+        
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Target.pri:
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compile):
+        * dfg/DFGStructureCheckHoistingPhase.cpp: Removed.
+        * dfg/DFGStructureCheckHoistingPhase.h: Removed.
+        * dfg/DFGTypeCheckHoistingPhase.cpp: Copied from Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp.
+        (JSC::DFG::TypeCheckHoistingPhase::TypeCheckHoistingPhase):
+        (JSC::DFG::performTypeCheckHoisting):
+        * dfg/DFGTypeCheckHoistingPhase.h: Copied from Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h.
+
 2013-05-09  Christophe Dumez  <ch.dumez@sisa.samsung.com>
 
         Unreviewed build fix after r149836.
index 1021f09..1bd4767 100644 (file)
@@ -270,8 +270,8 @@ javascriptcore_sources += \
        Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \
        Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
        Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h \
-       Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp \
-       Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h \
+       Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp \
+       Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.h \
        Source/JavaScriptCore/dfg/DFGThunks.cpp \
        Source/JavaScriptCore/dfg/DFGThunks.h \
        Source/JavaScriptCore/dfg/DFGUnificationPhase.cpp \
index 31fca36..580aa1e 100644 (file)
                0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; };
-               0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */; };
+               0F63943F15C75F19006A597C /* DFGTypeCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGTypeCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGTypeCheckHoistingPhase.cpp */; };
                0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63945115D07051006A597C /* ArrayProfile.cpp */; };
                0F63945515D07057006A597C /* ArrayProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63945215D07051006A597C /* ArrayProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; };
                0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; };
                0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; };
-               0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureCheckHoistingPhase.cpp; path = dfg/DFGStructureCheckHoistingPhase.cpp; sourceTree = "<group>"; };
-               0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureCheckHoistingPhase.h; path = dfg/DFGStructureCheckHoistingPhase.h; sourceTree = "<group>"; };
+               0F63943C15C75F14006A597C /* DFGTypeCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGTypeCheckHoistingPhase.cpp; path = dfg/DFGTypeCheckHoistingPhase.cpp; sourceTree = "<group>"; };
+               0F63943D15C75F14006A597C /* DFGTypeCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGTypeCheckHoistingPhase.h; path = dfg/DFGTypeCheckHoistingPhase.h; sourceTree = "<group>"; };
                0F63945115D07051006A597C /* ArrayProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayProfile.cpp; sourceTree = "<group>"; };
                0F63945215D07051006A597C /* ArrayProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayProfile.h; sourceTree = "<group>"; };
                0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureAbstractValue.h; path = dfg/DFGStructureAbstractValue.h; sourceTree = "<group>"; };
                };
                0FF4272E158EBCCE004CB9FF /* disassembler */ = {
                        isa = PBXGroup;
-                       children = (                    
+                       children = (
                                65C028591717966800351E35 /* ARMv7 */,
                                0FF42733158EBD64004CB9FF /* udis86 */,
                                65C0284F171795E200351E35 /* ARMv7Disassembler.cpp */,
                                86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */,
                                86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */,
                                0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */,
-                               0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */,
-                               0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */,
+                               0F63943C15C75F14006A597C /* DFGTypeCheckHoistingPhase.cpp */,
+                               0F63943D15C75F14006A597C /* DFGTypeCheckHoistingPhase.h */,
                                0FC0979F146B28C700CF2442 /* DFGThunks.cpp */,
                                0FC097A0146B28C700CF2442 /* DFGThunks.h */,
                                0FBE0F6F16C1DB010082C5E8 /* DFGUnificationPhase.cpp */,
                                0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */,
                                86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */,
                                0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
-                               0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */,
+                               0F63943F15C75F19006A597C /* DFGTypeCheckHoistingPhase.h in Headers */,
                                0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */,
                                0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */,
                                0F2BDC471522802500CD8910 /* DFGValueRecoveryOverride.h in Headers */,
                                86EC9DD21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp in Sources */,
                                86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */,
                                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
-                               0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */,
+                               0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */,
                                0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
                                0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */,
                                0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */,
index f132681..266ed41 100644 (file)
@@ -151,7 +151,7 @@ SOURCES += \
     dfg/DFGSpeculativeJIT.cpp \
     dfg/DFGSpeculativeJIT32_64.cpp \
     dfg/DFGSpeculativeJIT64.cpp \
-    dfg/DFGStructureCheckHoistingPhase.cpp \
+    dfg/DFGTypeCheckHoistingPhase.cpp \
     dfg/DFGThunks.cpp \
     dfg/DFGUnificationPhase.cpp \
     dfg/DFGUseKind.cpp \
index 1e75c78..09649cc 100644 (file)
@@ -45,7 +45,7 @@
 #include "DFGJITCompiler.h"
 #include "DFGPredictionInjectionPhase.h"
 #include "DFGPredictionPropagationPhase.h"
-#include "DFGStructureCheckHoistingPhase.h"
+#include "DFGTypeCheckHoistingPhase.h"
 #include "DFGUnificationPhase.h"
 #include "DFGValidate.h"
 #include "DFGVirtualRegisterAllocationPhase.h"
@@ -129,7 +129,7 @@ inline bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
     performBackwardsPropagation(dfg);
     performPredictionPropagation(dfg);
     performFixup(dfg);
-    performStructureCheckHoisting(dfg);
+    performTypeCheckHoisting(dfg);
     
     dfg.m_fixpointState = FixpointNotConverged;
 
index 85e0d0b..e69de29 100644 (file)
@@ -1,392 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "DFGStructureCheckHoistingPhase.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGBasicBlock.h"
-#include "DFGGraph.h"
-#include "DFGInsertionSet.h"
-#include "DFGPhase.h"
-#include "DFGVariableAccessDataDump.h"
-#include "Operations.h"
-#include <wtf/HashMap.h>
-
-namespace JSC { namespace DFG {
-
-enum CheckBallot { VoteOther, VoteStructureCheck };
-
-class StructureCheckHoistingPhase : public Phase {
-public:
-    StructureCheckHoistingPhase(Graph& graph)
-        : Phase(graph, "structure check hoisting")
-    {
-    }
-    
-    bool run()
-    {
-        ASSERT(m_graph.m_form == ThreadedCPS);
-        
-        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
-            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
-            if (!variable->isRoot())
-                continue;
-            variable->clearVotes();
-        }
-        
-        // Identify the set of variables that are always subject to the same structure
-        // checks. For now, only consider monomorphic structure checks (one structure).
-        
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block)
-                continue;
-            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
-                Node* node = block->at(indexInBlock);
-                switch (node->op()) {
-                case CheckStructure:
-                case StructureTransitionWatchpoint: {
-                    Node* child = node->child1().node();
-                    if (child->op() != GetLocal)
-                        break;
-                    VariableAccessData* variable = child->variableAccessData();
-                    variable->vote(VoteStructureCheck);
-                    if (!shouldConsiderForHoisting(variable))
-                        break;
-                    noticeStructureCheck(variable, node->structureSet());
-                    break;
-                }
-                    
-                case ForwardCheckStructure:
-                case ForwardStructureTransitionWatchpoint:
-                    // We currently rely on the fact that we're the only ones who would
-                    // insert this node.
-                    RELEASE_ASSERT_NOT_REACHED();
-                    break;
-                    
-                case GetByOffset:
-                case PutByOffset:
-                case PutStructure:
-                case AllocatePropertyStorage:
-                case ReallocatePropertyStorage:
-                case GetButterfly:
-                case GetByVal:
-                case PutByVal:
-                case PutByValAlias:
-                case GetArrayLength:
-                case CheckArray:
-                case GetIndexedPropertyStorage:
-                case Phantom:
-                    // Don't count these uses.
-                    break;
-                    
-                case ArrayifyToStructure:
-                case Arrayify:
-                    if (node->arrayMode().conversion() == Array::RageConvert) {
-                        // Rage conversion changes structures. We should avoid tying to do
-                        // any kind of hoisting when rage conversion is in play.
-                        Node* child = node->child1().node();
-                        if (child->op() != GetLocal)
-                            break;
-                        VariableAccessData* variable = child->variableAccessData();
-                        variable->vote(VoteOther);
-                        if (!shouldConsiderForHoisting(variable))
-                            break;
-                        noticeStructureCheck(variable, 0);
-                    }
-                    break;
-                    
-                case SetLocal: {
-                    // Find all uses of the source of the SetLocal. If any of them are a
-                    // kind of CheckStructure, then we should notice them to ensure that
-                    // we're not hoisting a check that would contravene checks that are
-                    // already being performed.
-                    VariableAccessData* variable = node->variableAccessData();
-                    if (!shouldConsiderForHoisting(variable))
-                        break;
-                    Node* source = node->child1().node();
-                    for (unsigned subIndexInBlock = 0; subIndexInBlock < block->size(); ++subIndexInBlock) {
-                        Node* subNode = block->at(subIndexInBlock);
-                        switch (subNode->op()) {
-                        case CheckStructure: {
-                            if (subNode->child1() != source)
-                                break;
-                            
-                            noticeStructureCheck(variable, subNode->structureSet());
-                            break;
-                        }
-                        case StructureTransitionWatchpoint: {
-                            if (subNode->child1() != source)
-                                break;
-                            
-                            noticeStructureCheck(variable, subNode->structure());
-                            break;
-                        }
-                        default:
-                            break;
-                        }
-                    }
-                    
-                    m_graph.voteChildren(node, VoteOther);
-                    break;
-                }
-                case GarbageValue:
-                    break;
-                    
-                default:
-                    m_graph.voteChildren(node, VoteOther);
-                    break;
-                }
-            }
-        }
-        
-        // Disable structure hoisting on variables that appear to mostly be used in
-        // contexts where it doesn't make sense.
-        
-        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
-            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
-            if (!variable->isRoot())
-                continue;
-            if (variable->voteRatio() >= Options::structureCheckVoteRatioForHoisting())
-                continue;
-            HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
-            if (iter == m_map.end())
-                continue;
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-            dataLog(
-                "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
-                " because the ratio is ", variable->voteRatio(), ".\n");
-#endif
-            iter->value.m_structure = 0;
-        }
-        
-        // Disable structure check hoisting for variables that cross the OSR entry that
-        // we're currently taking, and where the value currently does not have the
-        // structure we want.
-        
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block)
-                continue;
-            ASSERT(block->isReachable);
-            if (!block->isOSRTarget)
-                continue;
-            if (block->bytecodeBegin != m_graph.m_osrEntryBytecodeIndex)
-                continue;
-            for (size_t i = 0; i < m_graph.m_mustHandleValues.size(); ++i) {
-                int operand = m_graph.m_mustHandleValues.operandForIndex(i);
-                Node* node = block->variablesAtHead.operand(operand);
-                if (!node)
-                    continue;
-                VariableAccessData* variable = node->variableAccessData();
-                HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
-                if (iter == m_map.end())
-                    continue;
-                if (!iter->value.m_structure)
-                    continue;
-                JSValue value = m_graph.m_mustHandleValues[i];
-                if (!value || !value.isCell()) {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-                    dataLog(
-                        "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
-                        " because the OSR entry value is not a cell: ", value, ".\n");
-#endif
-                    iter->value.m_structure = 0;
-                    continue;
-                }
-                if (value.asCell()->structure() != iter->value.m_structure) {
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-                    dataLog(
-                        "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
-                        " because the OSR entry value has structure ",
-                        RawPointer(value.asCell()->structure()), " and we wanted ",
-                        RawPointer(iter->value.m_structure), ".\n");
-#endif
-                    iter->value.m_structure = 0;
-                    continue;
-                }
-            }
-        }
-
-        bool changed = false;
-
-#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-        for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin();
-             it != m_map.end(); ++it) {
-            if (!it->value.m_structure) {
-                dataLog(
-                    "Not hoisting checks for ", VariableAccessDataDump(m_graph, it->key),
-                    " because of heuristics.\n");
-                continue;
-            }
-            dataLog("Hoisting checks for ", VariableAccessDataDump(m_graph, it->key), "\n");
-        }
-#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
-        
-        // Place CheckStructure's at SetLocal sites.
-        
-        InsertionSet insertionSet(m_graph);
-        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
-            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
-            if (!block)
-                continue;
-            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
-                Node* node = block->at(indexInBlock);
-                // Be careful not to use 'node' after appending to the graph. In those switch
-                // cases where we need to append, we first carefully extract everything we need
-                // from the node, before doing any appending.
-                switch (node->op()) {
-                case SetArgument: {
-                    ASSERT(!blockIndex);
-                    // Insert a GetLocal and a CheckStructure immediately following this
-                    // SetArgument, if the variable was a candidate for structure hoisting.
-                    // If the basic block previously only had the SetArgument as its
-                    // variable-at-tail, then replace it with this GetLocal.
-                    VariableAccessData* variable = node->variableAccessData();
-                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
-                    if (iter == m_map.end())
-                        break;
-                    if (!iter->value.m_structure)
-                        break;
-                    
-                    CodeOrigin codeOrigin = node->codeOrigin;
-                    
-                    Node* getLocal = insertionSet.insertNode(
-                        indexInBlock + 1, variable->prediction(), GetLocal, codeOrigin,
-                        OpInfo(variable), Edge(node));
-                    insertionSet.insertNode(
-                        indexInBlock + 1, SpecNone, CheckStructure, codeOrigin,
-                        OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
-                        Edge(getLocal, CellUse));
-
-                    if (block->variablesAtTail.operand(variable->local()) == node)
-                        block->variablesAtTail.operand(variable->local()) = getLocal;
-                    
-                    m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocal);
-                    
-                    changed = true;
-                    break;
-                }
-                    
-                case SetLocal: {
-                    VariableAccessData* variable = node->variableAccessData();
-                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
-                    if (iter == m_map.end())
-                        break;
-                    if (!iter->value.m_structure)
-                        break;
-
-                    // First insert a dead SetLocal to tell OSR that the child's value should
-                    // be dropped into this bytecode variable if the CheckStructure decides
-                    // to exit.
-                    
-                    CodeOrigin codeOrigin = node->codeOrigin;
-                    Edge child1 = node->child1();
-                    
-                    insertionSet.insertNode(
-                        indexInBlock, SpecNone, SetLocal, codeOrigin, OpInfo(variable), child1);
-
-                    // Use a ForwardCheckStructure to indicate that we should exit to the
-                    // next bytecode instruction rather than reexecuting the current one.
-                    insertionSet.insertNode(
-                        indexInBlock, SpecNone, ForwardCheckStructure, codeOrigin,
-                        OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
-                        Edge(child1.node(), CellUse));
-                    changed = true;
-                    break;
-                }
-                    
-                default:
-                    break;
-                }
-            }
-            insertionSet.execute(block);
-        }
-        
-        return changed;
-    }
-
-private:
-    bool shouldConsiderForHoisting(VariableAccessData* variable)
-    {
-        if (!variable->shouldUnboxIfPossible())
-            return false;
-        if (variable->structureCheckHoistingFailed())
-            return false;
-        if (!isCellSpeculation(variable->prediction()))
-            return false;
-        return true;
-    }
-    
-    void noticeStructureCheck(VariableAccessData* variable, Structure* structure)
-    {
-        HashMap<VariableAccessData*, CheckData>::AddResult result =
-            m_map.add(variable, CheckData(structure));
-        if (result.isNewEntry)
-            return;
-        if (result.iterator->value.m_structure == structure)
-            return;
-        result.iterator->value.m_structure = 0;
-    }
-    
-    void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set)
-    {
-        if (set.size() != 1) {
-            noticeStructureCheck(variable, 0);
-            return;
-        }
-        noticeStructureCheck(variable, set.singletonStructure());
-    }
-    
-    struct CheckData {
-        Structure* m_structure;
-        
-        CheckData()
-            : m_structure(0)
-        {
-        }
-        
-        CheckData(Structure* structure)
-            : m_structure(structure)
-        {
-        }
-    };
-    
-    HashMap<VariableAccessData*, CheckData> m_map;
-};
-
-bool performStructureCheckHoisting(Graph& graph)
-{
-    SamplingRegion samplingRegion("DFG Structure Check Hoisting Phase");
-    return runPhase<StructureCheckHoistingPhase>(graph);
-}
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
-
index 1e6462a..e69de29 100644 (file)
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#ifndef DFGStructureCheckHoistingPhase_h
-#define DFGStructureCheckHoistingPhase_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
-
-namespace JSC { namespace DFG {
-
-class Graph;
-
-// Hoists CheckStructure on variables to assignments to those variables, if either of
-// the following is true:
-// A) The structure's transition watchpoint set is valid.
-// B) The span of code within which the variable is live has no effects that might
-//    clobber the structure.
-
-bool performStructureCheckHoisting(Graph&);
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // DFGStructureCheckHoistingPhase_h
-
diff --git a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp b/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
new file mode 100644 (file)
index 0000000..8756c83
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGTypeCheckHoistingPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGBasicBlock.h"
+#include "DFGGraph.h"
+#include "DFGInsertionSet.h"
+#include "DFGPhase.h"
+#include "DFGVariableAccessDataDump.h"
+#include "Operations.h"
+#include <wtf/HashMap.h>
+
+namespace JSC { namespace DFG {
+
+enum CheckBallot { VoteOther, VoteStructureCheck };
+
+class TypeCheckHoistingPhase : public Phase {
+public:
+    TypeCheckHoistingPhase(Graph& graph)
+        : Phase(graph, "structure check hoisting")
+    {
+    }
+    
+    bool run()
+    {
+        ASSERT(m_graph.m_form == ThreadedCPS);
+        
+        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
+            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
+            if (!variable->isRoot())
+                continue;
+            variable->clearVotes();
+        }
+        
+        // Identify the set of variables that are always subject to the same structure
+        // checks. For now, only consider monomorphic structure checks (one structure).
+        
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+            if (!block)
+                continue;
+            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+                Node* node = block->at(indexInBlock);
+                switch (node->op()) {
+                case CheckStructure:
+                case StructureTransitionWatchpoint: {
+                    Node* child = node->child1().node();
+                    if (child->op() != GetLocal)
+                        break;
+                    VariableAccessData* variable = child->variableAccessData();
+                    variable->vote(VoteStructureCheck);
+                    if (!shouldConsiderForHoisting(variable))
+                        break;
+                    noticeStructureCheck(variable, node->structureSet());
+                    break;
+                }
+                    
+                case ForwardCheckStructure:
+                case ForwardStructureTransitionWatchpoint:
+                    // We currently rely on the fact that we're the only ones who would
+                    // insert this node.
+                    RELEASE_ASSERT_NOT_REACHED();
+                    break;
+                    
+                case GetByOffset:
+                case PutByOffset:
+                case PutStructure:
+                case AllocatePropertyStorage:
+                case ReallocatePropertyStorage:
+                case GetButterfly:
+                case GetByVal:
+                case PutByVal:
+                case PutByValAlias:
+                case GetArrayLength:
+                case CheckArray:
+                case GetIndexedPropertyStorage:
+                case Phantom:
+                    // Don't count these uses.
+                    break;
+                    
+                case ArrayifyToStructure:
+                case Arrayify:
+                    if (node->arrayMode().conversion() == Array::RageConvert) {
+                        // Rage conversion changes structures. We should avoid tying to do
+                        // any kind of hoisting when rage conversion is in play.
+                        Node* child = node->child1().node();
+                        if (child->op() != GetLocal)
+                            break;
+                        VariableAccessData* variable = child->variableAccessData();
+                        variable->vote(VoteOther);
+                        if (!shouldConsiderForHoisting(variable))
+                            break;
+                        noticeStructureCheck(variable, 0);
+                    }
+                    break;
+                    
+                case SetLocal: {
+                    // Find all uses of the source of the SetLocal. If any of them are a
+                    // kind of CheckStructure, then we should notice them to ensure that
+                    // we're not hoisting a check that would contravene checks that are
+                    // already being performed.
+                    VariableAccessData* variable = node->variableAccessData();
+                    if (!shouldConsiderForHoisting(variable))
+                        break;
+                    Node* source = node->child1().node();
+                    for (unsigned subIndexInBlock = 0; subIndexInBlock < block->size(); ++subIndexInBlock) {
+                        Node* subNode = block->at(subIndexInBlock);
+                        switch (subNode->op()) {
+                        case CheckStructure: {
+                            if (subNode->child1() != source)
+                                break;
+                            
+                            noticeStructureCheck(variable, subNode->structureSet());
+                            break;
+                        }
+                        case StructureTransitionWatchpoint: {
+                            if (subNode->child1() != source)
+                                break;
+                            
+                            noticeStructureCheck(variable, subNode->structure());
+                            break;
+                        }
+                        default:
+                            break;
+                        }
+                    }
+                    
+                    m_graph.voteChildren(node, VoteOther);
+                    break;
+                }
+                case GarbageValue:
+                    break;
+                    
+                default:
+                    m_graph.voteChildren(node, VoteOther);
+                    break;
+                }
+            }
+        }
+        
+        // Disable structure hoisting on variables that appear to mostly be used in
+        // contexts where it doesn't make sense.
+        
+        for (unsigned i = m_graph.m_variableAccessData.size(); i--;) {
+            VariableAccessData* variable = &m_graph.m_variableAccessData[i];
+            if (!variable->isRoot())
+                continue;
+            if (variable->voteRatio() >= Options::structureCheckVoteRatioForHoisting())
+                continue;
+            HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
+            if (iter == m_map.end())
+                continue;
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+            dataLog(
+                "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
+                " because the ratio is ", variable->voteRatio(), ".\n");
+#endif
+            iter->value.m_structure = 0;
+        }
+        
+        // Disable structure check hoisting for variables that cross the OSR entry that
+        // we're currently taking, and where the value currently does not have the
+        // structure we want.
+        
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+            if (!block)
+                continue;
+            ASSERT(block->isReachable);
+            if (!block->isOSRTarget)
+                continue;
+            if (block->bytecodeBegin != m_graph.m_osrEntryBytecodeIndex)
+                continue;
+            for (size_t i = 0; i < m_graph.m_mustHandleValues.size(); ++i) {
+                int operand = m_graph.m_mustHandleValues.operandForIndex(i);
+                Node* node = block->variablesAtHead.operand(operand);
+                if (!node)
+                    continue;
+                VariableAccessData* variable = node->variableAccessData();
+                HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
+                if (iter == m_map.end())
+                    continue;
+                if (!iter->value.m_structure)
+                    continue;
+                JSValue value = m_graph.m_mustHandleValues[i];
+                if (!value || !value.isCell()) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                    dataLog(
+                        "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
+                        " because the OSR entry value is not a cell: ", value, ".\n");
+#endif
+                    iter->value.m_structure = 0;
+                    continue;
+                }
+                if (value.asCell()->structure() != iter->value.m_structure) {
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+                    dataLog(
+                        "Zeroing the structure to hoist for ", VariableAccessDataDump(m_graph, variable),
+                        " because the OSR entry value has structure ",
+                        RawPointer(value.asCell()->structure()), " and we wanted ",
+                        RawPointer(iter->value.m_structure), ".\n");
+#endif
+                    iter->value.m_structure = 0;
+                    continue;
+                }
+            }
+        }
+
+        bool changed = false;
+
+#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        for (HashMap<VariableAccessData*, CheckData>::iterator it = m_map.begin();
+            it != m_map.end(); ++it) {
+            if (!it->value.m_structure) {
+                dataLog(
+                    "Not hoisting checks for ", VariableAccessDataDump(m_graph, it->key),
+                    " because of heuristics.\n");
+                continue;
+            }
+            dataLog("Hoisting checks for ", VariableAccessDataDump(m_graph, it->key), "\n");
+        }
+#endif // DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
+        
+        // Place CheckStructure's at SetLocal sites.
+        
+        InsertionSet insertionSet(m_graph);
+        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
+            BasicBlock* block = m_graph.m_blocks[blockIndex].get();
+            if (!block)
+                continue;
+            for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
+                Node* node = block->at(indexInBlock);
+                // Be careful not to use 'node' after appending to the graph. In those switch
+                // cases where we need to append, we first carefully extract everything we need
+                // from the node, before doing any appending.
+                switch (node->op()) {
+                case SetArgument: {
+                    ASSERT(!blockIndex);
+                    // Insert a GetLocal and a CheckStructure immediately following this
+                    // SetArgument, if the variable was a candidate for structure hoisting.
+                    // If the basic block previously only had the SetArgument as its
+                    // variable-at-tail, then replace it with this GetLocal.
+                    VariableAccessData* variable = node->variableAccessData();
+                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
+                    if (iter == m_map.end())
+                        break;
+                    if (!iter->value.m_structure)
+                        break;
+                    
+                    CodeOrigin codeOrigin = node->codeOrigin;
+                    
+                    Node* getLocal = insertionSet.insertNode(
+                        indexInBlock + 1, variable->prediction(), GetLocal, codeOrigin,
+                        OpInfo(variable), Edge(node));
+                    insertionSet.insertNode(
+                        indexInBlock + 1, SpecNone, CheckStructure, codeOrigin,
+                        OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
+                        Edge(getLocal, CellUse));
+
+                    if (block->variablesAtTail.operand(variable->local()) == node)
+                        block->variablesAtTail.operand(variable->local()) = getLocal;
+                    
+                    m_graph.substituteGetLocal(*block, indexInBlock, variable, getLocal);
+                    
+                    changed = true;
+                    break;
+                }
+                    
+                case SetLocal: {
+                    VariableAccessData* variable = node->variableAccessData();
+                    HashMap<VariableAccessData*, CheckData>::iterator iter = m_map.find(variable);
+                    if (iter == m_map.end())
+                        break;
+                    if (!iter->value.m_structure)
+                        break;
+
+                    // First insert a dead SetLocal to tell OSR that the child's value should
+                    // be dropped into this bytecode variable if the CheckStructure decides
+                    // to exit.
+                    
+                    CodeOrigin codeOrigin = node->codeOrigin;
+                    Edge child1 = node->child1();
+                    
+                    insertionSet.insertNode(
+                        indexInBlock, SpecNone, SetLocal, codeOrigin, OpInfo(variable), child1);
+
+                    // Use a ForwardCheckStructure to indicate that we should exit to the
+                    // next bytecode instruction rather than reexecuting the current one.
+                    insertionSet.insertNode(
+                        indexInBlock, SpecNone, ForwardCheckStructure, codeOrigin,
+                        OpInfo(m_graph.addStructureSet(iter->value.m_structure)),
+                        Edge(child1.node(), CellUse));
+                    changed = true;
+                    break;
+                }
+                    
+                default:
+                    break;
+                }
+            }
+            insertionSet.execute(block);
+        }
+        
+        return changed;
+    }
+
+private:
+    bool shouldConsiderForHoisting(VariableAccessData* variable)
+    {
+        if (!variable->shouldUnboxIfPossible())
+            return false;
+        if (variable->structureCheckHoistingFailed())
+            return false;
+        if (!isCellSpeculation(variable->prediction()))
+            return false;
+        return true;
+    }
+    
+    void noticeStructureCheck(VariableAccessData* variable, Structure* structure)
+    {
+        HashMap<VariableAccessData*, CheckData>::AddResult result =
+            m_map.add(variable, CheckData(structure));
+        if (result.isNewEntry)
+            return;
+        if (result.iterator->value.m_structure == structure)
+            return;
+        result.iterator->value.m_structure = 0;
+    }
+    
+    void noticeStructureCheck(VariableAccessData* variable, const StructureSet& set)
+    {
+        if (set.size() != 1) {
+            noticeStructureCheck(variable, 0);
+            return;
+        }
+        noticeStructureCheck(variable, set.singletonStructure());
+    }
+    
+    struct CheckData {
+        Structure* m_structure;
+        
+        CheckData()
+            : m_structure(0)
+        {
+        }
+        
+        CheckData(Structure* structure)
+            : m_structure(structure)
+        {
+        }
+    };
+    
+    HashMap<VariableAccessData*, CheckData> m_map;
+};
+
+bool performTypeCheckHoisting(Graph& graph)
+{
+    SamplingRegion samplingRegion("DFG Type Check Hoisting Phase");
+    return runPhase<TypeCheckHoistingPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+
diff --git a/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.h b/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.h
new file mode 100644 (file)
index 0000000..97adaf2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGTypeCheckHoistingPhase_h
+#define DFGTypeCheckHoistingPhase_h
+
+#include <wtf/Platform.h>
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Hoists CheckStructure on variables to assignments to those variables, if either of
+// the following is true:
+// A) The structure's transition watchpoint set is valid.
+// B) The span of code within which the variable is live has no effects that might
+//    clobber the structure.
+
+bool performTypeCheckHoisting(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGTypeCheckHoistingPhase_h
+