• 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 offset = GetByteOffset(thisValue);
73                     GateRef size = GetByteLength(thisValue);
74                     GateRef elementSize = GetElementSize(type);
75                     BRANCH(Int32GreaterThan(Int32Add(index, elementSize), size), slowPath, &setValue);
76                     Bind(&setValue);
77                     {
78                         GateRef bufferIndex = Int32Add(index, offset);
79                         BuiltinsTypedArrayStubBuilder builder(this);
80                         GateRef pointer = builder.GetDataPointFromBuffer(buffer);
81                         GateRef doubleValue = TaggedGetNumber(value);
82                         if constexpr (type == DataViewType::INT32 || type == DataViewType::UINT32) {
83                             SetValueInBufferForInt32(glue, pointer, bufferIndex,
84                                                      DoubleToInt(glue, doubleValue), *isLittleEndian);
85                         } else if constexpr (type == DataViewType::FLOAT32) {
86                             GateRef flaotValue = TruncDoubleToFloat32(doubleValue);
87                             SetValueInBufferForInt32(glue, pointer, bufferIndex,
88                                                      CastFloat32ToInt32(flaotValue), *isLittleEndian);
89                         } else if constexpr (type == DataViewType::FLOAT64) {
90                             GateRef int64Value = CastDoubleToInt64(doubleValue);
91                             SetValueInBufferForInt64(glue, pointer, bufferIndex,
92                                                      int64Value, *isLittleEndian);
93                         }
94                         Jump(exit);
95                     }
96                 }
97             }
98         }
99     }
100 }
101 
102 template void BuiltinsDataViewStubBuilder::SetTypedValue<DataViewType::INT32>(GateRef glue, GateRef thisValue,
103     GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
104 template void BuiltinsDataViewStubBuilder::SetTypedValue<DataViewType::FLOAT32>(GateRef glue, GateRef thisValue,
105     GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
106 template void BuiltinsDataViewStubBuilder::SetTypedValue<DataViewType::FLOAT64>(GateRef glue, GateRef thisValue,
107     GateRef numArgs, Variable* res, Label *exit, Label *slowPath);
108 
SetValueInBufferForInt32(GateRef glue,GateRef pointer,GateRef offset,GateRef value,GateRef littleEndianHandle)109 void BuiltinsDataViewStubBuilder::SetValueInBufferForInt32(GateRef glue, GateRef pointer, GateRef offset,
110     GateRef value, GateRef littleEndianHandle)
111 {
112     auto env = GetEnvironment();
113     Label subentry(env);
114     env->SubCfgEntry(&subentry);
115     Label exit(env);
116     Label littleEnd(env);
117     Label notLittleEnd(env);
118     GateRef b0 = Int32And(value, Int32(0xFF));
119     GateRef b1 = Int32And(Int32LSR(value, Int32(builtins::BITS_EIGHT)), Int32(0xFF));
120     GateRef b2 = Int32And(Int32LSR(value, Int32(2 * builtins::BITS_EIGHT)), Int32(0xFF));
121     GateRef b3 = Int32LSR(value, Int32(builtins::BITS_TWENTY_FOUR));
122 
123     BRANCH(TaggedIsTrue(littleEndianHandle), &littleEnd, &notLittleEnd);
124     Bind(&littleEnd);
125     {
126         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b0));
127         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b1));
128         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b2));
129         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b3));
130         Jump(&exit);
131     }
132     Bind(&notLittleEnd);
133     {
134         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b3));
135         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b2));
136         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b1));
137         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b0));
138         Jump(&exit);
139     }
140     Bind(&exit);
141     env->SubCfgExit();
142 }
143 
SetValueInBufferForInt64(GateRef glue,GateRef pointer,GateRef offset,GateRef value,GateRef littleEndianHandle)144 void BuiltinsDataViewStubBuilder::SetValueInBufferForInt64(GateRef glue, GateRef pointer, GateRef offset,
145     GateRef value, GateRef littleEndianHandle)
146 {
147     auto env = GetEnvironment();
148     Label subentry(env);
149     env->SubCfgEntry(&subentry);
150     Label exit(env);
151     Label littleEnd(env);
152     Label notLittleEnd(env);
153     GateRef lowerInt32 = TruncInt64ToInt32(Int64And(value, Int64(0xFFFFFFFF))); // NOLINT
154     GateRef highInt32 = TruncInt64ToInt32(Int64LSR(Int64And(value, Int64(0xFFFFFFFF00000000)), Int64(32))); // NOLINT
155 
156     GateRef b0 = Int32And(lowerInt32, Int32(builtins::BITS_MASK_FF));
157     GateRef b1 = Int32And(Int32LSR(lowerInt32, Int32(builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
158     // 2: 2 * 8 bits
159     GateRef b2 = Int32And(Int32LSR(lowerInt32, Int32(2 * builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
160     GateRef b3 = Int32LSR(lowerInt32, Int32(builtins::BITS_TWENTY_FOUR));
161     GateRef b4 = Int32And(highInt32, Int32(builtins::BITS_MASK_FF));
162     GateRef b5 = Int32And(Int32LSR(highInt32, Int32(builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
163     // 2: 2 * 8 bits
164     GateRef b6 = Int32And(Int32LSR(highInt32, Int32(2 * builtins::BITS_EIGHT)), Int32(builtins::BITS_MASK_FF));
165     GateRef b7 = Int32LSR(highInt32, Int32(builtins::BITS_TWENTY_FOUR));
166 
167     BRANCH(TaggedIsTrue(littleEndianHandle), &littleEnd, &notLittleEnd);
168     Bind(&littleEnd);
169     {
170         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b0));
171         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b1));
172         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b2));
173         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b3));
174         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FOUR)), TruncInt32ToInt8(b4));
175         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FIVE)), TruncInt32ToInt8(b5));
176         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SIX)), TruncInt32ToInt8(b6));
177         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SEVEN)), TruncInt32ToInt8(b7));
178         Jump(&exit);
179     }
180     Bind(&notLittleEnd);
181     {
182         Store(VariableType::INT8(), glue, pointer, offset, TruncInt32ToInt8(b7));
183         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(1)), TruncInt32ToInt8(b6));
184         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::TWO)), TruncInt32ToInt8(b5));
185         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::THREE)), TruncInt32ToInt8(b4));
186         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FOUR)), TruncInt32ToInt8(b3));
187         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::FIVE)), TruncInt32ToInt8(b2));
188         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SIX)), TruncInt32ToInt8(b1));
189         Store(VariableType::INT8(), glue, pointer, Int32Add(offset, Int32(OffsetIndex::SEVEN)), TruncInt32ToInt8(b0));
190         Jump(&exit);
191     }
192     Bind(&exit);
193     env->SubCfgExit();
194 }
195 
GetElementSize(DataViewType type)196 GateRef BuiltinsDataViewStubBuilder::GetElementSize(DataViewType type)
197 {
198     GateRef size;
199     switch (type) {
200         case DataViewType::INT8:
201         case DataViewType::UINT8:
202         case DataViewType::UINT8_CLAMPED:
203             size = Int32(1);
204             break;
205         case DataViewType::INT16:
206         case DataViewType::UINT16:
207             size = Int32(2);  // 2 means the length
208             break;
209         case DataViewType::INT32:
210         case DataViewType::UINT32:
211         case DataViewType::FLOAT32:
212             size = Int32(4);  // 4 means the length
213             break;
214         case DataViewType::FLOAT64:
215         case DataViewType::BIGINT64:
216         case DataViewType::BIGUINT64:
217             size = Int32(8);  // 8 means the length
218             break;
219         default:
220             LOG_ECMA(FATAL) << "this branch is unreachable";
221             UNREACHABLE();
222     }
223     return size;
224 }
225 }  // namespace panda::ecmascript::kungfu
226