B3 -O1 should not allocateStackByGraphColoring
[WebKit-https.git] / Source / JavaScriptCore / b3 / air / AirCode.cpp
index 85b63ae..7cb8e70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 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 "AirCCallSpecial.h"
+#include "AirCFG.h"
 #include "B3BasicBlockUtils.h"
-#include "B3StackSlotValue.h"
+#include "B3Procedure.h"
+#include "B3StackSlot.h"
+#include <wtf/ListDump.h>
 
 namespace JSC { namespace B3 { namespace Air {
 
 Code::Code(Procedure& proc)
     : m_proc(proc)
+    , m_cfg(new CFG(*this))
     , m_lastPhaseName("initial")
 {
+    // Come up with initial orderings of registers. The user may replace this with something else.
+    forEachBank(
+        [&] (Bank bank) {
+            Vector<Reg> result;
+            RegisterSet all = bank == GP ? RegisterSet::allGPRs() : RegisterSet::allFPRs();
+            all.exclude(RegisterSet::stackRegisters());
+            all.exclude(RegisterSet::reservedHardwareRegisters());
+            RegisterSet calleeSave = RegisterSet::calleeSaveRegisters();
+            all.forEach(
+                [&] (Reg reg) {
+                    if (!calleeSave.get(reg))
+                        result.append(reg);
+                });
+            all.forEach(
+                [&] (Reg reg) {
+                    if (calleeSave.get(reg))
+                        result.append(reg);
+                });
+            setRegsInPriorityOrder(bank, result);
+        });
 }
 
 Code::~Code()
 {
 }
 
+void Code::setRegsInPriorityOrder(Bank bank, const Vector<Reg>& regs)
+{
+    regsInPriorityOrderImpl(bank) = regs;
+    m_mutableRegs = RegisterSet();
+    forEachBank(
+        [&] (Bank bank) {
+            for (Reg reg : regsInPriorityOrder(bank))
+                m_mutableRegs.set(reg);
+        });
+}
+
+void Code::pinRegister(Reg reg)
+{
+    Vector<Reg>& regs = regsInPriorityOrderImpl(Arg(Tmp(reg)).bank());
+    regs.removeFirst(reg);
+    m_mutableRegs.clear(reg);
+    ASSERT(!regs.contains(reg));
+}
+
+bool Code::needsUsedRegisters() const
+{
+    return m_proc.needsUsedRegisters();
+}
+
 BasicBlock* Code::addBlock(double frequency)
 {
     std::unique_ptr<BasicBlock> block(new BasicBlock(m_blocks.size(), frequency));
@@ -52,25 +100,27 @@ 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));
-    StackSlot* result = slot.get();
-    m_stackSlots.append(WTFMove(slot));
+    StackSlot* result = m_stackSlots.addNew(byteSize, kind, b3Slot);
+    if (m_stackIsAllocated) {
+        // FIXME: This is unnecessarily awful. Fortunately, it doesn't run often.
+        unsigned extent = WTF::roundUpToMultipleOf(result->alignment(), frameSize() + byteSize);
+        result->setOffsetFromFP(-static_cast<ptrdiff_t>(extent));
+        setFrameSize(WTF::roundUpToMultipleOf(stackAlignmentBytes(), extent));
+    }
     return result;
 }
 
-StackSlot* Code::addStackSlot(StackSlotValue* value)
+StackSlot* Code::addStackSlot(B3::StackSlot* b3Slot)
 {
-    return addStackSlot(value->byteSize(), value->kind(), value);
+    return addStackSlot(b3Slot->byteSize(), StackSlotKind::Locked, b3Slot);
 }
 
 Special* Code::addSpecial(std::unique_ptr<Special> special)
 {
-    Special* result = special.get();
-    result->m_code = this;
-    m_specials.append(WTFMove(special));
-    return result;
+    special->m_code = this;
+    return m_specials.add(WTFMove(special));
 }
 
 CCallSpecial* Code::cCallSpecial()
@@ -83,17 +133,60 @@ CCallSpecial* Code::cCallSpecial()
     return m_cCallSpecial;
 }
 
+bool Code::isEntrypoint(BasicBlock* block) const
+{
+    if (m_entrypoints.isEmpty())
+        return !block->index();
+    
+    for (const FrequentedBlock& entrypoint : m_entrypoints) {
+        if (entrypoint.block() == block)
+            return true;
+    }
+    return false;
+}
+
+void Code::setCalleeSaveRegisterAtOffsetList(RegisterAtOffsetList&& registerAtOffsetList, StackSlot* slot)
+{
+    m_uncorrectedCalleeSaveRegisterAtOffsetList = WTFMove(registerAtOffsetList);
+    for (const RegisterAtOffset& registerAtOffset : m_uncorrectedCalleeSaveRegisterAtOffsetList)
+        m_calleeSaveRegisters.set(registerAtOffset.reg());
+    m_calleeSaveStackSlot = slot;
+}
+
+RegisterAtOffsetList Code::calleeSaveRegisterAtOffsetList() const
+{
+    RegisterAtOffsetList result = m_uncorrectedCalleeSaveRegisterAtOffsetList;
+    if (StackSlot* slot = m_calleeSaveStackSlot) {
+        ptrdiff_t offset = slot->byteSize() + slot->offsetFromFP();
+        for (size_t i = result.size(); i--;) {
+            result.at(i) = RegisterAtOffset(
+                result.at(i).reg(),
+                result.at(i).offset() + offset);
+        }
+    }
+    return result;
+}
+
 void Code::resetReachability()
 {
-    B3::resetReachability(
-        m_blocks,
-        [&] (BasicBlock*) {
-            // We don't have to do anything special for deleted blocks.
-        });
+    clearPredecessors(m_blocks);
+    if (m_entrypoints.isEmpty())
+        updatePredecessorsAfter(m_blocks[0].get());
+    else {
+        for (const FrequentedBlock& entrypoint : m_entrypoints)
+            updatePredecessorsAfter(entrypoint.block());
+    }
+    
+    for (auto& block : m_blocks) {
+        if (isBlockDead(block.get()) && !isEntrypoint(block.get()))
+            block = nullptr;
+    }
 }
 
 void Code::dump(PrintStream& out) const
 {
+    if (!m_entrypoints.isEmpty())
+        out.print("Entrypoints: ", listDump(m_entrypoints), "\n");
     for (BasicBlock* block : *this)
         out.print(deepDump(block));
     if (stackSlots().size()) {
@@ -106,12 +199,13 @@ void Code::dump(PrintStream& out) const
         for (Special* special : specials())
             out.print("    ", deepDump(special), "\n");
     }
-    if (m_frameSize)
-        out.print("Frame size: ", m_frameSize, "\n");
+    if (m_frameSize || m_stackIsAllocated)
+        out.print("Frame size: ", m_frameSize, m_stackIsAllocated ? " (Allocated)" : "", "\n");
     if (m_callArgAreaSize)
         out.print("Call arg area size: ", m_callArgAreaSize, "\n");
-    if (m_calleeSaveRegisters.size())
-        out.print("Callee saves: ", m_calleeSaveRegisters, "\n");
+    RegisterAtOffsetList calleeSaveRegisters = this->calleeSaveRegisterAtOffsetList();
+    if (calleeSaveRegisters.size())
+        out.print("Callee saves: ", calleeSaveRegisters, "\n");
 }
 
 unsigned Code::findFirstBlockIndex(unsigned index) const
@@ -139,6 +233,34 @@ void Code::addFastTmp(Tmp tmp)
     m_fastTmps.add(tmp);
 }
 
+void* Code::addDataSection(size_t size)
+{
+    return m_proc.addDataSection(size);
+}
+
+unsigned Code::jsHash() const
+{
+    unsigned result = 0;
+    
+    for (BasicBlock* block : *this) {
+        result *= 1000001;
+        for (Inst& inst : *block) {
+            result *= 97;
+            result += inst.jsHash();
+        }
+        for (BasicBlock* successor : block->successorBlocks()) {
+            result *= 7;
+            result += successor->index();
+        }
+    }
+    for (StackSlot* slot : stackSlots()) {
+        result *= 101;
+        result += slot->jsHash();
+    }
+    
+    return result;
+}
+
 } } } // namespace JSC::B3::Air
 
 #endif // ENABLE(B3_JIT)