From dbc1cb1919e7c54dd7ea236e9c69410656e6948f Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Mon, 26 Dec 2016 11:27:27 +0200 Subject: [PATCH] Switch to unrelated ObjHeader and ArrayHeader. (#160) --- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 2 +- .../backend/konan/llvm/StaticObjects.kt | 3 +- runtime/src/main/cpp/Arrays.cpp | 110 +++++++++--------- runtime/src/main/cpp/Exceptions.cpp | 5 +- runtime/src/main/cpp/Memory.cpp | 18 ++- runtime/src/main/cpp/Memory.h | 36 +++++- runtime/src/main/cpp/Natives.cpp | 10 +- 7 files changed, 112 insertions(+), 72 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 0997f43363f..02c9246d3f2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -857,7 +857,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid if (it is IrSpreadElement) { val exp = evaluateExpression(it.expression)!! val array = codegen.bitcast(codegen.kArrayHeaderPtr, exp) - val sizePtr = LLVMBuildStructGEP(codegen.builder, array, 1, "") + val sizePtr = LLVMBuildStructGEP(codegen.builder, array, 2, "") return@map Element(exp, codegen.load(sizePtr!!), true) } val exp = evaluateExpression(it)!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt index 3725e2105f8..ba66483a302 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/StaticObjects.kt @@ -18,8 +18,7 @@ private fun StaticData.objHeader(containerOffsetNegative: Int, typeInfo: ConstPo private fun StaticData.arrayHeader(containerOffsetNegative: Int, typeInfo: ConstPointer, length: Int): Struct { assert (length >= 0) - val objHeader = objHeader(containerOffsetNegative, typeInfo) - return Struct(runtime.arrayHeaderType, objHeader, Int32(length)) + return Struct(runtime.arrayHeaderType, typeInfo, Int32(containerOffsetNegative), Int32(length)) } private fun requiredPadding(size: Int, align: Int): Int { diff --git a/runtime/src/main/cpp/Arrays.cpp b/runtime/src/main/cpp/Arrays.cpp index 4c5188f314b..ec8794dd5f1 100644 --- a/runtime/src/main/cpp/Arrays.cpp +++ b/runtime/src/main/cpp/Arrays.cpp @@ -13,7 +13,7 @@ extern "C" { // Array.kt KRef Kotlin_Array_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -21,7 +21,7 @@ KRef Kotlin_Array_get(KConstRef thiz, KInt index) { } void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -29,23 +29,23 @@ void Kotlin_Array_set(KRef thiz, KInt index, KConstRef value) { } KRef Kotlin_Array_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( array->type_info(), array->count_).GetPlace(); memcpy( ArrayAddressOfElementAt(result, 0), ArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_Array_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } void Kotlin_Array_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KRef value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (fromIndex < 0 || toIndex < fromIndex || toIndex > array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -57,8 +57,8 @@ void Kotlin_Array_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KRef value) void Kotlin_Array_copyImpl(KConstRef thiz, KInt fromIndex, KRef destination, KInt toIndex, KInt count) { - const ArrayHeader* array = static_cast(thiz); - ArrayHeader* destinationArray = static_cast(destination); + const ArrayHeader* array = thiz->array(); + ArrayHeader* destinationArray = destination->array(); if (fromIndex < 0 || fromIndex + count > array->count_ || toIndex < 0 || toIndex + count > destinationArray->count_) { ThrowArrayIndexOutOfBoundsException(); @@ -70,7 +70,7 @@ void Kotlin_Array_copyImpl(KConstRef thiz, KInt fromIndex, // Arrays.kt KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -78,7 +78,7 @@ KByte Kotlin_ByteArray_get(KConstRef thiz, KInt index) { } void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -86,23 +86,23 @@ void Kotlin_ByteArray_set(KRef thiz, KInt index, KByte value) { } KRef Kotlin_ByteArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theByteArrayTypeInfo, array->count_).GetPlace(); memcpy( ByteArrayAddressOfElementAt(result, 0), ByteArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_ByteArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } KChar Kotlin_CharArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -110,7 +110,7 @@ KChar Kotlin_CharArray_get(KConstRef thiz, KInt index) { } void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -118,18 +118,18 @@ void Kotlin_CharArray_set(KRef thiz, KInt index, KChar value) { } KRef Kotlin_CharArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theCharArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KRef Kotlin_CharArray_copyOf(KConstRef thiz, KInt newSize) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theCharArrayTypeInfo, newSize).GetPlace(); KInt toCopy = array->count_ < newSize ? array->count_ : newSize; @@ -137,16 +137,16 @@ KRef Kotlin_CharArray_copyOf(KConstRef thiz, KInt newSize) { PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), toCopy * sizeof(KChar)); - return result; + return result->obj(); } KInt Kotlin_CharArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } KShort Kotlin_ShortArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -154,7 +154,7 @@ KShort Kotlin_ShortArray_get(KConstRef thiz, KInt index) { } void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -162,23 +162,23 @@ void Kotlin_ShortArray_set(KRef thiz, KInt index, KShort value) { } KRef Kotlin_ShortArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theShortArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_ShortArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } KInt Kotlin_IntArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -186,31 +186,31 @@ KInt Kotlin_IntArray_get(KConstRef thiz, KInt index) { } void Kotlin_IntArray_set(KRef thiz, KInt index, KInt value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } *PrimitiveArrayAddressOfElementAt(array, index) = value; } -ObjHeader* Kotlin_IntArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); +KRef Kotlin_IntArray_clone(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theIntArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_IntArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } void Kotlin_IntArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KInt value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (fromIndex < 0 || toIndex < fromIndex || toIndex >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -221,8 +221,8 @@ void Kotlin_IntArray_fillImpl(KRef thiz, KInt fromIndex, KInt toIndex, KInt valu void Kotlin_IntArray_copyImpl(KConstRef thiz, KInt fromIndex, KRef destination, KInt toIndex, KInt count) { - const ArrayHeader* array = static_cast(thiz); - ArrayHeader* destinationArray = static_cast(destination); + const ArrayHeader* array = thiz->array(); + ArrayHeader* destinationArray = destination->array(); if (fromIndex < 0 || fromIndex + count > array->count_ || toIndex < 0 || toIndex + count > destinationArray->count_) { ThrowArrayIndexOutOfBoundsException(); @@ -233,7 +233,7 @@ void Kotlin_IntArray_copyImpl(KConstRef thiz, KInt fromIndex, } KLong Kotlin_LongArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); @@ -242,7 +242,7 @@ KLong Kotlin_LongArray_get(KConstRef thiz, KInt index) { } void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -250,23 +250,23 @@ void Kotlin_LongArray_set(KRef thiz, KInt index, KLong value) { } KRef Kotlin_LongArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theLongArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_LongArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } KFloat Kotlin_FloatArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -274,31 +274,31 @@ KFloat Kotlin_FloatArray_get(KConstRef thiz, KInt index) { } void Kotlin_FloatArray_set(KRef thiz, KInt index, KFloat value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } *PrimitiveArrayAddressOfElementAt(array, index) = value; } -ArrayHeader* Kotlin_FloatArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); +KRef Kotlin_FloatArray_clone(KConstRef thiz) { + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theFloatArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_FloatArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } KDouble Kotlin_DoubleArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -306,7 +306,7 @@ KDouble Kotlin_DoubleArray_get(KConstRef thiz, KInt index) { } void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -314,23 +314,23 @@ void Kotlin_DoubleArray_set(KRef thiz, KInt index, KDouble value) { } KRef Kotlin_DoubleArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theDoubleArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_DoubleArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } KBoolean Kotlin_BooleanArray_get(KConstRef thiz, KInt index) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -338,7 +338,7 @@ KBoolean Kotlin_BooleanArray_get(KConstRef thiz, KInt index) { } void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) { - ArrayHeader* array = static_cast(thiz); + ArrayHeader* array = thiz->array(); if (static_cast(index) >= array->count_) { ThrowArrayIndexOutOfBoundsException(); } @@ -346,18 +346,18 @@ void Kotlin_BooleanArray_set(KRef thiz, KInt index, KBoolean value) { } KRef Kotlin_BooleanArray_clone(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); ArrayHeader* result = ArrayContainer( theBooleanArrayTypeInfo, array->count_).GetPlace(); memcpy( PrimitiveArrayAddressOfElementAt(result, 0), PrimitiveArrayAddressOfElementAt(array, 0), ArrayDataSizeBytes(array)); - return result; + return result->obj(); } KInt Kotlin_BooleanArray_getArrayLength(KConstRef thiz) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); return array->count_; } diff --git a/runtime/src/main/cpp/Exceptions.cpp b/runtime/src/main/cpp/Exceptions.cpp index 2fe23579c2b..d404be7161d 100644 --- a/runtime/src/main/cpp/Exceptions.cpp +++ b/runtime/src/main/cpp/Exceptions.cpp @@ -36,8 +36,7 @@ class AutoFree { // TODO: this method ignores the encoding. KString CreateKotlinStringFromCString(const char* str) { - return static_cast(AllocStringInstance( - SCOPE_GLOBAL, str, strlen(str))); + return AllocStringInstance(SCOPE_GLOBAL, str, strlen(str))->array(); } #ifdef __cplusplus @@ -59,7 +58,7 @@ KRef GetCurrentStackTrace() { for (int i = 0; i < size; ++i) { KString symbol = CreateKotlinStringFromCString(symbols[i]); - Kotlin_Array_set(result, i, symbol); + Kotlin_Array_set(result, i, symbol->obj()); } return result; diff --git a/runtime/src/main/cpp/Memory.cpp b/runtime/src/main/cpp/Memory.cpp index 61136f7b1b5..eb997826059 100644 --- a/runtime/src/main/cpp/Memory.cpp +++ b/runtime/src/main/cpp/Memory.cpp @@ -1,6 +1,8 @@ #include #include +#include // for offsetof + #include "Assert.h" #include "Exceptions.h" #include "Memory.h" @@ -42,7 +44,7 @@ void ArrayContainer::Init(const TypeInfo* type_info, uint32_t elements) { if (header_) { header_->ref_count_ = CONTAINER_TAG_INCREMENT; GetPlace()->count_ = elements; - SetMeta(GetPlace(), type_info); + SetMeta(GetPlace()->obj(), type_info); } } @@ -64,7 +66,7 @@ ArrayHeader* ArenaContainer::PlaceArray(const TypeInfo* type_info, int count) { if (!result) { return nullptr; } - SetMeta(result, type_info); + SetMeta(result->obj(), type_info); result->count_ = count; return result; } @@ -74,6 +76,14 @@ extern "C" { #endif void InitMemory() { + RuntimeAssert(offsetof(ArrayHeader, type_info_) + == + offsetof(ObjHeader, type_info_), + "Layout mismatch"); + RuntimeAssert(offsetof(ArrayHeader, container_offset_negative_) + == + offsetof(ObjHeader , container_offset_negative_), + "Layout mismatch"); // TODO: initialize heap here. } @@ -86,7 +96,7 @@ ObjHeader* AllocInstance(const TypeInfo* type_info, PlacementHint hint) { ObjHeader* AllocArrayInstance( const TypeInfo* type_info, PlacementHint hint, uint32_t elements) { RuntimeAssert(type_info->instanceSize_ < 0, "must be an array"); - return ArrayContainer(type_info, elements).GetPlace(); + return ArrayContainer(type_info, elements).GetPlace()->obj(); } ObjHeader* AllocStringInstance( @@ -96,7 +106,7 @@ ObjHeader* AllocStringInstance( ByteArrayAddressOfElementAt(result, 0), data, length); - return result; + return result->obj(); } ObjHeader* InitInstance( diff --git a/runtime/src/main/cpp/Memory.h b/runtime/src/main/cpp/Memory.h index 1b8275cd4b5..759c4d42189 100644 --- a/runtime/src/main/cpp/Memory.h +++ b/runtime/src/main/cpp/Memory.h @@ -39,6 +39,8 @@ struct ContainerHeader { volatile uint32_t ref_count_; }; +struct ArrayHeader; + // Header of every object. struct ObjHeader { const TypeInfo* type_info_; @@ -63,10 +65,40 @@ struct ObjHeader { return reinterpret_cast( reinterpret_cast(this) - container_offset_negative_); } + + // Unsafe cast to ArrayHeader. Use carefully! + ArrayHeader* array() { return reinterpret_cast(this); } + const ArrayHeader* array() const { return reinterpret_cast(this); } }; -// Header of value type array objects. -struct ArrayHeader : public ObjHeader { +// Header of value type array objects. Keep layout in sync with that of object header. +struct ArrayHeader { + 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( + reinterpret_cast(this) - container_offset_negative_); + } + + ObjHeader* obj() { return reinterpret_cast(this); } + const ObjHeader* obj() const { return reinterpret_cast(this); } + // Elements count. Element size is stored in instanceSize_ field of TypeInfo, negated. uint32_t count_; }; diff --git a/runtime/src/main/cpp/Natives.cpp b/runtime/src/main/cpp/Natives.cpp index 1caa8280c40..7b9d717c7a1 100644 --- a/runtime/src/main/cpp/Natives.cpp +++ b/runtime/src/main/cpp/Natives.cpp @@ -77,7 +77,7 @@ KInt Kotlin_String_getStringLength(KString thiz) { } KString Kotlin_String_fromUtf8Array(KConstRef thiz, KInt start, KInt size) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); RuntimeAssert(array->type_info() == theByteArrayTypeInfo, "Must use a byte array"); if (start < 0 || size < 0 || start + size > array->count_) { ThrowArrayIndexOutOfBoundsException(); @@ -97,7 +97,7 @@ KString Kotlin_String_fromUtf8Array(KConstRef thiz, KInt start, KInt size) { } KString Kotlin_String_fromCharArray(KConstRef thiz, KInt start, KInt size) { - const ArrayHeader* array = static_cast(thiz); + const ArrayHeader* array = thiz->array(); RuntimeAssert(array->type_info() == theCharArrayTypeInfo, "Must use a byte array"); if (start < 0 || size < 0 || start + size > array->count_) { ThrowArrayIndexOutOfBoundsException(); @@ -124,7 +124,7 @@ KRef Kotlin_String_toCharArray(KString string) { *PrimitiveArrayAddressOfElementAt(result, index) = *ByteArrayAddressOfElementAt(string, index); } - return result; + return result->obj(); } @@ -151,8 +151,8 @@ KString Kotlin_String_plusImpl(KString thiz, KString other) { KBoolean Kotlin_String_equals(KString thiz, KConstRef other) { if (other == nullptr || other->type_info() != theStringTypeInfo) return false; // Important, due to literal internalization. - if (thiz == other) return true; - KString otherString = reinterpret_cast(other); + KString otherString = other->array(); + if (thiz == otherString) return true; return thiz->count_ == otherString->count_ && memcmp(ByteArrayAddressOfElementAt(thiz, 0), ByteArrayAddressOfElementAt(otherString, 0),