1 /**
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "compiler/optimizer/optimizations/inlining.h"
17 #include "optimizer/ir/graph.h"
18
19 namespace ark::compiler {
20 /*
21 1. Let actualLength = LoadObject obj (escompat.Array.actualLength)
22 2. BoundsCheck actualLength index (forced de-opt if check fails)
23 3. Let buffer = LoadObject obj (escompat.Array.buffer)
24 4. Let value = LoadArray buffer, index
25 Returns value
26 */
ExpandIntrinsicEscompatArrayGet(CallInst * callInst)27 void Inlining::ExpandIntrinsicEscompatArrayGet(CallInst *callInst)
28 {
29 auto bcAddr = callInst->GetPc();
30 auto *obj = callInst->GetInput(0).GetInst()->CastToNullCheck();
31 auto *index = callInst->GetInput(1).GetInst();
32 auto *saveState = callInst->GetInput(2).GetInst()->CastToSaveState();
33
34 auto *runtime = GetGraph()->GetRuntime();
35 auto *arrayClass = runtime->GetEscompatArrayClass();
36 auto *actualLengthField = runtime->GetEscompatArrayActualLength(arrayClass);
37 auto *bufferField = runtime->GetEscompatArrayBuffer(arrayClass);
38
39 auto *actualLength = GetGraph()->CreateInstLoadObject(
40 DataType::INT32, bcAddr, obj, TypeIdMixin {runtime->GetFieldId(actualLengthField), callInst->GetCallMethod()},
41 actualLengthField, runtime->IsFieldVolatile(actualLengthField));
42 BoundsCheckInst *boundsCheck =
43 GetGraph()->CreateInstBoundsCheck(DataType::INT32, bcAddr, actualLength, index, saveState);
44 boundsCheck->SetFlag(inst_flags::CAN_DEOPTIMIZE);
45
46 auto buffer = GetGraph()->CreateInstLoadObject(
47 DataType::REFERENCE, bcAddr, obj, TypeIdMixin {runtime->GetFieldId(bufferField), callInst->GetCallMethod()},
48 bufferField, runtime->IsFieldVolatile(bufferField));
49 auto *result = GetGraph()->CreateInstLoadArray(DataType::REFERENCE, bcAddr, buffer, boundsCheck);
50
51 callInst->InsertAfter(actualLength);
52 actualLength->InsertAfter(boundsCheck);
53 boundsCheck->InsertAfter(buffer);
54 buffer->InsertAfter(result);
55
56 callInst->ReplaceUsers(result);
57 }
58
59 /*
60 1. Let actualLength = LoadObject obj (escompat.Array.actualLength)
61 2. BoundsCheck actualLength index (forced de-opt if check fails)
62 3. Let buffer = LoadObject obj (escompat.Array.buffer)
63 4. StoreArray buffer, index, value
64 */
ExpandIntrinsicEscompatArraySet(CallInst * callInst)65 void Inlining::ExpandIntrinsicEscompatArraySet(CallInst *callInst)
66 {
67 auto bcAddr = callInst->GetPc();
68 auto *obj = callInst->GetInput(0).GetInst()->CastToNullCheck();
69 auto *index = callInst->GetInput(1).GetInst();
70 auto *value = callInst->GetInput(2).GetInst();
71 auto *saveState = callInst->GetInput(3).GetInst()->CastToSaveState();
72
73 auto *runtime = GetGraph()->GetRuntime();
74 auto *arrayClass = runtime->GetEscompatArrayClass();
75 auto *actualLengthField = runtime->GetEscompatArrayActualLength(arrayClass);
76 auto *bufferField = runtime->GetEscompatArrayBuffer(arrayClass);
77
78 auto *actualLength = GetGraph()->CreateInstLoadObject(
79 DataType::INT32, bcAddr, obj, TypeIdMixin {runtime->GetFieldId(actualLengthField), callInst->GetCallMethod()},
80 actualLengthField, runtime->IsFieldVolatile(actualLengthField));
81 auto *boundsCheck = GetGraph()->CreateInstBoundsCheck(DataType::INT32, bcAddr, actualLength, index, saveState);
82 boundsCheck->SetFlag(inst_flags::CAN_DEOPTIMIZE);
83
84 auto buffer = GetGraph()->CreateInstLoadObject(
85 DataType::REFERENCE, bcAddr, obj, TypeIdMixin {runtime->GetFieldId(bufferField), callInst->GetCallMethod()},
86 bufferField, runtime->IsFieldVolatile(bufferField));
87 // true : needBarrier
88 auto *storeValue = GetGraph()->CreateInstStoreArray(DataType::REFERENCE, bcAddr, buffer, boundsCheck, value, true);
89
90 callInst->InsertAfter(actualLength);
91 actualLength->InsertAfter(boundsCheck);
92 boundsCheck->InsertAfter(buffer);
93 buffer->InsertAfter(storeValue);
94 }
95 } // namespace ark::compiler
96