mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 998507 - add BinarySearch (r=sunfish)
--HG-- extra : rebase_source : 6ba04575a5dd8a886235e6799bc790c7a3afc64f
This commit is contained in:
parent
f359659e38
commit
854107dda5
@ -6,6 +6,8 @@
|
||||
|
||||
#include "jit/AsmJSSignalHandlers.h"
|
||||
|
||||
#include "mozilla/BinarySearch.h"
|
||||
|
||||
#include "assembler/assembler/MacroAssembler.h"
|
||||
#include "jit/AsmJSModule.h"
|
||||
|
||||
@ -207,35 +209,29 @@ SetXMMRegToNaN(bool isFloat32, T *xmm_reg)
|
||||
}
|
||||
}
|
||||
|
||||
struct GetHeapAccessOffset
|
||||
{
|
||||
const AsmJSModule &module;
|
||||
explicit GetHeapAccessOffset(const AsmJSModule &module) : module(module) {}
|
||||
uintptr_t operator[](size_t index) const {
|
||||
return module.heapAccess(index).offset();
|
||||
}
|
||||
};
|
||||
|
||||
// Perform a binary search on the projected offsets of the known heap accesses
|
||||
// in the module.
|
||||
static const AsmJSHeapAccess *
|
||||
LookupHeapAccess(const AsmJSModule &module, uint8_t *pc)
|
||||
{
|
||||
JS_ASSERT(module.containsPC(pc));
|
||||
size_t targetOffset = pc - module.codeBase();
|
||||
|
||||
if (module.numHeapAccesses() == 0)
|
||||
uintptr_t pcOff = pc - module.codeBase();
|
||||
|
||||
size_t match;
|
||||
if (!BinarySearch(GetHeapAccessOffset(module), 0, module.numHeapAccesses(), pcOff, &match))
|
||||
return nullptr;
|
||||
|
||||
size_t low = 0;
|
||||
size_t high = module.numHeapAccesses() - 1;
|
||||
while (high - low >= 2) {
|
||||
size_t mid = low + (high - low) / 2;
|
||||
uint32_t midOffset = module.heapAccess(mid).offset();
|
||||
if (targetOffset == midOffset)
|
||||
return &module.heapAccess(mid);
|
||||
if (targetOffset < midOffset)
|
||||
high = mid;
|
||||
else
|
||||
low = mid;
|
||||
}
|
||||
if (targetOffset == module.heapAccess(low).offset())
|
||||
return &module.heapAccess(low);
|
||||
if (targetOffset == module.heapAccess(high).offset())
|
||||
return &module.heapAccess(high);
|
||||
|
||||
return nullptr;
|
||||
return &module.heapAccess(match);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
62
mfbt/BinarySearch.h
Normal file
62
mfbt/BinarySearch.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_BinarySearch_h
|
||||
#define mozilla_BinarySearch_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* The algorithm searches the given container 'c' over the sorted index range
|
||||
* [begin, end) for an index 'i' where 'c[i] == target'. If such an index 'i' is
|
||||
* found, BinarySearch returns 'true' and the index is returned via the outparam
|
||||
* 'matchOrInsertionPoint'. If no index is found, BinarySearch returns 'false'
|
||||
* and the outparam returns the first index in [begin, end] where 'target' can
|
||||
* be inserted to maintain sorted order.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* Vector<int> sortedInts = ...
|
||||
*
|
||||
* size_t match;
|
||||
* if (BinarySearch(sortedInts, 0, sortedInts.length(), 13, &match))
|
||||
* printf("found 13 at %lu\n", match);
|
||||
*/
|
||||
|
||||
template <typename Container, typename T>
|
||||
bool
|
||||
BinarySearch(const Container &c, size_t begin, size_t end, T target, size_t *matchOrInsertionPoint)
|
||||
{
|
||||
MOZ_ASSERT(begin <= end);
|
||||
|
||||
size_t low = begin;
|
||||
size_t high = end;
|
||||
while (low != high) {
|
||||
size_t middle = low + (high - low) / 2;
|
||||
const T &middleValue = c[middle];
|
||||
|
||||
if (target == middleValue) {
|
||||
*matchOrInsertionPoint = middle;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (target < middleValue)
|
||||
high = middle;
|
||||
else
|
||||
low = middle + 1;
|
||||
}
|
||||
|
||||
*matchOrInsertionPoint = low;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_BinarySearch_h
|
@ -16,6 +16,7 @@ EXPORTS.mozilla = [
|
||||
'Assertions.h',
|
||||
'Atomics.h',
|
||||
'Attributes.h',
|
||||
'BinarySearch.h',
|
||||
'BloomFilter.h',
|
||||
'Casting.h',
|
||||
'ChaosMode.h',
|
||||
|
75
mfbt/tests/TestBinarySearch.cpp
Normal file
75
mfbt/tests/TestBinarySearch.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/Vector.h"
|
||||
|
||||
using mozilla::Vector;
|
||||
using mozilla::BinarySearch;
|
||||
|
||||
struct Person
|
||||
{
|
||||
int age;
|
||||
int id;
|
||||
Person(int age, int id) : age(age), id(id) {}
|
||||
};
|
||||
|
||||
struct GetAge
|
||||
{
|
||||
Vector<Person> &v;
|
||||
GetAge(Vector<Person> &v) : v(v) {}
|
||||
int operator[](size_t index) const { return v[index].age; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t m;
|
||||
|
||||
Vector<int> v1;
|
||||
v1.append(2);
|
||||
v1.append(4);
|
||||
v1.append(6);
|
||||
v1.append(8);
|
||||
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, v1.length(), 1, &m) && m == 0);
|
||||
MOZ_ASSERT( BinarySearch(v1, 0, v1.length(), 2, &m) && m == 0);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, v1.length(), 3, &m) && m == 1);
|
||||
MOZ_ASSERT( BinarySearch(v1, 0, v1.length(), 4, &m) && m == 1);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, v1.length(), 5, &m) && m == 2);
|
||||
MOZ_ASSERT( BinarySearch(v1, 0, v1.length(), 6, &m) && m == 2);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, v1.length(), 7, &m) && m == 3);
|
||||
MOZ_ASSERT( BinarySearch(v1, 0, v1.length(), 8, &m) && m == 3);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, v1.length(), 9, &m) && m == 4);
|
||||
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 1, &m) && m == 1);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 2, &m) && m == 1);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 3, &m) && m == 1);
|
||||
MOZ_ASSERT( BinarySearch(v1, 1, 3, 4, &m) && m == 1);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 5, &m) && m == 2);
|
||||
MOZ_ASSERT( BinarySearch(v1, 1, 3, 6, &m) && m == 2);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 7, &m) && m == 3);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 8, &m) && m == 3);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 1, 3, 9, &m) && m == 3);
|
||||
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, 0, 0, &m) && m == 0);
|
||||
MOZ_ASSERT(!BinarySearch(v1, 0, 0, 9, &m) && m == 0);
|
||||
|
||||
Vector<int> v2;
|
||||
MOZ_ASSERT(!BinarySearch(v2, 0, 0, 0, &m) && m == 0);
|
||||
MOZ_ASSERT(!BinarySearch(v2, 0, 0, 9, &m) && m == 0);
|
||||
|
||||
Vector<Person> v3;
|
||||
v3.append(Person(2, 42));
|
||||
v3.append(Person(4, 13));
|
||||
v3.append(Person(6, 360));
|
||||
MOZ_ASSERT(!BinarySearch(GetAge(v3), 0, v3.length(), 1, &m) && m == 0);
|
||||
MOZ_ASSERT( BinarySearch(GetAge(v3), 0, v3.length(), 2, &m) && m == 0);
|
||||
MOZ_ASSERT(!BinarySearch(GetAge(v3), 0, v3.length(), 3, &m) && m == 1);
|
||||
MOZ_ASSERT( BinarySearch(GetAge(v3), 0, v3.length(), 4, &m) && m == 1);
|
||||
MOZ_ASSERT(!BinarySearch(GetAge(v3), 0, v3.length(), 5, &m) && m == 2);
|
||||
MOZ_ASSERT( BinarySearch(GetAge(v3), 0, v3.length(), 6, &m) && m == 2);
|
||||
MOZ_ASSERT(!BinarySearch(GetAge(v3), 0, v3.length(), 7, &m) && m == 3);
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
|
||||
CPP_UNIT_TESTS += [
|
||||
'TestAtomics.cpp',
|
||||
'TestBinarySearch.cpp',
|
||||
'TestBloomFilter.cpp',
|
||||
'TestCasting.cpp',
|
||||
'TestCeilingFloor.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user