Commit c0921532 authored by Kenton Varda's avatar Kenton Varda

Starting work on C++ runtime.

parent fa8ca65d
all:
echo "You probably accidentally told Eclipse to build. Stopping."
once:
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -O2 -Wall' LIBS='-lz -pthread' ekam -j6
continuous:
CXX=g++-4.7 CXXFLAGS='-std=gnu++0x -g -Wall' LIBS='-lz -pthread' ekam -j6 -c -n :51315
clean:
rm -rf bin lib tmp
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "arena.h"
namespace capnproto {
Arena::~Arena() {}
} // namespace capnproto
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <inttypes.h>
#include <stddef.h>
#ifndef CAPNPROTO_ARENA_H_
#define CAPNPROTO_ARENA_H_
namespace capnproto {
class Segment;
class SegmentAllocator;
class Arena {
public:
Arena(SegmentAllocator* allocator);
~Arena();
const Segment* addReadSegment(uint32_t index, const void* data, size_t size);
const Segment* getSegment(uint32_t index) const;
Segment* getWritableSegment(uint32_t index);
// Get the segment at the given index.
Segment* getSegmentWithAvailable(uint32_t minimumSize);
// Find a segment that has at least the given number of bytes available.
void parseError(const char* message) const;
};
class Segment {
public:
inline void* allocate(uint32_t amount);
inline void* getPtrUnchecked(uint32_t offset);
inline uint32_t getOffset(const void* ptr) const;
inline const void* getPtrChecked(uint32_t offset, uint32_t bytesBefore,
uint32_t bytesAfter) const;
inline Arena* getArena();
inline const Arena* getArena() const;
inline uint32_t getSegmentId() const;
private:
Arena* arena;
uint32_t id;
void* start;
uint32_t size;
uint32_t pos;
int64_t* readLimit;
friend class Arena;
inline Segment(Arena* arena, uint32_t index, void* start, uint32_t size, uint32_t pos,
int64_t* readLimit);
inline ~Segment();
Segment(const Segment& other) = delete;
Segment& operator=(const Segment& other) = delete;
void readLimitReached() const;
// TODO: Do we need mutex locking?
};
class SegmentAllocator {
public:
virtual ~SegmentAllocator();
virtual void* allocate(size_t size);
virtual void free(void* ptr, size_t size);
};
// =======================================================================================
inline Segment::Segment(Arena* arena, uint32_t id, void* start, uint32_t size, uint32_t pos,
int64_t* readLimit)
: arena(arena), id(id), start(start), size(size), pos(pos),
readLimit(readLimit) {}
inline Segment::~Segment() {}
inline void* Segment::allocate(uint32_t amount) {
if (amount > size - pos) {
return nullptr;
} else {
uint32_t offset = pos;
pos += size;
return reinterpret_cast<char*>(start) + offset;
}
}
inline void* Segment::getPtrUnchecked(uint32_t offset) {
return reinterpret_cast<char*>(start) + offset;
}
inline uint32_t Segment::getOffset(const void* ptr) const {
return reinterpret_cast<const char*>(ptr) - reinterpret_cast<const char*>(start);
}
inline const void* Segment::getPtrChecked(uint32_t offset, uint32_t bytesBefore,
uint32_t bytesAfter) const {
// Check bounds. Watch out for overflow and underflow here.
if (offset > size || bytesBefore > offset || bytesAfter > size - offset) {
return nullptr;
} else {
// Enforce the read limit. Synchronization is not necessary because readLimit is just a rough
// counter to prevent infinite loops leading to DoS attacks.
if ((*readLimit -= bytesBefore + bytesAfter) < 0) readLimitReached();
return reinterpret_cast<char*>(start) + offset;
}
}
inline Arena* Segment::getArena() {
return arena;
}
inline const Arena* Segment::getArena() const {
return arena;
}
inline uint32_t Segment::getSegmentId() const {
return id;
}
} // namespace capnproto
#endif // CAPNPROTO_ARENA_H_
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "descriptor.h"
namespace capnproto {
namespace internal {
} // namespace internal
} // namespace capnproto
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file is NOT intended for use by clients, except in generated code.
//
// The structures declared here provide basic information about user-defined capnproto data types
// needed in order to read, write, and traverse the raw message data. Basically, descriptors
// serve two purposes:
// - Define the layout of struct types so that they can be allocated and so that incoming structs
// can be validated.
// - Define the default values used when fields are absent on the wire.
//
// We use raw structs with no inheritance in order to allow for static initialization via the data
// segment with no need to execute any code at startup.
#ifndef CAPNPROTO_DESCRIPTOR_H_
#define CAPNPROTO_DESCRIPTOR_H_
#include <inttypes.h>
#include "macros.h"
namespace capnproto {
namespace internal {
struct ListDescriptor;
struct StructDescriptor;
struct FieldDescriptor;
struct Descriptor {
// This is the "base type" for descriptors that describe the target of a reference.
// StructDescriptor and ListDescriptor should be treated as if they subclass this type. However,
// because subclassing breaks the ability to initialize structs using an initializer list -- which
// we need for static initialization purposes -- we don't actually use inheritance. Instead,
// each of the "subclasses" has a field of type Descriptor as its first field.
enum class Kind: uint8_t {
LIST, // This is a ListDescriptor
STRUCT // This is a StructDescriptor
};
Kind kind;
inline const ListDescriptor* asList() const;
inline const StructDescriptor* asStruct() const;
// Poor-man's downcast.
};
enum class FieldSize: uint8_t {
BIT,
BYTE,
TWO_BYTES,
FOUR_BYTES,
EIGHT_BYTES,
REFERENCE, // Indicates that the field lives in the reference segment, not the data segment.
KEY_REFERENCE, // A 64-bit key, 64-bit reference pair.
STRUCT // An arbitrary-sized inlined struct. Used only for list elements, not struct
// fields, since a struct cannot embed another struct inline.
};
inline int sizeInBits(FieldSize s) {
static const int table[] = {1, 8, 16, 32, 64, 64, 128, -1};
return table[static_cast<int>(s)];
}
inline int byteOffsetForFieldZero(FieldSize s) {
// For the given field size, get the offset, in bytes, between a struct pointer and the location
// of the struct's first field, if the struct's first field is of the given type. We use this
// to adjust pointers when non-struct lists are converted to struct lists or vice versa.
static const int table[] = {1, 1, 2, 4, 8, 0, 8, 0};
return table[static_cast<int>(s)];
}
struct ListDescriptor {
// Describes a list.
Descriptor base;
FieldSize elementSize;
// Size of each element of the list. Also determines whether it is a reference list or a data
// list.
const Descriptor* elementDescriptor;
// For a reference list, this is a descriptor of an element. Otherwise, NULL.
uint32_t defaultCount;
// Number of elements in the default value.
const void* defaultData;
// For a data list, points to an array of elements representing the default contents of the list.
// Note that unlike data segments of structs, this pointer points to the first byte of the data.
// For a reference list, points to an array of descriptor pointers -- use defaultReferences()
// for type-safety.
const Descriptor* const* defaultReferences() const {
// Convenience accessor for reference lists.
return reinterpret_cast<const Descriptor* const*>(defaultData);
}
};
static_assert(__builtin_offsetof(ListDescriptor, base) == 0,
"'base' must be the first member of ListDescriptor to allow reinterpret_cast from "
"Descriptor to ListDescriptor.");
struct StructDescriptor {
// Describes a struct.
Descriptor base;
uint8_t fieldCount;
// Number of fields in this type -- that we were aware of at compile time, of course.
uint8_t dataSize;
// Size of the data segment, in 64-bit words.
uint8_t referenceCount;
// Number of references in the reference segment.
const FieldDescriptor* fields;
// Array of FieldDescriptors.
const void* defaultData;
// Default data. The pointer actually points to the byte immediately after the end of the data.
const Descriptor* const* defaultReferences;
// Array of descriptors describing the references.
inline uint32_t wordSize() const {
// Size of the struct in words.
return static_cast<uint32_t>(fieldCount) + static_cast<uint32_t>(referenceCount);
}
};
static_assert(__builtin_offsetof(StructDescriptor, base) == 0,
"'base' must be the first member of StructDescriptor to allow reinterpret_cast from "
"Descriptor to StructDescriptor.");
struct FieldDescriptor {
// Describes one field of a struct.
uint8_t requiredDataSize;
// The minimum size of the data segment of any object which includes this field. This is always
// offset * size / 64 bits, rounded up. This value is useful for validating object references
// received on the wire -- if dataSize is insufficient to support fieldCount, don't trust it!
uint8_t requiredReferenceSize;
// The minimum size of the reference segment of any object which includes this field. Same deal
// as with requiredDataSize.
uint16_t offset;
// If the field is a data field (size != REFERENCE), then this is the offset within the object's
// data segment at which the field is positioned, measured in multiples of the field's size. This
// offset is intended to be *subtracted* from the object pointer, since the object pointer points
// to the beginning of the reference segment, which is located immediately after the data segment.
// Therefore, this offset can never be zero.
//
// For size == BIT, the meaning is slightly different: bits are numbered from zero, starting with
// the eight bits in the last byte of the data segment, followed by the eight bits in the byte
// before that, and so on. Within each byte, bits are numbered from least-significant to
// most-significant -- i.e. *not* backwards. This awkward numbering is necessary to allow a
// list of booleans to be upgraded to a list of structs where field number zero is a boolean --
// we need the first boolean in either a list or a struct to be located at the same end of its
// byte.
//
// If the field is a reference field (size == REFERENCE), then this is the index within the
// reference array at which the field is located.
FieldSize size;
// Size of this field.
uint8_t hole32Offset;
uint16_t hole16Offset;
uint16_t hole8Offset;
// In the case that this field is the last one in the object, and thus the object's data segment
// size is equal to requiredDataSize, then the following offsets indicate locations of "holes" in
// the data segment which are not occupied by any field. The packing algorithm guarantees that
// there can be at most one hole of each size. An offset of zero indicates that no hole is
// present. Each offset is measured in multiples two times the hole size. E.g. hole32Offset is
// measured in 64-bit words. (The packing algorithm guarantees that hole offsets will always be
// an even multiple of the hole size.)
uint16_t bitholeOffset;
// If the object contains boolean fields and the number of booleans is not divisible by 8, then
// there will also be a hole of 1-7 bits somewhere. bitholeOffset is the offset, in bits, of the
// first (most-significant) such missing bit. All subsequent (less-significant) bits within the
// same byte are also missing.
};
inline const ListDescriptor* Descriptor::asList() const {
CAPNPROTO_DEBUG_ASSERT(kind == Kind::LIST, "asList() called on Descriptor that isn't a list.");
return reinterpret_cast<const ListDescriptor*>(this);
}
inline const StructDescriptor* Descriptor::asStruct() const {
CAPNPROTO_DEBUG_ASSERT(
kind == Kind::STRUCT, "asStruct() called on Descriptor that isn't a struct.");
return reinterpret_cast<const StructDescriptor*>(this);
}
} // namespace internal
} // namespace capnproto
#endif // CAPNPROTO_DESCRIPTOR_H_
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "macros.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exception>
namespace capnproto {
namespace internal {
class Exception: public std::exception {
// Exception thrown in case of fatal errors.
public:
Exception(const char* file, int line, const char* expectation, const char* message);
virtual ~Exception() noexcept;
const char* getFile() { return file; }
int getLine() { return line; }
const char* getExpectation() { return expectation; }
const char* getMessage() { return message; }
virtual const char* what();
private:
const char* file;
int line;
const char* expectation;
const char* message;
char* whatBuffer;
};
Exception::Exception(
const char* file, int line, const char* expectation, const char* message)
: file(file), line(line), expectation(expectation), message(message), whatBuffer(nullptr) {
fprintf(stderr, "Captain Proto debug assertion failed:\n %s:%d: %s\n %s",
file, line, expectation, message);
}
Exception::~Exception() noexcept {
delete [] whatBuffer;
}
const char* Exception::what() {
whatBuffer = new char[strlen(file) + strlen(expectation) + strlen(message) + 256];
sprintf(whatBuffer, "Captain Proto debug assertion failed:\n %s:%d: %s\n %s",
file, line, expectation, message);
return whatBuffer;
}
void assertionFailure(const char* file, int line, const char* expectation, const char* message) {
throw Exception(file, line, expectation, message);
}
} // namespace internal
} // namespace capnproto
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CAPNPROTO_MACROS_H_
#define CAPNPROTO_MACROS_H_
namespace capnproto {
namespace internal {
#define CAPNPROTO_EXPECT_TRUE(condition) __builtin_expect(condition, true)
#define CAPNPROTO_EXPECT_FALSE(condition) __builtin_expect(condition, false)
// Branch prediction macros. Evaluates to the condition given, but also tells the compiler that we
// expect the condition to be true/false enough of the time that it's worth hard-coding branch
// prediction.
#define CAPNPROTO_ALWAYS_INLINE(prototype) inline prototype __attribute__((always_inline))
// Force a function to always be inlined. Apply only to the prototype, not to the definition.
void assertionFailure(const char* file, int line, const char* expectation, const char* message)
__attribute__((noreturn));
// CAPNPROTO_ASSERT is just like assert() except it avoids polluting the global namespace with an
// unqualified macro name and it throws an exception (derived from std::exception).
#ifdef NDEBUG
#define CAPNPROTO_DEBUG_ASSERT(condition, message)
#else
#define CAPNPROTO_DEBUG_ASSERT(condition, message) \
if (CAPNPROTO_EXPECT_TRUE(condition)); else ::capnproto::internal::assertionFailure(\
__FILE__, __LINE__, #condition, message)
#endif
#define CAPNPROTO_ASSERT(condition, message) \
::capnproto::internal::assertionFailure(__FILE__, __LINE__, #condition, message)
} // namespace internal
template <typename T, typename U>
T implicit_cast(U u) {
return u;
}
} // namespace capnproto
#endif // CAPNPROTO_MACROS_H_
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