The thing that B3 uses to describe a stack slot should not be a Value
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Jan 2016 22:05:28 +0000 (22:05 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Jan 2016 22:05:28 +0000 (22:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153491
rdar://problem/24349446

Reviewed by Geoffrey Garen and Saam Barati.

Prior to this change, B3 represented stack slots by having a StackSlotValue that carried
two meanings:

- It represented a stack slot.

- It was a kind of Value for getting the base of the stack slot.

This seems like a good idea until you consider the following issues.

1) A Value can be killed if it is on an unreachable path, or if it has no effects and
   nobody refers to it. But the FTL uses StackSlotValue to allocate space on the stack.
   When it does this, it doesn't want it to be killed. It will dereference the object, so
   killing it is a bug.

2) A premise of B3 is that it should be always legal to perform the following
   transformation on a value:

   value->replaceWithIdentity(insertionSet.insertValue(index, proc.clone(value)));

   This inserts a new value just before the old one. The new value is a clone of the old
   one. Then the old one is essentially deleted (anything that becomes an identity dies
   shortly thereafter). Problem (1) prevents this from being legal, which breaks a major
   premise of B3 IR.

3) A premise of B3 is that it should be always legal to perform the following
   transformation on a value:

   Before:
           @42 = Thing(...)

   After:
           Branch(@doesntMatter, #yes, #no)
       BB#yes:
           @42_one = Thing(...)
           Upsilon(@42_one, ^42)
           Jump(#done)
       BB#no:
           @42_two = Thing(...)
           Upsilon(@42_two, ^42)
           Jump(#done)
       BB#done:
           @42 = Phi()

   But prior to this change, such a transformation makes absolutely no sense for
   StackSlot. It will "work" in the sense that the compiler will proceed undaunted, but
   it will disable SSA fix-up for the cloned stack slot and we will end up allocating two
   stack slots instead of one, and then we will assume that they both escape, which will
   disable efficient stack allocation. Note that the moral equivalent of this
   transformation could already happen due to tail duplication, and the only reason why
   it's not a bug right now is that we happen to hoist stack slots to the root block. But
   the whole point of our stack slots was supposed to be that they do not have to be
   hoisted.

This change fixes this issue by splitting StackSlotValue into two things: SlotBaseValue,
which is a pure operation for getting the base address of a StackSlot, and StackSlot,
which is a representation of the actual stack slot. StackSlot cannot get duplicated and
can only be killed if it's anonymous. SlotBaseValue can be killed, moved, cloned,
hoisted, etc. Since it has no effects and it has a ValueKey, it's one of the most
permissive Values in the IR, just as one would hope (after all, there is actually zero
code that needs to execute to evaluate SlotBaseValue).

This fixes a crash that we saw with GuardMalloc and ASan. It also makes the IR a lot more
easy to reason about.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3EliminateCommonSubexpressions.cpp:
* b3/B3FixSSA.cpp:
(JSC::B3::demoteValues):
(JSC::B3::fixSSA):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::run):
(JSC::B3::Air::LowerToAir::effectiveAddr):
(JSC::B3::Air::LowerToAir::lower):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3Procedure.cpp:
(JSC::B3::Procedure::setBlockOrderImpl):
(JSC::B3::Procedure::addStackSlot):
(JSC::B3::Procedure::addAnonymousStackSlot):
(JSC::B3::Procedure::clone):
(JSC::B3::Procedure::dump):
(JSC::B3::Procedure::blocksInPostOrder):
(JSC::B3::Procedure::deleteStackSlot):
(JSC::B3::Procedure::deleteValue):
(JSC::B3::Procedure::calleeSaveRegisters):
(JSC::B3::Procedure::addStackSlotIndex):
(JSC::B3::Procedure::addValueIndex):
* b3/B3Procedure.h:
(JSC::B3::Procedure::setBlockOrder):
(JSC::B3::Procedure::StackSlotsCollection::StackSlotsCollection):
(JSC::B3::Procedure::StackSlotsCollection::size):
(JSC::B3::Procedure::StackSlotsCollection::at):
(JSC::B3::Procedure::StackSlotsCollection::operator[]):
(JSC::B3::Procedure::StackSlotsCollection::iterator::iterator):
(JSC::B3::Procedure::StackSlotsCollection::iterator::operator*):
(JSC::B3::Procedure::StackSlotsCollection::iterator::operator++):
(JSC::B3::Procedure::StackSlotsCollection::iterator::operator==):
(JSC::B3::Procedure::StackSlotsCollection::iterator::operator!=):
(JSC::B3::Procedure::StackSlotsCollection::iterator::findNext):
(JSC::B3::Procedure::StackSlotsCollection::begin):
(JSC::B3::Procedure::StackSlotsCollection::end):
(JSC::B3::Procedure::stackSlots):
(JSC::B3::Procedure::ValuesCollection::ValuesCollection):
* b3/B3ReduceStrength.cpp:
* b3/B3SlotBaseValue.cpp: Copied from Source/JavaScriptCore/b3/B3StackSlotValue.cpp.
(JSC::B3::SlotBaseValue::~SlotBaseValue):
(JSC::B3::SlotBaseValue::dumpMeta):
(JSC::B3::SlotBaseValue::cloneImpl):
(JSC::B3::StackSlotValue::~StackSlotValue): Deleted.
(JSC::B3::StackSlotValue::dumpMeta): Deleted.
(JSC::B3::StackSlotValue::cloneImpl): Deleted.
* b3/B3SlotBaseValue.h: Copied from Source/JavaScriptCore/b3/B3StackSlotValue.h.
* b3/B3StackSlot.cpp: Added.
(JSC::B3::StackSlot::~StackSlot):
(JSC::B3::StackSlot::dump):
(JSC::B3::StackSlot::deepDump):
(JSC::B3::StackSlot::StackSlot):
* b3/B3StackSlot.h: Added.
(JSC::B3::StackSlot::byteSize):
(JSC::B3::StackSlot::kind):
(JSC::B3::StackSlot::isLocked):
(JSC::B3::StackSlot::index):
(JSC::B3::StackSlot::offsetFromFP):
(JSC::B3::StackSlot::setOffsetFromFP):
(JSC::B3::DeepStackSlotDump::DeepStackSlotDump):
(JSC::B3::DeepStackSlotDump::dump):
(JSC::B3::deepDump):
* b3/B3StackSlotValue.cpp: Removed.
* b3/B3StackSlotValue.h: Removed.
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::checkOpcode):
* b3/B3ValueKey.cpp:
(JSC::B3::ValueKey::materialize):
* b3/air/AirCode.cpp:
(JSC::B3::Air::Code::addBlock):
(JSC::B3::Air::Code::addStackSlot):
(JSC::B3::Air::Code::addSpecial):
* b3/air/AirCode.h:
* b3/air/AirStackSlot.cpp:
(JSC::B3::Air::StackSlot::setOffsetFromFP):
(JSC::B3::Air::StackSlot::dump):
(JSC::B3::Air::StackSlot::deepDump):
(JSC::B3::Air::StackSlot::StackSlot):
* b3/air/AirStackSlot.h:
(JSC::B3::Air::StackSlot::alignment):
(JSC::B3::Air::StackSlot::b3Slot):
(JSC::B3::Air::StackSlot::offsetFromFP):
(WTF::printInternal):
(JSC::B3::Air::StackSlot::value): Deleted.
* b3/testb3.cpp:
(JSC::B3::testStackSlot):
(JSC::B3::testStoreLoadStackSlot):
* ftl/FTLB3Compile.cpp:
* ftl/FTLB3Output.cpp:
(JSC::FTL::Output::appendTo):
(JSC::FTL::Output::lockedStackSlot):
(JSC::FTL::Output::neg):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::framePointer):
(JSC::FTL::Output::constBool):
(JSC::FTL::Output::constInt32):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::lower):
* ftl/FTLState.h:

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

28 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/b3/B3EliminateCommonSubexpressions.cpp
Source/JavaScriptCore/b3/B3FixSSA.cpp
Source/JavaScriptCore/b3/B3LowerToAir.cpp
Source/JavaScriptCore/b3/B3Opcode.cpp
Source/JavaScriptCore/b3/B3Opcode.h
Source/JavaScriptCore/b3/B3Procedure.cpp
Source/JavaScriptCore/b3/B3Procedure.h
Source/JavaScriptCore/b3/B3ReduceStrength.cpp
Source/JavaScriptCore/b3/B3SlotBaseValue.cpp [moved from Source/JavaScriptCore/b3/B3StackSlotValue.cpp with 83% similarity]
Source/JavaScriptCore/b3/B3SlotBaseValue.h [new file with mode: 0644]
Source/JavaScriptCore/b3/B3StackSlot.cpp [new file with mode: 0644]
Source/JavaScriptCore/b3/B3StackSlot.h [moved from Source/JavaScriptCore/b3/B3StackSlotValue.h with 66% similarity]
Source/JavaScriptCore/b3/B3Validate.cpp
Source/JavaScriptCore/b3/B3Value.cpp
Source/JavaScriptCore/b3/B3ValueKey.cpp
Source/JavaScriptCore/b3/air/AirCode.cpp
Source/JavaScriptCore/b3/air/AirCode.h
Source/JavaScriptCore/b3/air/AirStackSlot.cpp
Source/JavaScriptCore/b3/air/AirStackSlot.h
Source/JavaScriptCore/b3/testb3.cpp
Source/JavaScriptCore/ftl/FTLB3Compile.cpp
Source/JavaScriptCore/ftl/FTLB3Output.cpp
Source/JavaScriptCore/ftl/FTLB3Output.h
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLState.h

index afc8152..d0f27cf 100644 (file)
@@ -147,11 +147,12 @@ set(JavaScriptCore_SOURCES
     b3/B3ReduceDoubleToFloat.cpp
     b3/B3ReduceStrength.cpp
     b3/B3SSACalculator.cpp
+    b3/B3SlotBaseValue.cpp
     b3/B3StackmapGenerationParams.cpp
     b3/B3StackmapSpecial.cpp
     b3/B3StackmapValue.cpp
     b3/B3StackSlotKind.cpp
-    b3/B3StackSlotValue.cpp
+    b3/B3StackSlot.cpp
     b3/B3SwitchCase.cpp
     b3/B3SwitchValue.cpp
     b3/B3TimingScope.cpp
index f3196e8..ff42895 100644 (file)
@@ -1,3 +1,181 @@
+2016-01-26  Filip Pizlo  <fpizlo@apple.com>
+
+        The thing that B3 uses to describe a stack slot should not be a Value
+        https://bugs.webkit.org/show_bug.cgi?id=153491
+        rdar://problem/24349446
+
+        Reviewed by Geoffrey Garen and Saam Barati.
+
+        Prior to this change, B3 represented stack slots by having a StackSlotValue that carried
+        two meanings:
+
+        - It represented a stack slot.
+
+        - It was a kind of Value for getting the base of the stack slot.
+
+        This seems like a good idea until you consider the following issues.
+
+        1) A Value can be killed if it is on an unreachable path, or if it has no effects and
+           nobody refers to it. But the FTL uses StackSlotValue to allocate space on the stack.
+           When it does this, it doesn't want it to be killed. It will dereference the object, so
+           killing it is a bug.
+
+        2) A premise of B3 is that it should be always legal to perform the following
+           transformation on a value:
+
+           value->replaceWithIdentity(insertionSet.insertValue(index, proc.clone(value)));
+
+           This inserts a new value just before the old one. The new value is a clone of the old
+           one. Then the old one is essentially deleted (anything that becomes an identity dies
+           shortly thereafter). Problem (1) prevents this from being legal, which breaks a major
+           premise of B3 IR.
+
+        3) A premise of B3 is that it should be always legal to perform the following
+           transformation on a value:
+
+           Before:
+                   @42 = Thing(...)
+
+           After:
+                   Branch(@doesntMatter, #yes, #no)
+               BB#yes:
+                   @42_one = Thing(...)
+                   Upsilon(@42_one, ^42)
+                   Jump(#done)
+               BB#no:
+                   @42_two = Thing(...)
+                   Upsilon(@42_two, ^42)
+                   Jump(#done)
+               BB#done:
+                   @42 = Phi()
+
+           But prior to this change, such a transformation makes absolutely no sense for
+           StackSlot. It will "work" in the sense that the compiler will proceed undaunted, but
+           it will disable SSA fix-up for the cloned stack slot and we will end up allocating two
+           stack slots instead of one, and then we will assume that they both escape, which will
+           disable efficient stack allocation. Note that the moral equivalent of this
+           transformation could already happen due to tail duplication, and the only reason why
+           it's not a bug right now is that we happen to hoist stack slots to the root block. But
+           the whole point of our stack slots was supposed to be that they do not have to be
+           hoisted.
+
+        This change fixes this issue by splitting StackSlotValue into two things: SlotBaseValue,
+        which is a pure operation for getting the base address of a StackSlot, and StackSlot,
+        which is a representation of the actual stack slot. StackSlot cannot get duplicated and
+        can only be killed if it's anonymous. SlotBaseValue can be killed, moved, cloned,
+        hoisted, etc. Since it has no effects and it has a ValueKey, it's one of the most
+        permissive Values in the IR, just as one would hope (after all, there is actually zero
+        code that needs to execute to evaluate SlotBaseValue).
+
+        This fixes a crash that we saw with GuardMalloc and ASan. It also makes the IR a lot more
+        easy to reason about.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3EliminateCommonSubexpressions.cpp:
+        * b3/B3FixSSA.cpp:
+        (JSC::B3::demoteValues):
+        (JSC::B3::fixSSA):
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::run):
+        (JSC::B3::Air::LowerToAir::effectiveAddr):
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3Procedure.cpp:
+        (JSC::B3::Procedure::setBlockOrderImpl):
+        (JSC::B3::Procedure::addStackSlot):
+        (JSC::B3::Procedure::addAnonymousStackSlot):
+        (JSC::B3::Procedure::clone):
+        (JSC::B3::Procedure::dump):
+        (JSC::B3::Procedure::blocksInPostOrder):
+        (JSC::B3::Procedure::deleteStackSlot):
+        (JSC::B3::Procedure::deleteValue):
+        (JSC::B3::Procedure::calleeSaveRegisters):
+        (JSC::B3::Procedure::addStackSlotIndex):
+        (JSC::B3::Procedure::addValueIndex):
+        * b3/B3Procedure.h:
+        (JSC::B3::Procedure::setBlockOrder):
+        (JSC::B3::Procedure::StackSlotsCollection::StackSlotsCollection):
+        (JSC::B3::Procedure::StackSlotsCollection::size):
+        (JSC::B3::Procedure::StackSlotsCollection::at):
+        (JSC::B3::Procedure::StackSlotsCollection::operator[]):
+        (JSC::B3::Procedure::StackSlotsCollection::iterator::iterator):
+        (JSC::B3::Procedure::StackSlotsCollection::iterator::operator*):
+        (JSC::B3::Procedure::StackSlotsCollection::iterator::operator++):
+        (JSC::B3::Procedure::StackSlotsCollection::iterator::operator==):
+        (JSC::B3::Procedure::StackSlotsCollection::iterator::operator!=):
+        (JSC::B3::Procedure::StackSlotsCollection::iterator::findNext):
+        (JSC::B3::Procedure::StackSlotsCollection::begin):
+        (JSC::B3::Procedure::StackSlotsCollection::end):
+        (JSC::B3::Procedure::stackSlots):
+        (JSC::B3::Procedure::ValuesCollection::ValuesCollection):
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3SlotBaseValue.cpp: Copied from Source/JavaScriptCore/b3/B3StackSlotValue.cpp.
+        (JSC::B3::SlotBaseValue::~SlotBaseValue):
+        (JSC::B3::SlotBaseValue::dumpMeta):
+        (JSC::B3::SlotBaseValue::cloneImpl):
+        (JSC::B3::StackSlotValue::~StackSlotValue): Deleted.
+        (JSC::B3::StackSlotValue::dumpMeta): Deleted.
+        (JSC::B3::StackSlotValue::cloneImpl): Deleted.
+        * b3/B3SlotBaseValue.h: Copied from Source/JavaScriptCore/b3/B3StackSlotValue.h.
+        * b3/B3StackSlot.cpp: Added.
+        (JSC::B3::StackSlot::~StackSlot):
+        (JSC::B3::StackSlot::dump):
+        (JSC::B3::StackSlot::deepDump):
+        (JSC::B3::StackSlot::StackSlot):
+        * b3/B3StackSlot.h: Added.
+        (JSC::B3::StackSlot::byteSize):
+        (JSC::B3::StackSlot::kind):
+        (JSC::B3::StackSlot::isLocked):
+        (JSC::B3::StackSlot::index):
+        (JSC::B3::StackSlot::offsetFromFP):
+        (JSC::B3::StackSlot::setOffsetFromFP):
+        (JSC::B3::DeepStackSlotDump::DeepStackSlotDump):
+        (JSC::B3::DeepStackSlotDump::dump):
+        (JSC::B3::deepDump):
+        * b3/B3StackSlotValue.cpp: Removed.
+        * b3/B3StackSlotValue.h: Removed.
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::checkOpcode):
+        * b3/B3ValueKey.cpp:
+        (JSC::B3::ValueKey::materialize):
+        * b3/air/AirCode.cpp:
+        (JSC::B3::Air::Code::addBlock):
+        (JSC::B3::Air::Code::addStackSlot):
+        (JSC::B3::Air::Code::addSpecial):
+        * b3/air/AirCode.h:
+        * b3/air/AirStackSlot.cpp:
+        (JSC::B3::Air::StackSlot::setOffsetFromFP):
+        (JSC::B3::Air::StackSlot::dump):
+        (JSC::B3::Air::StackSlot::deepDump):
+        (JSC::B3::Air::StackSlot::StackSlot):
+        * b3/air/AirStackSlot.h:
+        (JSC::B3::Air::StackSlot::alignment):
+        (JSC::B3::Air::StackSlot::b3Slot):
+        (JSC::B3::Air::StackSlot::offsetFromFP):
+        (WTF::printInternal):
+        (JSC::B3::Air::StackSlot::value): Deleted.
+        * b3/testb3.cpp:
+        (JSC::B3::testStackSlot):
+        (JSC::B3::testStoreLoadStackSlot):
+        * ftl/FTLB3Compile.cpp:
+        * ftl/FTLB3Output.cpp:
+        (JSC::FTL::Output::appendTo):
+        (JSC::FTL::Output::lockedStackSlot):
+        (JSC::FTL::Output::neg):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::framePointer):
+        (JSC::FTL::Output::constBool):
+        (JSC::FTL::Output::constInt32):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::lower):
+        * ftl/FTLState.h:
+
 2016-01-26  Benjamin Poulain  <benjamin@webkit.org>
 
         Remove a useless #include
index bff7715..b4d1aea 100644 (file)
                0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F93B4A918B92C4D00178A3F /* PutByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */; };
                0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F9495871C57F47500413A48 /* B3StackSlot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9495851C57F47500413A48 /* B3StackSlot.cpp */; };
+               0F9495881C57F47500413A48 /* B3StackSlot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9495861C57F47500413A48 /* B3StackSlot.h */; };
                0F952ABC1B487A7700C367C5 /* TrackedReferences.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */; };
                0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FEC85311BDACDAC0080FF74 /* B3StackmapSpecial.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84E71BDACDAC0080FF74 /* B3StackmapSpecial.h */; };
                0FEC85321BDACDAC0080FF74 /* B3StackSlotKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC84E81BDACDAC0080FF74 /* B3StackSlotKind.cpp */; };
                0FEC85331BDACDAC0080FF74 /* B3StackSlotKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84E91BDACDAC0080FF74 /* B3StackSlotKind.h */; };
-               0FEC85341BDACDAC0080FF74 /* B3StackSlotValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC84EA1BDACDAC0080FF74 /* B3StackSlotValue.cpp */; };
-               0FEC85351BDACDAC0080FF74 /* B3StackSlotValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84EB1BDACDAC0080FF74 /* B3StackSlotValue.h */; };
+               0FEC85341BDACDAC0080FF74 /* B3SlotBaseValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC84EA1BDACDAC0080FF74 /* B3SlotBaseValue.cpp */; };
+               0FEC85351BDACDAC0080FF74 /* B3SlotBaseValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84EB1BDACDAC0080FF74 /* B3SlotBaseValue.h */; };
                0FEC85361BDACDAC0080FF74 /* B3SuccessorCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84EC1BDACDAC0080FF74 /* B3SuccessorCollection.h */; };
                0FEC85371BDACDAC0080FF74 /* B3SwitchCase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEC84ED1BDACDAC0080FF74 /* B3SwitchCase.cpp */; };
                0FEC85381BDACDAC0080FF74 /* B3SwitchCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84EE1BDACDAC0080FF74 /* B3SwitchCase.h */; };
                0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
                0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdVariant.cpp; sourceTree = "<group>"; };
                0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdVariant.h; sourceTree = "<group>"; };
+               0F9495851C57F47500413A48 /* B3StackSlot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3StackSlot.cpp; path = b3/B3StackSlot.cpp; sourceTree = "<group>"; };
+               0F9495861C57F47500413A48 /* B3StackSlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3StackSlot.h; path = b3/B3StackSlot.h; sourceTree = "<group>"; };
                0F952ABA1B487A7700C367C5 /* TrackedReferences.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackedReferences.cpp; sourceTree = "<group>"; };
                0F952ABB1B487A7700C367C5 /* TrackedReferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackedReferences.h; sourceTree = "<group>"; };
                0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
                0FEC84E71BDACDAC0080FF74 /* B3StackmapSpecial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3StackmapSpecial.h; path = b3/B3StackmapSpecial.h; sourceTree = "<group>"; };
                0FEC84E81BDACDAC0080FF74 /* B3StackSlotKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3StackSlotKind.cpp; path = b3/B3StackSlotKind.cpp; sourceTree = "<group>"; };
                0FEC84E91BDACDAC0080FF74 /* B3StackSlotKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3StackSlotKind.h; path = b3/B3StackSlotKind.h; sourceTree = "<group>"; };
-               0FEC84EA1BDACDAC0080FF74 /* B3StackSlotValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3StackSlotValue.cpp; path = b3/B3StackSlotValue.cpp; sourceTree = "<group>"; };
-               0FEC84EB1BDACDAC0080FF74 /* B3StackSlotValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3StackSlotValue.h; path = b3/B3StackSlotValue.h; sourceTree = "<group>"; };
+               0FEC84EA1BDACDAC0080FF74 /* B3SlotBaseValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3SlotBaseValue.cpp; path = b3/B3SlotBaseValue.cpp; sourceTree = "<group>"; };
+               0FEC84EB1BDACDAC0080FF74 /* B3SlotBaseValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3SlotBaseValue.h; path = b3/B3SlotBaseValue.h; sourceTree = "<group>"; };
                0FEC84EC1BDACDAC0080FF74 /* B3SuccessorCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3SuccessorCollection.h; path = b3/B3SuccessorCollection.h; sourceTree = "<group>"; };
                0FEC84ED1BDACDAC0080FF74 /* B3SwitchCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3SwitchCase.cpp; path = b3/B3SwitchCase.cpp; sourceTree = "<group>"; };
                0FEC84EE1BDACDAC0080FF74 /* B3SwitchCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3SwitchCase.h; path = b3/B3SwitchCase.h; sourceTree = "<group>"; };
                                43422A651C16221E00E2EB98 /* B3ReduceDoubleToFloat.h */,
                                0FEC85B71BE1462F0080FF74 /* B3ReduceStrength.cpp */,
                                0FEC85B81BE1462F0080FF74 /* B3ReduceStrength.h */,
+                               0FEC84EA1BDACDAC0080FF74 /* B3SlotBaseValue.cpp */,
+                               0FEC84EB1BDACDAC0080FF74 /* B3SlotBaseValue.h */,
                                0F6B8ADA1C4EFAC300969052 /* B3SSACalculator.cpp */,
                                0F6B8ADB1C4EFAC300969052 /* B3SSACalculator.h */,
                                0F33FCF51C136E2500323F67 /* B3StackmapGenerationParams.cpp */,
                                0FEC84E71BDACDAC0080FF74 /* B3StackmapSpecial.h */,
                                0F338DEF1BE93AD10013C88F /* B3StackmapValue.cpp */,
                                0F338DF01BE93AD10013C88F /* B3StackmapValue.h */,
+                               0F9495851C57F47500413A48 /* B3StackSlot.cpp */,
+                               0F9495861C57F47500413A48 /* B3StackSlot.h */,
                                0FEC84E81BDACDAC0080FF74 /* B3StackSlotKind.cpp */,
                                0FEC84E91BDACDAC0080FF74 /* B3StackSlotKind.h */,
-                               0FEC84EA1BDACDAC0080FF74 /* B3StackSlotValue.cpp */,
-                               0FEC84EB1BDACDAC0080FF74 /* B3StackSlotValue.h */,
                                0FEC84EC1BDACDAC0080FF74 /* B3SuccessorCollection.h */,
                                0FEC84ED1BDACDAC0080FF74 /* B3SwitchCase.cpp */,
                                0FEC84EE1BDACDAC0080FF74 /* B3SwitchCase.h */,
                                0FEC85BD1BE1462F0080FF74 /* B3ReduceStrength.h in Headers */,
                                0FEC85311BDACDAC0080FF74 /* B3StackmapSpecial.h in Headers */,
                                0FEC85331BDACDAC0080FF74 /* B3StackSlotKind.h in Headers */,
-                               0FEC85351BDACDAC0080FF74 /* B3StackSlotValue.h in Headers */,
+                               0FEC85351BDACDAC0080FF74 /* B3SlotBaseValue.h in Headers */,
                                0FEC85361BDACDAC0080FF74 /* B3SuccessorCollection.h in Headers */,
                                0FEC85381BDACDAC0080FF74 /* B3SwitchCase.h in Headers */,
                                0FEC853A1BDACDAC0080FF74 /* B3SwitchValue.h in Headers */,
                                C218D1401655CFD50062BB81 /* CopyWorkList.h in Headers */,
                                C4F4B6F41A05C944005CAB76 /* cpp_generator.py in Headers */,
                                0F338E1C1BF286EA0013C88F /* B3BlockInsertionSet.h in Headers */,
+                               0F9495881C57F47500413A48 /* B3StackSlot.h in Headers */,
                                C4F4B6F31A05C944005CAB76 /* cpp_generator_templates.py in Headers */,
                                5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */,
                                9959E92B1BD17FA4001AA413 /* cssmin.py in Headers */,
                                0FEC85BC1BE1462F0080FF74 /* B3ReduceStrength.cpp in Sources */,
                                0FEC85301BDACDAC0080FF74 /* B3StackmapSpecial.cpp in Sources */,
                                0FEC85321BDACDAC0080FF74 /* B3StackSlotKind.cpp in Sources */,
-                               0FEC85341BDACDAC0080FF74 /* B3StackSlotValue.cpp in Sources */,
+                               0FEC85341BDACDAC0080FF74 /* B3SlotBaseValue.cpp in Sources */,
                                0FEC85371BDACDAC0080FF74 /* B3SwitchCase.cpp in Sources */,
                                0FEC85391BDACDAC0080FF74 /* B3SwitchValue.cpp in Sources */,
                                0F4570401BE584CA0062A629 /* B3TimingScope.cpp in Sources */,
                                0FE254F61ABDDD2200A7C6D2 /* DFGVarargsForwardingPhase.cpp in Sources */,
                                0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */,
                                0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */,
+                               0F9495871C57F47500413A48 /* B3StackSlot.cpp in Sources */,
                                0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */,
                                0F2BDC4A1522809A00CD8910 /* DFGVariableEventStream.cpp in Sources */,
                                0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */,
index f94fc85..0bfe0bb 100644 (file)
@@ -37,7 +37,8 @@
 #include "B3PhaseScope.h"
 #include "B3ProcedureInlines.h"
 #include "B3PureCSE.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3ValueKey.h"
 #include "B3ValueInlines.h"
 #include "DFGGraph.h"
@@ -130,7 +131,7 @@ public:
             m_impureBlockData[m_block] = m_data;
         }
 
-        for (StackSlotValue* stack : m_stacks)
+        for (SlotBaseValue* stack : m_stacks)
             m_insertionSet.insertValue(0, stack);
         for (BasicBlock* block : m_proc) {
             for (unsigned valueIndex = 0; valueIndex < block->size(); ++valueIndex) {
@@ -369,8 +370,8 @@ private:
         // Right now we're relying on the fact that CSE's position in the phase order is
         // almost right before SSA fixup.
             
-        StackSlotValue* stack = m_proc.add<StackSlotValue>(
-            m_value->origin(), sizeofType(m_value->type()), StackSlotKind::Anonymous);
+        SlotBaseValue* stack = m_proc.add<SlotBaseValue>(
+            m_value->origin(), m_proc.addAnonymousStackSlot(m_value->type()));
         m_stacks.append(stack);
 
         MemoryValue* load = m_insertionSet.insert<MemoryValue>(
@@ -498,7 +499,7 @@ private:
     unsigned m_index;
     Value* m_value;
 
-    Vector<StackSlotValue*> m_stacks;
+    Vector<SlotBaseValue*> m_stacks;
     HashMap<Value*, Vector<Value*>> m_stores;
 
     InsertionSet m_insertionSet;
index 967f920..8c74219 100644 (file)
@@ -38,7 +38,8 @@
 #include "B3PhaseScope.h"
 #include "B3ProcedureInlines.h"
 #include "B3SSACalculator.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3UpsilonValue.h"
 #include "B3ValueInlines.h"
 #include <wtf/CommaPrinter.h>
@@ -51,19 +52,19 @@ const bool verbose = false;
 
 void demoteValues(Procedure& proc, const IndexSet<Value>& values)
 {
-    HashMap<Value*, StackSlotValue*> map;
-    HashMap<Value*, StackSlotValue*> phiMap;
+    HashMap<Value*, SlotBaseValue*> map;
+    HashMap<Value*, SlotBaseValue*> phiMap;
 
     // Create stack slots.
     InsertionSet insertionSet(proc);
     for (Value* value : values.values(proc.values())) {
-        StackSlotValue* stack = insertionSet.insert<StackSlotValue>(
-            0, value->origin(), sizeofType(value->type()), StackSlotKind::Anonymous);
+        SlotBaseValue* stack = insertionSet.insert<SlotBaseValue>(
+            0, value->origin(), proc.addAnonymousStackSlot(value->type()));
         map.add(value, stack);
 
         if (value->opcode() == Phi) {
-            StackSlotValue* phiStack = insertionSet.insert<StackSlotValue>(
-                0, value->origin(), sizeofType(value->type()), StackSlotKind::Anonymous);
+            SlotBaseValue* phiStack = insertionSet.insert<SlotBaseValue>(
+                0, value->origin(), proc.addAnonymousStackSlot(value->type()));
             phiMap.add(value, phiStack);
         }
     }
@@ -89,31 +90,31 @@ void demoteValues(Procedure& proc, const IndexSet<Value>& values)
             Value* value = block->at(valueIndex);
 
             if (value->opcode() == Phi) {
-                if (StackSlotValue* stack = phiMap.get(value)) {
+                if (SlotBaseValue* slotBase = phiMap.get(value)) {
                     value->replaceWithIdentity(
                         insertionSet.insert<MemoryValue>(
-                            valueIndex, Load, value->type(), value->origin(), stack));
+                            valueIndex, Load, value->type(), value->origin(), slotBase));
                 }
             } else {
                 for (Value*& child : value->children()) {
-                    if (StackSlotValue* stack = map.get(child)) {
+                    if (SlotBaseValue* slotBase = map.get(child)) {
                         child = insertionSet.insert<MemoryValue>(
-                            valueIndex, Load, child->type(), value->origin(), stack);
+                            valueIndex, Load, child->type(), value->origin(), slotBase);
                     }
                 }
 
                 if (UpsilonValue* upsilon = value->as<UpsilonValue>()) {
-                    if (StackSlotValue* stack = phiMap.get(upsilon->phi())) {
+                    if (SlotBaseValue* slotBase = phiMap.get(upsilon->phi())) {
                         insertionSet.insert<MemoryValue>(
-                            valueIndex, Store, upsilon->origin(), upsilon->child(0), stack);
+                            valueIndex, Store, upsilon->origin(), upsilon->child(0), slotBase);
                         value->replaceWithNop();
                     }
                 }
             }
 
-            if (StackSlotValue* stack = map.get(value)) {
+            if (SlotBaseValue* slotBase = map.get(value)) {
                 insertionSet.insert<MemoryValue>(
-                    valueIndex + 1, Store, value->origin(), value, stack);
+                    valueIndex + 1, Store, value->origin(), value, slotBase);
             }
         }
         insertionSet.execute(block);
@@ -126,9 +127,10 @@ bool fixSSA(Procedure& proc)
     
     // Collect the stack "variables". If there aren't any, then we don't have anything to do.
     // That's a fairly common case.
-    HashMap<StackSlotValue*, Type> stackVariable;
+    HashMap<StackSlot*, Type> stackVariable;
     for (Value* value : proc.values()) {
-        if (StackSlotValue* stack = value->as<StackSlotValue>()) {
+        if (SlotBaseValue* slotBase = value->as<SlotBaseValue>()) {
+            StackSlot* stack = slotBase->slot();
             if (stack->kind() == StackSlotKind::Anonymous)
                 stackVariable.add(stack, Void);
         }
@@ -141,14 +143,16 @@ bool fixSSA(Procedure& proc)
     // Store on anonymous variables.
     for (Value* value : proc.values()) {
         auto reject = [&] (Value* value) {
-            if (StackSlotValue* stack = value->as<StackSlotValue>())
-                stackVariable.remove(stack);
+            if (SlotBaseValue* slotBase = value->as<SlotBaseValue>())
+                stackVariable.remove(slotBase->slot());
         };
         
         auto handleAccess = [&] (Value* access, Type type) {
-            StackSlotValue* stack = access->lastChild()->as<StackSlotValue>();
-            if (!stack)
+            SlotBaseValue* slotBase = access->lastChild()->as<SlotBaseValue>();
+            if (!slotBase)
                 return;
+
+            StackSlot* stack = slotBase->slot();
             
             if (value->as<MemoryValue>()->offset()) {
                 stackVariable.remove(stack);
@@ -184,16 +188,14 @@ bool fixSSA(Procedure& proc)
         }
     }
 
-    Vector<StackSlotValue*> deadValues;
+    Vector<StackSlot*> deadSlots;
     for (auto& entry : stackVariable) {
         if (entry.value == Void)
-            deadValues.append(entry.key);
+            deadSlots.append(entry.key);
     }
 
-    for (StackSlotValue* deadValue : deadValues) {
-        deadValue->replaceWithNop();
-        stackVariable.remove(deadValue);
-    }
+    for (StackSlot* deadSlot : deadSlots)
+        stackVariable.remove(deadSlot);
 
     if (stackVariable.isEmpty())
         return false;
@@ -204,11 +206,11 @@ bool fixSSA(Procedure& proc)
     SSACalculator ssa(proc);
 
     // Create a SSACalculator::Variable for every stack variable.
-    Vector<StackSlotValue*> variableToStack;
-    HashMap<StackSlotValue*, SSACalculator::Variable*> stackToVariable;
+    Vector<StackSlot*> variableToStack;
+    HashMap<StackSlot*, SSACalculator::Variable*> stackToVariable;
 
     for (auto& entry : stackVariable) {
-        StackSlotValue* stack = entry.key;
+        StackSlot* stack = entry.key;
         SSACalculator::Variable* variable = ssa.newVariable();
         RELEASE_ASSERT(variable->index() == variableToStack.size());
         variableToStack.append(stack);
@@ -221,10 +223,12 @@ bool fixSSA(Procedure& proc)
             if (value->opcode() != Store)
                 continue;
 
-            StackSlotValue* stack = value->child(1)->as<StackSlotValue>();
-            if (!stack)
+            SlotBaseValue* slotBase = value->child(1)->as<SlotBaseValue>();
+            if (!slotBase)
                 continue;
 
+            StackSlot* stack = slotBase->slot();
+
             if (SSACalculator::Variable* variable = stackToVariable.get(stack))
                 ssa.newDef(variable, block, value->child(0));
         }
@@ -233,8 +237,8 @@ bool fixSSA(Procedure& proc)
     // Decide where Phis are to be inserted. This creates them but does not insert them.
     ssa.computePhis(
         [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Value* {
-            StackSlotValue* stack = variableToStack[variable->index()];
-            Value* phi = proc.add<Value>(Phi, stackVariable.get(stack), stack->origin());
+            StackSlot* stack = variableToStack[variable->index()];
+            Value* phi = proc.add<Value>(Phi, stackVariable.get(stack), block->at(0)->origin());
             if (verbose) {
                 dataLog(
                     "Adding Phi for ", pointerDump(stack), " at ", *block, ": ",
@@ -245,12 +249,12 @@ bool fixSSA(Procedure& proc)
 
     // Now perform the conversion.
     InsertionSet insertionSet(proc);
-    HashMap<StackSlotValue*, Value*> mapping;
+    HashMap<StackSlot*, Value*> mapping;
     for (BasicBlock* block : proc.blocksInPreOrder()) {
         mapping.clear();
 
         for (auto& entry : stackToVariable) {
-            StackSlotValue* stack = entry.key;
+            StackSlot* stack = entry.key;
             SSACalculator::Variable* variable = entry.value;
 
             SSACalculator::Def* def = ssa.reachingDefAtHead(block, variable);
@@ -259,7 +263,7 @@ bool fixSSA(Procedure& proc)
         }
 
         for (SSACalculator::Def* phiDef : ssa.phisForBlock(block)) {
-            StackSlotValue* stack = variableToStack[phiDef->variable()->index()];
+            StackSlot* stack = variableToStack[phiDef->variable()->index()];
 
             insertionSet.insertValue(0, phiDef->value());
             mapping.set(stack, phiDef->value());
@@ -271,7 +275,8 @@ bool fixSSA(Procedure& proc)
 
             switch (value->opcode()) {
             case Load: {
-                if (StackSlotValue* stack = value->child(0)->as<StackSlotValue>()) {
+                if (SlotBaseValue* slotBase = value->child(0)->as<SlotBaseValue>()) {
+                    StackSlot* stack = slotBase->slot();
                     if (Value* replacement = mapping.get(stack))
                         value->replaceWithIdentity(replacement);
                 }
@@ -279,7 +284,8 @@ bool fixSSA(Procedure& proc)
             }
                 
             case Store: {
-                if (StackSlotValue* stack = value->child(1)->as<StackSlotValue>()) {
+                if (SlotBaseValue* slotBase = value->child(1)->as<SlotBaseValue>()) {
+                    StackSlot* stack = slotBase->slot();
                     if (stackToVariable.contains(stack)) {
                         mapping.set(stack, value->child(0));
                         value->replaceWithNop();
@@ -299,7 +305,7 @@ bool fixSSA(Procedure& proc)
             for (SSACalculator::Def* phiDef : ssa.phisForBlock(successorBlock)) {
                 Value* phi = phiDef->value();
                 SSACalculator::Variable* variable = phiDef->variable();
-                StackSlotValue* stack = variableToStack[variable->index()];
+                StackSlot* stack = variableToStack[variable->index()];
 
                 Value* mappedValue = mapping.get(stack);
                 if (verbose) {
@@ -319,10 +325,6 @@ bool fixSSA(Procedure& proc)
         insertionSet.execute(block);
     }
 
-    // Finally, kill the stack slots.
-    for (StackSlotValue* stack : variableToStack)
-        stack->replaceWithNop();
-
     if (verbose) {
         dataLog("B3 after SSA conversion:\n");
         dataLog(proc);
index a3ff13b..8146edb 100644 (file)
@@ -47,7 +47,8 @@
 #include "B3PhaseScope.h"
 #include "B3PhiChildren.h"
 #include "B3Procedure.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3UpsilonValue.h"
 #include "B3UseCounts.h"
 #include "B3ValueInlines.h"
@@ -92,16 +93,14 @@ public:
                     dataLog("Phi tmp for ", *value, ": ", m_phiToTmp[value], "\n");
                 break;
             }
-            case B3::StackSlot: {
-                StackSlotValue* stackSlotValue = value->as<StackSlotValue>();
-                m_stackToStack.add(stackSlotValue, m_code.addStackSlot(stackSlotValue));
-                break;
-            }
             default:
                 break;
             }
         }
 
+        for (B3::StackSlot* stack : m_procedure.stackSlots())
+            m_stackToStack.add(stack, m_code.addStackSlot(stack));
+
         // Figure out which blocks are not rare.
         m_fastWorklist.push(m_procedure[0]);
         while (B3::BasicBlock* block = m_fastWorklist.pop()) {
@@ -433,8 +432,8 @@ private:
         case FramePointer:
             return Arg::addr(Tmp(GPRInfo::callFrameRegister), offset);
 
-        case B3::StackSlot:
-            return Arg::stack(m_stackToStack.get(address->as<StackSlotValue>()), offset);
+        case SlotBase:
+            return Arg::stack(m_stackToStack.get(address->as<SlotBaseValue>()->slot()), offset);
 
         default:
             return fallback();
@@ -1914,10 +1913,10 @@ private:
             return;
         }
 
-        case B3::StackSlot: {
+        case SlotBase: {
             append(
                 Lea,
-                Arg::stack(m_stackToStack.get(m_value->as<StackSlotValue>())),
+                Arg::stack(m_stackToStack.get(m_value->as<SlotBaseValue>()->slot())),
                 tmp(m_value));
             return;
         }
@@ -2284,7 +2283,7 @@ private:
     IndexMap<Value, Tmp> m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is "pinned".
     IndexMap<Value, Tmp> m_phiToTmp; // Each Phi gets its own Tmp.
     IndexMap<B3::BasicBlock, Air::BasicBlock*> m_blockToBlock;
-    HashMap<StackSlotValue*, Air::StackSlot*> m_stackToStack;
+    HashMap<B3::StackSlot*, Air::StackSlot*> m_stackToStack;
 
     UseCounts m_useCounts;
     PhiChildren m_phiChildren;
index 4ac348b..3ad606a 100644 (file)
@@ -95,8 +95,8 @@ void printInternal(PrintStream& out, Opcode opcode)
     case ConstFloat:
         out.print("ConstFloat");
         return;
-    case StackSlot:
-        out.print("StackSlot");
+    case SlotBase:
+        out.print("SlotBase");
         return;
     case ArgumentReg:
         out.print("ArgumentReg");
index 23c1b14..e605846 100644 (file)
@@ -51,7 +51,7 @@ enum Opcode : int16_t {
     // The magical stack slot. This is viewed as executing at the top of the program regardless of
     // where in control flow you put it. Each instance of a StackSlot Value gets a disjoint range of
     // stack memory. Use the StackSlotValue class.
-    StackSlot,
+    SlotBase,
 
     // The magical argument register. This is viewed as executing at the top of the program
     // regardless of where in control flow you put it, and the compiler takes care to ensure that we
index b323f40..3502486 100644 (file)
@@ -36,6 +36,7 @@
 #include "B3DataSection.h"
 #include "B3Dominators.h"
 #include "B3OpaqueByproducts.h"
+#include "B3StackSlot.h"
 #include "B3ValueInlines.h"
 
 namespace JSC { namespace B3 {
@@ -91,6 +92,20 @@ void Procedure::setBlockOrderImpl(Vector<BasicBlock*>& blocks)
     }
 }
 
+StackSlot* Procedure::addStackSlot(unsigned byteSize, StackSlotKind kind)
+{
+    size_t index = addStackSlotIndex();
+    std::unique_ptr<StackSlot> slot(new StackSlot(index, byteSize, kind));
+    StackSlot* result = slot.get();
+    m_stackSlots[index] = WTFMove(slot);
+    return result;
+}
+
+StackSlot* Procedure::addAnonymousStackSlot(Type type)
+{
+    return addStackSlot(sizeofType(type), StackSlotKind::Anonymous);
+}
+
 Value* Procedure::clone(Value* value)
 {
     std::unique_ptr<Value> clone(value->cloneImpl());
@@ -192,6 +207,11 @@ void Procedure::dump(PrintStream& out) const
         }
         dataLog("    ", deepDump(*this, value), "\n");
     }
+    if (stackSlots().size()) {
+        out.print("Stack slots:\n");
+        for (StackSlot* slot : stackSlots())
+            out.print("    ", pointerDump(slot), ": ", deepDump(slot), "\n");
+    }
     if (m_byproducts->count())
         out.print(*m_byproducts);
 }
@@ -206,6 +226,14 @@ Vector<BasicBlock*> Procedure::blocksInPostOrder()
     return B3::blocksInPostOrder(at(0));
 }
 
+void Procedure::deleteStackSlot(StackSlot* stackSlot)
+{
+    RELEASE_ASSERT(m_stackSlots[stackSlot->index()].get() == stackSlot);
+    RELEASE_ASSERT(!stackSlot->isLocked());
+    m_stackSlotIndexFreeList.append(stackSlot->index());
+    m_stackSlots[stackSlot->index()] = nullptr;
+}
+
 void Procedure::deleteValue(Value* value)
 {
     RELEASE_ASSERT(m_values[value->index()].get() == value);
@@ -282,6 +310,17 @@ const RegisterAtOffsetList& Procedure::calleeSaveRegisters() const
     return code().calleeSaveRegisters();
 }
 
+size_t Procedure::addStackSlotIndex()
+{
+    if (m_stackSlotIndexFreeList.isEmpty()) {
+        size_t index = m_stackSlots.size();
+        m_stackSlots.append(nullptr);
+        return index;
+    }
+    
+    return m_stackSlotIndexFreeList.takeLast();
+}
+
 size_t Procedure::addValueIndex()
 {
     if (m_valueIndexFreeList.isEmpty()) {
index 4bf6845..c76e7f1 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "B3OpaqueByproducts.h"
 #include "B3Origin.h"
+#include "B3StackSlotKind.h"
 #include "B3Type.h"
 #include "B3ValueKey.h"
 #include "PureNaN.h"
@@ -49,6 +50,7 @@ class BasicBlock;
 class BlockInsertionSet;
 class CFG;
 class Dominators;
+class StackSlot;
 class Value;
 
 namespace Air { class Code; }
@@ -90,6 +92,9 @@ public:
             blocks.append(block);
         setBlockOrderImpl(blocks);
     }
+
+    JS_EXPORT_PRIVATE StackSlot* addStackSlot(unsigned byteSize, StackSlotKind);
+    JS_EXPORT_PRIVATE StackSlot* addAnonymousStackSlot(Type);
     
     template<typename ValueType, typename... Arguments>
     ValueType* add(Arguments...);
@@ -172,6 +177,75 @@ public:
     Vector<BasicBlock*> blocksInPreOrder();
     Vector<BasicBlock*> blocksInPostOrder();
 
+    class StackSlotsCollection {
+    public:
+        StackSlotsCollection(const Procedure& proc)
+            : m_proc(proc)
+        {
+        }
+
+        unsigned size() const { return m_proc.m_stackSlots.size(); }
+        StackSlot* at(unsigned index) const { return m_proc.m_stackSlots[index].get(); }
+        StackSlot* operator[](unsigned index) const { return at(index); }
+
+        class iterator {
+        public:
+            iterator()
+                : m_collection(nullptr)
+                , m_index(0)
+            {
+            }
+
+            iterator(const StackSlotsCollection& collection, unsigned index)
+                : m_collection(&collection)
+                , m_index(findNext(index))
+            {
+            }
+
+            StackSlot* operator*()
+            {
+                return m_collection->at(m_index);
+            }
+
+            iterator& operator++()
+            {
+                m_index = findNext(m_index + 1);
+                return *this;
+            }
+
+            bool operator==(const iterator& other) const
+            {
+                return m_index == other.m_index;
+            }
+
+            bool operator!=(const iterator& other) const
+            {
+                return !(*this == other);
+            }
+
+        private:
+            unsigned findNext(unsigned index)
+            {
+                while (index < m_collection->size() && !m_collection->at(index))
+                    index++;
+                return index;
+            }
+            
+            const StackSlotsCollection* m_collection;
+            unsigned m_index;
+        };
+
+        iterator begin() const { return iterator(*this, 0); }
+        iterator end() const { return iterator(*this, size()); }
+
+    private:
+        const Procedure& m_proc;
+    };
+
+    StackSlotsCollection stackSlots() const { return StackSlotsCollection(*this); }
+
+    void deleteStackSlot(StackSlot*);
+    
     class ValuesCollection {
     public:
         ValuesCollection(const Procedure& procedure)
@@ -292,10 +366,13 @@ private:
     
     void setBlockOrderImpl(Vector<BasicBlock*>&);
 
+    size_t addStackSlotIndex();
     JS_EXPORT_PRIVATE size_t addValueIndex();
-    
+
+    Vector<std::unique_ptr<StackSlot>> m_stackSlots;
     Vector<std::unique_ptr<BasicBlock>> m_blocks;
     Vector<std::unique_ptr<Value>> m_values;
+    Vector<size_t> m_stackSlotIndexFreeList;
     Vector<size_t> m_valueIndexFreeList;
     std::unique_ptr<CFG> m_cfg;
     std::unique_ptr<Dominators> m_dominators;
index 445739e..5f6f3d7 100644 (file)
@@ -40,6 +40,8 @@
 #include "B3PhiChildren.h"
 #include "B3ProcedureInlines.h"
 #include "B3PureCSE.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3UpsilonValue.h"
 #include "B3ValueKeyInlines.h"
 #include "B3ValueInlines.h"
@@ -2075,14 +2077,18 @@ private:
                 break;
         }
 
+        IndexSet<StackSlot> liveStackSlots;
+        
         for (BasicBlock* block : m_proc) {
             size_t sourceIndex = 0;
             size_t targetIndex = 0;
             while (sourceIndex < block->size()) {
                 Value* value = block->at(sourceIndex++);
-                if (worklist.saw(value))
+                if (worklist.saw(value)) {
+                    if (SlotBaseValue* slotBase = value->as<SlotBaseValue>())
+                        liveStackSlots.add(slotBase->slot());
                     block->at(targetIndex++) = value;
-                else {
+                else {
                     m_proc.deleteValue(value);
                     
                     // It's not entirely clear if this is needed. I think it makes sense to have
@@ -2094,6 +2100,12 @@ private:
             }
             block->values().resize(targetIndex);
         }
+
+        for (StackSlot* slot : m_proc.stackSlots()) {
+            if (slot->isLocked() || liveStackSlots.contains(slot))
+                continue;
+            m_proc.deleteStackSlot(slot);
+        }
     }
 
     void simplifySSA()
similarity index 83%
rename from Source/JavaScriptCore/b3/B3StackSlotValue.cpp
rename to Source/JavaScriptCore/b3/B3SlotBaseValue.cpp
index 650ea30..b5fd69b 100644 (file)
  */
 
 #include "config.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
 
 #if ENABLE(B3_JIT)
 
+#include "B3StackSlot.h"
+
 namespace JSC { namespace B3 {
 
-StackSlotValue::~StackSlotValue()
+SlotBaseValue::~SlotBaseValue()
 {
 }
 
-void StackSlotValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
+void SlotBaseValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
 {
-    out.print(comma, "byteSize = ", m_byteSize, ", kind = ", m_kind);
+    out.print(comma, pointerDump(m_slot));
 }
 
-Value* StackSlotValue::cloneImpl() const
+Value* SlotBaseValue::cloneImpl() const
 {
-    return new StackSlotValue(*this);
+    return new SlotBaseValue(*this);
 }
 
 } } // namespace JSC::B3
diff --git a/Source/JavaScriptCore/b3/B3SlotBaseValue.h b/Source/JavaScriptCore/b3/B3SlotBaseValue.h
new file mode 100644 (file)
index 0000000..e05f6a6
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015-2016 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 B3SlotBaseValue_h
+#define B3SlotBaseValue_h
+
+#if ENABLE(B3_JIT)
+
+#include "B3Value.h"
+
+namespace JSC { namespace B3 {
+
+class StackSlot;
+
+class JS_EXPORT_PRIVATE SlotBaseValue : public Value {
+public:
+    static bool accepts(Opcode opcode) { return opcode == SlotBase; }
+
+    ~SlotBaseValue();
+
+    StackSlot* slot() const { return m_slot; }
+
+protected:
+    void dumpMeta(CommaPrinter&, PrintStream&) const override;
+
+    Value* cloneImpl() const override;
+
+private:
+    friend class Procedure;
+
+    SlotBaseValue(unsigned index, Origin origin, StackSlot* slot)
+        : Value(index, CheckedOpcode, SlotBase, pointerType(), origin)
+        , m_slot(slot)
+    {
+    }
+
+    StackSlot* m_slot;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3SlotBaseValue_h
+
diff --git a/Source/JavaScriptCore/b3/B3StackSlot.cpp b/Source/JavaScriptCore/b3/B3StackSlot.cpp
new file mode 100644 (file)
index 0000000..8efd963
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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 "B3StackSlot.h"
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+StackSlot::~StackSlot()
+{
+}
+
+void StackSlot::dump(PrintStream& out) const
+{
+    out.print("stack", m_index);
+}
+
+void StackSlot::deepDump(PrintStream& out) const
+{
+    out.print("byteSize = ", m_byteSize, ", offsetFromFP = ", m_offsetFromFP, ", kind = ", m_kind);
+}
+
+StackSlot::StackSlot(unsigned index, unsigned byteSize, StackSlotKind kind)
+    : m_index(index)
+    , m_byteSize(byteSize)
+    , m_kind(kind)
+{
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
similarity index 66%
rename from Source/JavaScriptCore/b3/B3StackSlotValue.h
rename to Source/JavaScriptCore/b3/B3StackSlot.h
index dbac604..928dfca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#ifndef B3StackSlotValue_h
-#define B3StackSlotValue_h
+#ifndef B3StackSlot_h
+#define B3StackSlot_h
 
 #if ENABLE(B3_JIT)
 
 #include "B3StackSlotKind.h"
-#include "B3Value.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PrintStream.h>
 
 namespace JSC { namespace B3 {
 
+class Procedure;
+
 namespace Air {
 class StackSlot;
 } // namespace Air
 
-class JS_EXPORT_PRIVATE StackSlotValue : public Value {
-public:
-    static bool accepts(Opcode opcode) { return opcode == StackSlot; }
+class StackSlot {
+    WTF_MAKE_NONCOPYABLE(StackSlot);
+    WTF_MAKE_FAST_ALLOCATED;
 
-    ~StackSlotValue();
+public:
+    ~StackSlot();
 
     unsigned byteSize() const { return m_byteSize; }
     StackSlotKind kind() const { return m_kind; }
+    bool isLocked() const { return m_kind == StackSlotKind::Locked; }
+    unsigned index() const { return m_index; }
 
     // This gets assigned at the end of compilation. But, you can totally pin stack slots. Use the
     // set method to do that.
@@ -56,31 +63,48 @@ public:
         m_offsetFromFP = value;
     }
 
-protected:
-    void dumpMeta(CommaPrinter&, PrintStream&) const override;
-
-    Value* cloneImpl() const override;
+    void dump(PrintStream& out) const;
+    void deepDump(PrintStream&) const;
 
 private:
     friend class Air::StackSlot;
     friend class Procedure;
 
-    StackSlotValue(unsigned index, Origin origin, unsigned byteSize, StackSlotKind kind)
-        : Value(index, CheckedOpcode, StackSlot, pointerType(), origin)
-        , m_byteSize(byteSize)
-        , m_kind(kind)
-        , m_offsetFromFP(0)
-    {
-    }
+    StackSlot(unsigned index, unsigned byteSize, StackSlotKind);
 
+    unsigned m_index;
     unsigned m_byteSize;
     StackSlotKind m_kind;
-    intptr_t m_offsetFromFP;
+    intptr_t m_offsetFromFP { 0 };
 };
 
+class DeepStackSlotDump {
+public:
+    DeepStackSlotDump(const StackSlot* slot)
+        : m_slot(slot)
+    {
+    }
+
+    void dump(PrintStream& out) const
+    {
+        if (m_slot)
+            m_slot->deepDump(out);
+        else
+            out.print("<null>");
+    }
+
+private:
+    const StackSlot* m_slot;
+};
+
+inline DeepStackSlotDump deepDump(const StackSlot* slot)
+{
+    return DeepStackSlotDump(slot);
+}
+
 } } // namespace JSC::B3
 
 #endif // ENABLE(B3_JIT)
 
-#endif // B3StackSlotValue_h
+#endif // B3StackSlot_h
 
index 9d88f68..6fb06b2 100644 (file)
@@ -33,7 +33,8 @@
 #include "B3Dominators.h"
 #include "B3MemoryValue.h"
 #include "B3Procedure.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3UpsilonValue.h"
 #include "B3ValueInlines.h"
 #include <wtf/HashSet.h>
@@ -152,7 +153,7 @@ public:
                 VALIDATE(!value->numChildren(), ("At ", *value));
                 VALIDATE(value->type() == Float, ("At ", *value));
                 break;
-            case StackSlot:
+            case SlotBase:
             case FramePointer:
                 VALIDATE(!value->numChildren(), ("At ", *value));
                 VALIDATE(value->type() == pointerType(), ("At ", *value));
@@ -410,10 +411,12 @@ private:
     void validateStackAccess(Value* value)
     {
         MemoryValue* memory = value->as<MemoryValue>();
-        StackSlotValue* stack = value->lastChild()->as<StackSlotValue>();
-        if (!stack)
+        SlotBaseValue* slotBase = value->lastChild()->as<SlotBaseValue>();
+        if (!slotBase)
             return;
 
+        StackSlot* stack = slotBase->slot();
+
         VALIDATE(memory->offset() >= 0, ("At ", *value));
         VALIDATE(memory->offset() + memory->accessByteSize() <= stack->byteSize(), ("At ", *value));
     }
index 91c2335..0609f94 100644 (file)
@@ -34,7 +34,8 @@
 #include "B3MemoryValue.h"
 #include "B3OriginDump.h"
 #include "B3ProcedureInlines.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3UpsilonValue.h"
 #include "B3ValueInlines.h"
 #include "B3ValueKeyInlines.h"
@@ -383,7 +384,7 @@ Effects Value::effects() const
     case Const64:
     case ConstDouble:
     case ConstFloat:
-    case StackSlot:
+    case SlotBase:
     case ArgumentReg:
     case FramePointer:
     case Add:
@@ -535,6 +536,10 @@ ValueKey Value::key() const
         return ValueKey(
             ArgumentReg, type(),
             static_cast<int64_t>(as<ArgumentRegValue>()->argumentReg().index()));
+    case SlotBase:
+        return ValueKey(
+            SlotBase, type(),
+            static_cast<int64_t>(as<SlotBaseValue>()->slot()->index()));
     default:
         return ValueKey();
     }
@@ -565,7 +570,7 @@ void Value::checkOpcode(Opcode opcode)
     ASSERT(!ControlValue::accepts(opcode));
     ASSERT(!MemoryValue::accepts(opcode));
     ASSERT(!PatchpointValue::accepts(opcode));
-    ASSERT(!StackSlotValue::accepts(opcode));
+    ASSERT(!SlotBaseValue::accepts(opcode));
     ASSERT(!UpsilonValue::accepts(opcode));
 }
 #endif // !ASSERT_DISABLED
index 8983e5c..370fca0 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "B3ArgumentRegValue.h"
 #include "B3ProcedureInlines.h"
+#include "B3SlotBaseValue.h"
 #include "B3ValueInlines.h"
 #include "B3ValueKeyInlines.h"
 
@@ -104,6 +105,8 @@ Value* ValueKey::materialize(Procedure& proc, Origin origin) const
         return proc.add<ConstFloatValue>(origin, floatValue());
     case ArgumentReg:
         return proc.add<ArgumentRegValue>(origin, Reg::fromIndex(static_cast<unsigned>(value())));
+    case SlotBase:
+        return proc.add<SlotBaseValue>(origin, proc.stackSlots()[value()]);
     default:
         return nullptr;
     }
index 85b63ae..9d8b834 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,7 +30,7 @@
 
 #include "AirCCallSpecial.h"
 #include "B3BasicBlockUtils.h"
-#include "B3StackSlotValue.h"
+#include "B3StackSlot.h"
 
 namespace JSC { namespace B3 { namespace Air {
 
@@ -52,17 +52,17 @@ BasicBlock* Code::addBlock(double frequency)
     return result;
 }
 
-StackSlot* Code::addStackSlot(unsigned byteSize, StackSlotKind kind, StackSlotValue* value)
+StackSlot* Code::addStackSlot(unsigned byteSize, StackSlotKind kind, B3::StackSlot* b3Slot)
 {
-    std::unique_ptr<StackSlot> slot(new StackSlot(byteSize, m_stackSlots.size(), kind, value));
+    std::unique_ptr<StackSlot> slot(new StackSlot(byteSize, m_stackSlots.size(), kind, b3Slot));
     StackSlot* result = slot.get();
     m_stackSlots.append(WTFMove(slot));
     return result;
 }
 
-StackSlot* Code::addStackSlot(StackSlotValue* value)
+StackSlot* Code::addStackSlot(B3::StackSlot* b3Slot)
 {
-    return addStackSlot(value->byteSize(), value->kind(), value);
+    return addStackSlot(b3Slot->byteSize(), b3Slot->kind(), b3Slot);
 }
 
 Special* Code::addSpecial(std::unique_ptr<Special> special)
index fadaa61..82ee42c 100644 (file)
@@ -68,8 +68,8 @@ public:
     // of any prior stack slot. In fact, all stack slots you create in the future will have an index
     // that is >= stackSlots().size().
     JS_EXPORT_PRIVATE StackSlot* addStackSlot(
-        unsigned byteSize, StackSlotKind, StackSlotValue* = nullptr);
-    StackSlot* addStackSlot(StackSlotValue*);
+        unsigned byteSize, StackSlotKind, B3::StackSlot* = nullptr);
+    StackSlot* addStackSlot(B3::StackSlot*);
 
     Special* addSpecial(std::unique_ptr<Special>);
 
index 0eec337..c23e77a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #if ENABLE(B3_JIT)
 
-#include "B3StackSlotValue.h"
+#include "B3StackSlot.h"
 
 namespace JSC { namespace B3 { namespace Air {
 
 void StackSlot::setOffsetFromFP(intptr_t value)
 {
     m_offsetFromFP = value;
-    if (m_value)
-        m_value->m_offsetFromFP = value;
+    if (m_b3Slot)
+        m_b3Slot->m_offsetFromFP = value;
 }
 
 void StackSlot::dump(PrintStream& out) const
@@ -47,16 +47,16 @@ void StackSlot::dump(PrintStream& out) const
 void StackSlot::deepDump(PrintStream& out) const
 {
     out.print("byteSize = ", m_byteSize, ", offsetFromFP = ", m_offsetFromFP, ", kind = ", m_kind);
-    if (m_value)
-        out.print(", value = ", *m_value);
+    if (m_b3Slot)
+        out.print(", b3Slot = ", *m_b3Slot, ": (", B3::deepDump(m_b3Slot), ")");
 }
 
-StackSlot::StackSlot(unsigned byteSize, unsigned index, StackSlotKind kind, StackSlotValue* value)
+StackSlot::StackSlot(unsigned byteSize, unsigned index, StackSlotKind kind, B3::StackSlot* b3Slot)
     : m_byteSize(byteSize)
     , m_index(index)
-    , m_offsetFromFP(value ? value->offsetFromFP() : 0)
+    , m_offsetFromFP(b3Slot ? b3Slot->offsetFromFP() : 0)
     , m_kind(kind)
-    , m_value(value)
+    , m_b3Slot(b3Slot)
 {
     ASSERT(byteSize);
 }
index dd02729..524f0d1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,7 +35,7 @@
 
 namespace JSC { namespace B3 {
 
-class StackSlotValue;
+class StackSlot;
 
 namespace Air {
 
@@ -65,7 +65,7 @@ public:
         return 8;
     }
 
-    StackSlotValue* value() const { return m_value; }
+    B3::StackSlot* b3Slot() const { return m_b3Slot; }
 
     // Zero means that it's not yet assigned.
     intptr_t offsetFromFP() const { return m_offsetFromFP; }
@@ -80,13 +80,13 @@ public:
 private:
     friend class Code;
 
-    StackSlot(unsigned byteSize, unsigned index, StackSlotKind, StackSlotValue*);
+    StackSlot(unsigned byteSize, unsigned index, StackSlotKind, B3::StackSlot*);
     
     unsigned m_byteSize;
     unsigned m_index;
     intptr_t m_offsetFromFP;
     StackSlotKind m_kind;
-    StackSlotValue* m_value;
+    B3::StackSlot* m_b3Slot;
 };
 
 class DeepStackSlotDump {
@@ -119,7 +119,7 @@ namespace WTF {
 
 inline void printInternal(PrintStream& out, JSC::B3::Air::StackSlot* stackSlot)
 {
-    out.print(*stackSlot);
+    out.print(pointerDump(stackSlot));
 }
 
 } // namespace WTF
index 1be1314..1685f4a 100644 (file)
@@ -37,7 +37,8 @@
 #include "B3MathExtras.h"
 #include "B3MemoryValue.h"
 #include "B3Procedure.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
+#include "B3StackSlot.h"
 #include "B3StackmapGenerationParams.h"
 #include "B3SwitchValue.h"
 #include "B3UpsilonValue.h"
@@ -4987,7 +4988,8 @@ void testStackSlot()
     BasicBlock* root = proc.addBlock();
     root->appendNew<ControlValue>(
         proc, Return, Origin(),
-        root->appendNew<StackSlotValue>(proc, Origin(), 1, StackSlotKind::Anonymous));
+        root->appendNew<SlotBaseValue>(
+            proc, Origin(), proc.addStackSlot(1, StackSlotKind::Anonymous)));
 
     void* stackSlot = compileAndRun<void*>(proc);
     CHECK(stackSlot < &proc);
@@ -5015,8 +5017,8 @@ void testStoreLoadStackSlot(int value)
     Procedure proc;
     BasicBlock* root = proc.addBlock();
 
-    StackSlotValue* stack = root->appendNew<StackSlotValue>(
-        proc, Origin(), sizeof(int), StackSlotKind::Anonymous);
+    SlotBaseValue* stack = root->appendNew<SlotBaseValue>(
+        proc, Origin(), proc.addStackSlot(sizeof(int), StackSlotKind::Anonymous));
 
     root->appendNew<MemoryValue>(
         proc, Store, Origin(),
index 97f34e0..24fe46a 100644 (file)
@@ -31,7 +31,7 @@
 #include "AirCode.h"
 #include "B3Generate.h"
 #include "B3ProcedureInlines.h"
-#include "B3StackSlotValue.h"
+#include "B3StackSlot.h"
 #include "CodeBlockWithJITType.h"
 #include "CCallHelpers.h"
 #include "DFGCommon.h"
@@ -84,6 +84,12 @@ void compile(State& state, Safepoint::Result& safepointResult)
 
     int localsOffset =
         state.capturedValue->offsetFromFP() / sizeof(EncodedJSValue) + graph.m_nextMachineLocal;
+    if (shouldDumpDisassembly()) {
+        dataLog(
+            "localsOffset = ", localsOffset, " for stack slot: ",
+            pointerDump(state.capturedValue), " at ", RawPointer(state.capturedValue), "\n");
+    }
+    
     for (unsigned i = graph.m_inlineVariableData.size(); i--;) {
         InlineCallFrame* inlineCallFrame = graph.m_inlineVariableData[i].inlineCallFrame;
         
index 1720c2b..9f958d6 100644 (file)
@@ -79,9 +79,10 @@ void Output::appendTo(LBasicBlock block)
     m_block = block;
 }
 
-StackSlotValue* Output::lockedStackSlot(size_t bytes)
+SlotBaseValue* Output::lockedStackSlot(size_t bytes)
 {
-    return m_block->appendNew<StackSlotValue>(m_proc, origin(), bytes, StackSlotKind::Locked);
+    return m_block->appendNew<SlotBaseValue>(
+        m_proc, origin(), m_proc.addStackSlot(bytes, StackSlotKind::Locked));
 }
 
 LValue Output::neg(LValue value)
index 6a0c103..20977c1 100644 (file)
@@ -40,7 +40,7 @@
 #include "B3ControlValue.h"
 #include "B3MemoryValue.h"
 #include "B3Procedure.h"
-#include "B3StackSlotValue.h"
+#include "B3SlotBaseValue.h"
 #include "B3SwitchValue.h"
 #include "B3UpsilonValue.h"
 #include "B3ValueInlines.h"
@@ -102,7 +102,7 @@ public:
 
     LValue framePointer() { return m_block->appendNew<B3::Value>(m_proc, B3::FramePointer, origin()); }
 
-    B3::StackSlotValue* lockedStackSlot(size_t bytes);
+    B3::SlotBaseValue* lockedStackSlot(size_t bytes);
 
     LValue constBool(bool value) { return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value); }
     LValue constInt32(int32_t value) { return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value); }
index c46406a..beb510a 100644 (file)
@@ -207,9 +207,9 @@ public:
 
 #if FTL_USES_B3
         size_t sizeOfCaptured = sizeof(JSValue) * m_graph.m_nextMachineLocal;
-        B3::StackSlotValue* capturedBase = m_out.lockedStackSlot(sizeOfCaptured);
+        B3::SlotBaseValue* capturedBase = m_out.lockedStackSlot(sizeOfCaptured);
         m_captured = m_out.add(capturedBase, m_out.constIntPtr(sizeOfCaptured));
-        state->capturedValue = capturedBase;
+        state->capturedValue = capturedBase->slot();
 #else // FTL_USES_B3
         LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
         
index 852fb92..68eca33 100644 (file)
@@ -47,7 +47,7 @@ namespace JSC {
 
 namespace B3 {
 class PatchpointValue;
-class StackSlotValue;
+class StackSlot;
 } // namespace B3
 
 namespace FTL {
@@ -89,7 +89,7 @@ public:
     // are no applicable catch blocks anywhere in the Graph.
     RefPtr<PatchpointExceptionHandle> defaultExceptionHandle;
     Box<CCallHelpers::Label> exceptionHandler { Box<CCallHelpers::Label>::create() };
-    B3::StackSlotValue* capturedValue { nullptr };
+    B3::StackSlot* capturedValue { nullptr };
 #else // FTL_USES_B3
     unsigned handleStackOverflowExceptionStackmapID { UINT_MAX };
     unsigned handleExceptionStackmapID { UINT_MAX };