Commit 093fac4a authored by Kenton Varda's avatar Kenton Varda

WIP use bounded types -- all tests passing.

TODO:
- Rename Guarded to Bounded?
- Consider bounded array (where size and indexes are bounded quantities).
- Implement non-CAPNP_DEBUG_TYPES fallback.
  - Don't allow casting kj::maxValue to bounded type, this won't work right when not using debug types!
- Verify that this change doesn't hurt performance.
parent 0a54c46d
......@@ -1014,13 +1014,13 @@ struct PointerHelpers<AnyList, Kind::OTHER> {
template <>
struct OrphanGetImpl<AnyStruct, Kind::OTHER> {
static inline AnyStruct::Builder apply(_::OrphanBuilder& builder) {
return AnyStruct::Builder(builder.asStruct(_::StructSize(0 * WORDS, 0 * POINTERS)));
return AnyStruct::Builder(builder.asStruct(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
}
static inline AnyStruct::Reader applyReader(const _::OrphanBuilder& builder) {
return AnyStruct::Reader(builder.asStructReader(_::StructSize(0 * WORDS, 0 * POINTERS)));
return AnyStruct::Reader(builder.asStructReader(_::StructSize(ZERO * WORDS, ZERO * POINTERS)));
}
static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
builder.truncate(size, _::StructSize(0 * WORDS, 0 * POINTERS));
builder.truncate(size, _::StructSize(ZERO * WORDS, ZERO * POINTERS));
}
};
......
......@@ -370,7 +370,8 @@ inline bool SegmentReader::containsInterval(const void* from, const void* to) {
return from >= this->ptr.begin() && to <= this->ptr.end() && from <= to &&
readLimiter->canRead(
intervalLength(reinterpret_cast<const byte*>(from),
reinterpret_cast<const byte*>(to))
reinterpret_cast<const byte*>(to),
MAX_SEGMENT_WORDS * BYTES_PER_WORD)
/ BYTES_PER_WORD,
arena);
}
......@@ -383,8 +384,8 @@ inline Arena* SegmentReader::getArena() { return arena; }
inline SegmentId SegmentReader::getSegmentId() { return id; }
inline const word* SegmentReader::getStartPtr() { return ptr.begin(); }
inline SegmentWordCount SegmentReader::getOffsetTo(const word* ptr) {
KJ_IREQUIRE(this->ptr.begin() <= ptr && ptr < this->ptr.end());
return assumeBits<SEGMENT_WORD_COUNT_BITS>(intervalLength(this->ptr.begin(), ptr));
KJ_IREQUIRE(this->ptr.begin() <= ptr && ptr <= this->ptr.end());
return intervalLength(this->ptr.begin(), ptr, MAX_SEGMENT_WORDS);
}
inline SegmentWordCount SegmentReader::getSize() {
return assumeBits<SEGMENT_WORD_COUNT_BITS>(ptr.size()) * WORDS;
......@@ -412,7 +413,7 @@ inline SegmentBuilder::SegmentBuilder(BuilderArena* arena, SegmentId id, decltyp
pos(nullptr), readOnly(false) {}
inline word* SegmentBuilder::allocate(SegmentWordCount amount) {
if (intervalLength(pos, ptr.end()) < amount) {
if (intervalLength(pos, ptr.end(), MAX_SEGMENT_WORDS) < amount) {
// Not enough space in the segment for this allocation.
return nullptr;
} else {
......
......@@ -650,7 +650,7 @@ struct List<T, Kind::INTERFACE> {
Reader() = default;
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline uint size() const { return unguard(reader.size() / ELEMENTS); }
inline typename T::Client operator[](uint index) const {
KJ_IREQUIRE(index < size());
return typename T::Client(reader.getPointerElement(
......@@ -683,7 +683,7 @@ struct List<T, Kind::INTERFACE> {
inline operator Reader() const { return Reader(builder.asReader()); }
inline Reader asReader() const { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline uint size() const { return unguard(builder.size() / ELEMENTS); }
inline typename T::Client operator[](uint index) {
KJ_IREQUIRE(index < size());
return typename T::Client(builder.getPointerElement(
......
......@@ -405,6 +405,7 @@ using kj::assertMaxBits;
using kj::upgradeGuard;
using kj::ThrowOverflow;
using kj::assumeBits;
using kj::assumeMax;
using kj::subtractChecked;
template <typename T, typename U>
......@@ -480,33 +481,51 @@ constexpr auto MAX_LIST_ELEMENTS =
constexpr auto MAX_STUCT_DATA_WORDS =
guarded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS;
constexpr auto MAX_STRUCT_POINTER_COUNT =
guarded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() *POINTERS;
guarded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS;
using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD);
using StructDataElementOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS));
// Number of bits in a Struct data segment (should come out to BitCountN<22>).
using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS));
using StructPointerOffset = StructPointerCount;
// Type of a field offset.
inline StructDataOffset assumeDataOffset(uint32_t offset) {
return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS),
guarded(offset) * ELEMENTS);
}
inline StructPointerOffset assumePointerOffset(uint32_t offset) {
return assumeMax(MAX_STRUCT_POINTER_COUNT, guarded(offset) * POINTERS);
}
constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
typedef kj::Quantity<kj::Guarded<MAX_TEXT_SIZE, uint>, byte> TextSize;
// Not including NUL terminator.
template <typename T>
inline KJ_CONSTEXPR() decltype(BYTES / ELEMENTS) bytesPerElement() {
inline KJ_CONSTEXPR() decltype(guarded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() {
return guarded<sizeof(T)>() * BYTES / ELEMENTS;
}
template <typename T>
inline KJ_CONSTEXPR() decltype(BITS / ELEMENTS) bitsPerElement() {
return guarded<sizeof(T)>() * 8 * BITS / ELEMENTS;
inline KJ_CONSTEXPR() decltype(guarded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() {
return guarded<sizeof(T) * 8>() * BITS / ELEMENTS;
}
inline constexpr ByteCountN<sizeof(size_t) * 8, size_t>
intervalLength(const byte* a, const byte* b) {
return kj::guarded(b - a) * BYTES;
template <typename T, uint maxN>
inline constexpr kj::Quantity<kj::Guarded<maxN, size_t>, T>
intervalLength(const T* a, const T* b, kj::Quantity<kj::GuardedConst<maxN>, T>) {
return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::GuardedConst<1u>, T>>();
}
inline constexpr WordCountN<sizeof(size_t) * 8, size_t>
intervalLength(const word* a, const word* b) {
return kj::guarded(b - a) * WORDS;
template <typename T, typename U>
inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) {
return kj::ArrayPtr<const U>(ptr, unguard(size / kj::unit<kj::Quantity<T, U>>()));
}
template <typename T, typename U>
inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) {
return kj::ArrayPtr<U>(ptr, unguard(size / kj::unit<kj::Quantity<T, U>>()));
}
#else
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -369,7 +369,7 @@ public:
inline ListSchema getSchema() const { return schema; }
inline uint size() const { return reader.size() / ELEMENTS; }
inline uint size() const { return unguard(reader.size() / ELEMENTS); }
DynamicValue::Reader operator[](uint index) const;
typedef _::IndexingIterator<const Reader, DynamicValue::Reader> Iterator;
......@@ -411,7 +411,7 @@ public:
inline ListSchema getSchema() const { return schema; }
inline uint size() const { return builder.size() / ELEMENTS; }
inline uint size() const { return unguard(builder.size() / ELEMENTS); }
DynamicValue::Builder operator[](uint index);
void set(uint index, const DynamicValue::Reader& value);
DynamicValue::Builder init(uint index, uint size);
......
......@@ -311,8 +311,8 @@ inline constexpr uint sizeInWords() {
// Return the size, in words, of a Struct type, if allocated free-standing (not in a list).
// May be useful for pre-computing space needed in order to precisely allocate messages.
return (WordCount32(_::structSize<T>().data) +
_::structSize<T>().pointers * WORDS_PER_POINTER) / WORDS;
return unguard((upgradeGuard<uint>(_::structSize<T>().data) +
_::structSize<T>().pointers * WORDS_PER_POINTER) / WORDS);
}
} // namespace capnp
......
......@@ -29,7 +29,18 @@
namespace kj {
template <typename T, typename U>
String KJ_STRINGIFY(kj::Quantity<T, U> value) {
return kj::str(value / kj::unit<kj::Quantity<T, U>>());
return kj::str(unguardAs<uint64_t>(value / kj::unit<kj::Quantity<T, U>>()));
}
// Hack: Allow direct comparisons and multiplications so that we don't have to rewrite the code
// below.
template <uint64_t maxN, typename T>
inline constexpr Guarded<65535, T> operator*(uint a, Guarded<maxN, T> b) {
return assumeBits<16>(a * unguard(b));
}
template <uint b>
inline constexpr Guarded<65535, uint> operator*(uint a, GuardedConst<b>) {
return assumeBits<16>(a * b);
}
}
#endif
......
This diff is collapsed.
This diff is collapsed.
......@@ -114,7 +114,7 @@ struct List<T, Kind::PRIMITIVE> {
inline Reader(): reader(_::elementSizeForType<T>()) {}
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline uint size() const { return unguard(reader.size() / ELEMENTS); }
inline T operator[](uint index) const {
KJ_IREQUIRE(index < size());
return reader.template getDataElement<T>(guarded(index) * ELEMENTS);
......@@ -146,7 +146,7 @@ struct List<T, Kind::PRIMITIVE> {
inline operator Reader() const { return Reader(builder.asReader()); }
inline Reader asReader() const { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline uint size() const { return unguard(builder.size() / ELEMENTS); }
inline T operator[](uint index) {
KJ_IREQUIRE(index < size());
return builder.template getDataElement<T>(guarded(index) * ELEMENTS);
......@@ -210,7 +210,7 @@ struct List<T, Kind::STRUCT> {
inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline uint size() const { return unguard(reader.size() / ELEMENTS); }
inline typename T::Reader operator[](uint index) const {
KJ_IREQUIRE(index < size());
return typename T::Reader(reader.getStructElement(guarded(index) * ELEMENTS));
......@@ -242,7 +242,7 @@ struct List<T, Kind::STRUCT> {
inline operator Reader() const { return Reader(builder.asReader()); }
inline Reader asReader() const { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline uint size() const { return unguard(builder.size() / ELEMENTS); }
inline typename T::Builder operator[](uint index) {
KJ_IREQUIRE(index < size());
return typename T::Builder(builder.getStructElement(guarded(index) * ELEMENTS));
......@@ -332,7 +332,7 @@ struct List<List<T>, Kind::LIST> {
inline Reader(): reader(ElementSize::POINTER) {}
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline uint size() const { return unguard(reader.size() / ELEMENTS); }
inline typename List<T>::Reader operator[](uint index) const {
KJ_IREQUIRE(index < size());
return typename List<T>::Reader(_::PointerHelpers<List<T>>::get(
......@@ -365,7 +365,7 @@ struct List<List<T>, Kind::LIST> {
inline operator Reader() const { return Reader(builder.asReader()); }
inline Reader asReader() const { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline uint size() const { return unguard(builder.size() / ELEMENTS); }
inline typename List<T>::Builder operator[](uint index) {
KJ_IREQUIRE(index < size());
return typename List<T>::Builder(_::PointerHelpers<List<T>>::get(
......@@ -441,7 +441,7 @@ struct List<T, Kind::BLOB> {
inline Reader(): reader(ElementSize::POINTER) {}
inline explicit Reader(_::ListReader reader): reader(reader) {}
inline uint size() const { return reader.size() / ELEMENTS; }
inline uint size() const { return unguard(reader.size() / ELEMENTS); }
inline typename T::Reader operator[](uint index) const {
KJ_IREQUIRE(index < size());
return reader.getPointerElement(guarded(index) * ELEMENTS)
......@@ -474,7 +474,7 @@ struct List<T, Kind::BLOB> {
inline operator Reader() const { return Reader(builder.asReader()); }
inline Reader asReader() const { return Reader(builder.asReader()); }
inline uint size() const { return builder.size() / ELEMENTS; }
inline uint size() const { return unguard(builder.size() / ELEMENTS); }
inline typename T::Builder operator[](uint index) {
KJ_IREQUIRE(index < size());
return builder.getPointerElement(guarded(index) * ELEMENTS)
......
This diff is collapsed.
......@@ -600,119 +600,121 @@ private:
inline ::capnp::rpc::twoparty::Side VatId::Reader::getSide() const {
return _reader.getDataField< ::capnp::rpc::twoparty::Side>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline ::capnp::rpc::twoparty::Side VatId::Builder::getSide() {
return _builder.getDataField< ::capnp::rpc::twoparty::Side>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline void VatId::Builder::setSide( ::capnp::rpc::twoparty::Side value) {
_builder.setDataField< ::capnp::rpc::twoparty::Side>(
0 * ::capnp::ELEMENTS, value);
::kj::guarded<0>() * ::capnp::ELEMENTS, value);
}
inline ::uint32_t ProvisionId::Reader::getJoinId() const {
return _reader.getDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline ::uint32_t ProvisionId::Builder::getJoinId() {
return _builder.getDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline void ProvisionId::Builder::setJoinId( ::uint32_t value) {
_builder.setDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS, value);
::kj::guarded<0>() * ::capnp::ELEMENTS, value);
}
inline ::uint32_t JoinKeyPart::Reader::getJoinId() const {
return _reader.getDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline ::uint32_t JoinKeyPart::Builder::getJoinId() {
return _builder.getDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline void JoinKeyPart::Builder::setJoinId( ::uint32_t value) {
_builder.setDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS, value);
::kj::guarded<0>() * ::capnp::ELEMENTS, value);
}
inline ::uint16_t JoinKeyPart::Reader::getPartCount() const {
return _reader.getDataField< ::uint16_t>(
2 * ::capnp::ELEMENTS);
::kj::guarded<2>() * ::capnp::ELEMENTS);
}
inline ::uint16_t JoinKeyPart::Builder::getPartCount() {
return _builder.getDataField< ::uint16_t>(
2 * ::capnp::ELEMENTS);
::kj::guarded<2>() * ::capnp::ELEMENTS);
}
inline void JoinKeyPart::Builder::setPartCount( ::uint16_t value) {
_builder.setDataField< ::uint16_t>(
2 * ::capnp::ELEMENTS, value);
::kj::guarded<2>() * ::capnp::ELEMENTS, value);
}
inline ::uint16_t JoinKeyPart::Reader::getPartNum() const {
return _reader.getDataField< ::uint16_t>(
3 * ::capnp::ELEMENTS);
::kj::guarded<3>() * ::capnp::ELEMENTS);
}
inline ::uint16_t JoinKeyPart::Builder::getPartNum() {
return _builder.getDataField< ::uint16_t>(
3 * ::capnp::ELEMENTS);
::kj::guarded<3>() * ::capnp::ELEMENTS);
}
inline void JoinKeyPart::Builder::setPartNum( ::uint16_t value) {
_builder.setDataField< ::uint16_t>(
3 * ::capnp::ELEMENTS, value);
::kj::guarded<3>() * ::capnp::ELEMENTS, value);
}
inline ::uint32_t JoinResult::Reader::getJoinId() const {
return _reader.getDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline ::uint32_t JoinResult::Builder::getJoinId() {
return _builder.getDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS);
::kj::guarded<0>() * ::capnp::ELEMENTS);
}
inline void JoinResult::Builder::setJoinId( ::uint32_t value) {
_builder.setDataField< ::uint32_t>(
0 * ::capnp::ELEMENTS, value);
::kj::guarded<0>() * ::capnp::ELEMENTS, value);
}
inline bool JoinResult::Reader::getSucceeded() const {
return _reader.getDataField<bool>(
32 * ::capnp::ELEMENTS);
::kj::guarded<32>() * ::capnp::ELEMENTS);
}
inline bool JoinResult::Builder::getSucceeded() {
return _builder.getDataField<bool>(
32 * ::capnp::ELEMENTS);
::kj::guarded<32>() * ::capnp::ELEMENTS);
}
inline void JoinResult::Builder::setSucceeded(bool value) {
_builder.setDataField<bool>(
32 * ::capnp::ELEMENTS, value);
::kj::guarded<32>() * ::capnp::ELEMENTS, value);
}
inline bool JoinResult::Reader::hasCap() const {
return !_reader.getPointerField(0 * ::capnp::POINTERS).isNull();
return !_reader.getPointerField(
::kj::guarded<0>() * ::capnp::POINTERS).isNull();
}
inline bool JoinResult::Builder::hasCap() {
return !_builder.getPointerField(0 * ::capnp::POINTERS).isNull();
return !_builder.getPointerField(
::kj::guarded<0>() * ::capnp::POINTERS).isNull();
}
inline ::capnp::AnyPointer::Reader JoinResult::Reader::getCap() const {
return ::capnp::AnyPointer::Reader(
_reader.getPointerField(0 * ::capnp::POINTERS));
return ::capnp::AnyPointer::Reader(_reader.getPointerField(
::kj::guarded<0>() * ::capnp::POINTERS));
}
inline ::capnp::AnyPointer::Builder JoinResult::Builder::getCap() {
return ::capnp::AnyPointer::Builder(
_builder.getPointerField(0 * ::capnp::POINTERS));
return ::capnp::AnyPointer::Builder(_builder.getPointerField(
::kj::guarded<0>() * ::capnp::POINTERS));
}
inline ::capnp::AnyPointer::Builder JoinResult::Builder::initCap() {
auto result = ::capnp::AnyPointer::Builder(
_builder.getPointerField(0 * ::capnp::POINTERS));
auto result = ::capnp::AnyPointer::Builder(_builder.getPointerField(
::kj::guarded<0>() * ::capnp::POINTERS));
result.clear();
return result;
}
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment