From 6ff1095159bebe287a898b07eace357be171dca7 Mon Sep 17 00:00:00 2001
From: whh8b <whh8b@git.zephyr-software.com>
Date: Fri, 24 Oct 2014 17:36:08 +0000
Subject: [PATCH] Implement binary search for memory space free ranges

---
 include/memory_space.h | 12 +++++--
 include/range.h        |  4 +--
 src/memory_space.cpp   | 75 ++++++++++++++++++++++++++++++++++++++++++
 src/zipr.cpp           |  3 ++
 4 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/include/memory_space.h b/include/memory_space.h
index 8133d21..1b466bd 100644
--- a/include/memory_space.h
+++ b/include/memory_space.h
@@ -36,8 +36,8 @@ class Options_t;
 class MemorySpace_t
 {
 	public:
-		MemorySpace_t():m_opts(NULL) { }
-		MemorySpace_t(Options_t *opts):m_opts(opts) { }
+		MemorySpace_t():m_opts(NULL),m_is_sorted(false),free_ranges_ptrs(NULL) { }
+		MemorySpace_t(Options_t *opts):m_opts(opts),m_is_sorted(false),free_ranges_ptrs(NULL) { }
 
 		// range operatations
 		void SplitFreeRange(RangeAddress_t addr);
@@ -53,10 +53,18 @@ class MemorySpace_t
 
 		int GetRangeCount();
 
+		void Sort();
+
 		void PrintMemorySpace(std::ostream &out);
 	protected:
 		std::list<Range_t> free_ranges;   // keep ordered
 		Options_t *m_opts;
+		bool m_is_sorted;
+	private:
+		std::list<Range_t>::iterator FindFreeRangeB(int startIndex, int stopIndex,
+			RangeAddress_t addr);
+		std::list<Range_t>::iterator **free_ranges_ptrs;
+		int free_ranges_ptrs_size;
 };
 
 #endif
diff --git a/include/range.h b/include/range.h
index e0ec3b7..ce8b45b 100644
--- a/include/range.h
+++ b/include/range.h
@@ -40,8 +40,8 @@ class Range_t
 		Range_t(RangeAddress_t p_s, RangeAddress_t p_e) : m_start(p_s), m_end(p_e) { }
 		Range_t() : m_start(0), m_end(0) { }
 
-		RangeAddress_t GetStart() { return m_start; }
-		RangeAddress_t GetEnd() { return m_end; }
+		RangeAddress_t GetStart() const { return m_start; }
+		RangeAddress_t GetEnd() const { return m_end; }
 
 		bool Is2ByteRange()
 		{
diff --git a/src/memory_space.cpp b/src/memory_space.cpp
index c63ff25..6195896 100644
--- a/src/memory_space.cpp
+++ b/src/memory_space.cpp
@@ -6,6 +6,35 @@
 using namespace zipr;
 using namespace std;
 
+static bool range_compare(const Range_t first, const Range_t second)
+{
+	return first.GetStart() < second.GetStart();
+}
+
+void MemorySpace_t::Sort()
+{
+	int i = 0;
+	list<Range_t>::iterator it;
+
+	if (free_ranges_ptrs != NULL)
+	{
+		for (int j = 0; j<free_ranges_ptrs_size; j++)
+			delete free_ranges_ptrs[j];
+		free(free_ranges_ptrs);
+	}
+
+	free_ranges.sort(range_compare);
+
+	free_ranges_ptrs = (std::list<Range_t>::iterator**)malloc(sizeof(std::list<Range_t>::iterator*)*free_ranges.size());
+	for(i=0,it=free_ranges.begin();it!=free_ranges.end();++it,++i)
+	{
+		free_ranges_ptrs[i] = new std::list<Range_t>::iterator(it);
+	}
+
+	m_is_sorted = true;
+	free_ranges_ptrs_size = free_ranges.size();
+}
+
 void MemorySpace_t::SplitFreeRange(RangeAddress_t addr)
 {
 	list<Range_t>::iterator it=FindFreeRange(addr);
@@ -13,6 +42,8 @@ void MemorySpace_t::SplitFreeRange(RangeAddress_t addr)
 
 	Range_t r=*it;
 
+	m_is_sorted = false;
+
 	if(r.GetStart()==r.GetEnd())
 	{
 		assert(addr==r.GetEnd());
@@ -50,6 +81,9 @@ void MemorySpace_t::MergeFreeRange(RangeAddress_t addr)
 	Range_t nr(addr, addr);
 	bool merged = false;
 	list<Range_t>::iterator it=free_ranges.begin();
+
+	m_is_sorted = false;
+
 	for(;it!=free_ranges.end();++it)
 	{
 		Range_t r=*it;
@@ -154,8 +188,48 @@ void MemorySpace_t::PrintMemorySpace(std::ostream &out)
 	}
 }
 
+std::list<Range_t>::iterator MemorySpace_t::FindFreeRangeB(
+	int startIndex,
+	int stopIndex,
+	RangeAddress_t addr)
+{
+	std::list<Range_t>::iterator *start = free_ranges_ptrs[startIndex];
+	std::list<Range_t>::iterator *stop = free_ranges_ptrs[stopIndex];
+	Range_t startRange = **start;
+	Range_t stopRange = **stop;
+	if (startIndex == stopIndex)
+		return free_ranges.end();
+	else if (startRange.GetStart() <= addr && addr <=startRange.GetEnd())
+		return *start;
+	else if (stopRange.GetStart() <= addr && addr <=stopRange.GetEnd())
+		return *stop;
+	else
+	{
+		/*
+		 * mid startIndex - stopIndex 
+		 */
+		int midIndex = startIndex + ((stopIndex-startIndex)/2);
+		Range_t mid = **(free_ranges_ptrs[midIndex]);
+
+		if (mid.GetStart() <= addr && addr <=mid.GetEnd())
+			return *free_ranges_ptrs[midIndex];
+		else if (addr <= mid.GetStart()) {
+			return FindFreeRangeB(startIndex, std::max(0, std::max(--midIndex, startIndex)), addr);
+		}
+		else
+		{
+			return FindFreeRangeB(std::min(++midIndex, stopIndex), stopIndex, addr);
+		}
+	}
+}
+
 std::list<Range_t>::iterator MemorySpace_t::FindFreeRange(RangeAddress_t addr)
 {
+	if (m_is_sorted)
+	{
+		return FindFreeRangeB(0, free_ranges.size()-1, addr);
+	}
+
 	for( list<Range_t>::iterator it=free_ranges.begin();
 		it!=free_ranges.end();
 		++it)
@@ -203,6 +277,7 @@ bool MemorySpace_t::IsByteFree(RangeAddress_t addr)
 
 void MemorySpace_t::AddFreeRange(Range_t newRange)
 {
+	m_is_sorted = false;
 	free_ranges.push_back(Range_t(newRange.GetStart(), newRange.GetEnd()));
 }
 int MemorySpace_t::GetRangeCount()
diff --git a/src/zipr.cpp b/src/zipr.cpp
index 6acd690..55591c6 100644
--- a/src/zipr.cpp
+++ b/src/zipr.cpp
@@ -95,8 +95,10 @@ void Zipr_t::CreateBinaryFile(const std::string &name)
 			printf("Going to Re PreReserve2ByteJumpTargets.\n");
 			PreReserve2ByteJumpTargets();
 		}
+		memory_space.Sort();
 	}
 
+
 	// Convert all 5-byte pins into full fragments
 	OptimizePinnedInstructions();
 
@@ -108,6 +110,7 @@ void Zipr_t::CreateBinaryFile(const std::string &name)
 	UpdateCallbacks();
 
 	m_stats->total_free_ranges = memory_space.GetRangeCount();
+	memory_space.Sort();
 
 	// write binary file to disk 
 	OutputBinaryFile(name);
-- 
GitLab