More stdlib implementation. (#17)
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user