Arquivos
hhvm/hphp/util/tiny_vector.h
T
Todd Nowacki adda9a5022 HPHP Changes for Clang
More changes for HPHP to help make it clang friendly

~~~hphp/compiler/expression/constant_expression.h
~~~hphp/compiler/expression/function_call.h
  rfind returns a size_t/unsigned int

~~~hphp/runtime/base/server/http_protocol.cpp
  Switched to std::to_string. Assuming [] was not intended here

~~~hphp/runtime/base/ref_data.h
  These fields were accessed in a public manner, assuming public was intended
  instead of private

~~~hphp/runtime/base/variable_serializer.cpp
  Switched to using [] and & to make clang happy. Assuming this was to either
  take or drop the first char.

~~~hphp/runtime/ext/asio/asio_external_thread_event_queue.h
~~~hphp/runtime/ext/asio/asio_external_thread_event_queue.cpp
  Cast  which performs the conversions of a reinterpret_cast is not
  allowed in a constant expression. This is been moved to a macro as a temporary
  fix.

+++hphp/runtime/ext/ext_misc.cpp
  Added std::atomic to supress warnings

~~~hphp/runtime/vm/jit/simplifier.cpp
  Chosen constructor is explicit in copy-initialization

~~~hphp/runtime/vm/jit/translator-asm-helpers.S
  Ambiguous instructions require an explicit suffix
  Changed cmp to cmpl

~~~hphp/runtime/vm/jit/translator-x64-helpers.cpp
  Clang does not support global register variables

+++hphp/runtime/vm/unwind.cpp
  describeFault was only used when DEBUG or USE_TRACE was defined

~~~hphp/runtime/vm/verifier/check_unit.cpp
  Made fmt pointer const to avoid string format issues/warnings

~~~hphp/util/stack_trace.cpp
  Clang does not support variable-length arrays.
  Uniqe_ptr is used instead to take advantage runtime-sized arrays, a
  restriced form of variable-length arrays

~~~hphp/util/thread_local.h
  Clang seems to be supporting the __thread attribute, or at the very least
  it is not complaining about it.

~~~hphp/util/tiny_vector.h
  Clang does not like the flexible array here, since T is not always POD.
  I have reimplemented the array here by just sticking one value in the struct
  and calculating the offset from its address manually.
  Alterinatively, we could change the the non-POD types to be pointers, or
  we could edit their implemenations.

+++hphp/util/util.h
  Created a template for the union,
  A function declared with the constexpr specifier cannot contain
  type declarations that do not define classes or enumerations

+++hphp/runtime/vm/jit/x64-util.h
  Added a TODO
  The way hphp/runtime/vm/jit/x64-util.h is currently implemented, it only
  works if USE_GCC_FAST_TLS is defined
2013-06-25 13:19:03 -07:00

218 linhas
6.3 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_UTIL_TINYVECTOR_H_
#define incl_HPHP_UTIL_TINYVECTOR_H_
#include <stdlib.h>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <algorithm>
#include "hphp/util/alloc.h"
#include "hphp/util/assertions.h"
#include "hphp/util/compact_sized_ptr.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
/*
* Simple, small buffer-optimized sequence of T.
*
* Notes:
*
* - Unlike std::vector, storage is not guaranteed to be contiguous.
*
* - Insertion and removal can only happen at the end of the
* sequence (although you can modify elements anywhere in the
* sequence).
*
* - There is no non-const iterator support, and we have forward
* iterators only.
*
* - The elements must be trivially copyable/assignable and have
* trivial destructors.
*
* Currently, does not invalidate pointers or references to elements
* at indexes less than InternalSize, but we don't want to depend on
* this without documenting it here. Iterators should be considered
* invalidated after any mutation.
*
* Also: if you have a T*, and the list almost always contains at most
* one element, PointerList is a smaller object so may be preferable
* in that case. (Unless you want the first element to remain
* accessible inline instead of moved to the heap.)
*/
template<class T, size_t InternalSize = 1, size_t MinHeapCapacity = 0>
struct TinyVector : private boost::noncopyable {
struct const_iterator;
#ifndef __INTEL_COMPILER
static_assert(boost::has_trivial_destructor<T>::value,
"TinyVector only supports elements with trivial destructors");
static_assert(boost::has_trivial_copy<T>::value &&
boost::has_trivial_assign<T>::value,
"TinyVector only supports elements with trivial copy "
"constructors and trivial assignment operators");
#endif
static_assert(InternalSize >= 1,
"TinyVector assumes that the internal size is at least 1");
~TinyVector() { clear(); }
size_t size() const { return m_data.size(); }
bool empty() const { return !size(); }
const_iterator begin() const { return const_iterator(this, 0); }
const_iterator end() const { return const_iterator(this); }
T& operator[](size_t index) {
assert(index < size());
return *location(index);
}
const T& operator[](size_t index) const {
return const_cast<TinyVector*>(this)->operator[](index);
}
void clear() {
if (HeapData* p = m_data.ptr()) {
free(p);
}
m_data.set(0, 0);
}
void push_back(const T& t) {
size_t current = size();
reserve(current + 1);
*location(current) = t;
m_data.set(current + 1, m_data.ptr());
}
void pop_back() {
assert(!empty());
m_data.set(size() - 1, m_data.ptr());
}
T& back() {
assert(!empty());
return (*this)[size() - 1];
}
const T& back() const {
assert(!empty());
return (*this)[size() - 1];
}
T& front() {
assert(!empty());
return m_vals[0];
}
const T& front() const {
assert(!empty());
return m_vals[0];
}
void reserve(size_t sz) {
if (sz < InternalSize) return;
const size_t currentHeap = m_data.ptr() ? m_data.ptr()->capacity : 0;
const size_t neededHeap = sz - InternalSize;
if (neededHeap <= currentHeap) {
return;
}
const size_t newCapacity = std::max(
currentHeap ? currentHeap * 4 / 3
: std::max(neededHeap, MinHeapCapacity),
neededHeap);
HeapData* newHeap = static_cast<HeapData*>(
malloc(sizeof(HeapData) + sizeof(T) * newCapacity));
newHeap->capacity = (malloc_usable_size(newHeap) -
offsetof(HeapData, vals)) / sizeof(T);
std::copy(&m_data.ptr()->vals[0],
&m_data.ptr()->vals[size() - InternalSize],
&newHeap->vals[0]);
free(m_data.ptr());
m_data.set(size(), newHeap);
}
private:
struct HeapData {
uint32_t capacity; // numbers of vals---excludes this capacity field
T vals[0];
};
T* location(size_t index) {
return index < InternalSize ? &m_vals[index]
: &m_data.ptr()->vals[index - InternalSize];
}
private:
CompactSizedPtr<HeapData> m_data;
T m_vals[InternalSize];
};
//////////////////////////////////////////////////////////////////////
template<class T, size_t InternalSize, size_t MinHeapCapacity>
struct TinyVector<T,InternalSize,MinHeapCapacity>::const_iterator
: boost::iterator_facade<const_iterator,
const T,
boost::forward_traversal_tag>
{
explicit const_iterator(const TinyVector* p, uint32_t idx)
: m_p(p)
, m_idx(idx)
{}
explicit const_iterator(const TinyVector* p)
: m_p(p)
, m_idx(m_p->size())
{}
private:
friend class boost::iterator_core_access;
void increment() {
++m_idx;
}
bool equal(const const_iterator& o) const {
assert(m_p == o.m_p);
return m_idx == o.m_idx;
}
const T& dereference() const {
return (*m_p)[m_idx];
}
private:
const TinyVector* m_p;
uint32_t m_idx;
};
//////////////////////////////////////////////////////////////////////
}
#endif