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