1 /*
2 * Copyright (c) 2021-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/circuit_builder.h"
17
18 #include "ecmascript/compiler/new_object_stub_builder.h"
19 #include "ecmascript/deoptimizer/deoptimizer.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_array_iterator.h"
22 #include "ecmascript/js_primitive_ref.h"
23 #include "ecmascript/lexical_env.h"
24
25 namespace panda::ecmascript::kungfu {
26
Merge(const std::vector<GateRef> & inList)27 GateRef CircuitBuilder::Merge(const std::vector<GateRef> &inList)
28 {
29 return circuit_->NewGate(circuit_->Merge(inList.size()), inList);
30 }
31
Selector(OpCode opcode,MachineType machineType,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)32 GateRef CircuitBuilder::Selector(OpCode opcode, MachineType machineType, GateRef control,
33 const std::vector<GateRef> &values, int valueCounts, VariableType type)
34 {
35 std::vector<GateRef> inList;
36 inList.push_back(control);
37 if (values.size() == 0) {
38 for (int i = 0; i < valueCounts; i++) {
39 inList.push_back(Circuit::NullGate());
40 }
41 } else {
42 for (int i = 0; i < valueCounts; i++) {
43 inList.push_back(values[i]);
44 }
45 }
46 ASSERT((opcode == OpCode::VALUE_SELECTOR) || (opcode == OpCode::DEPEND_SELECTOR));
47 const GateMetaData* meta = (opcode == OpCode::DEPEND_SELECTOR) ?
48 circuit_->DependSelector(valueCounts) : circuit_->ValueSelector(valueCounts);
49 return circuit_->NewGate(meta, machineType, inList.size(), inList.data(), type.GetGateType());
50 }
51
Selector(OpCode opcode,GateRef control,const std::vector<GateRef> & values,int valueCounts,VariableType type)52 GateRef CircuitBuilder::Selector(OpCode opcode, GateRef control,
53 const std::vector<GateRef> &values, int valueCounts, VariableType type)
54 {
55 MachineType machineType = (opcode == OpCode::DEPEND_SELECTOR) ?
56 MachineType::NOVALUE : MachineType::FLEX;
57 return Selector(opcode, machineType, control, values, valueCounts, type);
58 }
59
Nop()60 GateRef CircuitBuilder::Nop()
61 {
62 return circuit_->NewGate(circuit_->Nop(), {});
63 }
64
UndefineConstant()65 GateRef CircuitBuilder::UndefineConstant()
66 {
67 auto type = GateType::TaggedValue();
68 return circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
69 }
70
Branch(GateRef state,GateRef condition,uint32_t trueWeight,uint32_t falseWeight,const char * comment)71 GateRef CircuitBuilder::Branch(GateRef state, GateRef condition, uint32_t trueWeight, uint32_t falseWeight,
72 const char* comment)
73 {
74 auto value = BranchAccessor::ToValue(trueWeight, falseWeight);
75 return circuit_->NewGate(circuit_->IfBranch(value), { state, condition }, comment);
76 }
77
SwitchBranch(GateRef state,GateRef index,int caseCounts)78 GateRef CircuitBuilder::SwitchBranch(GateRef state, GateRef index, int caseCounts)
79 {
80 return circuit_->NewGate(circuit_->SwitchBranch(caseCounts), { state, index });
81 }
82
Return(GateRef state,GateRef depend,GateRef value)83 GateRef CircuitBuilder::Return(GateRef state, GateRef depend, GateRef value)
84 {
85 auto returnList = circuit_->GetReturnRoot();
86 return circuit_->NewGate(circuit_->Return(), { state, depend, value, returnList });
87 }
88
ReturnVoid(GateRef state,GateRef depend)89 GateRef CircuitBuilder::ReturnVoid(GateRef state, GateRef depend)
90 {
91 auto returnList = circuit_->GetReturnRoot();
92 return circuit_->NewGate(circuit_->ReturnVoid(), { state, depend, returnList });
93 }
94
Goto(GateRef state)95 GateRef CircuitBuilder::Goto(GateRef state)
96 {
97 return circuit_->NewGate(circuit_->OrdinaryBlock(), { state });
98 }
99
LoopBegin(GateRef state)100 GateRef CircuitBuilder::LoopBegin(GateRef state)
101 {
102 auto nullGate = Circuit::NullGate();
103 return circuit_->NewGate(circuit_->LoopBegin(2), { state, nullGate }); // 2: entry&back
104 }
105
LoopEnd(GateRef state)106 GateRef CircuitBuilder::LoopEnd(GateRef state)
107 {
108 return circuit_->NewGate(circuit_->LoopBack(), { state });
109 }
110
LoopExit(GateRef state)111 GateRef CircuitBuilder::LoopExit(GateRef state)
112 {
113 return circuit_->NewGate(circuit_->LoopExit(), { state });
114 }
115
LoopExitDepend(GateRef state,GateRef depend)116 GateRef CircuitBuilder::LoopExitDepend(GateRef state, GateRef depend)
117 {
118 return circuit_->NewGate(circuit_->LoopExitDepend(), { state, depend });
119 }
120
LoopExitValue(GateRef state,GateRef value)121 GateRef CircuitBuilder::LoopExitValue(GateRef state, GateRef value)
122 {
123 auto machineType = acc_.GetMachineType(value);
124 auto gateType = acc_.GetGateType(value);
125 return circuit_->NewGate(circuit_->LoopExitValue(), machineType, { state, value }, gateType);
126 }
127
IfTrue(GateRef ifBranch)128 GateRef CircuitBuilder::IfTrue(GateRef ifBranch)
129 {
130 return circuit_->NewGate(circuit_->IfTrue(), { ifBranch });
131 }
132
IfFalse(GateRef ifBranch)133 GateRef CircuitBuilder::IfFalse(GateRef ifBranch)
134 {
135 return circuit_->NewGate(circuit_->IfFalse(), { ifBranch });
136 }
137
SwitchCase(GateRef switchBranch,int64_t value)138 GateRef CircuitBuilder::SwitchCase(GateRef switchBranch, int64_t value)
139 {
140 return circuit_->NewGate(circuit_->SwitchCase(value), { switchBranch });
141 }
142
DefaultCase(GateRef switchBranch)143 GateRef CircuitBuilder::DefaultCase(GateRef switchBranch)
144 {
145 return circuit_->NewGate(circuit_->DefaultCase(), { switchBranch });
146 }
147
DependRelay(GateRef state,GateRef depend)148 GateRef CircuitBuilder::DependRelay(GateRef state, GateRef depend)
149 {
150 return circuit_->NewGate(circuit_->DependRelay(), { state, depend });
151 }
152
Arguments(size_t index)153 GateRef CircuitBuilder::Arguments(size_t index)
154 {
155 auto argListOfCircuit = circuit_->GetArgRoot();
156 return GetCircuit()->NewArg(MachineType::I64, index, GateType::NJSValue(), argListOfCircuit);
157 }
158
IsJsCOWArray(GateRef obj)159 GateRef CircuitBuilder::IsJsCOWArray(GateRef obj)
160 {
161 // Elements of JSArray are shared and properties are not yet.
162 GateRef elements = GetElementsArray(obj);
163 GateRef objectType = GetObjectType(LoadHClass(elements));
164 return IsCOWArray(objectType);
165 }
166
IsCOWArray(GateRef objectType)167 GateRef CircuitBuilder::IsCOWArray(GateRef objectType)
168 {
169 return BitOr(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_TAGGED_ARRAY))),
170 Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_MUTANT_TAGGED_ARRAY))));
171 }
172
IsTaggedArray(GateRef object)173 GateRef CircuitBuilder::IsTaggedArray(GateRef object)
174 {
175 GateRef objectType = GetObjectType(LoadHClass(object));
176 return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::TAGGED_ARRAY)));
177 }
178
IsMutantTaggedArray(GateRef objectType)179 GateRef CircuitBuilder::IsMutantTaggedArray(GateRef objectType)
180 {
181 return BitOr(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::MUTANT_TAGGED_ARRAY))),
182 Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::COW_MUTANT_TAGGED_ARRAY))));
183 }
184
GetElementsArray(GateRef object)185 GateRef CircuitBuilder::GetElementsArray(GateRef object)
186 {
187 GateRef elementsOffset = IntPtr(JSObject::ELEMENTS_OFFSET);
188 return Load(VariableType::JS_POINTER(), object, elementsOffset);
189 }
190
GetLengthOfTaggedArray(GateRef array)191 GateRef CircuitBuilder::GetLengthOfTaggedArray(GateRef array)
192 {
193 return Load(VariableType::INT32(), array, IntPtr(TaggedArray::LENGTH_OFFSET));
194 }
195
GetLengthOfJSTypedArray(GateRef array)196 GateRef CircuitBuilder::GetLengthOfJSTypedArray(GateRef array)
197 {
198 return Load(VariableType::INT32(), array, IntPtr(JSTypedArray::ARRAY_LENGTH_OFFSET));
199 }
200
GetDataOfTaggedArray(GateRef array)201 GateRef CircuitBuilder::GetDataOfTaggedArray(GateRef array)
202 {
203 return PtrAdd(array, Int64(TaggedArray::DATA_OFFSET));
204 }
205
GetLengthOfJSArray(GateRef array)206 GateRef CircuitBuilder::GetLengthOfJSArray(GateRef array)
207 {
208 return Load(VariableType::INT32(), array, IntPtr(JSArray::LENGTH_OFFSET));
209 }
210
IsTypedArray(GateRef array)211 GateRef CircuitBuilder::IsTypedArray(GateRef array)
212 {
213 GateRef hclass = LoadHClass(array);
214 GateRef type = GetObjectType(hclass);
215 return BitAnd(Int32GreaterThan(type, Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_FIRST))),
216 Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_TYPED_ARRAY_LAST)), type));
217 }
218
IsSharedTypedArray(GateRef array)219 GateRef CircuitBuilder::IsSharedTypedArray(GateRef array)
220 {
221 GateRef hclass = LoadHClass(array);
222 GateRef type = GetObjectType(hclass);
223 return BitAnd(Int32GreaterThan(type, Int32(static_cast<int32_t>(JSType::JS_SHARED_TYPED_ARRAY_FIRST))),
224 Int32GreaterThanOrEqual(Int32(static_cast<int32_t>(JSType::JS_SHARED_TYPED_ARRAY_LAST)), type));
225 }
226
Jump(Label * label)227 void CircuitBuilder::Jump(Label *label)
228 {
229 ASSERT(label);
230 auto currentLabel = env_->GetCurrentLabel();
231 auto currentControl = currentLabel->GetControl();
232 auto jump = Goto(currentControl);
233 currentLabel->SetControl(jump);
234 label->AppendPredecessor(currentLabel);
235 label->MergeControl(currentLabel->GetControl());
236 env_->SetCurrentLabel(nullptr);
237 }
238
Branch(GateRef condition,Label * trueLabel,Label * falseLabel,uint32_t trueWeight,uint32_t falseWeight,const char * comment)239 void CircuitBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel,
240 uint32_t trueWeight, uint32_t falseWeight, const char* comment)
241 {
242 auto currentLabel = env_->GetCurrentLabel();
243 auto currentControl = currentLabel->GetControl();
244 GateRef ifBranch = Branch(currentControl, condition, trueWeight, falseWeight, comment);
245 currentLabel->SetControl(ifBranch);
246 GateRef ifTrue = IfTrue(ifBranch);
247 trueLabel->AppendPredecessor(GetCurrentLabel());
248 trueLabel->MergeControl(ifTrue);
249 GateRef ifFalse = IfFalse(ifBranch);
250 falseLabel->AppendPredecessor(GetCurrentLabel());
251 falseLabel->MergeControl(ifFalse);
252 env_->SetCurrentLabel(nullptr);
253 }
254
255 template <class LabelPtrGetter>
SwitchGeneric(GateRef index,Label * defaultLabel,Span<const int64_t> keysValue,LabelPtrGetter getIthLabelFn)256 void CircuitBuilder::SwitchGeneric(GateRef index, Label *defaultLabel, Span<const int64_t> keysValue,
257 LabelPtrGetter getIthLabelFn)
258 {
259 static_assert(std::is_invocable_r_v<Label*, LabelPtrGetter, size_t>, "Invalid call signature.");
260 size_t numberOfKeys = keysValue.Size();
261 auto currentLabel = env_->GetCurrentLabel();
262 auto currentControl = currentLabel->GetControl();
263 GateRef switchBranch = SwitchBranch(currentControl, index, numberOfKeys);
264 currentLabel->SetControl(switchBranch);
265 for (size_t i = 0; i < numberOfKeys; i++) {
266 GateRef switchCase = SwitchCase(switchBranch, keysValue[i]);
267 Label *curLabel = std::invoke(getIthLabelFn, i);
268 curLabel->AppendPredecessor(currentLabel);
269 curLabel->MergeControl(switchCase);
270 }
271
272 GateRef defaultCase = DefaultCase(switchBranch);
273 defaultLabel->AppendPredecessor(currentLabel);
274 defaultLabel->MergeControl(defaultCase);
275 env_->SetCurrentLabel(nullptr);
276 }
277
Switch(GateRef index,Label * defaultLabel,const int64_t * keysValue,Label * keysLabel,int numberOfKeys)278 void CircuitBuilder::Switch(GateRef index, Label *defaultLabel,
279 const int64_t *keysValue, Label *keysLabel, int numberOfKeys)
280 {
281 return SwitchGeneric(index, defaultLabel, {keysValue, numberOfKeys}, [keysLabel](size_t i) {
282 return &keysLabel[i];
283 });
284 }
285
Switch(GateRef index,Label * defaultLabel,const int64_t * keysValue,Label * const * keysLabel,int numberOfKeys)286 void CircuitBuilder::Switch(GateRef index, Label *defaultLabel,
287 const int64_t *keysValue, Label * const *keysLabel, int numberOfKeys)
288 {
289 return SwitchGeneric(index, defaultLabel, {keysValue, numberOfKeys}, [keysLabel](size_t i) {
290 return keysLabel[i];
291 });
292 }
293
LoopBegin(Label * loopHead)294 void CircuitBuilder::LoopBegin(Label *loopHead)
295 {
296 ASSERT(loopHead);
297 auto loopControl = LoopBegin(loopHead->GetControl());
298 loopHead->SetControl(loopControl);
299 loopHead->SetPreControl(loopControl);
300 loopHead->Bind();
301 env_->SetCurrentLabel(loopHead);
302 }
303
LoopEnd(Label * loopHead)304 void CircuitBuilder::LoopEnd(Label *loopHead)
305 {
306 ASSERT(loopHead);
307 auto currentLabel = GetCurrentLabel();
308 auto currentControl = currentLabel->GetControl();
309 auto loopend = LoopEnd(currentControl);
310 currentLabel->SetControl(loopend);
311 loopHead->AppendPredecessor(currentLabel);
312 loopHead->MergeControl(loopend);
313 loopHead->Seal();
314 loopHead->MergeAllControl();
315 loopHead->MergeAllDepend();
316 env_->SetCurrentLabel(nullptr);
317 }
318
319 // add loop exit info at begin of label (only support not merge label)
LoopExit(const std::vector<Variable * > & vars,size_t diff)320 void CircuitBuilder::LoopExit(const std::vector<Variable *> &vars, size_t diff)
321 {
322 auto currentLabel = env_->GetCurrentLabel();
323 auto loopExit = currentLabel->GetControl();
324 auto loopExitDepend = currentLabel->GetDepend();
325 std::vector<GateRef> loopExitValues;
326 for (size_t i = 0; i < diff; ++i) {
327 loopExit = LoopExit(loopExit);
328 loopExitDepend = LoopExitDepend(loopExit, loopExitDepend);
329 for (const auto &var : vars) {
330 auto loopExitValue = LoopExitValue(loopExit, var->ReadVariable());
331 var->WriteVariable(loopExitValue);
332 }
333 }
334 currentLabel->SetControl(loopExit);
335 currentLabel->SetDepend(loopExitDepend);
336 }
337
ClearConstantCache(GateRef gate)338 void CircuitBuilder::ClearConstantCache(GateRef gate)
339 {
340 ASSERT(acc_.GetOpCode(gate) == OpCode::CONSTANT);
341 auto machineType = acc_.GetMachineType(gate);
342 auto value = acc_.GetConstantValue(gate);
343 auto gateType = acc_.GetGateType(gate);
344 GetCircuit()->ClearConstantCache(machineType, value, gateType);
345 }
346
DeoptCheck(GateRef condition,GateRef frameState,DeoptType type)347 void CircuitBuilder::DeoptCheck(GateRef condition, GateRef frameState, DeoptType type)
348 {
349 std::string comment = Deoptimizier::DisplayItems(type);
350 auto currentLabel = env_->GetCurrentLabel();
351 auto currentControl = currentLabel->GetControl();
352 auto currentDepend = currentLabel->GetDepend();
353 ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
354 GateRef deoptCheck = GetCircuit()->NewGate(circuit_->DeoptCheck(),
355 MachineType::I1, { currentControl, currentDepend, condition,
356 frameState, Int64(static_cast<int64_t>(type))}, GateType::NJSValue(), comment.c_str());
357 // Add a state output to avoid schedule a phi node to deoptCheck's BB by mistake
358 GateRef trueBB = circuit_->NewGate(circuit_->OrdinaryBlock(), { deoptCheck });
359 auto dependRelay = DependRelay(trueBB, currentDepend);
360 currentLabel->SetControl(trueBB);
361 currentLabel->SetDepend(dependRelay);
362 }
363
GetSuperConstructor(GateRef ctor)364 GateRef CircuitBuilder::GetSuperConstructor(GateRef ctor)
365 {
366 auto currentLabel = env_->GetCurrentLabel();
367 auto currentControl = currentLabel->GetControl();
368 auto currentDepend = currentLabel->GetDepend();
369 auto ret = GetCircuit()->NewGate(circuit_->GetSuperConstructor(), MachineType::ANYVALUE,
370 { currentControl, currentDepend, ctor }, GateType::TaggedValue());
371 currentLabel->SetControl(ret);
372 currentLabel->SetDepend(ret);
373 return ret;
374 }
375
Int8(int8_t val)376 GateRef CircuitBuilder::Int8(int8_t val)
377 {
378 return GetCircuit()->GetConstantGate(MachineType::I8, val, GateType::NJSValue());
379 }
380
Int16(int16_t val)381 GateRef CircuitBuilder::Int16(int16_t val)
382 {
383 return GetCircuit()->GetConstantGate(MachineType::I16, val, GateType::NJSValue());
384 }
385
Int32(int32_t val)386 GateRef CircuitBuilder::Int32(int32_t val)
387 {
388 return GetCircuit()->GetConstantGate(MachineType::I32, static_cast<BitField>(val), GateType::NJSValue());
389 }
390
Int64(int64_t val)391 GateRef CircuitBuilder::Int64(int64_t val)
392 {
393 return GetCircuit()->GetConstantGate(MachineType::I64, val, GateType::NJSValue());
394 }
395
IntPtr(int64_t val)396 GateRef CircuitBuilder::IntPtr(int64_t val)
397 {
398 return GetCircuit()->GetConstantGate(MachineType::ARCH, val, GateType::NJSValue());
399 }
400
StringPtr(std::string_view str)401 GateRef CircuitBuilder::StringPtr(std::string_view str)
402 {
403 return GetCircuit()->GetConstantStringGate(MachineType::ARCH, str, GateType::NJSValue());
404 }
405
RelocatableData(uint64_t val)406 GateRef CircuitBuilder::RelocatableData(uint64_t val)
407 {
408 return GetCircuit()->NewGate(circuit_->RelocatableData(val),
409 MachineType::ARCH, GateType::TaggedValue());
410 }
411
Boolean(bool val)412 GateRef CircuitBuilder::Boolean(bool val)
413 {
414 return GetCircuit()->GetConstantGate(MachineType::I1, val ? 1 : 0, GateType::NJSValue());
415 }
416
Double(double val)417 GateRef CircuitBuilder::Double(double val)
418 {
419 return GetCircuit()->GetConstantGate(MachineType::F64, base::bit_cast<int64_t>(val), GateType::NJSValue());
420 }
421
HoleConstant()422 GateRef CircuitBuilder::HoleConstant()
423 {
424 auto type = GateType::TaggedValue();
425 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_HOLE, type);
426 }
427
SpecialHoleConstant()428 GateRef CircuitBuilder::SpecialHoleConstant()
429 {
430 auto type = GateType::NJSValue();
431 return GetCircuit()->GetConstantGate(MachineType::I64, base::SPECIAL_HOLE, type);
432 }
433
NullPtrConstant()434 GateRef CircuitBuilder::NullPtrConstant()
435 {
436 auto type = GateType::TaggedValue();
437 return GetCircuit()->GetConstantGate(MachineType::I64, 0u, type);
438 }
439
NullConstant()440 GateRef CircuitBuilder::NullConstant()
441 {
442 auto type = GateType::TaggedValue();
443 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_NULL, type);
444 }
445
TaggedValueConstant(JSTaggedValue taggedValue)446 GateRef CircuitBuilder::TaggedValueConstant(JSTaggedValue taggedValue)
447 {
448 auto type = GateType::TaggedValue();
449 return GetCircuit()->GetConstantGate(MachineType::I64, taggedValue.GetRawData(), type);
450 }
451
ExceptionConstant()452 GateRef CircuitBuilder::ExceptionConstant()
453 {
454 auto type = GateType::TaggedValue();
455 return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_EXCEPTION, type);
456 }
457
NanValue()458 GateRef CircuitBuilder::NanValue()
459 {
460 return Double(std::numeric_limits<double>::quiet_NaN());
461 }
462
LoadObjectFromConstPool(GateRef constPool,GateRef index)463 GateRef CircuitBuilder::LoadObjectFromConstPool(GateRef constPool, GateRef index)
464 {
465 return GetValueFromTaggedArray(constPool, TruncInt64ToInt32(index));
466 }
467
IsAccessorInternal(GateRef accessor)468 GateRef CircuitBuilder::IsAccessorInternal(GateRef accessor)
469 {
470 return Int32Equal(GetObjectType(LoadHClass(accessor)),
471 Int32(static_cast<int32_t>(JSType::INTERNAL_ACCESSOR)));
472 }
473
AppendFrameArgs(std::vector<GateRef> & args,GateRef hirGate)474 void CircuitBuilder::AppendFrameArgs(std::vector<GateRef> &args, GateRef hirGate)
475 {
476 GateRef frameArgs = acc_.GetFrameArgs(hirGate);
477 if (frameArgs == Circuit::NullGate()) {
478 args.emplace_back(IntPtr(0));
479 } else {
480 args.emplace_back(frameArgs);
481 }
482 }
483
GetGlobalEnv()484 GateRef CircuitBuilder::GetGlobalEnv()
485 {
486 auto currentLabel = env_->GetCurrentLabel();
487 auto currentDepend = currentLabel->GetDepend();
488 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnv(), MachineType::I64,
489 { currentDepend },
490 GateType::AnyType());
491 currentLabel->SetDepend(newGate);
492 return newGate;
493 }
494
GetGlobalEnvObj(GateRef env,size_t index)495 GateRef CircuitBuilder::GetGlobalEnvObj(GateRef env, size_t index)
496 {
497 auto currentLabel = env_->GetCurrentLabel();
498 auto currentDepend = currentLabel->GetDepend();
499 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnvObj(index), MachineType::I64,
500 { currentDepend, env },
501 GateType::AnyType());
502 currentLabel->SetDepend(newGate);
503 return newGate;
504 }
505
GetGlobalEnvObjHClass(GateRef env,size_t index)506 GateRef CircuitBuilder::GetGlobalEnvObjHClass(GateRef env, size_t index)
507 {
508 auto currentLabel = env_->GetCurrentLabel();
509 auto currentDepend = currentLabel->GetDepend();
510 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalEnvObjHClass(index), MachineType::I64,
511 { currentDepend, env },
512 GateType::AnyType());
513 currentLabel->SetDepend(newGate);
514 return newGate;
515 }
516
GetGlobalConstantValue(ConstantIndex index)517 GateRef CircuitBuilder::GetGlobalConstantValue(ConstantIndex index)
518 {
519 auto currentLabel = env_->GetCurrentLabel();
520 auto currentDepend = currentLabel->GetDepend();
521 auto newGate = GetCircuit()->NewGate(circuit_->GetGlobalConstantValue(static_cast<size_t>(index)),
522 MachineType::I64, { currentDepend }, GateType::AnyType());
523 currentLabel->SetDepend(newGate);
524 return newGate;
525 }
526
HasPendingException(GateRef glue)527 GateRef CircuitBuilder::HasPendingException(GateRef glue)
528 {
529 GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env_->IsArch32Bit()));
530 GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
531 return TaggedIsNotHole(exception);
532 }
533
IsUtf8String(GateRef string)534 GateRef CircuitBuilder::IsUtf8String(GateRef string)
535 {
536 // compressedStringsEnabled fixed to true constant
537 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
538 return Int32Equal(
539 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
540 Int32(EcmaString::STRING_COMPRESSED));
541 }
542
IsUtf16String(GateRef string)543 GateRef CircuitBuilder::IsUtf16String(GateRef string)
544 {
545 // compressedStringsEnabled fixed to true constant
546 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
547 return Int32Equal(
548 Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
549 Int32(EcmaString::STRING_UNCOMPRESSED));
550 }
551
IsInternString(GateRef string)552 GateRef CircuitBuilder::IsInternString(GateRef string)
553 {
554 GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
555 return Int32NotEqual(Int32And(len, Int32(EcmaString::STRING_INTERN_BIT)), Int32(0));
556 }
557
GetGlobalObject(GateRef glue)558 GateRef CircuitBuilder::GetGlobalObject(GateRef glue)
559 {
560 GateRef offset = IntPtr(JSThread::GlueData::GetGlobalObjOffset(cmpCfg_->Is32Bit()));
561 return Load(VariableType::JS_ANY(), glue, offset);
562 }
563
GetMethodFromFunction(GateRef function)564 GateRef CircuitBuilder::GetMethodFromFunction(GateRef function)
565 {
566 GateRef offset = IntPtr(JSFunctionBase::METHOD_OFFSET);
567 return Load(VariableType::JS_POINTER(), function, offset);
568 }
569
GetModuleFromFunction(GateRef function)570 GateRef CircuitBuilder::GetModuleFromFunction(GateRef function)
571 {
572 GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
573 return Load(VariableType::JS_POINTER(), function, offset);
574 }
575
GetSendableEnvFromModule(GateRef module)576 GateRef CircuitBuilder::GetSendableEnvFromModule(GateRef module)
577 {
578 return Load(VariableType::JS_POINTER(), module, IntPtr(SourceTextModule::SENDABLE_ENV_OFFSET));
579 }
580
SetSendableEnvToModule(GateRef glue,GateRef module,GateRef value)581 void CircuitBuilder::SetSendableEnvToModule(GateRef glue, GateRef module, GateRef value)
582 {
583 GateRef offset = IntPtr(SourceTextModule::SENDABLE_ENV_OFFSET);
584 Store(VariableType::JS_POINTER(), glue, module, offset, value);
585 }
586
GetHomeObjectFromFunction(GateRef function)587 GateRef CircuitBuilder::GetHomeObjectFromFunction(GateRef function)
588 {
589 GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
590 return Load(VariableType::JS_POINTER(), function, offset);
591 }
592
GetConstPoolFromFunction(GateRef jsFunc)593 GateRef CircuitBuilder::GetConstPoolFromFunction(GateRef jsFunc)
594 {
595 GateRef method = GetMethodFromFunction(jsFunc);
596 return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
597 }
598
GetUnsharedConstpoolFromGlue(GateRef glue,GateRef constpool)599 GateRef CircuitBuilder::GetUnsharedConstpoolFromGlue(GateRef glue, GateRef constpool)
600 {
601 Label entryPass(env_);
602 SubCfgEntry(&entryPass);
603 DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
604 Label canGetUnsharedCp(env_);
605 Label exit(env_);
606 GateRef unshareIdx = GetUnsharedConstpoolIndex(constpool);
607 GateRef unsharedCpArrayLen = GetUnsharedConstpoolArrayLen(glue);
608 GateRef indexLessThanUnsharedCpArrayLen = Int32LessThan(TaggedGetInt(unshareIdx), unsharedCpArrayLen);
609 BRANCH(indexLessThanUnsharedCpArrayLen, &canGetUnsharedCp, &exit);
610 Bind(&canGetUnsharedCp);
611 {
612 GateRef unshareCpOffset =
613 static_cast<int32_t>(JSThread::GlueData::GetUnSharedConstpoolsOffset(env_->Is32Bit()));
614 GateRef unshareCpAddr = Load(VariableType::NATIVE_POINTER(), glue, IntPtr(unshareCpOffset));
615 result = GetUnsharedConstpool(unshareCpAddr, unshareIdx);
616 Jump(&exit);
617 }
618 Bind(&exit);
619 auto ret = *result;
620 SubCfgExit();
621 return ret;
622 }
623
GetUnsharedConstpoolArrayLen(GateRef glue)624 GateRef CircuitBuilder::GetUnsharedConstpoolArrayLen(GateRef glue)
625 {
626 GateRef unshareCpArrayLenOffset = static_cast<int32_t>(
627 JSThread::GlueData::GetUnSharedConstpoolsArrayLenOffset(env_->Is32Bit()));
628 return Load(VariableType::INT32(), glue, IntPtr(unshareCpArrayLenOffset));
629 }
630
GetUnsharedConstpoolIndex(GateRef constpool)631 GateRef CircuitBuilder::GetUnsharedConstpoolIndex(GateRef constpool)
632 {
633 GateRef constPoolSize = GetLengthOfTaggedArray(constpool);
634 GateRef unshareIdx = Int32Sub(constPoolSize, Int32(ConstantPool::UNSHARED_CONSTPOOL_INDEX));
635 return GetValueFromTaggedArray(constpool, unshareIdx);
636 }
637
GetUnsharedConstpool(GateRef arrayAddr,GateRef index)638 GateRef CircuitBuilder::GetUnsharedConstpool(GateRef arrayAddr, GateRef index)
639 {
640 GateRef dataOffset = PtrAdd(arrayAddr,
641 PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()), ZExtInt32ToPtr(TaggedGetInt(index))));
642 return Load(VariableType::JS_ANY(), dataOffset, IntPtr(0));
643 }
644
GetEmptyArray(GateRef glue)645 GateRef CircuitBuilder::GetEmptyArray(GateRef glue)
646 {
647 GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
648 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
649 GateRef offset = GetGlobalConstantOffset(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
650 return Load(VariableType::JS_ANY(), gConstAddr, offset);
651 }
652
GetPrototypeFromHClass(GateRef hClass)653 GateRef CircuitBuilder::GetPrototypeFromHClass(GateRef hClass)
654 {
655 GateRef protoOffset = IntPtr(JSHClass::PROTOTYPE_OFFSET);
656 return Load(VariableType::JS_ANY(), hClass, protoOffset);
657 }
658
GetEnumCacheFromHClass(GateRef hClass)659 GateRef CircuitBuilder::GetEnumCacheFromHClass(GateRef hClass)
660 {
661 GateRef offset = IntPtr(JSHClass::ENUM_CACHE_OFFSET);
662 return Load(VariableType::JS_ANY(), hClass, offset);
663 }
664
GetProtoChangeMarkerFromHClass(GateRef hClass)665 GateRef CircuitBuilder::GetProtoChangeMarkerFromHClass(GateRef hClass)
666 {
667 GateRef offset = IntPtr(JSHClass::PROTO_CHANGE_MARKER_OFFSET);
668 return Load(VariableType::JS_ANY(), hClass, offset);
669 }
670
GetLengthFromForInIterator(GateRef iter)671 GateRef CircuitBuilder::GetLengthFromForInIterator(GateRef iter)
672 {
673 GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
674 return Load(VariableType::INT32(), iter, offset);
675 }
676
GetIndexFromForInIterator(GateRef iter)677 GateRef CircuitBuilder::GetIndexFromForInIterator(GateRef iter)
678 {
679 GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
680 return Load(VariableType::INT32(), iter, offset);
681 }
682
GetKeysFromForInIterator(GateRef iter)683 GateRef CircuitBuilder::GetKeysFromForInIterator(GateRef iter)
684 {
685 GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
686 return Load(VariableType::JS_ANY(), iter, offset);
687 }
688
GetObjectFromForInIterator(GateRef iter)689 GateRef CircuitBuilder::GetObjectFromForInIterator(GateRef iter)
690 {
691 GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
692 return Load(VariableType::JS_ANY(), iter, offset);
693 }
694
GetCachedHclassFromForInIterator(GateRef iter)695 GateRef CircuitBuilder::GetCachedHclassFromForInIterator(GateRef iter)
696 {
697 GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
698 return Load(VariableType::JS_ANY(), iter, offset);
699 }
700
GetArrayIterationKind(GateRef iter)701 GateRef CircuitBuilder::GetArrayIterationKind(GateRef iter)
702 {
703 static_assert(JSArrayIterator::SIZE - JSArrayIterator::BIT_FIELD_OFFSET <= sizeof(uint32_t));
704 GateRef bitfield = Load(VariableType::INT32(), iter, IntPtr(JSArrayIterator::BIT_FIELD_OFFSET));
705 GateRef mask = Int32((1LLU << JSArrayIterator::ITERATION_KIND_BITS) - 1);
706 return Int32And(bitfield, mask);
707 }
708
SetLengthOfForInIterator(GateRef glue,GateRef iter,GateRef length)709 void CircuitBuilder::SetLengthOfForInIterator(GateRef glue, GateRef iter, GateRef length)
710 {
711 GateRef offset = IntPtr(JSForInIterator::LENGTH_OFFSET);
712 Store(VariableType::INT32(), glue, iter, offset, length);
713 }
714
SetIndexOfForInIterator(GateRef glue,GateRef iter,GateRef index)715 void CircuitBuilder::SetIndexOfForInIterator(GateRef glue, GateRef iter, GateRef index)
716 {
717 GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
718 Store(VariableType::INT32(), glue, iter, offset, index);
719 }
720
SetKeysOfForInIterator(GateRef glue,GateRef iter,GateRef keys)721 void CircuitBuilder::SetKeysOfForInIterator(GateRef glue, GateRef iter, GateRef keys)
722 {
723 GateRef offset = IntPtr(JSForInIterator::KEYS_OFFSET);
724 Store(VariableType::JS_ANY(), glue, iter, offset, keys);
725 }
726
SetObjectOfForInIterator(GateRef glue,GateRef iter,GateRef object)727 void CircuitBuilder::SetObjectOfForInIterator(GateRef glue, GateRef iter, GateRef object)
728 {
729 GateRef offset = IntPtr(JSForInIterator::OBJECT_OFFSET);
730 Store(VariableType::JS_ANY(), glue, iter, offset, object);
731 }
732
SetCachedHclassOfForInIterator(GateRef glue,GateRef iter,GateRef hclass)733 void CircuitBuilder::SetCachedHclassOfForInIterator(GateRef glue, GateRef iter, GateRef hclass)
734 {
735 GateRef offset = IntPtr(JSForInIterator::CACHED_HCLASS_OFFSET);
736 Store(VariableType::JS_ANY(), glue, iter, offset, hclass);
737 }
738
SetNextIndexOfArrayIterator(GateRef glue,GateRef iter,GateRef nextIndex)739 void CircuitBuilder::SetNextIndexOfArrayIterator(GateRef glue, GateRef iter, GateRef nextIndex)
740 {
741 GateRef offset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET);
742 Store(VariableType::INT32(), glue, iter, offset, nextIndex);
743 }
744
SetIteratedArrayOfArrayIterator(GateRef glue,GateRef iter,GateRef iteratedArray)745 void CircuitBuilder::SetIteratedArrayOfArrayIterator(GateRef glue, GateRef iter, GateRef iteratedArray)
746 {
747 GateRef offset = IntPtr(JSArrayIterator::ITERATED_ARRAY_OFFSET);
748 Store(VariableType::JS_ANY(), glue, iter, offset, iteratedArray);
749 }
750
SetBitFieldOfArrayIterator(GateRef glue,GateRef iter,GateRef kind)751 void CircuitBuilder::SetBitFieldOfArrayIterator(GateRef glue, GateRef iter, GateRef kind)
752 {
753 GateRef offset = IntPtr(JSArrayIterator::BIT_FIELD_OFFSET);
754 Store(VariableType::INT32(), glue, iter, offset, kind);
755 }
756
IncreaseArrayIteratorIndex(GateRef glue,GateRef iter,GateRef index)757 void CircuitBuilder::IncreaseArrayIteratorIndex(GateRef glue, GateRef iter, GateRef index)
758 {
759 static_assert(JSArrayIterator::BIT_FIELD_OFFSET - JSArrayIterator::NEXT_INDEX_OFFSET <= sizeof(uint32_t));
760 GateRef newIndex = Int32Add(index, Int32(1));
761 GateRef offset = IntPtr(JSArrayIterator::NEXT_INDEX_OFFSET);
762 Store(VariableType::INT32(), glue, iter, offset, newIndex);
763 }
764
IncreaseIteratorIndex(GateRef glue,GateRef iter,GateRef index)765 void CircuitBuilder::IncreaseIteratorIndex(GateRef glue, GateRef iter, GateRef index)
766 {
767 GateRef newIndex = Int32Add(index, Int32(1));
768 GateRef offset = IntPtr(JSForInIterator::INDEX_OFFSET);
769 Store(VariableType::INT32(), glue, iter, offset, newIndex);
770 }
771
GetHasChanged(GateRef object)772 GateRef CircuitBuilder::GetHasChanged(GateRef object)
773 {
774 GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
775 GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
776 GateRef mask = Int32(1LLU << (ProtoChangeMarker::HAS_CHANGED_BITS - 1));
777 return Int32NotEqual(Int32And(bitfield, mask), Int32(0));
778 }
779
GetNotFoundHasChanged(GateRef object)780 GateRef CircuitBuilder::GetNotFoundHasChanged(GateRef object)
781 {
782 GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
783 GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
784 return Int32NotEqual(
785 Int32And(Int32LSR(bitfield, Int32(ProtoChangeMarker::NotFoundHasChangedBits::START_BIT)),
786 Int32((1LLU << ProtoChangeMarker::NotFoundHasChangedBits::SIZE) - 1)),
787 Int32(0));
788 }
789
GetAccessorHasChanged(GateRef object)790 GateRef CircuitBuilder::GetAccessorHasChanged(GateRef object)
791 {
792 GateRef bitfieldOffset = IntPtr(ProtoChangeMarker::BIT_FIELD_OFFSET);
793 GateRef bitfield = Load(VariableType::INT32(), object, bitfieldOffset);
794 return Int32NotEqual(
795 Int32And(Int32LSR(bitfield, Int32(ProtoChangeMarker::AccessorHasChangedBits::START_BIT)),
796 Int32((1LLU << ProtoChangeMarker::AccessorHasChangedBits::SIZE) - 1)),
797 Int32(0));
798 }
799
HasDeleteProperty(GateRef hClass)800 GateRef CircuitBuilder::HasDeleteProperty(GateRef hClass)
801 {
802 GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD1_OFFSET));
803 return Int32NotEqual(
804 Int32And(Int32LSR(bitfield, Int32(JSHClass::HasDeletePropertyBit::START_BIT)),
805 Int32((1LLU << JSHClass::HasDeletePropertyBit::SIZE) - 1)),
806 Int32(0));
807 }
808
IsOnHeap(GateRef hClass)809 GateRef CircuitBuilder::IsOnHeap(GateRef hClass)
810 {
811 GateRef bitfield = Load(VariableType::INT32(), hClass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
812 return Int32NotEqual(
813 Int32And(Int32LSR(bitfield, Int32(JSHClass::IsOnHeap::START_BIT)),
814 Int32((1LU << JSHClass::IsOnHeap::SIZE) - 1)),
815 Int32(0));
816 }
817
IsEcmaObject(GateRef obj)818 GateRef CircuitBuilder::IsEcmaObject(GateRef obj)
819 {
820 return LogicAndBuilder(env_).And(TaggedIsHeapObject(obj)).And(TaggedObjectIsEcmaObject(obj)).Done();
821 }
822
CheckJSType(GateRef object,JSType jsType)823 GateRef CircuitBuilder::CheckJSType(GateRef object, JSType jsType)
824 {
825 Label entryPass(env_);
826 SubCfgEntry(&entryPass);
827 DEFVALUE(result, env_, VariableType::BOOL(), False());
828 Label heapObj(env_);
829 Label exit(env_);
830 GateRef isHeapObject = TaggedIsHeapObject(object);
831 BRANCH(isHeapObject, &heapObj, &exit);
832 Bind(&heapObj);
833 {
834 GateRef objectType = GetObjectType(LoadHClass(object));
835 result = Int32Equal(objectType, Int32(static_cast<int32_t>(jsType)));
836 Jump(&exit);
837 }
838 Bind(&exit);
839 auto ret = *result;
840 SubCfgExit();
841 return ret;
842 }
843
GetObjectByIndexFromConstPool(GateRef glue,GateRef hirGate,GateRef frameState,GateRef index,ConstPoolType type)844 GateRef CircuitBuilder::GetObjectByIndexFromConstPool(GateRef glue, GateRef hirGate, GateRef frameState, GateRef index,
845 ConstPoolType type)
846 {
847 ArgumentAccessor argAcc(circuit_);
848 GateRef jsFunc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::FUNC);
849 GateRef module = GetModuleFromFunction(jsFunc);
850 GateRef sharedConstpool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::SHARED_CONST_POOL);
851 GateRef unsharedConstPool = unsharedConstPool = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::UNSHARED_CONST_POOL);
852 GateRef obj = GetObjectFromConstPool(glue, hirGate, sharedConstpool, unsharedConstPool, module, index, type);
853 return obj;
854 }
855
GetObjectFromConstPool(GateRef glue,GateRef hirGate,GateRef sharedConstPool,GateRef unsharedConstPool,GateRef module,GateRef index,ConstPoolType type)856 GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef sharedConstPool,
857 GateRef unsharedConstPool, GateRef module, GateRef index,
858 ConstPoolType type)
859 {
860 Label entry(env_);
861 SubCfgEntry(&entry);
862 Label exit(env_);
863 Label cacheMiss(env_);
864 Label cache(env_);
865 Label unshareCpHit(env_);
866 Label unshareCpMiss(env_);
867
868 // HirGate Can not be a nullGate in Aot
869 if (GetCircuit()->IsOptimizedOrFastJit() && hirGate == Circuit::NullGate()) {
870 hirGate = index;
871 }
872 // Call runtime to create unshared constpool when current context's cache is hole in multi-thread.
873 DEFVALUE(cacheValue, env_, VariableType::JS_ANY(), Hole());
874 if (type == ConstPoolType::ARRAY_LITERAL || type == ConstPoolType::OBJECT_LITERAL) {
875 BRANCH(TaggedIsNotHole(unsharedConstPool), &unshareCpHit, &unshareCpMiss);
876 Bind(&unshareCpHit);
877 {
878 cacheValue = GetValueFromTaggedArray(unsharedConstPool, index);
879 Jump(&unshareCpMiss);
880 }
881 } else {
882 cacheValue = GetValueFromTaggedArray(sharedConstPool, index);
883 Jump(&unshareCpMiss);
884 }
885 Bind(&unshareCpMiss);
886 DEFVALUE(result, env_, VariableType::JS_ANY(), *cacheValue);
887 BRANCH(BitOr(TaggedIsHole(*result), TaggedIsNullPtr(*result)), &cacheMiss, &cache);
888 Bind(&cacheMiss);
889 {
890 if (type == ConstPoolType::STRING) {
891 result = CallRuntime(glue, RTSTUB_ID(GetStringFromCache), Gate::InvalidGateRef,
892 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
893 } else if (type == ConstPoolType::ARRAY_LITERAL) {
894 result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
895 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
896 } else if (type == ConstPoolType::OBJECT_LITERAL) {
897 result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
898 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
899 } else {
900 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
901 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
902 }
903 Jump(&exit);
904 }
905 Bind(&cache);
906 {
907 if (type == ConstPoolType::METHOD) {
908 Label isHeapObj(env_);
909 Label checkInteger(env_);
910 BRANCH(TaggedIsHeapObject(*result), &isHeapObj, &checkInteger);
911 Bind(&isHeapObj);
912 {
913 Label isAOTLiteralInfo(env_);
914 BRANCH(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
915 Bind(&isAOTLiteralInfo);
916 {
917 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
918 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
919 Jump(&exit);
920 }
921 }
922 Bind(&checkInteger);
923 {
924 Label isInteger(env_);
925 BRANCH(TaggedIsInt(*result), &isInteger, &exit);
926 Bind(&isInteger);
927 {
928 result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
929 { sharedConstPool, Int32ToTaggedInt(index) }, hirGate);
930 Jump(&exit);
931 }
932 }
933 } else if (type == ConstPoolType::ARRAY_LITERAL) {
934 Label isHeapObj(env_);
935 BRANCH(TaggedIsHeapObject(*result), &isHeapObj, &exit);
936 Bind(&isHeapObj);
937 {
938 Label isAOTLiteralInfo(env_);
939 BRANCH(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
940 Bind(&isAOTLiteralInfo);
941 {
942 result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
943 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
944 Jump(&exit);
945 }
946 }
947 } else if (type == ConstPoolType::OBJECT_LITERAL) {
948 Label isHeapObj(env_);
949 BRANCH(TaggedIsHeapObject(*result), &isHeapObj, &exit);
950 Bind(&isHeapObj);
951 {
952 Label isAOTLiteralInfo(env_);
953 BRANCH(IsAOTLiteralInfo(*result), &isAOTLiteralInfo, &exit);
954 Bind(&isAOTLiteralInfo);
955 {
956 result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
957 { sharedConstPool, Int32ToTaggedInt(index), module }, hirGate);
958 Jump(&exit);
959 }
960 }
961 } else {
962 Jump(&exit);
963 }
964 }
965 Bind(&exit);
966 auto ret = *result;
967 SubCfgExit();
968 return ret;
969 }
970
GetFunctionLexicalEnv(GateRef function)971 GateRef CircuitBuilder::GetFunctionLexicalEnv(GateRef function)
972 {
973 return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
974 }
975
SetLengthToFunction(GateRef glue,GateRef function,GateRef value)976 void CircuitBuilder::SetLengthToFunction(GateRef glue, GateRef function, GateRef value)
977 {
978 GateRef offset = IntPtr(JSFunction::LENGTH_OFFSET);
979 Store(VariableType::INT32(), glue, function, offset, value);
980 }
981
SetLexicalEnvToFunction(GateRef glue,GateRef function,GateRef value)982 void CircuitBuilder::SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value)
983 {
984 GateRef offset = IntPtr(JSFunction::LEXICAL_ENV_OFFSET);
985 Store(VariableType::JS_ANY(), glue, function, offset, value);
986 }
987
SetHomeObjectToFunction(GateRef glue,GateRef function,GateRef value)988 void CircuitBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value)
989 {
990 GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
991 Store(VariableType::JS_ANY(), glue, function, offset, value);
992 }
993
SetModuleToFunction(GateRef glue,GateRef function,GateRef value)994 void CircuitBuilder::SetModuleToFunction(GateRef glue, GateRef function, GateRef value)
995 {
996 GateRef offset = IntPtr(JSFunction::ECMA_MODULE_OFFSET);
997 Store(VariableType::JS_POINTER(), glue, function, offset, value);
998 }
999
GetGlobalEnvValue(VariableType type,GateRef env,size_t index)1000 GateRef CircuitBuilder::GetGlobalEnvValue(VariableType type, GateRef env, size_t index)
1001 {
1002 auto valueIndex = IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
1003 return Load(type, env, valueIndex);
1004 }
1005
GetCodeAddr(GateRef jsFunc)1006 GateRef CircuitBuilder::GetCodeAddr(GateRef jsFunc)
1007 {
1008 auto codeAddOffset = IntPtr(JSFunction::CODE_ENTRY_OFFSET);
1009 return Load(VariableType::NATIVE_POINTER(), jsFunc, codeAddOffset);
1010 }
1011
GetBaselineCodeAddr(GateRef baselineCode)1012 GateRef CircuitBuilder::GetBaselineCodeAddr(GateRef baselineCode)
1013 {
1014 auto codeAddrOffset = IntPtr(MachineCode::FUNCADDR_OFFSET);
1015 return Load(VariableType::NATIVE_POINTER(), baselineCode, codeAddrOffset);
1016 }
1017
GetHClassGateFromIndex(GateRef gate,int32_t index)1018 GateRef CircuitBuilder::GetHClassGateFromIndex(GateRef gate, int32_t index)
1019 {
1020 ArgumentAccessor argAcc(circuit_);
1021 GateRef unsharedConstpool = argAcc.GetFrameArgsIn(gate, FrameArgIdx::UNSHARED_CONST_POOL);
1022 return LoadHClassFromConstpool(unsharedConstpool, index);
1023 }
1024
AddPhiOperand(GateRef val)1025 GateRef Variable::AddPhiOperand(GateRef val)
1026 {
1027 ASSERT(GateAccessor(env_->GetCircuit()).IsValueSelector(val));
1028 Label label = env_->GetLabelFromSelector(val);
1029 size_t idx = 0;
1030 for (auto pred : label.GetPredecessors()) {
1031 auto preVal = pred.ReadVariable(this);
1032 ASSERT(!GateAccessor(env_->GetCircuit()).IsNop(preVal));
1033 idx++;
1034 val = AddOperandToSelector(val, idx, preVal);
1035 }
1036 return TryRemoveTrivialPhi(val);
1037 }
1038
AddOperandToSelector(GateRef val,size_t idx,GateRef in)1039 GateRef Variable::AddOperandToSelector(GateRef val, size_t idx, GateRef in)
1040 {
1041 GateAccessor(env_->GetCircuit()).NewIn(val, idx, in);
1042 return val;
1043 }
1044
TryRemoveTrivialPhi(GateRef phi)1045 GateRef Variable::TryRemoveTrivialPhi(GateRef phi)
1046 {
1047 GateAccessor acc(GetCircuit());
1048 GateRef same = Gate::InvalidGateRef;
1049 const size_t inNum = acc.GetNumIns(phi);
1050 for (size_t i = 1; i < inNum; ++i) {
1051 GateRef phiIn = acc.GetIn(phi, i);
1052 if (phiIn == same || phiIn == phi) {
1053 continue; // unique value or self-reference
1054 }
1055 if (same != Gate::InvalidGateRef) {
1056 return phi; // the phi merges at least two valusses: not trivial
1057 }
1058 same = phiIn;
1059 }
1060 if (same == Gate::InvalidGateRef) {
1061 // the phi is unreachable or in the start block
1062 GateType type = acc.GetGateType(phi);
1063 same = env_->GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, type);
1064 }
1065 // remove the trivial phi
1066 // get all users of phi except self
1067 std::vector<GateRef> outs;
1068 auto uses = acc.Uses(phi);
1069 for (auto use = uses.begin(); use != uses.end();) {
1070 GateRef u = *use;
1071 if (u != phi) {
1072 outs.push_back(u);
1073 use = acc.ReplaceIn(use, same);
1074 } else {
1075 use++;
1076 }
1077 }
1078 acc.DeleteGate(phi);
1079
1080 // try to recursiveby remove all phi users, which might have vecome trivial
1081 for (auto out : outs) {
1082 if (acc.IsValueSelector(out)) {
1083 auto result = TryRemoveTrivialPhi(out);
1084 if (same == out) {
1085 same = result;
1086 }
1087 }
1088 }
1089 return same;
1090 }
1091
ElementsKindIsInt(GateRef kind)1092 GateRef CircuitBuilder::ElementsKindIsInt(GateRef kind)
1093 {
1094 return Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::INT)));
1095 }
1096
ElementsKindIsIntOrHoleInt(GateRef kind)1097 GateRef CircuitBuilder::ElementsKindIsIntOrHoleInt(GateRef kind)
1098 {
1099 GateRef kindIsInt = Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::INT)));
1100 GateRef kindIsHoleInt = Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE_INT)));
1101 return BitOr(kindIsInt, kindIsHoleInt);
1102 }
1103
ElementsKindIsNumber(GateRef kind)1104 GateRef CircuitBuilder::ElementsKindIsNumber(GateRef kind)
1105 {
1106 return Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::NUMBER)));
1107 }
1108
ElementsKindIsNumOrHoleNum(GateRef kind)1109 GateRef CircuitBuilder::ElementsKindIsNumOrHoleNum(GateRef kind)
1110 {
1111 GateRef kindIsNum = Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::NUMBER)));
1112 GateRef kindIsHoleNum = Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)));
1113 return BitOr(kindIsNum, kindIsHoleNum);
1114 }
1115
ElementsKindIsString(GateRef kind)1116 GateRef CircuitBuilder::ElementsKindIsString(GateRef kind)
1117 {
1118 return Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::STRING)));
1119 }
1120
ElementsKindIsStringOrHoleString(GateRef kind)1121 GateRef CircuitBuilder::ElementsKindIsStringOrHoleString(GateRef kind)
1122 {
1123 GateRef kindIsString = Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::STRING)));
1124 GateRef kindIsHoleString = Int32Equal(kind, Int32(Elements::ToUint(ElementsKind::HOLE_STRING)));
1125 return BitOr(kindIsString, kindIsHoleString);
1126 }
1127
ElementsKindIsHeapKind(GateRef kind)1128 GateRef CircuitBuilder::ElementsKindIsHeapKind(GateRef kind)
1129 {
1130 GateRef overString = Int32GreaterThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::STRING)));
1131 GateRef isHoleOrNone = Int32LessThanOrEqual(kind, Int32(Elements::ToUint(ElementsKind::HOLE)));
1132 return BitOr(overString, isHoleOrNone);
1133 }
1134
ElementsKindHasHole(GateRef kind)1135 GateRef CircuitBuilder::ElementsKindHasHole(GateRef kind)
1136 {
1137 return Int32NotEqual(Int32And(kind, Int32(Elements::ToUint(ElementsKind::HOLE))), Int32(0));
1138 }
1139
LoadBuiltinObject(size_t offset)1140 GateRef CircuitBuilder::LoadBuiltinObject(size_t offset)
1141 {
1142 auto currentLabel = env_->GetCurrentLabel();
1143 auto currentControl = currentLabel->GetControl();
1144 auto currentDepend = currentLabel->GetDepend();
1145 auto frameState = acc_.FindNearestFrameState(currentDepend);
1146 GateRef ret = GetCircuit()->NewGate(circuit_->LoadBuiltinObject(offset),
1147 MachineType::I64,
1148 {currentControl, currentDepend, frameState},
1149 GateType::AnyType());
1150 currentLabel->SetControl(ret);
1151 currentLabel->SetDepend(ret);
1152 return ret;
1153 }
1154
GetKeyFromLexivalEnv(GateRef lexicalEnv,GateRef levelIndex,GateRef slotIndex)1155 GateRef CircuitBuilder::GetKeyFromLexivalEnv(GateRef lexicalEnv, GateRef levelIndex, GateRef slotIndex)
1156 {
1157 Label entry(env_);
1158 SubCfgEntry(&entry);
1159 Label exit(env_);
1160 Label loopHead(env_);
1161 Label loopEnd(env_);
1162 Label afterLoop(env_);
1163
1164 DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
1165 DEFVALUE(currentEnv, env_, VariableType::JS_ANY(), lexicalEnv);
1166 DEFVALUE(i, env_, VariableType::INT32(), Int32(0));
1167
1168 Branch(Int32LessThan(*i, levelIndex), &loopHead, &afterLoop);
1169 LoopBegin(&loopHead);
1170 {
1171 currentEnv = GetParentEnv(*currentEnv);
1172 i = Int32Add(*i, Int32(1));
1173 Branch(Int32LessThan(*i, levelIndex), &loopEnd, &afterLoop);
1174 Bind(&loopEnd);
1175 LoopEnd(&loopHead);
1176 }
1177 Bind(&afterLoop);
1178 {
1179 result = GetPropertiesFromLexicalEnv(*currentEnv, slotIndex);
1180 Jump(&exit);
1181 }
1182 Bind(&exit);
1183 auto ret = *result;
1184 SubCfgExit();
1185 return ret;
1186 }
1187
GetParentEnv(GateRef object)1188 GateRef CircuitBuilder::GetParentEnv(GateRef object)
1189 {
1190 GateRef index = Int32(LexicalEnv::PARENT_ENV_INDEX);
1191 return GetValueFromTaggedArray(object, index);
1192 }
1193
GetSendableParentEnv(GateRef object)1194 GateRef CircuitBuilder::GetSendableParentEnv(GateRef object)
1195 {
1196 GateRef index = Int32(SendableEnv::SENDABLE_PARENT_ENV_INDEX);
1197 return GetValueFromTaggedArray(object, index);
1198 }
1199
GetPropertiesFromLexicalEnv(GateRef object,GateRef index)1200 GateRef CircuitBuilder::GetPropertiesFromLexicalEnv(GateRef object, GateRef index)
1201 {
1202 GateRef valueIndex = Int32Add(index, Int32(LexicalEnv::RESERVED_ENV_LENGTH));
1203 return GetValueFromTaggedArray(object, valueIndex);
1204 }
1205
NewJSPrimitiveRef(GateRef glue,size_t index,GateRef obj)1206 GateRef CircuitBuilder::NewJSPrimitiveRef(GateRef glue, size_t index, GateRef obj)
1207 {
1208 GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env_->Is32Bit()));
1209 GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
1210 GateRef func = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
1211 GateRef protoOrHclass = Load(VariableType::JS_ANY(), func, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
1212 NewObjectStubBuilder newBuilder(env_);
1213 GateRef newObj = newBuilder.NewJSObject(glue, protoOrHclass);
1214 GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET);
1215 Store(VariableType::JS_ANY(), glue, newObj, valueOffset, obj);
1216 return newObj;
1217 }
1218
ToObject(GateRef glue,GateRef obj)1219 GateRef CircuitBuilder::ToObject(GateRef glue, GateRef obj)
1220 {
1221 Label entry(env_);
1222 env_->SubCfgEntry(&entry);
1223 Label exit(env_);
1224 DEFVALUE(result, env_, VariableType::JS_ANY(), obj);
1225 DEFVALUE(taggedId, env_, VariableType::INT32(), Int32(0));
1226 Label isNumber(env_);
1227 Label notNumber(env_);
1228 Label isBoolean(env_);
1229 Label notBoolean(env_);
1230 Label isString(env_);
1231 Label notString(env_);
1232 Label isECMAObject(env_);
1233 Label notIsECMAObject(env_);
1234 Label isSymbol(env_);
1235 Label notSymbol(env_);
1236 Label isUndefined(env_);
1237 Label notIsUndefined(env_);
1238 Label isNull(env_);
1239 Label notIsNull(env_);
1240 Label isHole(env_);
1241 Label notIsHole(env_);
1242 Label isBigInt(env_);
1243 Label notIsBigInt(env_);
1244 Label throwError(env_);
1245 BRANCH(IsEcmaObject(obj), &isECMAObject, ¬IsECMAObject);
1246 Bind(&isECMAObject);
1247 {
1248 result = obj;
1249 Jump(&exit);
1250 }
1251 Bind(¬IsECMAObject);
1252 BRANCH(TaggedIsNumber(obj), &isNumber, ¬Number);
1253 Bind(&isNumber);
1254 {
1255 result = NewJSPrimitiveRef(glue, GlobalEnv::NUMBER_FUNCTION_INDEX, obj);
1256 Jump(&exit);
1257 }
1258 Bind(¬Number);
1259 BRANCH(TaggedIsBoolean(obj), &isBoolean, ¬Boolean);
1260 Bind(&isBoolean);
1261 {
1262 result = NewJSPrimitiveRef(glue, GlobalEnv::BOOLEAN_FUNCTION_INDEX, obj);
1263 Jump(&exit);
1264 }
1265 Bind(¬Boolean);
1266 BRANCH(TaggedIsString(obj), &isString, ¬String);
1267 Bind(&isString);
1268 {
1269 result = NewJSPrimitiveRef(glue, GlobalEnv::STRING_FUNCTION_INDEX, obj);
1270 Jump(&exit);
1271 }
1272 Bind(¬String);
1273 BRANCH(TaggedIsSymbol(obj), &isSymbol, ¬Symbol);
1274 Bind(&isSymbol);
1275 {
1276 result = NewJSPrimitiveRef(glue, GlobalEnv::SYMBOL_FUNCTION_INDEX, obj);
1277 Jump(&exit);
1278 }
1279 Bind(¬Symbol);
1280 BRANCH(TaggedIsUndefined(obj), &isUndefined, ¬IsUndefined);
1281 Bind(&isUndefined);
1282 {
1283 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotUndefinedObject));
1284 Jump(&throwError);
1285 }
1286 Bind(¬IsUndefined);
1287 BRANCH(TaggedIsHole(obj), &isHole, ¬IsHole);
1288 Bind(&isHole);
1289 {
1290 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotHoleObject));
1291 Jump(&throwError);
1292 }
1293 Bind(¬IsHole);
1294 BRANCH(TaggedIsNull(obj), &isNull, ¬IsNull);
1295 Bind(&isNull);
1296 {
1297 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
1298 Jump(&throwError);
1299 }
1300 Bind(¬IsNull);
1301 BRANCH(TaggedIsBigInt(obj), &isBigInt, ¬IsBigInt);
1302 Bind(&isBigInt);
1303 {
1304 result = NewJSPrimitiveRef(glue, GlobalEnv::BIGINT_FUNCTION_INDEX, obj);
1305 Jump(&exit);
1306 }
1307 Bind(¬IsBigInt);
1308 {
1309 taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotNullObject));
1310 Jump(&throwError);
1311 }
1312 Bind(&throwError);
1313 {
1314 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef, { Int32ToTaggedInt(*taggedId) }, glue);
1315 result = ExceptionConstant();
1316 Jump(&exit);
1317 }
1318 Bind(&exit);
1319 auto ret = *result;
1320 env_->SubCfgExit();
1321 return ret;
1322 }
1323
GetPrototype(GateRef glue,GateRef object)1324 GateRef CircuitBuilder::GetPrototype(GateRef glue, GateRef object)
1325 {
1326 Label entry(env_);
1327 env_->SubCfgEntry(&entry);
1328 DEFVALUE(result, env_, VariableType::JS_ANY(), Hole());
1329 Label exit(env_);
1330 Label objectIsHeapObject(env_);
1331 Label objectIsEcmaObject(env_);
1332 Label objectNotEcmaObject(env_);
1333
1334 BRANCH(TaggedIsHeapObject(object), &objectIsHeapObject, &objectNotEcmaObject);
1335 Bind(&objectIsHeapObject);
1336 BRANCH(TaggedObjectIsEcmaObject(object), &objectIsEcmaObject, &objectNotEcmaObject);
1337 Bind(&objectNotEcmaObject);
1338 {
1339 GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
1340 CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef, { Int32ToTaggedInt(taggedId) }, glue);
1341 result = ExceptionConstant();
1342 Jump(&exit);
1343 }
1344 Bind(&objectIsEcmaObject);
1345 {
1346 Label objectIsJsProxy(env_);
1347 Label objectNotIsJsProxy(env_);
1348 BRANCH(IsJsProxy(object), &objectIsJsProxy, &objectNotIsJsProxy);
1349 Bind(&objectIsJsProxy);
1350 {
1351 result = CallRuntime(glue, RTSTUB_ID(CallGetPrototype), Gate::InvalidGateRef, { object }, glue);
1352 Jump(&exit);
1353 }
1354 Bind(&objectNotIsJsProxy);
1355 {
1356 result = GetPrototypeFromHClass(LoadHClass(object));
1357 Jump(&exit);
1358 }
1359 }
1360 Bind(&exit);
1361 auto ret = *result;
1362 env_->SubCfgExit();
1363 return ret;
1364 }
1365
GetGlobalConstantValue(VariableType type,GateRef glue,ConstantIndex index)1366 GateRef CircuitBuilder::GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index)
1367 {
1368 GateRef gConstAddr = Load(VariableType::JS_ANY(), glue,
1369 IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
1370 auto constantIndex = IntPtr(JSTaggedValue::TaggedTypeSize() * static_cast<size_t>(index));
1371 return Load(type, gConstAddr, constantIndex);
1372 }
1373
TransProtoWithoutLayout(GateRef glue,GateRef hClass,GateRef proto)1374 GateRef CircuitBuilder::TransProtoWithoutLayout(GateRef glue, GateRef hClass, GateRef proto)
1375 {
1376 Label entry(env_);
1377 env_->SubCfgEntry(&entry);
1378 Label exit(env_);
1379 DEFVALUE(result, env_, VariableType::JS_ANY(), Undefined());
1380
1381 GateRef key = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1382 ConstantIndex::PROTOTYPE_STRING_INDEX);
1383 GateRef newClass = CallNGCRuntime(glue, RTSTUB_ID(JSHClassFindProtoTransitions), Gate::InvalidGateRef,
1384 { hClass, key, proto }, glue);
1385 Label undef(env_);
1386 Label find(env_);
1387 BRANCH(IntPtrEqual(TaggedCastToIntPtr(newClass), IntPtr(0)), &undef, &find);
1388 Bind(&find);
1389 {
1390 result = newClass;
1391 Jump(&exit);
1392 }
1393 Bind(&undef);
1394 {
1395 result = CallRuntime(glue, RTSTUB_ID(HClassCloneWithAddProto), Gate::InvalidGateRef,
1396 { hClass, key, proto }, glue);
1397 Jump(&exit);
1398 }
1399 Bind(&exit);
1400 auto ret = *result;
1401 env_->SubCfgExit();
1402 return ret;
1403 }
1404
1405
OrdinaryNewJSObjectCreate(GateRef glue,GateRef proto)1406 GateRef CircuitBuilder::OrdinaryNewJSObjectCreate(GateRef glue, GateRef proto)
1407 {
1408 Label entry(env_);
1409 env_->SubCfgEntry(&entry);
1410 Label exit(env_);
1411 DEFVALUE(result, env_, VariableType::JS_ANY(), Undefined());
1412
1413 GateRef hClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1414 ConstantIndex::OBJECT_HCLASS_INDEX);
1415 GateRef newClass = TransProtoWithoutLayout(glue, hClass, proto);
1416 Label exception(env_);
1417 Label noexception(env_);
1418 BRANCH(TaggedIsException(newClass), &exception, &noexception);
1419 Bind(&exception);
1420 {
1421 result = ExceptionConstant();
1422 Jump(&exit);
1423 }
1424 Bind(&noexception);
1425 NewObjectStubBuilder newBuilder(env_);
1426 GateRef newObj = newBuilder.NewJSObject(glue, newClass);
1427 Label exceptionNewObj(env_);
1428 Label noexceptionNewObj(env_);
1429 BRANCH(TaggedIsException(newObj), &exceptionNewObj, &noexceptionNewObj);
1430 Bind(&exceptionNewObj);
1431 {
1432 result = ExceptionConstant();
1433 Jump(&exit);
1434 }
1435 Bind(&noexceptionNewObj);
1436 {
1437 SetExtensibleToBitfield(glue, newObj, True());
1438 result = newObj;
1439 Jump(&exit);
1440 }
1441 Bind(&exit);
1442 auto ret = *result;
1443 env_->SubCfgExit();
1444 return ret;
1445 }
1446
GetPropertiesFromSendableEnv(GateRef object,GateRef index)1447 GateRef CircuitBuilder::GetPropertiesFromSendableEnv(GateRef object, GateRef index)
1448 {
1449 GateRef valueIndex = Int32Add(index, Int32(SendableEnv::SENDABLE_RESERVED_ENV_LENGTH));
1450 return GetValueFromTaggedArray(object, valueIndex);
1451 }
1452
GetProfileTypeInfo(GateRef function)1453 GateRef CircuitBuilder::GetProfileTypeInfo(GateRef function)
1454 {
1455 GateRef raw = Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
1456 return Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
1457 }
1458
SetRawProfileTypeInfoToFunction(GateRef glue,GateRef function,GateRef value)1459 void CircuitBuilder::SetRawProfileTypeInfoToFunction(GateRef glue, GateRef function, GateRef value)
1460 {
1461 GateRef offset = IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET);
1462 Store(VariableType::JS_ANY(), glue, function, offset, value);
1463 }
1464
UpdateProfileTypeInfoCellToFunction(GateRef glue,GateRef function,GateRef profileTypeInfo,GateRef slotId)1465 void CircuitBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
1466 GateRef profileTypeInfo, GateRef slotId)
1467 {
1468 Label subEntry(env_);
1469 env_->SubCfgEntry(&subEntry);
1470
1471 Label profileTypeInfoNotUndefined(env_);
1472 Label slotValueUpdate(env_);
1473 Label slotValueNotUndefined(env_);
1474 Label profileTypeInfoEnd(env_);
1475 NewObjectStubBuilder newBuilder(env_);
1476 BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
1477 Bind(&profileTypeInfoNotUndefined);
1478 {
1479 GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
1480 BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
1481 Bind(&slotValueUpdate);
1482 {
1483 GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
1484 SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
1485 SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
1486 Jump(&profileTypeInfoEnd);
1487 }
1488 Bind(&slotValueNotUndefined);
1489 UpdateProfileTypeInfoCellType(glue, slotValue);
1490 SetRawProfileTypeInfoToFunction(glue, function, slotValue);
1491 Jump(&profileTypeInfoEnd);
1492 }
1493 Bind(&profileTypeInfoEnd);
1494
1495 env_->SubCfgExit();
1496 }
1497
UpdateProfileTypeInfoCellType(GateRef glue,GateRef profileTypeInfoCell)1498 void CircuitBuilder::UpdateProfileTypeInfoCellType(GateRef glue, GateRef profileTypeInfoCell)
1499 {
1500 Label subEntry(env_);
1501 env_->SubCfgEntry(&subEntry);
1502
1503 // ProfileTypeInfoCell0 -> Cell1 -> CellN
1504 Label isProfileTypeInfoCell0(env_);
1505 Label notProfileTypeInfoCell0(env_);
1506 Label isProfileTypeInfoCell1(env_);
1507 Label endProfileTypeInfoCellType(env_);
1508 GateRef objectType = GetObjectType(LoadHClass(profileTypeInfoCell));
1509 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::PROFILE_TYPE_INFO_CELL_0))),
1510 &isProfileTypeInfoCell0, ¬ProfileTypeInfoCell0);
1511 Bind(&isProfileTypeInfoCell0);
1512 {
1513 auto profileTypeInfoCell1Class = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1514 ConstantIndex::PROFILE_TYPE_INFO_CELL_1_CLASS_INDEX);
1515 StoreHClassWithoutBarrier(glue, profileTypeInfoCell, profileTypeInfoCell1Class);
1516 Jump(&endProfileTypeInfoCellType);
1517 }
1518 Bind(¬ProfileTypeInfoCell0);
1519 BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::PROFILE_TYPE_INFO_CELL_1))),
1520 &isProfileTypeInfoCell1, &endProfileTypeInfoCellType);
1521 Bind(&isProfileTypeInfoCell1);
1522 {
1523 auto profileTypeInfoCellNClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
1524 ConstantIndex::PROFILE_TYPE_INFO_CELL_N_CLASS_INDEX);
1525 StoreHClassWithoutBarrier(glue, profileTypeInfoCell, profileTypeInfoCellNClass);
1526 Jump(&endProfileTypeInfoCellType);
1527 }
1528 Bind(&endProfileTypeInfoCellType);
1529 env_->SubCfgExit();
1530 }
1531
FastToBoolean(GateRef value)1532 GateRef CircuitBuilder::FastToBoolean(GateRef value)
1533 {
1534 Label entry(env_);
1535 env_->SubCfgEntry(&entry);
1536 DEFVALUE(result, env_, VariableType::JS_ANY(), HoleConstant());
1537 Label exit(env_);
1538
1539 Label isSpecial(env_);
1540 Label notSpecial(env_);
1541 Label isNumber(env_);
1542 Label isInt(env_);
1543 Label isDouble(env_);
1544 Label notNumber(env_);
1545 Label notNan(env_);
1546 Label isString(env_);
1547 Label notString(env_);
1548 Label isBigint(env_);
1549 Label lengthIsOne(env_);
1550 Label returnTrue(env_);
1551 Label returnFalse(env_);
1552
1553 BRANCH(TaggedIsSpecial(value), &isSpecial, ¬Special);
1554 Bind(&isSpecial);
1555 {
1556 BRANCH(TaggedIsTrue(value), &returnTrue, &returnFalse);
1557 }
1558 Bind(¬Special);
1559 {
1560 BRANCH(TaggedIsNumber(value), &isNumber, ¬Number);
1561 Bind(¬Number);
1562 {
1563 BRANCH(TaggedIsString(value), &isString, ¬String);
1564 Bind(&isString);
1565 {
1566 auto len = GetLengthFromString(value);
1567 BRANCH(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
1568 }
1569 Bind(¬String);
1570 BRANCH(TaggedIsBigInt(value), &isBigint, &returnTrue);
1571 Bind(&isBigint);
1572 {
1573 auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
1574 BRANCH(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
1575 Bind(&lengthIsOne);
1576 {
1577 auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
1578 auto data0 = Load(VariableType::INT32(), data, Int32(0));
1579 BRANCH(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
1580 }
1581 }
1582 }
1583 Bind(&isNumber);
1584 {
1585 BRANCH(TaggedIsInt(value), &isInt, &isDouble);
1586 Bind(&isInt);
1587 {
1588 auto intValue = GetInt32OfTInt(value);
1589 BRANCH(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
1590 }
1591 Bind(&isDouble);
1592 {
1593 auto doubleValue = GetDoubleOfTDouble(value);
1594 BRANCH(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
1595 Bind(¬Nan);
1596 BRANCH(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
1597 }
1598 }
1599 }
1600 Bind(&returnTrue);
1601 {
1602 result = TaggedTrue();
1603 Jump(&exit);
1604 }
1605 Bind(&returnFalse);
1606 {
1607 result = TaggedFalse();
1608 Jump(&exit);
1609 }
1610 Bind(&exit);
1611 auto ret = *result;
1612 env_->SubCfgExit();
1613 return ret;
1614 }
1615
IsStableArrayLengthWriteable(GateRef array)1616 GateRef CircuitBuilder::IsStableArrayLengthWriteable(GateRef array)
1617 {
1618 Label entry(env_);
1619 env_->SubCfgEntry(&entry);
1620 DEFVALUE(result, env_, VariableType::BOOL(), False());
1621 GateRef hClass = LoadHClassByConstOffset(array);
1622 GateRef attrOffset = IntPtr(JSHClass::LAYOUT_OFFSET);
1623 GateRef layout = Load(VariableType::JS_POINTER(), hClass, attrOffset);
1624 GateRef entryHandler = Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX);
1625 GateRef index =
1626 Int32Add(Int32LSL(entryHandler, Int32(LayoutInfo::ELEMENTS_INDEX_LOG2)), Int32(LayoutInfo::ATTR_INDEX_OFFSET));
1627 GateRef attr = GetInt64OfTInt(GetValueFromTaggedArray(layout, index));
1628 GateRef writeableField =
1629 Int32And(TruncInt64ToInt32(Int64LSR(attr, Int64(PropertyAttributes::WritableField::START_BIT))),
1630 Int32((1LLU << PropertyAttributes::WritableField::SIZE) - 1));
1631 result = Int32NotEqual(writeableField, Int32(0));
1632 auto ret = *result;
1633 env_->SubCfgExit();
1634 return ret;
1635 }
1636 } // namespace panda::ecmascript::kungfu
1637