bool GeneratedSourceMap::searchLineByOffset(JSContext* cx, uint32_t offset, size_t* exprlocIndex) { MOZ_ASSERT(!exprlocs_.empty()); size_t exprlocsLength = exprlocs_.length(); // Lazily build sorted array for fast log(n) lookup. if (!sortedByOffsetExprLocIndices_) { ExprLocIndexVector scratch; auto indices = MakeUnique<ExprLocIndexVector>(); if (!indices || !indices->resize(exprlocsLength) || !scratch.resize(exprlocsLength)) { ReportOutOfMemory(cx); return false; } sortedByOffsetExprLocIndices_ = Move(indices); for (size_t i = 0; i < exprlocsLength; i++) (*sortedByOffsetExprLocIndices_)[i] = i; auto compareExprLocViaIndex = [&](uint32_t i, uint32_t j, bool* lessOrEqualp) -> bool { *lessOrEqualp = exprlocs_[i].offset <= exprlocs_[j].offset; return true; }; MOZ_ALWAYS_TRUE(MergeSort(sortedByOffsetExprLocIndices_->begin(), exprlocsLength, scratch.begin(), compareExprLocViaIndex)); } // Allowing non-exact search and if BinarySearchIf returns out-of-bound // index, moving the index to the last index. auto lookupFn = [&](uint32_t i) -> int { const ExprLoc& loc = exprlocs_[i]; return offset == loc.offset ? 0 : offset < loc.offset ? -1 : 1; }; size_t match; Unused << BinarySearchIf(sortedByOffsetExprLocIndices_->begin(), 0, exprlocsLength, lookupFn, &match); if (match >= exprlocsLength) match = exprlocsLength - 1; *exprlocIndex = (*sortedByOffsetExprLocIndices_)[match]; return true; }
int32_t gfxMathTable::GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph) { using mozilla::BinarySearch; using mozilla::BinarySearchIf; if (uint16_t(aCoverage->mFormat) == 1) { // Coverage Format 1: list of individual glyph indices in the glyph set. const CoverageFormat1* table = reinterpret_cast<const CoverageFormat1*>(aCoverage); const uint16_t count = table->mGlyphCount; const char* start = reinterpret_cast<const char*>(table + 1); if (ValidStructure(start, count * sizeof(GlyphID))) { const GlyphID* glyphArray = reinterpret_cast<const GlyphID*>(start); size_t index; if (BinarySearch(GlyphArrayWrapper(glyphArray), 0, count, aGlyph, &index)) { return index; } } } else if (uint16_t(aCoverage->mFormat) == 2) { // Coverage Format 2: ranges of consecutive indices. const CoverageFormat2* table = reinterpret_cast<const CoverageFormat2*>(aCoverage); const uint16_t count = table->mRangeCount; const char* start = reinterpret_cast<const char*>(table + 1); if (ValidStructure(start, count * sizeof(RangeRecord))) { const RangeRecord* rangeArray = reinterpret_cast<const RangeRecord*>(start); size_t index; if (BinarySearchIf(rangeArray, 0, count, RangeRecordComparator(aGlyph), &index)) { uint16_t rStart = rangeArray[index].mStart; uint16_t startCoverageIndex = rangeArray[index].mStartCoverageIndex; return (startCoverageIndex + aGlyph - rStart); } } } return -1; }
bool DebugState::getLineOffsets(JSContext* cx, size_t lineno, Vector<uint32_t>* offsets) { if (!debugEnabled()) return true; if (binarySource_) { const CallSite* callsite = SlowCallSiteSearchByOffset(metadata(Tier::Debug), lineno); if (callsite && !offsets->append(lineno)) return false; return true; } if (!ensureSourceMap(cx)) return false; if (!maybeSourceMap_) return true; // no source text available, keep offsets empty. ExprLocVector& exprlocs = maybeSourceMap_->exprlocs(); // Binary search for the expression with the specified line number and // rewind to the first expression, if more than one expression on the same line. size_t match; if (!BinarySearchIf(exprlocs, 0, exprlocs.length(), LineComparator(lineno), &match)) return true; while (match > 0 && exprlocs[match - 1].lineno == lineno) match--; // Return all expression offsets that were printed on the specified line. for (size_t i = match; i < exprlocs.length() && exprlocs[i].lineno == lineno; i++) { if (!offsets->append(exprlocs[i].offset)) return false; } return true; }