const BitArray getActiveInputChannels() const { BitArray inputBits; for (int i = 0; i < inputPorts.size(); i++) if (JUCE_NAMESPACE::jack_port_connected ((jack_port_t*) inputPorts [i])) inputBits.setBit (i); return inputBits; }
Error Context::livenessAnalysis() { uint32_t bLen = static_cast<uint32_t>( ((_contextVd.getLength() + BitArray::kEntityBits - 1) / BitArray::kEntityBits)); // No variables. if (bLen == 0) return kErrorOk; HLFunc* func = getFunc(); HLJump* from = NULL; LivenessTarget* ltCur = NULL; LivenessTarget* ltUnused = NULL; PodList<HLNode*>::Link* retPtr = _returningList.getFirst(); ASMJIT_ASSERT(retPtr != NULL); HLNode* node = retPtr->getValue(); size_t varMapToVaListOffset = _varMapToVaListOffset; BitArray* bCur = newBits(bLen); if (bCur == NULL) goto _NoMemory; // Allocate bits for code visited first time. _OnVisit: for (;;) { if (node->hasLiveness()) { if (bCur->_addBitsDelSource(node->getLiveness(), bCur, bLen)) goto _OnPatch; else goto _OnDone; } BitArray* bTmp = copyBits(bCur, bLen); if (bTmp == NULL) goto _NoMemory; node->setLiveness(bTmp); VarMap* map = node->getMap(); if (map != NULL) { uint32_t vaCount = map->getVaCount(); VarAttr* vaList = reinterpret_cast<VarAttr*>(((uint8_t*)map) + varMapToVaListOffset); for (uint32_t i = 0; i < vaCount; i++) { VarAttr* va = &vaList[i]; VarData* vd = va->getVd(); uint32_t flags = va->getFlags(); uint32_t ctxId = vd->getLocalId(); if ((flags & kVarAttrWAll) && !(flags & kVarAttrRAll)) { // Write-Only. bTmp->setBit(ctxId); bCur->delBit(ctxId); } else { // Read-Only or Read/Write. bTmp->setBit(ctxId); bCur->setBit(ctxId); } } } if (node->getType() == kHLNodeTypeLabel) goto _OnTarget; if (node == func) goto _OnDone; ASMJIT_ASSERT(node->getPrev()); node = node->getPrev(); } // Patch already generated liveness bits. _OnPatch: for (;;) { ASMJIT_ASSERT(node->hasLiveness()); BitArray* bNode = node->getLiveness(); if (!bNode->_addBitsDelSource(bCur, bLen)) goto _OnDone; if (node->getType() == kHLNodeTypeLabel) goto _OnTarget; if (node == func) goto _OnDone; node = node->getPrev(); } _OnTarget: if (static_cast<HLLabel*>(node)->getNumRefs() != 0) { // Push a new LivenessTarget onto the stack if needed. if (ltCur == NULL || ltCur->node != node) { // Allocate a new LivenessTarget object (from pool or zone). LivenessTarget* ltTmp = ltUnused; if (ltTmp != NULL) { ltUnused = ltUnused->prev; } else { ltTmp = _zoneAllocator.allocT<LivenessTarget>( sizeof(LivenessTarget) - sizeof(BitArray) + bLen * sizeof(uintptr_t)); if (ltTmp == NULL) goto _NoMemory; } // Initialize and make current - ltTmp->from will be set later on. ltTmp->prev = ltCur; ltTmp->node = static_cast<HLLabel*>(node); ltCur = ltTmp; from = static_cast<HLLabel*>(node)->getFrom(); ASMJIT_ASSERT(from != NULL); } else { from = ltCur->from; goto _OnJumpNext; } // Visit/Patch. do { ltCur->from = from; bCur->copyBits(node->getLiveness(), bLen); if (!from->hasLiveness()) { node = from; goto _OnVisit; } // Issue #25: Moved '_OnJumpNext' here since it's important to patch // code again if there are more live variables than before. _OnJumpNext: if (bCur->delBits(from->getLiveness(), bLen)) { node = from; goto _OnPatch; } from = from->getJumpNext(); } while (from != NULL); // Pop the current LivenessTarget from the stack. { LivenessTarget* ltTmp = ltCur; ltCur = ltCur->prev; ltTmp->prev = ltUnused; ltUnused = ltTmp; } } bCur->copyBits(node->getLiveness(), bLen); node = node->getPrev(); if (node->isJmp() || !node->isFetched()) goto _OnDone; if (!node->hasLiveness()) goto _OnVisit; if (bCur->delBits(node->getLiveness(), bLen)) goto _OnPatch; _OnDone: if (ltCur != NULL) { node = ltCur->node; from = ltCur->from; goto _OnJumpNext; } retPtr = retPtr->getNext(); if (retPtr != NULL) { node = retPtr->getValue(); goto _OnVisit; } return kErrorOk; _NoMemory: return setLastError(kErrorNoHeapMemory); }