• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "ecmascript/compiler/builtins/builtins_dataview_stub_builder.h"
17 
18 #include "ecmascript/builtins/builtins_arraybuffer.h"
19 #include "ecmascript/compiler/builtins/builtins_typedarray_stub_builder.h"
20 #include "ecmascript/compiler/new_object_stub_builder.h"
21 #include "ecmascript/compiler/stub_builder-inl.h"
22 
23 namespace panda::ecmascript::kungfu {
24 template <DataViewType type>
SetTypedValue(GateRef glue,GateRef thisValue,GateRef numArgs,Variable * res,Label * exit,Label * slowPath)25 void BuiltinsDataViewStubBuilder::SetTypedValue(GateRef glue, GateRef thisValue,
26     GateRef numArgs, [[maybe_unused]] Variable* res, Label *exit, Label *slowPath)
27 {
28     auto env = GetEnvironment();
29     Label thisIsHeapObject(env);
30     Label thisIsDataView(env);
31     Label indexIsInt(env);
32     BRANCH(TaggedIsHeapObject(thisValue), &thisIsHeapObject, slowPath);
33     Bind(&thisIsHeapObject);
34     BRANCH(IsDataView(thisValue), &thisIsDataView, slowPath);
35     Bind(&thisIsDataView);
36     GateRef indexTagged = GetCallArg0(numArgs);
37     GateRef value = GetCallArg1(numArgs);
38     BRANCH(TaggedIsInt(indexTagged), &indexIsInt, slowPath);
39     Bind(&indexIsInt);
40     {
41         DEFVARIABLE(isLittleEndian, VariableType::JS_ANY(), TaggedFalse());
42         Label indexIsValid(env);
43         Label valueIsValid(env);
44         Label checkOffset(env);
45         Label getArrayBuffer(env);
46         Label setValue(env);
47         Label toBool(env);
48         GateRef index = GetInt32OfTInt(indexTagged);
49         BRANCH(Int32LessThan(index, Int32(0)), slowPath, &indexIsValid);
50         Bind(&indexIsValid);
51         {
52             BRANCH(TaggedIsNumber(value), &valueIsValid, slowPath);
53             Bind(&valueIsValid);
54             GateRef littleEndianHandle; // need to init
55             if constexpr (type == DataViewType::UINT8 || type == DataViewType::INT8) {
56                 littleEndianHandle = TaggedTrue();
57             } else {
58                 littleEndianHandle = GetCallArg2(numArgs);
59             }
60             BRANCH(TaggedIsUndefined(littleEndianHandle), &getArrayBuffer, &toBool);
61             Bind(&toBool);
62             {
63                 isLittleEndian = FastToBoolean(littleEndianHandle, 1);
64                 Jump(&getArrayBuffer);
65             }
66             Bind(&getArrayBuffer);
67             {
68                 GateRef buffer = GetViewedArrayBuffer(thisValue);
69                 BRANCH(IsDetachedBuffer(buffer), slowPath, &checkOffset);
70                 Bind(&checkOffset);
71                 {
72                     GateRef size = ZExtInt32ToInt64(GetByteLength(thisValue));
73                     GateRef elementSize = ZExtInt32ToInt64(GetElementSize(type));
74                     GateRef indexInt64 = ZExtInt32ToInt64(index);
75                     BRANCH(Int64UnsignedGreaterThan(Int64Add(indexInt64, elementSize), size), slowPath, &setValue);
76                     Bind(&setValue);
77                     {
78                         GateRef offset = ZExtInt32ToInt64(GetByteOffset(thisValue));
79                         GateRef bufferIndex = TruncInt64ToInt32(Int64Add(indexInt64, offset));
80                         BuiltinsTypedArrayStubBuilder builder(this);
81                         GateRef pointer = builder.GetDataPointFromBuffer(buffer);
82                         GateRef doubleValue = TaggedGetNumber(value);
83                         if constexpr (type == DataViewType::INT32 || type == DataViewType::UINT32) {
84                             SetValueInBufferForInt32(glue, pointer, bufferIndex,
85                                                      DoubleToInt(glue, doubleValue), *isLittleEndian);
86                         } else if constexpr (type == DataViewType::FLOAT32) {
87                             GateRef flaotValue = TruncDoubleToFloat32(doubleValue);
88                             SetValueInBufferForInt32(glue, pointer, bufferIndex,
89                                                      CastFloat32ToInt32(flaotValue), *isLittleEndian);
90                         } else if constexpr (type == DataViewType::FLOAT64) {
91                             GateRef int64Value = CastDoubleToInt64(doubleValue);
92                             SetValueInBufferForInt64(glue, pointer, bufferIndex,
93                                                      int64Value, *isLittleEndian);
94                         }
95                         Jump(exit);
96                     }
97                 }
98             }
99         }
100     }
101 }
102 
103 template void BuiltinsDataViewStubBuilder::SetTypedValue<DataViewType::INT32>(GateRef glue, GateRef thisValue,
104     GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
105 template void BuiltinsDataViewStubBuilder::SetTypedValue<DataViewType::FLOAT32>(GateRef glue, GateRef thisValue,
106     GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
107 template void BuiltinsDataViewStubBuilder::SetTypedValue<DataViewType::FLOAT64>(GateRef glue, GateRef thisValue,
108     GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
109 
SetValueInBufferForInt32(GateRef glue,GateRef pointer,GateRef offset,GateRef value,GateRef littleEndianHandle)110 void BuiltinsDataViewStubBuilder::SetValueInBufferForInt32(GateRef glue, GateRef pointer, GateRef offset,
111     GateRef value, GateRef littleEndianHandle)
112 {
113     auto env = GetEnvironment();
114     Label subentry(env);
115     env->SubCfgEntry(&subentry);
116     Label exit(env);
117     Label littleEnd(env);
118     Label notLittleEnd(env);
119     GateRef b0 = Int32And(value, Int32(0xFF));
120     GateRef b1 = Int32And(Int32LSR(value, Int32(builtins::BITS_EIGHT)), Int32(0xFF));
121     GateRef b2 = Int32And(Int32LSR(value, Int32(2 * builtins::BITS_EIGHT)), Int32(0xFF));
122     GateRef b3 = Int32LSR(value, Int32(builtins::BITS_TWENTY_FOUR));
123 
124     BRANCH(TaggedIsTrue(littleEndianHandle), &littleEnd, &notLittleEnd);
125     Bind(&littleEnd);
126     {
127         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b0));
128         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b1));
129         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b2));
130         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b3));
131         Jump(&exit);
132     }
133     Bind(&notLittleEnd);
134     {
135         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b3));
136         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b2));
137         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b1));
138         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b0));
139         Jump(&exit);
140     }
141     Bind(&exit);
142     env->SubCfgExit();
143 }
144 
SetValueInBufferForInt64(GateRef glue,GateRef pointer,GateRef offset,GateRef value,GateRef littleEndianHandle)145 void BuiltinsDataViewStubBuilder::SetValueInBufferForInt64(GateRef glue, GateRef pointer, GateRef offset,
146     GateRef value, GateRef littleEndianHandle)
147 {
148     auto env = GetEnvironment();
149     Label subentry(env);
150     env->SubCfgEntry(&subentry);
151     Label exit(env);
152     Label littleEnd(env);
153     Label notLittleEnd(env);
154     GateRef lowerInt32 = TruncInt64ToInt32(Int64And(value, Int64(0xFFFFFFFF))); // NOLINT
155     GateRef highInt32 = TruncInt64ToInt32(Int64LSR(Int64And(value, Int64(0xFFFFFFFF00000000)), Int64(32))); // NOLINT
156 
157     GateRef b0 = Int32And(lowerInt32, Int32(builtins::BITS_MASK_FF));
158     GateRef b1 = Int32And(Int32LSR(lowerInt32, Int32(builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
159     // 2: 2 * 8 bits
160     GateRef b2 = Int32And(Int32LSR(lowerInt32, Int32(2 * builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
161     GateRef b3 = Int32LSR(lowerInt32, Int32(builtins::BITS_TWENTY_FOUR));
162     GateRef b4 = Int32And(highInt32, Int32(builtins::BITS_MASK_FF));
163     GateRef b5 = Int32And(Int32LSR(highInt32, Int32(builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
164     // 2: 2 * 8 bits
165     GateRef b6 = Int32And(Int32LSR(highInt32, Int32(2 * builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
166     GateRef b7 = Int32LSR(highInt32, Int32(builtins::BITS_TWENTY_FOUR));
167 
168     BRANCH(TaggedIsTrue(littleEndianHandle), &littleEnd, &notLittleEnd);
169     Bind(&littleEnd);
170     {
171         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b0));
172         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b1));
173         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b2));
174         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b3));
175         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FOUR)), TruncInt32ToInt8(b4));
176         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FIVE)), TruncInt32ToInt8(b5));
177         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SIX)), TruncInt32ToInt8(b6));
178         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SEVEN)), TruncInt32ToInt8(b7));
179         Jump(&exit);
180     }
181     Bind(&notLittleEnd);
182     {
183         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b7));
184         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b6));
185         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b5));
186         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b4));
187         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FOUR)), TruncInt32ToInt8(b3));
188         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FIVE)), TruncInt32ToInt8(b2));
189         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SIX)), TruncInt32ToInt8(b1));
190         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SEVEN)), TruncInt32ToInt8(b0));
191         Jump(&exit);
192     }
193     Bind(&exit);
194     env->SubCfgExit();
195 }
196 
GetElementSize(DataViewType type)197 GateRef BuiltinsDataViewStubBuilder::GetElementSize(DataViewType type)
198 {
199     GateRef size;
200     switch (type) {
201         case DataViewType::INT8:
202         case DataViewType::UINT8:
203         case DataViewType::UINT8_CLAMPED:
204             size = Int32(1);
205             break;
206         case DataViewType::INT16:
207         case DataViewType::UINT16:
208             size = Int32(2);  // 2 means the length
209             break;
210         case DataViewType::INT32:
211         case DataViewType::UINT32:
212         case DataViewType::FLOAT32:
213             size = Int32(4);  // 4 means the length
214             break;
215         case DataViewType::FLOAT64:
216         case DataViewType::BIGINT64:
217         case DataViewType::BIGUINT64:
218             size = Int32(8);  // 8 means the length
219             break;
220         default:
221             LOG_ECMA(FATAL) << "this branch is unreachable";
222             UNREACHABLE();
223     }
224     return size;
225 }
226 }  // namespace panda::ecmascript::kungfu
227