diff --git a/static_core/plugins/ets/runtime/ets_stubs.cpp b/static_core/plugins/ets/runtime/ets_stubs.cpp index 7d8e16dcfd3c4473535fd9766d9a428cda0b7b4e..692d40c2106959b651a9e81dad121a5815e7c9b7 100644 --- a/static_core/plugins/ets/runtime/ets_stubs.cpp +++ b/static_core/plugins/ets/runtime/ets_stubs.cpp @@ -14,13 +14,19 @@ * limitations under the License. */ +#include #include "plugins/ets/runtime/ets_class_linker_extension.h" #include "plugins/ets/runtime/ets_stubs-inl.h" #include "plugins/ets/runtime/ets_utils.h" +#include "plugins/ets/runtime/types/ets_array.h" #include "plugins/ets/runtime/types/ets_base_enum.h" #include "plugins/ets/runtime/types/ets_box_primitive.h" +#include "plugins/ets/runtime/types/ets_class.h" #include "plugins/ets/runtime/types/ets_method.h" +#include "plugins/ets/runtime/types/ets_object.h" +#include "plugins/ets/runtime/types/ets_primitives.h" #include "plugins/ets/runtime/types/ets_string.h" +#include "types/ets_type.h" #ifdef PANDA_ETS_INTEROP_JS #include "plugins/ets/runtime/interop_js/intrinsics_api_impl.h" @@ -365,47 +371,176 @@ inline EtsMethod *FindSetMethod(EtsCoroutine *coro, EtsClass *cls) return setMethod; } -EtsObject *EtsLdbyidx(EtsCoroutine *coro, EtsObject *thisObj, [[maybe_unused]] uint32_t index) +static EtsObject *FixedArrayGetByIdx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx) { - if (thisObj->GetClass()->GetRuntimeClass()->IsXRefClass()) { - PANDA_ETS_INTEROP_JS_GUARD({ - ASSERT(thisObj->GetClass() == PlatformTypes(coro)->interopJSValue); - auto thisValue = JSValue::FromEtsObject(thisObj); - return interop::js::JSValueIndexedGetter(thisValue, index); - }); + if (thisObj->GetClass()->GetComponentType()->IsPrimitive()) { + EtsType type = ConvertPandaTypeToEtsType(thisObj->GetClass()->GetComponentType()->GetType()); + switch (type) { + case EtsType::BOOLEAN: { + auto thisFixedArray = EtsBooleanArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::BYTE: { + auto thisFixedArray = EtsByteArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::CHAR: { + auto thisFixedArray = EtsCharArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::SHORT: { + auto thisFixedArray = EtsShortArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::INT: { + auto thisFixedArray = EtsIntArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::LONG: { + auto thisFixedArray = EtsLongArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::FLOAT: { + auto thisFixedArray = EtsFloatArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + case EtsType::DOUBLE: { + auto thisFixedArray = EtsDoubleArray::FromEtsObject(thisObj); + return reinterpret_cast(GetBoxedValue(coro, ark::Value(thisFixedArray->Get(idx)), type)); + } + default: { + // invariant broken!!! + UNREACHABLE(); + } + } } else { + // true: if it's a typed array, then we can use the EtsObjectArray to access the elements + auto thisFixedArray = EtsObjectArray::FromEtsObject(thisObj); + return thisFixedArray->Get(idx); + } +} + +static void FixedArraySetByIdx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx, EtsObject *valueToSet) +{ + if (thisObj->GetClass()->GetComponentType()->IsPrimitive()) { + EtsType type = ConvertPandaTypeToEtsType(thisObj->GetClass()->GetComponentType()->GetType()); + ark::Value etsVal = GetUnboxedValue(coro, valueToSet); + switch (type) { + case EtsType::BOOLEAN: { + auto thisFixedArray = EtsBooleanArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::BYTE: { + auto thisFixedArray = EtsByteArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::CHAR: { + auto thisFixedArray = EtsCharArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::SHORT: { + auto thisFixedArray = EtsShortArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::INT: { + auto thisFixedArray = EtsIntArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::LONG: { + auto thisFixedArray = EtsLongArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::FLOAT: { + auto thisFixedArray = EtsFloatArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + case EtsType::DOUBLE: { + auto thisFixedArray = EtsDoubleArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, etsVal.GetAs()); + return; + } + default: { + // invariant broken!!! + UNREACHABLE(); + } + } + } else { + // true: if it's a typed array, then we can use the EtsObjectArray to access the elements + auto thisFixedArray = EtsObjectArray::FromEtsObject(thisObj); + thisFixedArray->Set(idx, valueToSet, std::memory_order_relaxed); + } +} + +static EtsObject *StaicObjectGetByIdx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx) +{ + // Check if thisObj is a typed array + if (thisObj->IsArrayClass()) { + // true: it is fixed array + return FixedArrayGetByIdx(coro, thisObj, idx); + } else { + // false: otherwise, we need to use the $_get method to access the elements auto getMethod = FindGetMethod(coro, thisObj->GetClass()); if (getMethod == nullptr) { return nullptr; } - std::array args {ark::Value(thisObj->GetCoreType()), ark::Value(index)}; + std::array args {ark::Value(thisObj->GetCoreType()), ark::Value(idx)}; Value res = getMethod->GetPandaMethod()->Invoke(coro, args.data()); return EtsObject::FromCoreType(res.GetAs()); } } -bool EtsStbyidx(EtsCoroutine *coro, EtsObject *obj, uint32_t idx, EtsObject *value) +static bool StaicObjectSetByIdx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx, EtsObject *valueToSet) { - if (obj->GetClass()->GetRuntimeClass()->IsXRefClass()) { + // Check if thisObj is a typed array + if (thisObj->IsArrayClass()) { + // true: it is a fixed array + FixedArraySetByIdx(coro, thisObj, idx, valueToSet); + return true; + } else { + // false: otherwise, we need to use the $_set method to access the elements + auto setMethod = FindSetMethod(coro, thisObj->GetClass()); + if (setMethod == nullptr) { + return false; + } + std::array args {ark::Value(thisObj->GetCoreType()), ark::Value(idx), ark::Value(valueToSet->GetCoreType())}; + setMethod->GetPandaMethod()->Invoke(coro, args.data()); + return true; + } +} + +EtsObject *EtsLdbyidx(EtsCoroutine *coro, EtsObject *thisObj, [[maybe_unused]] uint32_t idx) +{ + if (thisObj->GetClass()->GetRuntimeClass()->IsXRefClass()) { PANDA_ETS_INTEROP_JS_GUARD({ - ASSERT(obj->GetClass() == PlatformTypes(coro)->interopJSValue); - auto thisValue = JSValue::FromEtsObject(obj); + ASSERT(thisObj->GetClass() == PlatformTypes(coro)->interopJSValue); + auto thisValue = JSValue::FromEtsObject(thisObj); + return interop::js::JSValueIndexedGetter(thisValue, idx); + }); + } else { + return StaicObjectGetByIdx(coro, thisObj, idx); + } +} + +bool EtsStbyidx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx, EtsObject *value) +{ + if (thisObj->GetClass()->GetRuntimeClass()->IsXRefClass()) { + PANDA_ETS_INTEROP_JS_GUARD({ + ASSERT(thisObj->GetClass() == PlatformTypes(coro)->interopJSValue); + auto thisValue = JSValue::FromEtsObject(thisObj); interop::js::SetIndexedPropertyWithObject(thisValue, idx, value); return true; }); } else { // ASSERTION. LHS is not a JSValue // then it is must a static object - auto unboxedValue = GetBoxedNumericValue(PlatformTypes(coro), value); - if (unboxedValue.has_value()) { - auto setMethod = FindSetMethod(coro, obj->GetClass()); - if (setMethod == nullptr) { - return false; - } - std::array args {ark::Value(obj->GetCoreType()), ark::Value(idx), ark::Value(value->GetCoreType())}; - setMethod->GetPandaMethod()->Invoke(coro, args.data()); - return true; - } + return StaicObjectSetByIdx(coro, thisObj, idx, value); } UNREACHABLE(); } @@ -444,25 +579,20 @@ EtsObject *EtsLdbyval(EtsCoroutine *coro, EtsObject *thisObj, EtsObject *valObj) } auto unboxedValue = GetBoxedNumericValue(PlatformTypes(coro), valObj); if (unboxedValue.has_value()) { - auto getMethod = FindGetMethod(coro, thisObj->GetClass()); - if (getMethod == nullptr) { - return nullptr; - } - std::array args {ark::Value(thisObj->GetCoreType()), ark::Value(unboxedValue.value())}; - ark::Value res = getMethod->GetPandaMethod()->Invoke(coro, args.data()); - return EtsObject::FromCoreType(res.GetAs()); + uint32_t idx = unboxedValue.value(); + return StaicObjectGetByIdx(coro, thisObj, idx); } ThrowEtsInvalidKey(coro, valObj->GetClass()->GetDescriptor()); return nullptr; } } -bool EtsStbyval(EtsCoroutine *coro, EtsObject *obj, EtsObject *key, EtsObject *value) +bool EtsStbyval(EtsCoroutine *coro, EtsObject *thisObj, EtsObject *key, EtsObject *value) { - if (obj->GetClass()->GetRuntimeClass()->IsXRefClass()) { + if (thisObj->GetClass()->GetRuntimeClass()->IsXRefClass()) { PANDA_ETS_INTEROP_JS_GUARD({ - ASSERT(obj->GetClass() == PlatformTypes(coro)->interopJSValue); - auto thisValue = JSValue::FromEtsObject(obj); + ASSERT(thisObj->GetClass() == PlatformTypes(coro)->interopJSValue); + auto thisValue = JSValue::FromEtsObject(thisObj); if (key->IsStringClass()) { interop::js::SetNamedPropertyWithObject( thisValue, utf::Mutf8AsCString(EtsString::FromEtsObject(key)->GetDataMUtf8()), value); @@ -485,23 +615,20 @@ bool EtsStbyval(EtsCoroutine *coro, EtsObject *obj, EtsObject *key, EtsObject *v // then it is must a static object if (key->IsStringClass()) { auto fieldName = EtsString::FromEtsObject(key)->GetDataMUtf8(); - auto fieldIndex = obj->GetClass()->GetFieldIndexByName(utf::Mutf8AsCString(fieldName)); - EtsField *field = obj->GetClass()->GetFieldByIndex(fieldIndex); + auto fieldIndex = thisObj->GetClass()->GetFieldIndexByName(utf::Mutf8AsCString(fieldName)); + EtsField *field = thisObj->GetClass()->GetFieldByIndex(fieldIndex); if (field == nullptr) { return false; } - return SetPropertyValue(coro, obj, field, value); + return SetPropertyValue(coro, thisObj, field, value); } auto unboxedValue = GetBoxedNumericValue(PlatformTypes(coro), key); if (unboxedValue.has_value()) { - auto setMethod = FindSetMethod(coro, obj->GetClass()); - if (setMethod == nullptr) { - return false; - } - std::array args {ark::Value(obj->GetCoreType()), ark::Value(unboxedValue.value()), - ark::Value(value->GetCoreType())}; - setMethod->GetPandaMethod()->Invoke(coro, args.data()); - return true; + uint32_t idx = unboxedValue.value(); + + // ASSERTION. LHS is not a JSValue + // then it is must a static object + return StaicObjectSetByIdx(coro, thisObj, idx, value); } ThrowEtsInvalidKey(coro, key->GetClass()->GetDescriptor()); return false; diff --git a/static_core/plugins/ets/runtime/ets_stubs.h b/static_core/plugins/ets/runtime/ets_stubs.h index 8e05713372d82b6f318cae70e4bd67861a40166c..22fb3087fe39912674c25bf4853da7f144f5db0d 100644 --- a/static_core/plugins/ets/runtime/ets_stubs.h +++ b/static_core/plugins/ets/runtime/ets_stubs.h @@ -51,11 +51,11 @@ EtsObject *EtsLdbyname(EtsCoroutine *coro, EtsObject *thisObj, panda_file::File: void EtsStbyname(EtsCoroutine *coro, EtsObject *obj, panda_file::File::StringData propName, EtsObject *value); -EtsObject *EtsLdbyidx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t index); +EtsObject *EtsLdbyidx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx); -bool EtsStbyidx(EtsCoroutine *coro, EtsObject *obj, uint32_t idx, EtsObject *value); +bool EtsStbyidx(EtsCoroutine *coro, EtsObject *thisObj, uint32_t idx, EtsObject *value); -bool EtsStbyval(EtsCoroutine *coro, EtsObject *obj, EtsObject *key, EtsObject *value); +bool EtsStbyval(EtsCoroutine *coro, EtsObject *thisObj, EtsObject *key, EtsObject *value); EtsObject *EtsLdbyval(EtsCoroutine *coro, EtsObject *thisObj, EtsObject *valObj); diff --git a/static_core/plugins/ets/tests/interop_js/tests/interop_isa/index.js b/static_core/plugins/ets/tests/interop_js/tests/interop_isa/index.js index dae24860c9d3ba0fdff22f0c125de15ae790b9e9..0d8242e3372b4fee5aa63f8b22bafdb1b59eb2ee 100644 --- a/static_core/plugins/ets/tests/interop_js/tests/interop_isa/index.js +++ b/static_core/plugins/ets/tests/interop_js/tests/interop_isa/index.js @@ -91,9 +91,13 @@ let doTestStValIdx = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestStValId let doTestLdbyvalFooStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestLdbyvalFooStatic'); let doTestLdbyvalArrayStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestLdbyvalArrayStatic'); let doTestLdByIdxArrayStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestLdByIdxArrayStatic'); +let doTestLdByIdxFixedArrayPrimitiveStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestLdByIdxFixedArrayPrimitiveStatic'); +let doTestLdByIdxFixedArrayReferenceStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestLdByIdxFixedArrayReferenceStatic'); let doTestStByValArrayStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestStByValArrayStatic'); let doTestStByValFooStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestStByValFooStatic'); let doTestStByIdxArrayStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestStByIdxArrayStatic'); +let doTestStByIdxFixedArrayPrimitiveStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestStByIdxFixedArrayPrimitiveStatic'); +let doTestStByIdxFixedArrayReferenceStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestStByIdxFixedArrayReferenceStatic'); let doTestIsTrue = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestIsTrue'); let doTestTypeOf = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestTypeOf'); @@ -104,7 +108,7 @@ let doTestCallStatic = etsVm.getFunction('Ltest-static/ETSGLOBAL;', 'doTestCallS function anyInstanceOfTest() { ASSERT_TRUE(testInstanceOf(new C(), C)); - ASSERT_TRUE(!testInstanceOf({f: 1}, C)); + ASSERT_TRUE(!testInstanceOf({ f: 1 }, C)); } function anyCallRangeTest() { @@ -151,41 +155,41 @@ function anyCallNewShortTest() { } function anyLdByValTest() { - ASSERT_EQ(doTestVal({a: 1}, 'a'), 1); + ASSERT_EQ(doTestVal({ a: 1 }, 'a'), 1); } function anyLdByNameTest() { - ASSERT_EQ(doTestValName({a: 1}), 1); + ASSERT_EQ(doTestValName({ a: 1 }), 1); } function anyLdByNameVTest() { - ASSERT_EQ(doTestValNameV({a: 1}), 1); + ASSERT_EQ(doTestValNameV({ a: 1 }), 1); } function anyLdByIdxTest() { - ASSERT_EQ(doTestValIdx({1: 1}), 1); + ASSERT_EQ(doTestValIdx({ 1: 1 }), 1); } function anyStByValTest() { - let o = {a: 0}; + let o = { a: 0 }; doTestStVal(o, 'a', 1); ASSERT_EQ(o.a, 1); } function anyStByNameTest() { - let o = {a: 0}; + let o = { a: 0 }; doTestStValName(o, 1); ASSERT_EQ(o.a, 1); } function anyStByNameVTest() { - let o = {a: 0}; + let o = { a: 0 }; doTestStValNameV(o, 1); ASSERT_EQ(o.a, 1); } function anyStByIdxTest() { - let o = {1:0}; + let o = { 1: 0 }; doTestStValIdx(o, 1); ASSERT_EQ(o[1], 1); } @@ -208,6 +212,18 @@ function doTestLdByIdxArrayStaticTest() { ASSERT_EQ(o, 0x7c00); } +// Enable once FE create any bytecode for pure static code +function doTestLdByIdxFixedArrayPrimitiveStaticTest() { + let res = doTestLdByIdxFixedArrayPrimitiveStatic(); + ASSERT_EQ(res, 0x7c00); +} + +// Enable once FE create any bytecode for pure static code +function doTestLdByIdxFixedArrayReferenceStaticTest() { + let o = doTestLdByIdxFixedArrayReferenceStatic(); + ASSERT_EQ(o, 0x7c00); +} + // Enable once FE create any bytecode for pure static code function doTestStByValArrayStaticTest() { let o = doTestStByValArrayStatic(); @@ -226,6 +242,18 @@ function doTestStByIdxArrayStaticTest() { ASSERT_EQ(o, 0xcafe); } +// Enable once FE create any bytecode for pure static code +function doTestStByIdxFixedArrayPrimitiveStaticTest() { + let res = doTestStByIdxFixedArrayPrimitiveStatic(); + ASSERT_EQ(res, 0xcafe); +} + +// Enable once FE create any bytecode for pure static code +function doTestStByIdxFixedArrayReferenceStaticTest() { + let o = doTestStByIdxFixedArrayReferenceStatic(); + ASSERT_EQ(o, 0xcafe); +} + function doTestAnyCallStaticTest() { ASSERT_EQ(doTestCallStatic(), 1); } @@ -288,6 +316,10 @@ doTestAnyCallStaticTest(); doTestLdbyvalFooStaticTest(); doTestLdbyvalArrayStaticTest(); doTestLdByIdxArrayStaticTest(); +doTestLdByIdxFixedArrayPrimitiveStaticTest(); +doTestLdByIdxFixedArrayReferenceStaticTest(); doTestStByValArrayStaticTest(); doTestStByValFooStaticTest(); -doTestStByIdxArrayStaticTest(); \ No newline at end of file +doTestStByIdxArrayStaticTest(); +doTestStByIdxFixedArrayPrimitiveStaticTest(); +doTestStByIdxFixedArrayReferenceStaticTest(); \ No newline at end of file diff --git a/static_core/plugins/ets/tests/interop_js/tests/interop_isa/test.pa b/static_core/plugins/ets/tests/interop_js/tests/interop_isa/test.pa index 900ac028347da223a1125dd49ea20c365365e3c0..c4f512ef129793590c19545783dc27c14f1254f2 100644 --- a/static_core/plugins/ets/tests/interop_js/tests/interop_isa/test.pa +++ b/static_core/plugins/ets/tests/interop_js/tests/interop_isa/test.pa @@ -14,6 +14,8 @@ .language eTS +.array array_0 i32 2 { 21930 31744 } + .record escompat.Array .record std.core.Object @@ -252,6 +254,32 @@ jump_label_1: return.obj } +.function std.core.Object test-static.ETSGLOBAL.doTestLdByIdxFixedArrayPrimitiveStatic() { + lda.const v0, array_0 + lda.obj v0 + + fldai.64 0x3ff0000000000000 + any.ldbyidx v0 + return.obj +} + +.function std.core.Object test-static.ETSGLOBAL.doTestLdByIdxFixedArrayReferenceStatic() { + movi v1, 0x2 + newarr v0, v1, std.core.Double[] + fldai.64 0x40d56a8000000000 + call.acc.short std.core.Double.valueOf:(f64), v0, 0x0 + movi v1, 0x0 + starr.obj v0, v1 + fldai.64 0x40df000000000000 + call.acc.short std.core.Double.valueOf:(f64), v0, 0x0 + movi v1, 0x1 + starr.obj v0, v1 + + fldai.64 0x3ff0000000000000 + any.ldbyidx v0 + return.obj +} + .function std.core.Object test-static.ETSGLOBAL.doTestLdByIdxArrayStatic() { movi v1, 0x2 newarr v0, v1, std.core.Double[] @@ -345,6 +373,52 @@ jump_label_1: return.obj } +.function std.core.Object test-static.ETSGLOBAL.doTestStByIdxFixedArrayPrimitiveStatic() { + lda.const v0, array_0 + lda.obj v0 + + # value to set + newobj v2, std.core.Int + ldai 0xcafe + call.acc.short std.core.Int._ctor_:(std.core.Int,i32), v2, 0x1 + lda.obj v2 + + # index + fmovi.64 v1, 0x3ff0000000000000 + + # stbyidx + # v0[v1] = acc + any.stbyidx v0, v1 + + # get the result + fldai.64 0x3ff0000000000000 + any.ldbyidx v0 + return.obj +} + +.function std.core.Object test-static.ETSGLOBAL.doTestStByIdxFixedArrayReferenceStatic() { + movi v1, 0x2 + newarr v0, v1, std.core.Double[] + fldai.64 0x40d56a8000000000 + call.acc.short std.core.Double.valueOf:(f64), v0, 0x0 + movi v1, 0x0 + starr.obj v0, v1 + fldai.64 0x40df000000000000 + call.acc.short std.core.Double.valueOf:(f64), v0, 0x0 + movi v1, 0x1 + starr.obj v0, v1 + + fmovi.64 v1, 0x3ff0000000000000 + newobj v2, std.core.Double + fldai.64 0x40e95fc000000000 + call.acc.short std.core.Double._ctor_:(std.core.Double,f64), v2, 0x1 + lda.obj v2 + any.stbyidx v0, v1 + fldai.64 0x3ff0000000000000 + any.ldbyidx v0 + return.obj +} + .function u1 test-static.ETSGLOBAL.doTestIsTrue(std.core.Object a0) { ets.istrue a0 return