Commit 9c54bce6 authored by Kenton Varda's avatar Kenton Varda

Fix problems with AnyStruct / AnyList change.

parent fff8e987
......@@ -177,10 +177,11 @@ struct AnyPointer {
inline BuilderFor<T> initAs(ListSchema schema, uint elementCount);
// Only valid for T = DynamicList. Requires `#include <capnp/dynamic.h>`.
inline AnyList::Builder initAsAnyList(_::FieldSize elementSize, uint elementCount);
inline AnyList::Builder initAsAnyList(ElementSize elementSize, uint elementCount);
// Note: Does not accept INLINE_COMPOSITE for elementSize.
inline List<AnyStruct>::Builder initAsListOfAnyStruct(uint dataWordCount, uint pointerCount, uint elementCount);
inline List<AnyStruct>::Builder initAsListOfAnyStruct(
uint dataWordCount, uint pointerCount, uint elementCount);
inline AnyStruct::Builder initAsAnyStruct(uint dataWordCount, uint pointerCount);
......@@ -540,10 +541,8 @@ public:
Reader() = default;
inline Reader(_::ListReader reader): _reader(reader) {}
_::FieldSize getElementSize();
ElementCount size() {
return _reader.size();
}
inline ElementSize getElementSize() { return _reader.getElementSize(); }
inline uint size() { return _reader.size() / ELEMENTS; }
template <typename T> ReaderFor<T> as() {
// T must be List<U>.
......@@ -556,13 +555,10 @@ private:
class AnyList::Builder {
public:
inline Builder(decltype(nullptr)) {}
inline Builder(_::PointerBuilder builder, _::FieldSize size, const word* defaultValue = nullptr): _builder(builder.getList(size, defaultValue)) {}
inline Builder(_::ListBuilder builder): _builder(builder) {}
_::FieldSize getElementSize();
ElementCount size() {
return _builder.size();
}
inline ElementSize getElementSize() { return _builder.getElementSize(); }
inline uint size() { return _builder.size() / ELEMENTS; }
template <typename T> BuilderFor<T> as() {
// T must be List<U>.
......@@ -576,39 +572,49 @@ private:
_::ListBuilder _builder;
};
namespace _ { // (private)
namespace _ { // (private)
template <>
struct PointerHelpers<AnyStruct, Kind::OTHER> {
static inline typename AnyStruct::Reader get(PointerReader reader, const word* defaultValue = nullptr) {
static inline typename AnyStruct::Reader get(
PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyStruct::Reader(reader.getStruct(defaultValue));
}
static inline typename AnyStruct::Builder get(PointerBuilder builder,
const word* defaultValue = nullptr) {
return typename AnyStruct::Builder(builder, /* TODO: allow specifying the size! */ _::StructSize(0, 0), defaultValue);
static inline typename AnyStruct::Builder get(
PointerBuilder builder, const word* defaultValue = nullptr) {
// TODO(someday): allow specifying the size
return typename AnyStruct::Builder(
builder, _::StructSize(0 * WORDS, 0 * POINTERS), defaultValue);
}
static inline typename AnyStruct::Builder init(PointerBuilder builder, uint dataWordCount, uint pointerCount) {
return typename AnyStruct::Builder(builder.initStruct(StructSize(dataWordCount, pointerCount)));
static inline typename AnyStruct::Builder init(
PointerBuilder builder, uint dataWordCount, uint pointerCount) {
return typename AnyStruct::Builder(builder.initStruct(
StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
}
};
template <>
struct PointerHelpers<AnyList, Kind::OTHER> {
static inline typename AnyList::Reader get(PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyList::Reader(reader.getList(/* TODO: allow specifying the size! */ FieldSize::VOID, defaultValue));
static inline typename AnyList::Reader get(
PointerReader reader, const word* defaultValue = nullptr) {
return typename AnyList::Reader(reader.getListAnySize(defaultValue));
}
static inline typename AnyList::Builder get(PointerBuilder builder,
const word* defaultValue = nullptr) {
return typename AnyList::Builder(builder, /* TODO: allow specifying the size! */ FieldSize::VOID, defaultValue);
static inline typename AnyList::Builder get(
PointerBuilder builder, const word* defaultValue = nullptr) {
return typename AnyList::Builder(builder.getListAnySize(defaultValue));
}
static inline typename AnyList::Builder init(PointerBuilder builder, FieldSize elementSize, uint elementCount) {
return typename AnyList::Builder(builder.initList(elementSize, elementCount));
static inline typename AnyList::Builder init(
PointerBuilder builder, ElementSize elementSize, uint elementCount) {
return typename AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
}
static inline typename AnyList::Builder init(PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) {
static inline typename AnyList::Builder init(
PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) {
return typename AnyList::Builder(builder.initStructList(
elementCount,
StructSize(dataWordCount, pointerCount)));
elementCount * ELEMENTS, StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
}
};
} // end namespace _ (private)
} // namespace _ (private)
// =======================================================================================
// Pipeline helpers
......@@ -701,14 +707,20 @@ inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) {
return _::PointerHelpers<T>::init(builder, elementCount);
}
inline AnyList::Builder AnyPointer::Builder::initAsAnyList(_::FieldSize elementSize, uint elementCount) {
return _::PointerHelpers<AnyList>::init(builder, elementSize, elementCount);
inline AnyList::Builder AnyPointer::Builder::initAsAnyList(
ElementSize elementSize, uint elementCount) {
return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
}
// inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(uint dataWordCount, uint pointerCount, uint elementCount);
inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(
uint dataWordCount, uint pointerCount, uint elementCount) {
return List<AnyStruct>::Builder(builder.initStructList(elementCount * ELEMENTS,
_::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
}
inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) {
return _::PointerHelpers<AnyStruct>::init(builder, dataWordCount, pointerCount);
return AnyStruct::Builder(builder.initStruct(
_::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
}
template <typename T>
......
......@@ -80,6 +80,21 @@ enum class Kind: uint8_t {
// special handling. This includes types like AnyPointer, Dynamic*, etc.
};
enum class ElementSize: uint8_t {
// Size of a list element.
VOID = 0,
BIT = 1,
BYTE = 2,
TWO_BYTES = 3,
FOUR_BYTES = 4,
EIGHT_BYTES = 5,
POINTER = 6,
INLINE_COMPOSITE = 7
};
namespace schemas {
template <typename T>
......
This diff is collapsed.
......@@ -78,51 +78,10 @@ class BuilderArena;
// =============================================================================
enum class FieldSize: uint8_t {
// TODO(cleanup): Rename to FieldLayout or maybe ValueLayout.
// Notice that each member of this enum, when representing a list element size, represents a
// size that is greater than or equal to the previous members, since INLINE_COMPOSITE is used
// only for multi-word structs. This is important because it allows us to compare FieldSize
// values for the purpose of deciding when we need to upgrade a list.
VOID = 0,
BIT = 1,
BYTE = 2,
TWO_BYTES = 3,
FOUR_BYTES = 4,
EIGHT_BYTES = 5,
POINTER = 6, // Indicates that the field lives in the pointer section, not the data section.
INLINE_COMPOSITE = 7
// A composite type of fixed width. This serves two purposes:
// 1) For lists of composite types where all the elements would have the exact same width,
// allocating a list of pointers which in turn point at the elements would waste space. We
// can avoid a layer of indirection by placing all the elements in a flat sequence, and only
// indicating the element properties (e.g. field count for structs) once.
//
// Specifically, a list pointer indicating INLINE_COMPOSITE element size actually points to
// a "tag" describing one element. This tag is formatted like a wire pointer, but the
// "offset" instead stores the element count of the list. The flat list of elements appears
// immediately after the tag. In the list pointer itself, the element count is replaced with
// a word count for the whole list (excluding tag). This allows the tag and elements to be
// precached in a single step rather than two sequential steps.
//
// It is NOT intended to be possible to substitute an INLINE_COMPOSITE list for a POINTER
// list or vice-versa without breaking recipients. Recipients expect one or the other
// depending on the message definition.
//
// However, it IS allowed to substitute an INLINE_COMPOSITE list -- specifically, of structs --
// when a list was expected, or vice versa, with the assumption that the first field of the
// struct (field number zero) correspond to the element type. This allows a list of
// primitives to be upgraded to a list of structs, avoiding the need to use parallel arrays
// when you realize that you need to attach some extra information to each element of some
// primitive list.
//
// 2) At one point there was a notion of "inline" struct fields, but it was deemed too much of
// an implementation burden for too little gain, and so was deleted.
};
using FieldSize = capnp::ElementSize;
// Legacy typedef.
//
// TODO(cleanup): Replace all uses.
typedef decltype(BITS / ELEMENTS) BitsPerElement;
typedef decltype(POINTERS / ELEMENTS) PointersPerElement;
......@@ -330,6 +289,7 @@ public:
StructBuilder getStruct(StructSize size, const word* defaultValue);
ListBuilder getList(FieldSize elementSize, const word* defaultValue);
ListBuilder getStructList(StructSize elementSize, const word* defaultValue);
ListBuilder getListAnySize(const word* defaultValue);
template <typename T> typename T::Builder getBlob(const void* defaultValue,ByteCount defaultSize);
#if !CAPNP_LITE
kj::Own<ClientHook> getCapability();
......@@ -409,6 +369,7 @@ public:
StructReader getStruct(const word* defaultValue) const;
ListReader getList(FieldSize expectedElementSize, const word* defaultValue) const;
ListReader getListAnySize(const word* defaultValue) const;
template <typename T>
typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const;
#if !CAPNP_LITE
......@@ -612,6 +573,8 @@ public:
}
}
inline ElementSize getElementSize() const { return elementSize; }
inline ElementCount size() const;
// The number of elements in the list.
......@@ -680,6 +643,8 @@ public:
inline ElementCount size() const;
// The number of elements in the list.
inline ElementSize getElementSize() const { return elementSize; }
Text::Reader asText();
Data::Reader asData();
// Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
......@@ -854,7 +819,9 @@ inline Data::Builder StructBuilder::getDataSectionAsBlob() {
}
inline _::ListBuilder StructBuilder::getPointerSectionAsList() {
return _::ListBuilder(segment, pointers, pointerCount * BITS_PER_WORD / ELEMENTS, pointerCount, 0, 1, FieldSize::POINTER);
return _::ListBuilder(segment, pointers, pointerCount * BITS_PER_POINTER / ELEMENTS,
pointerCount * (1 * ELEMENTS / POINTERS),
0 * BITS, 1 * POINTERS, FieldSize::POINTER);
}
template <typename T>
......@@ -936,7 +903,9 @@ inline Data::Reader StructReader::getDataSectionAsBlob() {
}
inline _::ListReader StructReader::getPointerSectionAsList() {
return _::ListReader(segment, pointers, pointerCount, pointerCount * BITS_PER_WORD / ELEMENTS, 0, 1, FieldSize::POINTER, nestingLimit);
return _::ListReader(segment, pointers, pointerCount * (1 * ELEMENTS / POINTERS),
pointerCount * BITS_PER_POINTER / ELEMENTS,
0 * BITS, 1 * POINTERS, FieldSize::POINTER, nestingLimit);
}
template <typename T>
......
......@@ -24,7 +24,6 @@
#include "layout.h"
#include "list.h"
// #include "any.h"
namespace capnp {
namespace _ { // private
......
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