More stdlib implementation. (#17)

This commit is contained in:
Nikolay Igotti
2016-10-26 18:37:02 +03:00
committed by GitHub
parent 622ae34e61
commit 8ce0bddc17
6 changed files with 103 additions and 32 deletions
+31 -10
View File
@@ -32,10 +32,37 @@ typedef enum {
// Could be made 64-bit for large memory configs.
typedef uint32_t container_offset_t;
// Header of all container objects. Contains reference counter.
struct ContainerHeader {
// Reference counter of container. Uses two lower bits of counter for
// container type (for polymorphism in ::Release()).
volatile uint32_t ref_count_;
};
// Header of every object.
struct ObjHeader {
const TypeInfo* type_info_;
container_offset_t container_offset_negative_;
const TypeInfo* type_info() const {
// TODO: for moving collectors use meta-objects approach:
// - store tag in lower bit TypeInfo, which marks if meta-object is in place
// - when reading type_info_ check if it is unaligned
// - if it is, pointer points to the MetaObject
// - otherwise this is direct pointer to TypeInfo
// Meta-object allows storing additional data associated with some objects,
// such as stable hash code.
return type_info_;
}
void set_type_info(const TypeInfo* type_info) {
type_info_ = type_info;
}
ContainerHeader* container() const {
return reinterpret_cast<ContainerHeader*>(
reinterpret_cast<uintptr_t>(this) - container_offset_negative_);
}
};
// Header of value type array objects.
@@ -44,13 +71,6 @@ struct ArrayHeader : public ObjHeader {
uint32_t count_;
};
// Header of all container objects. Contains reference counter.
struct ContainerHeader {
// Reference counter of container. Uses two lower bits of counter for
// container type (for polymorphism in ::Release()).
volatile uint32_t ref_count_;
};
struct ArenaContainerHeader : public ContainerHeader {
// Current allocation limit.
uint8_t* current_;
@@ -61,12 +81,13 @@ struct ArenaContainerHeader : public ContainerHeader {
inline void* AddressOfElementAt(ArrayHeader* obj, int32_t index) {
// Instance size is negative.
return reinterpret_cast<uint8_t*>(obj + 1) - obj->type_info_->instanceSize_ * index;
return reinterpret_cast<uint8_t*>(obj + 1) -
obj->type_info()->instanceSize_ * index;
}
inline uint32_t ArraySizeBytes(const ArrayHeader* obj) {
// Instance size is negative.
return -obj->type_info_->instanceSize_ * obj->count_;
return -obj->type_info()->instanceSize_ * obj->count_;
}
@@ -135,7 +156,7 @@ class Container {
void SetMeta(ObjHeader* obj, const TypeInfo* type_info) {
obj->container_offset_negative_ =
reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(header_);
obj->type_info_ = type_info;
obj->set_type_info(type_info);
}
public:
+30 -4
View File
@@ -9,6 +9,22 @@
extern "C" {
// Any.kt
KBool Kotlin_Any_equals(const ObjHeader* thiz, const ObjHeader* other) {
return thiz == other;
}
KInt Kotlin_Any_hashCode(const ObjHeader* thiz) {
// Here we will use different mechanism for stable hashcode, using meta-objects
// if moving collector will be used.
return reinterpret_cast<uintptr_t>(thiz);
}
ArrayHeader* Kotlin_Any_toString(const ObjHeader* thiz) {
return nullptr;
}
// Arrays.kt
// TODO: those must be compiler intrinsics afterwards.
KByte Kotlin_ByteArray_get(const ArrayHeader* obj, KInt index) {
@@ -97,7 +113,7 @@ KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* array) {
// io/Console.kt
void Kotlin_io_Console_print(const ArrayHeader* array) {
RuntimeAssert(array->type_info_ == theStringTypeInfo, "Must use a string");
RuntimeAssert(array->type_info() == theStringTypeInfo, "Must use a string");
// TODO: system stdout must be aware about UTF-8.
write(STDOUT_FILENO, ByteArrayAddressOfElementAt(array, 0), array->count_);
}
@@ -122,7 +138,7 @@ KInt Kotlin_String_getStringLength(const ArrayHeader* array) {
}
ArrayHeader* Kotlin_String_fromUtf8Array(const ArrayHeader* array) {
RuntimeAssert(array->type_info_ == theByteArrayTypeInfo, "Must use a byte array");
RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array");
uint32_t length = ArraySizeBytes(array);
// TODO: support full UTF-8.
ArrayHeader* result = ArrayContainer(theStringTypeInfo, length).GetPlace();
@@ -136,8 +152,8 @@ ArrayHeader* Kotlin_String_fromUtf8Array(const ArrayHeader* array) {
ArrayHeader* Kotlin_String_plusImpl(
const ArrayHeader* obj, const ArrayHeader* other) {
// TODO: support UTF-8
RuntimeAssert(obj->type_info_ == theStringTypeInfo, "Must be a string");
RuntimeAssert(other->type_info_ == theStringTypeInfo, "Must be a string");
RuntimeAssert(obj->type_info() == theStringTypeInfo, "Must be a string");
RuntimeAssert(other->type_info() == theStringTypeInfo, "Must be a string");
uint32_t result_length = obj->count_ + other->count_;
ArrayHeader* result = ArrayContainer(
theStringTypeInfo, result_length).GetPlace();
@@ -152,4 +168,14 @@ ArrayHeader* Kotlin_String_plusImpl(
return result;
}
KBool Kotlin_String_equals(
const ArrayHeader* thiz, const ObjHeader* other) {
if (other == nullptr || other->type_info() != theStringTypeInfo) return 0;
const ArrayHeader* otherString = reinterpret_cast<const ArrayHeader*>(other);
return thiz->count_ == otherString->count_ &&
memcmp(ByteArrayAddressOfElementAt(thiz, 0),
ByteArrayAddressOfElementAt(otherString, 0),
thiz->count_) == 0;
}
}
+25 -18
View File
@@ -4,6 +4,7 @@
#include "Memory.h"
#include "Types.h"
typedef uint8_t KBool;
typedef uint8_t KByte;
typedef uint16_t KChar;
// Note that it is signed.
@@ -40,32 +41,38 @@ inline const KInt* IntArrayAddressOfElementAt(const ArrayHeader* obj, KInt index
extern "C" {
#endif
// Any.kt
KBool Kotlin_Any_equals(const ObjHeader* thiz, const ObjHeader* other);
KInt Kotlin_Any_hashCode(const ObjHeader* thiz);
ArrayHeader* Kotlin_Any_toString(const ObjHeader* thiz);
// Arrays.kt
// TODO: those must be compiler intrinsics afterwards.
// Arrays.kt
ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* obj);
KByte Kotlin_ByteArray_get(const ArrayHeader* obj, KInt index);
void Kotlin_ByteArray_set(ArrayHeader* obj, KInt index, KByte value);
KInt Kotlin_ByteArray_getArrayLength(const ArrayHeader* obj);
ArrayHeader* Kotlin_ByteArray_clone(const ArrayHeader* thiz);
KByte Kotlin_ByteArray_get(const ArrayHeader* thiz, KInt index);
void Kotlin_ByteArray_set(ArrayHeader* thiz, KInt index, KByte value);
KInt Kotlin_ByteArray_getArrayLength(const ArrayHeader* thiz);
ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* obj);
KChar Kotlin_CharArray_get(const ArrayHeader* obj, KInt index);
void Kotlin_CharArray_set(ArrayHeader* obj, KInt index, KChar value);
KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* obj);
ArrayHeader* Kotlin_CharArray_clone(const ArrayHeader* thiz);
KChar Kotlin_CharArray_get(const ArrayHeader* thiz, KInt index);
void Kotlin_CharArray_set(ArrayHeader* thiz, KInt index, KChar value);
KInt Kotlin_CharArray_getArrayLength(const ArrayHeader* thiz);
ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* obj);
KInt Kotlin_IntArray_get(const ArrayHeader* obj, KInt index);
void Kotlin_IntArray_set(ArrayHeader* obj, KInt index, KInt value);
KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* obj);
ArrayHeader* Kotlin_IntArray_clone(const ArrayHeader* thiz);
KInt Kotlin_IntArray_get(const ArrayHeader* thiz, KInt index);
void Kotlin_IntArray_set(ArrayHeader* thiz, KInt index, KInt value);
KInt Kotlin_IntArray_getArrayLength(const ArrayHeader* thiz);
// io/Console.kt
void Kotlin_io_Console_print(const ArrayHeader* obj);
void Kotlin_io_Console_print(const ArrayHeader* thiz);
// String.kt
KInt Kotlin_String_compareTo(const ArrayHeader* obj, const ArrayHeader* other);
KChar Kotlin_String_get(const ArrayHeader* obj, KInt index);
KInt Kotlin_String_compareTo(const ArrayHeader* thiz, const ArrayHeader* other);
KChar Kotlin_String_get(const ArrayHeader* thiz, KInt index);
ArrayHeader* Kotlin_String_fromUtf8Array(const ArrayHeader* array);
ArrayHeader* Kotlin_String_plusImpl(const ArrayHeader* obj, const ArrayHeader* other);
KInt Kotlin_String_getStringLength(const ArrayHeader* obj);
ArrayHeader* Kotlin_String_plusImpl(const ArrayHeader* thiz, const ArrayHeader* other);
KInt Kotlin_String_getStringLength(const ArrayHeader* thiz);
KBool Kotlin_String_equals(const ArrayHeader* thiz, const ObjHeader* other);
#ifdef __cplusplus
}
+1
View File
@@ -27,6 +27,7 @@ struct TypeInfo {
int32_t instanceSize_;
// Must be pointer to Any for array classes, and null for Any.
const TypeInfo* superType_;
// All object references inside this object.
const int* objOffsets_;
int objOffsetsCount_;
const TypeInfo* const* implementedInterfaces_;
@@ -0,0 +1,13 @@
package kotlin_native
public open class Any0 {
// @SymbolName("Kotlin_Any_equals")
// external public open operator fun equals0(other: Any0?): Boolean
// TODO: do we need that in Any?
@SymbolName("Kotlin_Any_hashCode")
external public open fun hashCode0(): Int
@SymbolName("Kotlin_Any_toString")
external public open fun toString0(): String
}
@@ -24,4 +24,7 @@ class String {
@SymbolName("Kotlin_String_plusImpl")
external private fun plusImpl(other:Any): String
@SymbolName("Kotlin_String_equals")
external public override operator fun equals(other: Any?): Boolean
}