[Native] remove isSameEncoding and redundant static_asserts
diff --git a/kotlin-native/runtime/src/main/cpp/KString.cpp b/kotlin-native/runtime/src/main/cpp/KString.cpp
index 3f09426..22673da 100644
--- a/kotlin-native/runtime/src/main/cpp/KString.cpp
+++ b/kotlin-native/runtime/src/main/cpp/KString.cpp
@@ -70,11 +70,6 @@
     return std::all_of(utf8, utf8 + lengthBytes, [](char c) { return c >= 0; });
 }
 
-template <typename String1, typename String2>
-constexpr bool isSameEncoding(String1&& a, String2&& b) {
-    return std::is_same_v<std::decay_t<String1>, std::decay_t<String2>>;
-}
-
 template <typename String, typename It>
 bool isInSurrogatePair(String&& string, It&& it) {
     return string.at(it.ptr()) != it;
@@ -246,7 +241,7 @@
             ThrowOutOfMemoryError();
         }
 
-        if (isSameEncoding(thiz, other) &&
+        if (thiz.encoding == other.encoding &&
             // In non-UTF-16 encodings, the total size in units could still overflow, e.g.
             // UTF-8 has characters that encode to 3 bytes while only needing 2 in UTF-16.
             (thiz.encoding == StringEncoding::kUTF16 || thiz.sizeInUnits() < std::numeric_limits<size_t>::max() - other.sizeInUnits())
@@ -343,7 +338,7 @@
     return encodingAware(thiz, other, [=](auto thiz, auto other) {
         auto begin1 = thiz.begin(), end1 = thiz.end();
         auto begin2 = other.begin(), end2 = other.end();
-        if constexpr (isSameEncoding(thiz, other)) {
+        if constexpr (thiz.encoding == other.encoding) {
             auto [ptr1, ptr2] = std::mismatch(begin1.ptr(), end1.ptr(), begin2.ptr(), end2.ptr());
             return Kotlin_String_compareAt(thiz.at(ptr1), end1, other.at(ptr2), end2);
         } else {
@@ -397,7 +392,7 @@
     if (other == nullptr || other->type_info() != theStringTypeInfo) return false;
     // TODO: if hash code is computed and unequal, then strings are also unequal
     return thiz == other || encodingAware(thiz, other, [=](auto thiz, auto other) {
-        if constexpr (isSameEncoding(thiz, other)) {
+        if constexpr (thiz.encoding == other.encoding) {
             return std::equal(thiz.begin().ptr(), thiz.end().ptr(), other.begin().ptr(), other.end().ptr());
         } else {
             return std::equal(thiz.begin(), thiz.end(), other.begin(), other.end());
@@ -414,20 +409,21 @@
         // and then compare the known fixed range, or to decode characters one by one and count while comparing?
         auto end1 = begin1 + length;
         auto end2 = begin2 + length;
-        if constexpr (!isSameEncoding(thiz, other)) {
+        if constexpr (thiz.encoding == other.encoding) {
+            // Assuming only one "canonical" encoding, can byte-compare encoded values.
+            // Since ptr() is only well-defined at unit boundaries, surrogates at ends should be checked separately.
+            bool startsWithUnequalLowSurrogate = isInSurrogatePair(thiz, begin1)
+                ? !isInSurrogatePair(other, begin2) || *begin1++ != *begin2++ // safe because length != 0
+                : isInSurrogatePair(other, begin2);
+            if (startsWithUnequalLowSurrogate) return false;
+            bool endsWithUnequalHighSurrogate = isInSurrogatePair(thiz, end1)
+                ? !isInSurrogatePair(other, end2) || *--end1 != *--end2 // safe because begin1 and begin2 are not in a surrogate pair
+                : isInSurrogatePair(other, end2);
+            if (endsWithUnequalHighSurrogate) return false;
+            return std::equal(begin1.ptr(), end1.ptr(), begin2.ptr(), end2.ptr());
+        } else {
             return std::equal(begin1, end1, begin2, end2);
         }
-        // Assuming only one "canonical" encoding, can byte-compare encoded values.
-        // Since ptr() is only well-defined at unit boundaries, surrogates at ends should be checked separately.
-        bool startsWithUnequalLowSurrogate = isInSurrogatePair(thiz, begin1)
-            ? !isInSurrogatePair(other, begin2) || *begin1++ != *begin2++ // safe because length != 0
-            : isInSurrogatePair(other, begin2);
-        if (startsWithUnequalLowSurrogate) return false;
-        bool endsWithUnequalHighSurrogate = isInSurrogatePair(thiz, end1)
-            ? !isInSurrogatePair(other, end2) || *--end1 != *--end2 // safe because begin1 and begin2 are not in a surrogate pair
-            : isInSurrogatePair(other, end2);
-        if (endsWithUnequalHighSurrogate) return false;
-        return std::equal(begin1.ptr(), end1.ptr(), begin2.ptr(), end2.ptr());
     });
 }
 
@@ -482,7 +478,7 @@
 
         auto start = thiz.begin() + unsignedIndex, end = thiz.end();
         auto patternStart = other.begin(), patternEnd = other.end();
-        if constexpr (isSameEncoding(thiz, other)) {
+        if constexpr (thiz.encoding == other.encoding) {
             auto shift = unsignedIndex;
             while (start != end) {
                 if (isInSurrogatePair(thiz, start)) {
diff --git a/kotlin-native/runtime/src/main/cpp/KString.h b/kotlin-native/runtime/src/main/cpp/KString.h
index 2948d2b..f4d3dcb 100644
--- a/kotlin-native/runtime/src/main/cpp/KString.h
+++ b/kotlin-native/runtime/src/main/cpp/KString.h
@@ -31,7 +31,7 @@
     ARRAY_HEADER_FIELDS
     int32_t hashCode_; // if ArrayHeader has padding, this will go into it instead of the array's data
     uint16_t flags_;
-    char data_[];
+    alignas(KChar) char data_[];
 
     enum {
         IGNORE_LAST_BYTE = 1 << 0,
@@ -53,9 +53,6 @@
     }
 };
 
-static_assert(offsetof(StringHeader, data_) >= sizeof(ArrayHeader));
-static_assert((offsetof(StringHeader, data_) - sizeof(ArrayHeader)) % 2 == 0);
-
 template <StringEncoding encoding>
 struct StringData;
 
@@ -68,8 +65,8 @@
     struct Iterator {
         using difference_type = size_t;
         using value_type = KChar;
-        using pointer = const KChar*;
-        using reference = const KChar&;
+        using pointer = void;
+        using reference = void;
         using iterator_category = std::bidirectional_iterator_tag;
 
         const unit* p_;