diff --git a/ecmascript/compiler/ntype_hcr_lowering.cpp b/ecmascript/compiler/ntype_hcr_lowering.cpp index 64de450525..3061399875 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.cpp +++ b/ecmascript/compiler/ntype_hcr_lowering.cpp @@ -56,6 +56,10 @@ void NTypeHCRLowering::Lower(GateRef gate) case EcmaOpcode::WIDE_STOWNBYINDEX_PREF_V8_IMM32: LowerTypedStownByIndex(gate); break; + case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8: + case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: + LowerTypedStOwnByName(gate); + break; default: break; } @@ -90,6 +94,42 @@ void NTypeHCRLowering::LowerTypedStownByIndex(GateRef gate) acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate()); } +void NTypeHCRLowering::LowerTypedStOwnByName(GateRef gate) +{ + // 3: number of value inputs + ASSERT(acc_.GetNumValueIn(gate) == 3); + auto constData = acc_.GetValueIn(gate, 0); + uint16_t propIndex = acc_.GetConstantValue(constData); + auto thread = tsManager_->GetEcmaVM()->GetJSThread(); + auto propKey = tsManager_->GetStringFromConstantPool(propIndex); + + GateRef receiver = acc_.GetValueIn(gate, 1); + GateRef value = acc_.GetValueIn(gate, 2); + + GateType receiverType = acc_.GetGateType(receiver); + receiverType = tsManager_->TryNarrowUnionType(receiverType); + + int hclassIndex = -1; + if (tsManager_->IsObjectTypeKind(receiverType)) { + hclassIndex = tsManager_->GetHClassIndexByObjectType(receiverType); + } + if (hclassIndex == -1) { // slowpath + return; + } + JSHClass *hclass = JSHClass::Cast(tsManager_->GetHClassFromCache(hclassIndex).GetTaggedObject()); + + PropertyLookupResult plr = JSHClass::LookupPropertyInAotHClass(thread, hclass, propKey); + if (!plr.IsFound() || !plr.IsLocal() || plr.IsAccessor() || !plr.IsWritable()) { // slowpath + return; + } + AddProfiling(gate); + + GateRef pfrGate = builder_.Int32(plr.GetData()); + builder_.StoreProperty(receiver, pfrGate, value); + + acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate()); +} + void NTypeHCRLowering::AddProfiling(GateRef gate) { if (IsTraceBC()) { diff --git a/ecmascript/compiler/ntype_hcr_lowering.h b/ecmascript/compiler/ntype_hcr_lowering.h index dfc20d1d7f..5e32b96398 100644 --- a/ecmascript/compiler/ntype_hcr_lowering.h +++ b/ecmascript/compiler/ntype_hcr_lowering.h @@ -44,6 +44,7 @@ private: void Lower(GateRef gate); void LowerTypedCreateEmptyArray(GateRef gate); void LowerTypedStownByIndex(GateRef gate); + void LowerTypedStOwnByName(GateRef gate); bool IsLogEnabled() const { diff --git a/ecmascript/compiler/type_inference/pgo_type_infer.cpp b/ecmascript/compiler/type_inference/pgo_type_infer.cpp index b130aae3b4..0b5a603313 100644 --- a/ecmascript/compiler/type_inference/pgo_type_infer.cpp +++ b/ecmascript/compiler/type_inference/pgo_type_infer.cpp @@ -87,6 +87,10 @@ void PGOTypeInfer::RunTypeInfer(GateRef gate) case EcmaOpcode::STTHISBYNAME_IMM16_ID16: InferStObjByName(gate, true); break; + case EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8: + case EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8: + InferStOwnByName(gate); + break; default: break; } @@ -288,6 +292,21 @@ void PGOTypeInfer::InferStObjByName(GateRef gate, bool isThis) UpdateTypeForRWOp(gate, receiver, prop); } +void PGOTypeInfer::InferStOwnByName(GateRef gate) +{ + if (!builder_->ShouldPGOTypeInfer(gate)) { + return; + } + // 3: number of value inputs + ASSERT(acc_.GetNumValueIn(gate) == 3); + GateRef constData = acc_.GetValueIn(gate, 0); + uint16_t propIndex = acc_.GetConstantValue(constData); + JSTaggedValue prop = tsManager_->GetStringFromConstantPool(propIndex); + GateRef receiver = acc_.GetValueIn(gate, 1); + + UpdateTypeForRWOp(gate, receiver, prop); +} + void PGOTypeInfer::UpdateTypeForRWOp(GateRef gate, GateRef receiver, JSTaggedValue prop) { GateType tsType = acc_.GetGateType(receiver); diff --git a/ecmascript/compiler/type_inference/pgo_type_infer.h b/ecmascript/compiler/type_inference/pgo_type_infer.h index 8713ff865a..83e81ad942 100644 --- a/ecmascript/compiler/type_inference/pgo_type_infer.h +++ b/ecmascript/compiler/type_inference/pgo_type_infer.h @@ -67,6 +67,7 @@ private: void RunTypeInfer(GateRef gate); void InferLdObjByName(GateRef gate); void InferStObjByName(GateRef gate, bool isThis); + void InferStOwnByName(GateRef gate); void UpdateTypeForRWOp(GateRef gate, GateRef receiver, JSTaggedValue prop); void CollectGateType(CollectedType &types, GateType tsType, PGORWOpType pgoTypes); diff --git a/test/aottest/stownbyname/expect_output.txt b/test/aottest/stownbyname/expect_output.txt index b30e0ffbc9..991bae6db4 100644 --- a/test/aottest/stownbyname/expect_output.txt +++ b/test/aottest/stownbyname/expect_output.txt @@ -13,3 +13,5 @@ a b +100 +helloworld diff --git a/test/aottest/stownbyname/stownbyname.ts b/test/aottest/stownbyname/stownbyname.ts index 56e64c2570..6bf66c8747 100644 --- a/test/aottest/stownbyname/stownbyname.ts +++ b/test/aottest/stownbyname/stownbyname.ts @@ -18,4 +18,37 @@ var foo = { bar: [ "a", "b" ] }; print(foo.bar[0]); -print(foo.bar[1]); \ No newline at end of file +print(foo.bar[1]); + +interface objInterface { + [key: string]: any +} +let obj:objInterface = {}; +obj.a = 100; +obj.b = "helloworld"; +print(obj.a) +print(obj.b); + +function ArkFunc(depth: number, tag: string): { + array: number[], + string: string +} | { + left: object, + right: object +} { + if (depth == 0) { + return { + array: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + string: 'Ark ' + tag + ' Departure!' + }; + } else { + return { + left: ArkFunc(depth - 1, tag), + right: ArkFunc(depth - 1, tag) + }; + } +} + +var arkDepth: number = 5; +var arkTag: number = 18; +var arkResult = ArkFunc(arkDepth, String(arkTag)); \ No newline at end of file