[Wasm] Make Any hashCode and typeId fields generated by compiler.

Replace property access with intrinsic functions.

This makes them consistent with other compiler-generated fields,
 like v-table.

Compiler treats internal visibility as possibly-public by friends and
generates fake-override for get/set accessors in
 **every** subclass of Any, which causes unnecessary noise in IR and
 tools working with API visibility.
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt
index 0d8c632..69c50e8 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt
@@ -230,6 +230,9 @@
     val startUnitTests = maybeGetFunction("startUnitTests", kotlinTestPackage)
 
     val wasmTypeId = getInternalFunction("wasmTypeId")
+    val wasmGetTypeIdField = getInternalFunction("wasmGetTypeIdField")
+    val wasmGetHashCodeField = getInternalFunction("wasmGetHashCodeField")
+    val wasmSetHashCodeField = getInternalFunction("wasmSetHashCodeField")
 
     val wasmIsInterface = getInternalFunction("wasmIsInterface")
 
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
index f5d2cd2..b1ce226 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
@@ -338,10 +338,8 @@
             body.buildIf("this_init")
             generateAnyParameters(parentClass.symbol, location)
             val irFields: List<IrField> = parentClass.allFields(backendContext.irBuiltIns)
-            irFields.forEachIndexed { index, field ->
-                if (index > 1) {
-                    generateDefaultInitializerForType(context.transformType(field.type), body)
-                }
+            irFields.forEach { field ->
+                generateDefaultInitializerForType(context.transformType(field.type), body)
             }
             body.buildStructNew(context.referenceGcType(parentClass.symbol), location)
             body.buildSetLocal(thisParameter, location)
@@ -435,7 +433,7 @@
                 //TODO: check why it could be needed
                 generateRefCast(receiver.type, klass.defaultType, location)
 
-                body.buildStructGet(context.referenceGcType(klass.symbol), WasmSymbol(0), location)
+                body.buildStructGet(context.referenceGcType(klass.symbol), WasmSymbol(WasmStructLayout.VTABLE_FIELD_INDEX), location)
                 body.buildStructGet(context.referenceVTableGcType(klass.symbol), WasmSymbol(vfSlot), location)
                 body.buildInstr(WasmOp.CALL_REF, location, WasmImmediate.TypeIdx(context.referenceFunctionType(function.symbol)))
                 body.commentGroupEnd()
@@ -445,7 +443,7 @@
                     generateExpression(call.dispatchReceiver!!)
 
                     body.commentGroupStart { "interface call: ${function.fqNameWhenAvailable}" }
-                    body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1), location)
+                    body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(WasmStructLayout.ITABLE_FIELD_INDEX), location)
 
                     val classITableReference = context.referenceClassITableGcType(symbol)
                     body.buildRefCastStatic(classITableReference, location)
@@ -527,6 +525,18 @@
         val location = call.getSourceLocation()
 
         when (function.symbol) {
+            wasmSymbols.wasmGetTypeIdField -> {
+                body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(WasmStructLayout.TYPE_ID_FIELD_INDEX), location)
+            }
+
+            wasmSymbols.wasmGetHashCodeField -> {
+                body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(WasmStructLayout.HASH_CODE_FIELD_INDEX), location)
+            }
+
+            wasmSymbols.wasmSetHashCodeField -> {
+                body.buildStructSet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(WasmStructLayout.HASH_CODE_FIELD_INDEX), location)
+            }
+
             wasmSymbols.wasmTypeId -> {
                 val klass = call.getTypeArgument(0)!!.getClass()
                     ?: error("No class given for wasmTypeId intrinsic")
@@ -544,7 +554,7 @@
                     body.buildBlock("isInterface", WasmI32) { outerLabel ->
                         body.buildBlock("isInterface", WasmRefNullType(WasmHeapType.Simple.Struct)) { innerLabel ->
                             body.buildGetLocal(parameterLocal, location)
-                            body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(1), location)
+                            body.buildStructGet(context.referenceGcType(irBuiltIns.anyClass), WasmSymbol(WasmStructLayout.ITABLE_FIELD_INDEX), location)
 
                             body.buildBrOnCastInstr(
                                 WasmOp.BR_ON_CAST_FAIL,
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt
index ce66cdb..ec4fa47 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt
@@ -377,6 +377,9 @@
             val fields = mutableListOf<WasmStructFieldDeclaration>()
             fields.add(WasmStructFieldDeclaration("vtable", vtableRefGcType, false))
             fields.add(WasmStructFieldDeclaration("itable", classITableRefGcType, false))
+            fields.add(WasmStructFieldDeclaration("typeId", WasmI32, false))
+            fields.add(WasmStructFieldDeclaration("_hashCode", WasmI32, true))
+
             declaration.allFields(irBuiltIns).mapTo(fields) {
                 WasmStructFieldDeclaration(
                     name = it.name.toString(),
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt
index 7e9e84e..f9ded86 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt
@@ -183,7 +183,7 @@
     fun getStructFieldRef(field: IrField): WasmSymbol<Int> {
         val klass = field.parentAsClass
         val metadata = getClassMetadata(klass.symbol)
-        val fieldId = metadata.fields.indexOf(field) + 2 //Implicit vtable and vtable field
+        val fieldId = metadata.fields.indexOf(field) + WasmStructLayout.NUMBER_OF_IMPLICIT_FIELDS
         return WasmSymbol(fieldId)
     }
 
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmStructLayout.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmStructLayout.kt
new file mode 100644
index 0000000..ab9f482
--- /dev/null
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmStructLayout.kt
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.backend.wasm.ir2wasm
+
+object WasmStructLayout {
+    const val VTABLE_FIELD_INDEX = 0    // GC reference
+    const val ITABLE_FIELD_INDEX = 1    // GC reference
+    const val TYPE_ID_FIELD_INDEX = 2   // i32
+    const val HASH_CODE_FIELD_INDEX = 3 // i32
+
+    const val NUMBER_OF_IMPLICIT_FIELDS = 4
+}
\ No newline at end of file
diff --git a/libraries/stdlib/wasm/builtins/kotlin/Any.kt b/libraries/stdlib/wasm/builtins/kotlin/Any.kt
index c756874..3c35d41 100644
--- a/libraries/stdlib/wasm/builtins/kotlin/Any.kt
+++ b/libraries/stdlib/wasm/builtins/kotlin/Any.kt
@@ -13,11 +13,6 @@
  * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
  */
 public open class Any @WasmPrimitiveConstructor constructor() {
-    // Pointer to runtime type info
-    // Initialized by a compiler
-    @Suppress("MUST_BE_INITIALIZED_OR_BE_ABSTRACT")
-    internal var typeInfo: Int
-
     /**
      * Indicates whether some other object is "equal to" this one. Implementations must fulfil the following
      * requirements:
@@ -39,7 +34,6 @@
      * * Whenever it is invoked on the same object more than once, the `hashCode` method must consistently return the same integer, provided no information used in `equals` comparisons on the object is modified.
      * * If two objects are equal according to the `equals()` method, then calling the `hashCode` method on each of the two objects must produce the same integer result.
      */
-    internal var _hashCode: Int = 0
     public open fun hashCode(): Int {
         return identityHashCode()
     }
@@ -48,7 +42,7 @@
      * Returns a string representation of the object.
      */
     public open fun toString(): String {
-        val typeInfoPtr = this.typeInfo
+        val typeInfoPtr = wasmGetTypeIdField(this)
         val packageName = getPackageName(typeInfoPtr)
         val simpleName = getSimpleName(typeInfoPtr)
         val qualifiedName = if (packageName.isEmpty()) simpleName else "$packageName.$simpleName"
@@ -60,7 +54,8 @@
 // Don't inline it into usages, specifically to `hashCode`. 
 // It was extracted to remove `toString`'s dependency on `hashCode`, which improves output size when DCE is involved.
 private fun Any.identityHashCode(): Int {
-    if (_hashCode == 0)
-        _hashCode = Random.nextInt(1, Int.MAX_VALUE)
-    return _hashCode
+    if (wasmGetHashCodeField(this) == 0) {
+        wasmSetHashCodeField(this, Random.nextInt(1, Int.MAX_VALUE))
+    }
+    return wasmGetHashCodeField(this)
 }
diff --git a/libraries/stdlib/wasm/builtins/kotlin/String.kt b/libraries/stdlib/wasm/builtins/kotlin/String.kt
index 91df1ad..7e61714 100644
--- a/libraries/stdlib/wasm/builtins/kotlin/String.kt
+++ b/libraries/stdlib/wasm/builtins/kotlin/String.kt
@@ -103,8 +103,8 @@
         val otherLength = otherString.length
         if (thisLength != otherLength) return false
 
-        val thisHash = this._hashCode
-        val otherHash = other._hashCode
+        val thisHash = wasmGetHashCodeField(this)
+        val otherHash = wasmGetHashCodeField(other)
         if (thisHash != otherHash && thisHash != 0 && otherHash != 0) return false
 
         val thisChars = this.chars
@@ -119,7 +119,7 @@
     public override fun toString(): String = this
 
     public override fun hashCode(): Int {
-        if (_hashCode != 0) return _hashCode
+        if (wasmGetHashCodeField(this) != 0) return wasmGetHashCodeField(this)
         val thisLength = this.length
         if (thisLength == 0) return 0
 
@@ -128,8 +128,8 @@
         repeat(thisLength) {
             hash = (hash shl 5) - hash + thisChars.get(it).code
         }
-        _hashCode = hash
-        return _hashCode
+        wasmSetHashCodeField(this, hash)
+        return wasmGetHashCodeField(this)
     }
 }
 
diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt
index 227cb12..929b28c 100644
--- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt
+++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt
@@ -7,6 +7,21 @@
 
 package kotlin.wasm.internal
 
+/** Set hidden built-in hashCode field */
+@ExcludedFromCodegen
+internal fun wasmSetHashCodeField(obj: Any, value: Int): Unit =
+    implementedAsIntrinsic
+
+/** Get hidden built-in hashCode field */
+@ExcludedFromCodegen
+internal fun wasmGetHashCodeField(obj: Any): Int =
+    implementedAsIntrinsic
+
+/** Get hidden built-in typeID field */
+@ExcludedFromCodegen
+internal fun wasmGetTypeIdField(obj: Any): Int =
+    implementedAsIntrinsic
+
 internal const val CHAR_SIZE_BYTES = 2
 
 internal fun unsafeRawMemoryToWasmCharArray(srcAddr: Int, dstOffset: Int, dstLength: Int, dst: WasmCharArray) {
diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt
index a093b14..2feff1c 100644
--- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt
+++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt
@@ -55,8 +55,8 @@
     wasm_i32_load(typeInfoPtr + TYPE_INFO_SUPER_TYPE_OFFSET)
 
 internal fun isInterfaceById(obj: Any, interfaceId: Int): Boolean {
-    val interfaceListSize = wasm_i32_load(obj.typeInfo + TYPE_INFO_ITABLE_SIZE_OFFSET)
-    val interfaceListPtr = obj.typeInfo + TYPE_INFO_ITABLE_OFFSET
+    val interfaceListSize = wasm_i32_load(wasmGetTypeIdField(obj) + TYPE_INFO_ITABLE_SIZE_OFFSET)
+    val interfaceListPtr = wasmGetTypeIdField(obj) + TYPE_INFO_ITABLE_OFFSET
 
     var interfaceSlot = 0
     while (interfaceSlot < interfaceListSize) {
diff --git a/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt b/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt
index 31a8597..49f03d0 100644
--- a/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt
+++ b/libraries/stdlib/wasm/js/builtins/kotlin/Throwable.kt
@@ -8,6 +8,7 @@
 import kotlin.wasm.internal.ExternalInterfaceType
 import kotlin.wasm.internal.getSimpleName
 import kotlin.wasm.internal.jsToKotlinStringAdapter
+import kotlin.wasm.internal.wasmGetTypeIdField
 
 /**
  * The base class for all errors and exceptions. Only instances of this class can be thrown or caught.
@@ -43,7 +44,7 @@
      * followed by the exception message if it is not null.
      */
     public override fun toString(): String {
-        val s = getSimpleName(this.typeInfo)
+        val s = getSimpleName(wasmGetTypeIdField(this))
         return if (message != null) s + ": " + message.toString() else s
     }
 }
diff --git a/libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt b/libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt
index 241d9a2..c5a676f 100644
--- a/libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt
+++ b/libraries/stdlib/wasm/js/internal/ExceptionHelpers.kt
@@ -17,5 +17,5 @@
 }
 
 internal fun throwAsJsException(t: Throwable): Nothing {
-    throwJsError(t.message, getSimpleName(t.typeInfo), t.jsStack)
+    throwJsError(t.message, getSimpleName(wasmGetTypeIdField(t)), t.jsStack)
 }
\ No newline at end of file
diff --git a/libraries/stdlib/wasm/js/internal/ExternalWrapper.kt b/libraries/stdlib/wasm/js/internal/ExternalWrapper.kt
index 85002f1..e0d3a9c 100644
--- a/libraries/stdlib/wasm/js/internal/ExternalWrapper.kt
+++ b/libraries/stdlib/wasm/js/internal/ExternalWrapper.kt
@@ -25,10 +25,10 @@
         }
 
     override fun hashCode(): Int {
-        var hashCode = _hashCode
+        var hashCode = wasmGetHashCodeField(this)
         if (hashCode != 0) return hashCode
         hashCode = externrefHashCode(ref)
-        _hashCode = hashCode
+        wasmSetHashCodeField(this, hashCode)
         return hashCode
     }
 }
diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt
index 593800e..f78b572 100644
--- a/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt
+++ b/libraries/stdlib/wasm/src/kotlin/reflect/KClassImpl.kt
@@ -5,6 +5,7 @@
 package kotlin.reflect.wasm.internal
 
 import kotlin.reflect.*
+import kotlin.wasm.internal.*
 import kotlin.wasm.internal.TypeInfoData
 import kotlin.wasm.internal.getSuperTypeId
 import kotlin.wasm.internal.isInterfaceById
@@ -36,7 +37,7 @@
         if (typeData.packageName.isEmpty()) typeData.typeName else "${typeData.packageName}.${typeData.typeName}"
 
     private fun checkSuperTypeInstance(obj: Any): Boolean {
-        var typeId = obj.typeInfo
+        var typeId = wasmGetTypeIdField(obj)
         while (typeId != -1) {
             if (typeData.typeId == typeId) return true
             typeId = getSuperTypeId(typeId)
diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/reflection.kt b/libraries/stdlib/wasm/src/kotlin/reflect/reflection.kt
index 5d1ebd6..e101313 100644
--- a/libraries/stdlib/wasm/src/kotlin/reflect/reflection.kt
+++ b/libraries/stdlib/wasm/src/kotlin/reflect/reflection.kt
@@ -34,7 +34,7 @@
         is DoubleArray -> PrimitiveClasses.doubleArrayClass
         is KClass<*> -> KClass::class
         is Array<*> -> PrimitiveClasses.arrayClass
-        else -> getKClass(getTypeInfoTypeDataByPtr(e.typeInfo))
+        else -> getKClass(getTypeInfoTypeDataByPtr(wasmGetTypeIdField(e)))
     } as KClass<T>
 
 @Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
diff --git a/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt b/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt
index baddf1a..b56c6aa 100644
--- a/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt
+++ b/libraries/stdlib/wasm/wasi/builtins/kotlin/Throwable.kt
@@ -6,6 +6,7 @@
 package kotlin
 
 import kotlin.wasm.internal.getSimpleName
+import kotlin.wasm.internal.wasmGetTypeIdField
 
 /**
  * The base class for all errors and exceptions. Only instances of this class can be thrown or caught.
@@ -30,7 +31,7 @@
      * followed by the exception message if it is not null.
      */
     public override fun toString(): String {
-        val s = getSimpleName(this.typeInfo)
+        val s = getSimpleName(wasmGetTypeIdField(this))
         return if (message != null) s + ": " + message.toString() else s
     }
 }
\ No newline at end of file