1/*
2 * Copyright (c) 2021 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/argument_accessor.h"
17#include "ecmascript/compiler/circuit_builder.h"
18#include "ecmascript/compiler/gate_accessor.h"
19#include "ecmascript/compiler/graph_editor.h"
20#include "ecmascript/js_tagged_value-inl.h"
21#include "ecmascript/mem/assert_scope.h"
22
23namespace panda::ecmascript::kungfu {
24using UseIterator = GateAccessor::UseIterator;
25
26size_t GateAccessor::GetNumIns(GateRef gate) const
27{
28    Gate *gatePtr = circuit_->LoadGatePtr(gate);
29    return gatePtr->GetNumIns();
30}
31
32MarkCode GateAccessor::GetMark(GateRef gate) const
33{
34    return circuit_->GetMark(gate);
35}
36
37void GateAccessor::SetMark(GateRef gate, MarkCode mark)
38{
39    circuit_->SetMark(gate, mark);
40}
41
42bool GateAccessor::IsFinished(GateRef gate) const
43{
44    return GetMark(gate) == MarkCode::FINISHED;
45}
46
47bool GateAccessor::IsVisited(GateRef gate) const
48{
49    return GetMark(gate) == MarkCode::VISITED;
50}
51
52bool GateAccessor::IsPrevisit(GateRef gate) const
53{
54    return GetMark(gate) == MarkCode::PREVISIT;
55}
56
57bool GateAccessor::IsNotMarked(GateRef gate) const
58{
59    return GetMark(gate) == MarkCode::NO_MARK;
60}
61
62void GateAccessor::SetFinished(GateRef gate)
63{
64    SetMark(gate, MarkCode::FINISHED);
65}
66
67void GateAccessor::SetVisited(GateRef gate)
68{
69    SetMark(gate, MarkCode::VISITED);
70}
71
72void GateAccessor::SetPrevisit(GateRef gate)
73{
74    SetMark(gate, MarkCode::PREVISIT);
75}
76
77OpCode GateAccessor::GetOpCode(GateRef gate) const
78{
79    Gate *gatePtr = circuit_->LoadGatePtr(gate);
80    return gatePtr->GetOpCode();
81}
82
83BitField GateAccessor::TryGetValue(GateRef gate) const
84{
85    Gate *gatePtr = circuit_->LoadGatePtr(gate);
86    return gatePtr->TryGetValue();
87}
88
89ICmpCondition GateAccessor::GetICmpCondition(GateRef gate) const
90{
91    ASSERT(GetOpCode(gate) == OpCode::ICMP);
92    Gate *gatePtr = circuit_->LoadGatePtr(gate);
93    return static_cast<ICmpCondition>(gatePtr->GetOneParameterMetaData()->GetValue());
94}
95
96FCmpCondition GateAccessor::GetFCmpCondition(GateRef gate) const
97{
98    ASSERT(GetOpCode(gate) == OpCode::FCMP);
99    Gate *gatePtr = circuit_->LoadGatePtr(gate);
100    return static_cast<FCmpCondition>(gatePtr->GetOneParameterMetaData()->GetValue());
101}
102
103size_t GateAccessor::GetOffset(GateRef gate) const
104{
105    ASSERT(GetOpCode(gate) == OpCode::LOAD_CONST_OFFSET ||
106           GetOpCode(gate) == OpCode::STORE_CONST_OFFSET);
107    Gate *gatePtr = circuit_->LoadGatePtr(gate);
108    auto accessor = LoadStoreConstOffsetAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
109    return accessor.GetOffset();
110}
111
112size_t GateAccessor::GetInitOffset(GateRef gate) const
113{
114    ASSERT(GetOpCode(gate) == OpCode::INITVREG);
115    Gate *gatePtr = circuit_->LoadGatePtr(gate);
116    return gatePtr->GetOneParameterMetaData()->GetValue();
117}
118
119uint32_t GateAccessor::GetTrueWeight(GateRef gate) const
120{
121    ASSERT(GetOpCode(gate) == OpCode::IF_BRANCH);
122    Gate *gatePtr = circuit_->LoadGatePtr(gate);
123    auto accessor = BranchAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
124    return accessor.GetTrueWeight();
125}
126
127uint32_t GateAccessor::GetFalseWeight(GateRef gate) const
128{
129    ASSERT(GetOpCode(gate) == OpCode::IF_BRANCH);
130    Gate *gatePtr = circuit_->LoadGatePtr(gate);
131    auto accessor = BranchAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
132    return accessor.GetFalseWeight();
133}
134
135MemoryAttribute GateAccessor::GetMemoryAttribute(GateRef gate) const
136{
137    auto op = GetOpCode(gate);
138    Gate *gatePtr = circuit_->LoadGatePtr(gate);
139    switch (op) {
140        case OpCode::LOAD:
141        case OpCode::STORE_WITHOUT_BARRIER:
142        case OpCode::STORE: {
143            auto accessor = LoadStoreAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
144            return accessor.GetMemoryAttribute();
145        }
146        case OpCode::LOAD_CONST_OFFSET:
147        case OpCode::STORE_CONST_OFFSET: {
148            auto accessor = LoadStoreConstOffsetAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
149            return accessor.GetMemoryAttribute();
150        }
151        default: {
152            UNREACHABLE();
153            break;
154        }
155    }
156    return MemoryAttribute::Default();
157}
158
159bool GateAccessor::HasBranchWeight(GateRef gate) const
160{
161    ASSERT(GetOpCode(gate) == OpCode::IF_BRANCH);
162    Gate *gatePtr = circuit_->LoadGatePtr(gate);
163    auto accessor = BranchAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
164    return (accessor.GetTrueWeight() != 0) || (accessor.GetFalseWeight() != 0);
165}
166
167size_t GateAccessor::GetIndex(GateRef gate) const
168{
169    ASSERT(GetOpCode(gate) == OpCode::GET_GLOBAL_ENV_OBJ_HCLASS ||
170           GetOpCode(gate) == OpCode::GET_GLOBAL_CONSTANT_VALUE ||
171           GetOpCode(gate) == OpCode::GET_GLOBAL_ENV_OBJ ||
172           GetOpCode(gate) == OpCode::LOAD_HCLASS_FROM_CONSTPOOL ||
173           GetOpCode(gate) == OpCode::LOAD_BUILTIN_OBJECT);
174    Gate *gatePtr = circuit_->LoadGatePtr(gate);
175    return gatePtr->GetOneParameterMetaData()->GetValue();
176}
177
178size_t GateAccessor::GetJSType(GateRef gate) const
179{
180    ASSERT(GetOpCode(gate) == OpCode::IS_SPECIFIC_OBJECT_TYPE);
181    Gate *gatePtr = circuit_->LoadGatePtr(gate);
182    return gatePtr->GetOneParameterMetaData()->GetValue();
183}
184
185uint32_t GateAccessor::GetArraySize(GateRef gate) const
186{
187    ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
188           GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
189    Gate *gatePtr = circuit_->LoadGatePtr(gate);
190    auto array = gatePtr->GetOneParameterMetaData()->GetValue();
191    return ArrayMetaDataAccessor(array).GetArrayLength();
192}
193
194void GateAccessor::SetArraySize(GateRef gate, uint32_t size)
195{
196    ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
197           GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
198    uint32_t curSize = GetArraySize(gate);
199    if (curSize != size) {
200        Gate *gatePtr = circuit_->LoadGatePtr(gate);
201        ArrayMetaDataAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
202        accessor.SetArrayLength(size);
203        if (GetOpCode(gate) == OpCode::CREATE_ARRAY) {
204            auto meta = circuit_->CreateArray(accessor.ToValue());
205            SetMetaData(gate, meta);
206        } else {
207            auto meta = circuit_->CreateArrayWithBuffer(accessor.ToValue());
208            SetMetaData(gate, meta);
209        }
210    }
211}
212
213ElementsKind GateAccessor::GetElementsKind(GateRef gate) const
214{
215    ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
216           GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
217    Gate *gatePtr = circuit_->LoadGatePtr(gate);
218    auto array = gatePtr->GetOneParameterMetaData()->GetValue();
219    return ArrayMetaDataAccessor(array).GetElementsKind();
220}
221
222void GateAccessor::SetElementsKind(GateRef gate, ElementsKind kind)
223{
224    ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
225           GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
226    Gate *gatePtr = circuit_->LoadGatePtr(gate);
227    ArrayMetaDataAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
228    accessor.SetElementsKind(kind);
229    const_cast<OneParameterMetaData *>(gatePtr->GetOneParameterMetaData())->SetValue(accessor.ToValue());
230}
231
232RegionSpaceFlag GateAccessor::GetRegionSpaceFlag(GateRef gate) const
233{
234    ASSERT(GetOpCode(gate) == OpCode::CREATE_ARRAY ||
235           GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
236    Gate *gatePtr = circuit_->LoadGatePtr(gate);
237    auto array = gatePtr->GetOneParameterMetaData()->GetValue();
238    return ArrayMetaDataAccessor(array).GetRegionSpaceFlag();
239}
240
241uint32_t GateAccessor::GetStringStatus(GateRef gate) const
242{
243    ASSERT(GetOpCode(gate) == OpCode::STRING_ADD);
244    Gate *gatePtr = circuit_->LoadGatePtr(gate);
245    StringStatusAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
246    return accessor.GetStringStatus();
247}
248
249void GateAccessor::SetStringStatus(GateRef gate, uint32_t type)
250{
251    ASSERT(GetOpCode(gate) == OpCode::STRING_ADD);
252    uint32_t curStatus = GetStringStatus(gate);
253    if (curStatus != type) {
254        StringStatusAccessor accessor(static_cast<uint64_t>(type));
255        auto meta = circuit_->StringAdd(accessor.ToValue());
256        SetMetaData(gate, meta);
257    }
258}
259
260TypedUnaryAccessor GateAccessor::GetTypedUnAccessor(GateRef gate) const
261{
262    ASSERT((GetOpCode(gate) == OpCode::TYPED_UNARY_OP));
263    Gate *gatePtr = circuit_->LoadGatePtr(gate);
264    return TypedUnaryAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
265}
266
267TypedBinaryAccessor GateAccessor::GetTypedBinaryAccessor(GateRef gate) const
268{
269    Gate *gatePtr = circuit_->LoadGatePtr(gate);
270    return TypedBinaryAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
271}
272
273TypedJumpAccessor GateAccessor::GetTypedJumpAccessor(GateRef gate) const
274{
275    ASSERT(GetOpCode(gate) == OpCode::TYPED_CONDITION_JUMP);
276    Gate *gatePtr = circuit_->LoadGatePtr(gate);
277    return TypedJumpAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
278}
279
280ArrayMetaDataAccessor GateAccessor::GetArrayMetaDataAccessor(GateRef gate) const
281{
282    ASSERT(GetOpCode(gate) == OpCode::STABLE_ARRAY_CHECK ||
283           GetOpCode(gate) == OpCode::HCLASS_STABLE_ARRAY_CHECK ||
284           GetOpCode(gate) == OpCode::ELEMENTSKIND_CHECK ||
285           GetOpCode(gate) == OpCode::CREATE_ARRAY ||
286           GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER ||
287           GetOpCode(gate) == OpCode::CREATE_ARGUMENTS ||
288           GetOpCode(gate) == OpCode::LOAD_ARRAY_LENGTH);
289    Gate *gatePtr = circuit_->LoadGatePtr(gate);
290    return ArrayMetaDataAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
291}
292
293bool GateAccessor::NeedPushArgv(GateRef gate) const
294{
295    ASSERT(GetOpCode(gate) == OpCode::CALL_NEW);
296    Gate *gatePtr = circuit_->LoadGatePtr(gate);
297    return gatePtr->GetNewConstructMetaData()->NeedPushArgv();
298}
299
300CreateArgumentsAccessor GateAccessor::GetCreateArgumentsAccessor(GateRef gate) const
301{
302    ASSERT(GetOpCode(gate) == OpCode::CREATE_ARGUMENTS);
303    Gate *gatePtr = circuit_->LoadGatePtr(gate);
304    return CreateArgumentsAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
305}
306
307ObjectTypeAccessor GateAccessor::GetObjectTypeAccessor(GateRef gate) const
308{
309    ASSERT(GetOpCode(gate) == OpCode::OBJECT_TYPE_CHECK);
310    Gate *gatePtr = circuit_->LoadGatePtr(gate);
311    return ObjectTypeAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
312}
313
314BuiltinPrototypeHClassAccessor GateAccessor::GetBuiltinHClassAccessor(GateRef gate) const
315{
316    ASSERT(GetOpCode(gate) == OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK);
317    Gate *gatePtr = circuit_->LoadGatePtr(gate);
318    return BuiltinPrototypeHClassAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
319}
320
321TypedArrayMetaDataAccessor GateAccessor::GetTypedArrayMetaDataAccessor(GateRef gate) const
322{
323    ASSERT(GetOpCode(gate) == OpCode::TYPED_ARRAY_CHECK || GetOpCode(gate) == OpCode::LOAD_TYPED_ARRAY_LENGTH);
324    Gate *gatePtr = circuit_->LoadGatePtr(gate);
325    return TypedArrayMetaDataAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
326}
327
328LoadElementAccessor GateAccessor::GetLoadElementAccessor(GateRef gate) const
329{
330    ASSERT(GetOpCode(gate) == OpCode::LOAD_ELEMENT);
331    Gate *gatePtr = circuit_->LoadGatePtr(gate);
332    return LoadElementAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
333}
334
335StoreElementAccessor GateAccessor::GetStoreElementAccessor(GateRef gate) const
336{
337    ASSERT(GetOpCode(gate) == OpCode::STORE_ELEMENT);
338    Gate *gatePtr = circuit_->LoadGatePtr(gate);
339    return StoreElementAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
340}
341
342bool GateAccessor::TypedOpIsTypedArray(GateRef gate, TypedOpKind kind) const
343{
344    switch (kind) {
345        case TypedOpKind::TYPED_LOAD_OP: {
346            TypedLoadOp op = GetTypedLoadOp(gate);
347            return TypedLoadOp::TYPED_ARRAY_FIRST <= op && op <=TypedLoadOp::TYPED_ARRAY_LAST;
348        }
349        case TypedOpKind::TYPED_STORE_OP: {
350            TypedStoreOp op = GetTypedStoreOp(gate);
351            return TypedStoreOp::TYPED_ARRAY_FIRST <= op && op <= TypedStoreOp::TYPED_ARRAY_LAST;
352        }
353        default:
354            LOG_ECMA(FATAL) << "this branch is unreachable";
355            UNREACHABLE();
356    }
357}
358
359TypedLoadOp GateAccessor::GetTypedLoadOp(GateRef gate) const
360{
361    ASSERT(GetOpCode(gate) == OpCode::LOAD_ELEMENT);
362    Gate *gatePtr = circuit_->LoadGatePtr(gate);
363    return static_cast<TypedLoadOp>(gatePtr->GetOneParameterMetaData()->GetValue());
364}
365
366TypedStoreOp GateAccessor::GetTypedStoreOp(GateRef gate) const
367{
368    ASSERT(GetOpCode(gate) == OpCode::STORE_ELEMENT);
369    Gate *gatePtr = circuit_->LoadGatePtr(gate);
370    return static_cast<TypedStoreOp>(gatePtr->GetOneParameterMetaData()->GetValue());
371}
372
373TypedCallTargetCheckOp GateAccessor::GetTypedCallTargetCheckOp(GateRef gate) const
374{
375    ASSERT(GetOpCode(gate) == OpCode::TYPED_CALLTARGETCHECK_OP);
376    TypedCallTargetCheckAccessor accessor(TryGetValue(gate));
377    return accessor.GetCallTargetCheckOp();
378}
379
380MemoryType GateAccessor::GetMemoryType(GateRef gate) const
381{
382    ASSERT(GetOpCode(gate) == OpCode::STORE_MEMORY);
383    Gate *gatePtr = circuit_->LoadGatePtr(gate);
384    return static_cast<MemoryType>(gatePtr->GetOneParameterMetaData()->GetValue());
385}
386
387uint32_t GateAccessor::GetHClassIndex(GateRef gate) const
388{
389    ASSERT(GetOpCode(gate) == OpCode::STORE_PROPERTY ||
390           GetOpCode(gate) == OpCode::PROTOTYPE_CHECK);
391    Gate *gatePtr = circuit_->LoadGatePtr(gate);
392    return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue());
393}
394
395TypedBinOp GateAccessor::GetTypedBinaryOp(GateRef gate) const
396{
397    ASSERT(GetOpCode(gate) == OpCode::TYPED_BINARY_OP);
398    TypedBinaryAccessor accessor(TryGetValue(gate));
399    return accessor.GetTypedBinOp();
400}
401
402bool GateAccessor::HasNumberType(GateRef gate) const
403{
404    OpCode op = GetOpCode(gate);
405    if (op == OpCode::TYPED_BINARY_OP) {
406        TypedBinaryAccessor accessor(TryGetValue(gate));
407        return accessor.GetParamType().HasNumberType();
408    }
409    return false;
410}
411
412bool GateAccessor::HasStringType(GateRef gate) const
413{
414    OpCode op = GetOpCode(gate);
415    if (op == OpCode::TYPED_BINARY_OP) {
416        TypedBinaryAccessor accessor(TryGetValue(gate));
417        return accessor.GetParamType().IsStringType();
418    }
419    return false;
420}
421
422GlobalTSTypeRef GateAccessor::GetFuncGT(GateRef gate) const
423{
424    ASSERT(GetOpCode(gate) == OpCode::JSINLINETARGET_TYPE_CHECK);
425    Gate *gatePtr = circuit_->LoadGatePtr(gate);
426    auto value = static_cast<uint32_t>((gatePtr->GetOneParameterMetaData()->GetValue()));
427    return GlobalTSTypeRef(value);
428}
429
430GateType GateAccessor::GetParamGateType(GateRef gate) const
431{
432    // NOTICE-PGO: consider to delete this function in Part3, only primitive_type_check use,
433    // which is generate in the retype pass
434    ASSERT(GetOpCode(gate) == OpCode::PRIMITIVE_TYPE_CHECK);
435    Gate *gatePtr = circuit_->LoadGatePtr(gate);
436    GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
437    return accessor.GetGateType();
438}
439
440ParamType GateAccessor::GetParamType(GateRef gate) const
441{
442    Gate *gatePtr = circuit_->LoadGatePtr(gate);
443    GateTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
444    return accessor.GetParamType();
445}
446
447bool GateAccessor::IsConvertSupport(GateRef gate) const
448{
449    ASSERT(GetOpCode(gate) == OpCode::CONVERT ||
450           GetOpCode(gate) == OpCode::CHECK_AND_CONVERT);
451    Gate *gatePtr = circuit_->LoadGatePtr(gate);
452    ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
453    return accessor.IsConvertSupport();
454}
455
456ValueType GateAccessor::GetSrcType(GateRef gate) const
457{
458    ASSERT(GetOpCode(gate) == OpCode::CONVERT ||
459           GetOpCode(gate) == OpCode::CHECK_AND_CONVERT);
460    Gate *gatePtr = circuit_->LoadGatePtr(gate);
461    ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
462    return accessor.GetSrcType();
463}
464
465ValueType GateAccessor::GetDstType(GateRef gate) const
466{
467    ASSERT(GetOpCode(gate) == OpCode::CONVERT ||
468           GetOpCode(gate) == OpCode::CHECK_AND_CONVERT);
469    Gate *gatePtr = circuit_->LoadGatePtr(gate);
470    ValuePairTypeAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
471    return accessor.GetDstType();
472}
473
474uint32_t GateAccessor::GetFirstValue(GateRef gate) const
475{
476    ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD);
477    Gate *gatePtr = circuit_->LoadGatePtr(gate);
478    UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
479    return accessor.GetFirstValue();
480}
481
482uint32_t GateAccessor::GetSecondValue(GateRef gate) const
483{
484    ASSERT(GetOpCode(gate) == OpCode::RANGE_GUARD);
485    Gate *gatePtr = circuit_->LoadGatePtr(gate);
486    UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
487    return accessor.GetSecondValue();
488}
489
490size_t GateAccessor::GetVirtualRegisterIndex(GateRef gate) const
491{
492    ASSERT(GetOpCode(gate) == OpCode::SAVE_REGISTER ||
493           GetOpCode(gate) == OpCode::RESTORE_REGISTER);
494    Gate *gatePtr = circuit_->LoadGatePtr(gate);
495    return static_cast<size_t>(gatePtr->GetOneParameterMetaData()->GetValue());
496}
497
498uint64_t GateAccessor::GetConstantValue(GateRef gate) const
499{
500    ASSERT(GetOpCode(gate) == OpCode::CONSTANT);
501    Gate *gatePtr = circuit_->LoadGatePtr(gate);
502    return gatePtr->GetOneParameterMetaData()->GetValue();
503}
504
505const ChunkVector<char>& GateAccessor::GetConstantString(GateRef gate) const
506{
507    ASSERT(GetOpCode(gate) == OpCode::CONSTSTRING);
508    Gate *gatePtr = circuit_->LoadGatePtr(gate);
509    return gatePtr->GetStringMetaData()->GetString();
510}
511
512bool GateAccessor::IsVtable(GateRef gate) const
513{
514    ASSERT(GetOpCode(gate) == OpCode::LOAD_PROPERTY);
515    Gate *gatePtr = circuit_->LoadGatePtr(gate);
516    return gatePtr->GetBoolMetaData()->GetBool();
517}
518
519bool GateAccessor::GetNoGCFlag(GateRef gate) const
520{
521    if (gate == Circuit::NullGate()) {
522        return false;
523    }
524    OpCode op = GetOpCode(gate);
525    if (op != OpCode::TYPEDCALL && op != OpCode::TYPEDFASTCALL) {
526        return false;
527    }
528    return TypedCallIsNoGC(gate);
529}
530
531bool GateAccessor::TypedCallIsNoGC(GateRef gate) const
532{
533    ASSERT(GetOpCode(gate) == OpCode::TYPEDCALL || GetOpCode(gate) == OpCode::TYPEDFASTCALL);
534    Gate *gatePtr = circuit_->LoadGatePtr(gate);
535    return gatePtr->GetTypedCallMetaData()->IsNoGC();
536}
537
538bool GateAccessor::IsNoGC(GateRef gate) const
539{
540    ASSERT(GetOpCode(gate) == OpCode::CALL_OPTIMIZED || GetOpCode(gate) == OpCode::FAST_CALL_OPTIMIZED);
541    Gate *gatePtr = circuit_->LoadGatePtr(gate);
542    return gatePtr->GetBoolMetaData()->GetBool();
543}
544
545uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const
546{
547    Gate *gatePtr = circuit_->LoadGatePtr(gate);
548    OpCode op = GetOpCode(gate);
549    switch (op) {
550        case OpCode::JS_BYTECODE:
551            return gatePtr->GetJSBytecodeMetaData()->GetPcOffset();
552        case OpCode::TYPED_CALL_BUILTIN:
553        case OpCode::TYPED_CALL_BUILTIN_SIDE_EFFECT:
554        case OpCode::CONSTRUCT:
555        case OpCode::CALL_NEW:
556        case OpCode::CALL_GETTER:
557        case OpCode::CALL_SETTER:
558        case OpCode::ARRAY_FOR_EACH:
559        case OpCode::ARRAY_FIND_OR_FINDINDEX:
560        case OpCode::ARRAY_FILTER:
561        case OpCode::ARRAY_MAP:
562        case OpCode::ARRAY_SOME:
563        case OpCode::ARRAY_EVERY:
564        case OpCode::FLOAT32_ARRAY_CONSTRUCTOR:
565            return static_cast<uint32_t>(gatePtr->GetOneParameterMetaData()->GetValue());
566        case OpCode::TYPEDCALL:
567        case OpCode::TYPEDFASTCALL:
568            return static_cast<uint32_t>(gatePtr->GetTypedCallMetaData()->GetValue());
569        case OpCode::FRAME_STATE: {
570            UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
571            return accessor.GetFirstValue();
572        }
573        default:
574            break;
575    }
576    return 0;
577}
578
579uint32_t GateAccessor::TryGetBcIndex(GateRef gate) const
580{
581    Gate *gatePtr = circuit_->LoadGatePtr(gate);
582    OpCode op = GetOpCode(gate);
583    switch (op) {
584        case OpCode::JS_BYTECODE:
585            return gatePtr->GetJSBytecodeMetaData()->GetBcIndex();
586        default:
587            break;
588    }
589    return INVALID_BC_INDEX;
590}
591
592uint32_t GateAccessor::TryGetMethodOffset(GateRef gate) const
593{
594    Gate *gatePtr = circuit_->LoadGatePtr(gate);
595    OpCode op = GetOpCode(gate);
596    switch (op) {
597        case OpCode::FRAME_ARGS: {
598            UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
599            return accessor.GetFirstValue();
600        }
601        case OpCode::JS_BYTECODE: {
602            return gatePtr->GetJSBytecodeMetaData()->GetMethodId();
603        }
604        default:
605            break;
606    }
607    return 0;
608}
609
610GateRef GateAccessor::GetFrameArgs(GateRef gate) const
611{
612    if (!HasFrameState(gate)) {
613        return Circuit::NullGate();
614    }
615    if (GetOpCode(gate) == OpCode::FRAME_STATE) {
616        return GetValueIn(gate, 0); // 0: frame args
617    }
618    GateRef frameState = GetFrameState(gate);
619    OpCode op = GetOpCode(frameState);
620    if (op == OpCode::FRAME_ARGS) {
621        return frameState;
622    }
623    if (op == OpCode::FRAME_STATE) {
624        return GetValueIn(frameState, 0); // 0: frame args
625    }
626    return Circuit::NullGate();
627}
628
629void GateAccessor::UpdateMethodOffset(GateRef gate, uint32_t methodOffset)
630{
631    ASSERT(GetOpCode(gate) == OpCode::FRAME_ARGS);
632    Gate *gatePtr = circuit_->LoadGatePtr(gate);
633    UInt32PairAccessor accessor(methodOffset, 0);
634    const_cast<OneParameterMetaData *>(gatePtr->GetOneParameterMetaData())->SetValue(accessor.ToValue());
635}
636
637PGOTypeRef GateAccessor::TryGetPGOType(GateRef gate) const
638{
639    Gate *gatePtr = circuit_->LoadGatePtr(gate);
640    OpCode op = GetOpCode(gate);
641    if (op == OpCode::JS_BYTECODE) {
642        return gatePtr->GetJSBytecodeMetaData()->GetType();
643    }
644    return PGOTypeRef::NoneType();
645}
646
647void GateAccessor::TrySetPGOType(GateRef gate, PGOTypeRef type)
648{
649    Gate *gatePtr = circuit_->LoadGatePtr(gate);
650    OpCode op = GetOpCode(gate);
651    if (op == OpCode::JS_BYTECODE) {
652        const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetType(type);
653    }
654}
655
656uint32_t GateAccessor::TryGetArrayElementsLength(GateRef gate) const
657{
658    Gate *gatePtr = circuit_->LoadGatePtr(gate);
659    OpCode op = GetOpCode(gate);
660    if (op == OpCode::JS_BYTECODE) {
661        return gatePtr->GetJSBytecodeMetaData()->GetElementsLength();
662    }
663    return 0;
664}
665
666void GateAccessor::TrySetArrayElementsLength(GateRef gate, uint32_t length)
667{
668    Gate *gatePtr = circuit_->LoadGatePtr(gate);
669    OpCode op = GetOpCode(gate);
670    if (op == OpCode::JS_BYTECODE) {
671        const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetElementsLength(length);
672    }
673}
674
675RegionSpaceFlag GateAccessor::TryGetRegionSpaceFlag(GateRef gate) const
676{
677    Gate *gatePtr = circuit_->LoadGatePtr(gate);
678    OpCode op = GetOpCode(gate);
679    if (op == OpCode::JS_BYTECODE) {
680        return gatePtr->GetJSBytecodeMetaData()->GetRegionSpaceFlag();
681    }
682    return RegionSpaceFlag::IN_YOUNG_SPACE;
683}
684
685void GateAccessor::TrySetRegionSpaceFlag(GateRef gate, RegionSpaceFlag flag)
686{
687    Gate *gatePtr = circuit_->LoadGatePtr(gate);
688    OpCode op = GetOpCode(gate);
689    if (op == OpCode::JS_BYTECODE) {
690        const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetRegionSpaceFlag(flag);
691    }
692}
693
694ElementsKind GateAccessor::TryGetElementsKind(GateRef gate) const
695{
696    Gate *gatePtr = circuit_->LoadGatePtr(gate);
697    OpCode op = GetOpCode(gate);
698    if (op == OpCode::JS_BYTECODE) {
699        return Elements::FixElementsKind(gatePtr->GetJSBytecodeMetaData()->GetElementsKind());
700    }
701    return ElementsKind::GENERIC;
702}
703
704// Default is getting elementsKind before possible transition
705ElementsKind GateAccessor::TryGetArrayElementsKind(GateRef gate) const
706{
707    Gate *gatePtr = circuit_->LoadGatePtr(gate);
708    OpCode op = GetOpCode(gate);
709    if (op == OpCode::JS_BYTECODE) {
710        ElementsKind kind = gatePtr->GetJSBytecodeMetaData()->GetElementsKind();
711        if (Elements::IsGeneric(kind)) {
712            return kind;
713        }
714        std::vector<ElementsKind> kinds = gatePtr->GetJSBytecodeMetaData()->GetElementsKinds();
715        for (auto &x : kinds) {
716            kind = Elements::MergeElementsKind(kind, x);
717        }
718        return kind;
719    }
720    return ElementsKind::GENERIC;
721}
722
723ElementsKind GateAccessor::TryGetArrayElementsKindAfterTransition(GateRef gate) const
724{
725    Gate *gatePtr = circuit_->LoadGatePtr(gate);
726    OpCode op = GetOpCode(gate);
727    if (op == OpCode::JS_BYTECODE) {
728        ElementsKind kind = gatePtr->GetJSBytecodeMetaData()->GetTransitionElementsKind();
729        if (Elements::IsGeneric(kind)) {
730            return kind;
731        }
732        std::vector<ElementsKind> kinds = gatePtr->GetJSBytecodeMetaData()->GetTransitionElementsKinds();
733        for (auto &x : kinds) {
734            kind = Elements::MergeElementsKind(kind, x);
735        }
736        return kind;
737    }
738    return ElementsKind::GENERIC;
739}
740
741void GateAccessor::TrySetElementsKind(GateRef gate, ElementsKind kind)
742{
743    Gate *gatePtr = circuit_->LoadGatePtr(gate);
744    OpCode op = GetOpCode(gate);
745    if (op == OpCode::JS_BYTECODE) {
746        const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetElementsKind(kind);
747    }
748}
749
750void GateAccessor::TrySetTransitionElementsKind(GateRef gate, ElementsKind kind)
751{
752    Gate *gatePtr = circuit_->LoadGatePtr(gate);
753    OpCode op = GetOpCode(gate);
754    if (op == OpCode::JS_BYTECODE) {
755        const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetTransitionElementsKind(kind);
756    }
757}
758
759void GateAccessor::TrySetOnHeapMode(GateRef gate, OnHeapMode onHeapMode) const
760{
761    Gate *gatePtr = circuit_->LoadGatePtr(gate);
762    OpCode op = GetOpCode(gate);
763    if (op == OpCode::JS_BYTECODE) {
764        const_cast<JSBytecodeMetaData *>(gatePtr->GetJSBytecodeMetaData())->SetOnHeapMode(onHeapMode);
765    }
766}
767
768OnHeapMode GateAccessor::TryGetOnHeapMode(GateRef gate) const
769{
770    Gate *gatePtr = circuit_->LoadGatePtr(gate);
771    OpCode op = GetOpCode(gate);
772    if (op == OpCode::JS_BYTECODE) {
773        return gatePtr->GetJSBytecodeMetaData()->GetOnHeapMode();
774    }
775    return OnHeapMode::NONE;
776}
777
778EcmaOpcode GateAccessor::GetByteCodeOpcode(GateRef gate) const
779{
780    ASSERT(GetOpCode(gate) == OpCode::JS_BYTECODE);
781    Gate *gatePtr = circuit_->LoadGatePtr(gate);
782    return gatePtr->GetJSBytecodeMetaData()->GetByteCodeOpcode();
783}
784
785void GateAccessor::Print(GateRef gate) const
786{
787    Gate *gatePtr = circuit_->LoadGatePtr(gate);
788    auto comment = circuit_->GetComment(gate);
789    gatePtr->Print("", false, -1, comment);
790}
791
792std::string GateAccessor::ToString(GateRef gate) const
793{
794    Gate *gatePtr = circuit_->LoadGatePtr(gate);
795    return gatePtr->ToString();
796}
797
798#ifndef NDEBUG
799void GateAccessor::PrintById(size_t id) const
800{
801    GateRef gate = circuit_->GetGateRefById(id);
802    if (gate != Circuit::NullGate()) {
803        Gate *gatePtr = circuit_->LoadGatePtr(gate);
804        gatePtr->PrintWithBytecode(circuit_->GetComment(gate));
805    } else {
806        LOG_COMPILER(INFO) << "id overflow!";
807    }
808}
809#endif
810
811void GateAccessor::PrintWithBytecode(GateRef gate) const
812{
813    Gate *gatePtr = circuit_->LoadGatePtr(gate);
814    gatePtr->PrintWithBytecode(circuit_->GetComment(gate));
815}
816
817void GateAccessor::ShortPrint(GateRef gate) const
818{
819    Gate *gatePtr = circuit_->LoadGatePtr(gate);
820    gatePtr->ShortPrint();
821}
822
823GateId GateAccessor::GetId(GateRef gate) const
824{
825    Gate *gatePtr = circuit_->LoadGatePtr(gate);
826    return gatePtr->GetId();
827}
828
829size_t GateAccessor::GetInValueStarts(GateRef gate) const
830{
831    Gate *gatePtr = circuit_->LoadGatePtr(gate);
832    return gatePtr->GetInValueStarts();
833}
834
835GateRef GateAccessor::GetValueIn(GateRef gate, size_t idx) const
836{
837    Gate *gatePtr = circuit_->LoadGatePtr(gate);
838    ASSERT(idx < gatePtr->GetInValueCount());
839    size_t valueIndex = gatePtr->GetInValueStarts();
840    return circuit_->GetIn(gate, valueIndex + idx);
841}
842
843size_t GateAccessor::GetNumValueIn(GateRef gate) const
844{
845    Gate *gatePtr = circuit_->LoadGatePtr(gate);
846    return gatePtr->GetInValueCount();
847}
848
849std::vector<GateRef> GateAccessor::GetValueIns(GateRef gate) const
850{
851    size_t num = GetNumValueIn(gate);
852    std::vector<GateRef> valueIns(num);
853    for (size_t i = 0; i < num; ++i) {
854        valueIns[i] = GetValueIn(gate, i);
855    }
856    return valueIns;
857}
858
859bool GateAccessor::IsGCRelated(GateRef gate) const
860{
861    return GetGateType(gate).IsGCRelated();
862}
863
864GateRef GateAccessor::GetIn(GateRef gate, size_t idx) const
865{
866    return circuit_->GetIn(gate, idx);
867}
868
869GateRef GateAccessor::GetState(GateRef gate, size_t idx) const
870{
871    ASSERT(idx < circuit_->LoadGatePtr(gate)->GetStateCount());
872    return circuit_->GetIn(gate, idx);
873}
874
875void GateAccessor::GetInStates(GateRef gate, std::vector<GateRef>& ins) const
876{
877    const Gate *curGate = circuit_->LoadGatePtrConst(gate);
878    for (size_t idx = 0; idx < curGate->GetStateCount(); idx++) {
879        ins.push_back(circuit_->GetGateRef(curGate->GetInGateConst(idx)));
880    }
881}
882
883void GateAccessor::GetIns(GateRef gate, std::vector<GateRef>& ins) const
884{
885    const Gate *curGate = circuit_->LoadGatePtrConst(gate);
886    for (size_t idx = 0; idx < curGate->GetNumIns(); idx++) {
887        ins.push_back(circuit_->GetGateRef(curGate->GetInGateConst(idx)));
888    }
889}
890
891void GateAccessor::GetOuts(GateRef gate, std::vector<GateRef>& outs) const
892{
893    const Gate *curGate = circuit_->LoadGatePtrConst(gate);
894    if (!curGate->IsFirstOutNull()) {
895        const Out *curOut = curGate->GetFirstOutConst();
896        GateRef ref = circuit_->GetGateRef(curOut->GetGateConst());
897        outs.push_back(ref);
898        while (!curOut->IsNextOutNull()) {
899            curOut = curOut->GetNextOutConst();
900            ref = circuit_->GetGateRef(curOut->GetGateConst());
901            outs.push_back(ref);
902        }
903    }
904}
905
906bool GateAccessor::HasOuts(GateRef gate) const
907{
908    const Gate *curGate = circuit_->LoadGatePtrConst(gate);
909    return !curGate->IsFirstOutNull();
910}
911
912void GateAccessor::DeleteGateIfNoUse(GateRef gate)
913{
914    if (!HasOuts(gate)) {
915        DeleteGate(gate);
916    }
917}
918
919void GateAccessor::GetOutStates(GateRef gate, std::vector<GateRef>& outStates) const
920{
921    const Gate *curGate = circuit_->LoadGatePtrConst(gate);
922    if (!curGate->IsFirstOutNull()) {
923        const Out *curOut = curGate->GetFirstOutConst();
924        GateRef ref = circuit_->GetGateRef(curOut->GetGateConst());
925        if (GetMetaData(ref)->IsState()) {
926            outStates.push_back(ref);
927        }
928        while (!curOut->IsNextOutNull()) {
929            curOut = curOut->GetNextOutConst();
930            ref = circuit_->GetGateRef(curOut->GetGateConst());
931            if (GetMetaData(ref)->IsState()) {
932                outStates.push_back(ref);
933            }
934        }
935    }
936}
937
938void GateAccessor::GetStateUses(GateRef gate, std::vector<GateRef> &stateUses)
939{
940    stateUses.clear();
941    auto uses = Uses(gate);
942    for (auto it = uses.begin(); it != uses.end(); it++) {
943        if (IsStateIn(it)) {
944            stateUses.emplace_back(*it);
945        }
946    }
947}
948
949void GateAccessor::GetDependUses(GateRef gate, std::vector<GateRef> &dependUses)
950{
951    dependUses.clear();
952    auto uses = Uses(gate);
953    for (auto it = uses.begin(); it != uses.end(); it++) {
954        if (IsDependIn(it)) {
955            dependUses.emplace_back(*it);
956        }
957    }
958}
959
960void GateAccessor::GetValueUses(GateRef gate, std::vector<GateRef> &valueUses)
961{
962    valueUses.clear();
963    auto uses = Uses(gate);
964    for (auto it = uses.begin(); it != uses.end(); it++) {
965        if (IsValueIn(it)) {
966            valueUses.emplace_back(*it);
967        }
968    }
969}
970
971size_t GateAccessor::GetValueUsesCount(GateRef gate)
972{
973    size_t count = 0;
974    auto uses = Uses(gate);
975    for (auto it = uses.begin(); it != uses.end(); it++) {
976        if (IsValueIn(it)) {
977            count++;
978        }
979    }
980    return count;
981}
982
983void GateAccessor::GetAllGates(std::vector<GateRef>& gates) const
984{
985    circuit_->GetAllGates(gates);
986}
987
988bool GateAccessor::IsInGateNull(GateRef gate, size_t idx) const
989{
990    return circuit_->IsInGateNull(gate, idx);
991}
992
993bool GateAccessor::IsValueSelector(GateRef g) const
994{
995    return GetOpCode(g) == OpCode::VALUE_SELECTOR;
996}
997
998bool GateAccessor::IsSelector(GateRef g) const
999{
1000    auto op = GetOpCode(g);
1001    return (op == OpCode::VALUE_SELECTOR) || (op == OpCode::DEPEND_SELECTOR);
1002}
1003
1004bool GateAccessor::IsFrameValues(GateRef g) const
1005{
1006    auto op = GetOpCode(g);
1007    return op == OpCode::FRAME_VALUES;
1008}
1009
1010bool GateAccessor::IsIn(GateRef g, GateRef in) const
1011{
1012    size_t n = GetNumIns(g);
1013    for (size_t id = 0; id < n; id++) {
1014        GateRef i = GetIn(g, id);
1015        if (i == in) {
1016            return true;
1017        }
1018    }
1019    return false;
1020}
1021
1022bool GateAccessor::IsSimpleState(GateRef g) const
1023{
1024    auto op = GetOpCode(g);
1025    return (op == OpCode::IF_TRUE ||
1026            op == OpCode::IF_FALSE ||
1027            op == OpCode::SWITCH_CASE ||
1028            op == OpCode::DEFAULT_CASE ||
1029            op == OpCode::LOOP_BACK ||
1030            op == OpCode::MERGE ||
1031            op == OpCode::VALUE_SELECTOR ||
1032            op == OpCode::DEPEND_SELECTOR ||
1033            op == OpCode::DEPEND_RELAY ||
1034            op == OpCode::ORDINARY_BLOCK);
1035}
1036
1037bool GateAccessor::IsControlCase(GateRef gate) const
1038{
1039    return circuit_->IsControlCase(gate);
1040}
1041
1042bool GateAccessor::IsLoopExit(GateRef gate) const
1043{
1044    return (GetOpCode(gate) == OpCode::LOOP_EXIT);
1045}
1046
1047bool GateAccessor::IsLoopExitRelated(GateRef gate) const
1048{
1049    return (GetOpCode(gate) == OpCode::LOOP_EXIT) ||
1050           (GetOpCode(gate) == OpCode::LOOP_EXIT_DEPEND) ||
1051           (GetOpCode(gate) == OpCode::LOOP_EXIT_VALUE);
1052}
1053
1054bool GateAccessor::IsLoopHead(GateRef gate) const
1055{
1056    return circuit_->IsLoopHead(gate);
1057}
1058
1059bool GateAccessor::IsLoopBack(GateRef gate) const
1060{
1061    return GetOpCode(gate) == OpCode::LOOP_BACK;
1062}
1063
1064bool GateAccessor::IsState(GateRef gate) const
1065{
1066    return GetMetaData(gate)->IsState();
1067}
1068
1069bool GateAccessor::IsConstant(GateRef gate) const
1070{
1071    return GetMetaData(gate)->IsConstant();
1072}
1073
1074bool GateAccessor::IsDependSelector(GateRef gate) const
1075{
1076    return GetMetaData(gate)->IsDependSelector();
1077}
1078
1079bool GateAccessor::IsConstantValue(GateRef gate, uint64_t value) const
1080{
1081    if (GetOpCode(gate) == OpCode::CONSTANT) {
1082        uint64_t bitField = GetConstantValue(gate);
1083        return bitField == value;
1084    }
1085    return false;
1086}
1087
1088bool GateAccessor::IsConstantTaggedValue(GateRef gate, uint64_t value) const
1089{
1090    if (GetMachineType(gate) != MachineType::I64 || GetGateType(gate).IsNJSValueType()) {
1091        return false;
1092    }
1093    if (GetOpCode(gate) == OpCode::CONSTANT) {
1094        uint64_t bitField = GetConstantValue(gate);
1095        return bitField == value;
1096    }
1097    return false;
1098}
1099
1100bool GateAccessor::IsConstantUndefined(GateRef gate) const
1101{
1102    return IsConstantTaggedValue(gate, JSTaggedValue::VALUE_UNDEFINED);
1103}
1104
1105bool GateAccessor::IsUndefinedOrNullOrHole(GateRef gate) const
1106{
1107    return IsConstantTaggedValue(gate, JSTaggedValue::VALUE_UNDEFINED) ||
1108           IsConstantTaggedValue(gate, JSTaggedValue::VALUE_NULL) ||
1109           IsConstantTaggedValue(gate, JSTaggedValue::VALUE_HOLE);
1110}
1111
1112bool GateAccessor::IsTypedOperator(GateRef gate) const
1113{
1114    return GetMetaData(gate)->IsTypedOperator();
1115}
1116
1117bool GateAccessor::IsNotWrite(GateRef gate) const
1118{
1119    return GetMetaData(gate)->IsNotWrite();
1120}
1121
1122bool GateAccessor::IsCheckWithTwoIns(GateRef gate) const
1123{
1124    return GetMetaData(gate)->IsCheckWithTwoIns();
1125}
1126
1127bool GateAccessor::IsCheckWithOneIn(GateRef gate) const
1128{
1129    return GetMetaData(gate)->IsCheckWithOneIn();
1130}
1131
1132bool GateAccessor::IsSchedulable(GateRef gate) const
1133{
1134    return GetMetaData(gate)->IsSchedulable();
1135}
1136
1137bool GateAccessor::IsVirtualState(GateRef gate) const
1138{
1139    return GetMetaData(gate)->IsVirtualState();
1140}
1141
1142bool GateAccessor::IsGeneralState(GateRef gate) const
1143{
1144    return GetMetaData(gate)->IsGeneralState();
1145}
1146
1147bool GateAccessor::IsIfOrSwitchRelated(GateRef gate) const
1148{
1149    return GetMetaData(gate)->IsIfOrSwitchRelated();
1150}
1151
1152GateRef GateAccessor::GetDep(GateRef gate, size_t idx) const
1153{
1154    Gate *gatePtr = circuit_->LoadGatePtr(gate);
1155    ASSERT(idx < gatePtr->GetDependCount());
1156    size_t dependIndex = gatePtr->GetStateCount();
1157    return circuit_->GetIn(gate, dependIndex + idx);
1158}
1159
1160size_t GateAccessor::GetImmediateId(GateRef gate) const
1161{
1162    Gate *gatePtr = circuit_->LoadGatePtr(gate);
1163    ASSERT(gatePtr->GetGateType() == GateType::NJSValue());
1164    ASSERT(gatePtr->GetOpCode() == OpCode::CONSTANT);
1165    ASSERT(gatePtr->GetMachineType() == MachineType::I64);
1166    size_t imm = gatePtr->GetOneParameterMetaData()->GetValue();
1167    return imm;
1168}
1169
1170void GateAccessor::SetDep(GateRef gate, GateRef depGate, size_t idx)
1171{
1172    Gate *gatePtr = circuit_->LoadGatePtr(gate);
1173    ASSERT(idx < gatePtr->GetDependCount());
1174    size_t dependIndex = gatePtr->GetStateCount();
1175    gatePtr->ModifyIn(dependIndex + idx, circuit_->LoadGatePtr(depGate));
1176}
1177
1178UseIterator GateAccessor::ReplaceIn(const UseIterator &useIt, GateRef replaceGate)
1179{
1180    UseIterator next = useIt;
1181    next++;
1182    Gate *curGatePtr = circuit_->LoadGatePtr(*useIt);
1183    Gate *replaceGatePtr = circuit_->LoadGatePtr(replaceGate);
1184    curGatePtr->ModifyIn(useIt.GetIndex(), replaceGatePtr);
1185    return next;
1186}
1187
1188GateType GateAccessor::GetGateType(GateRef gate) const
1189{
1190    return circuit_->LoadGatePtr(gate)->GetGateType();
1191}
1192
1193void GateAccessor::SetGateType(GateRef gate, GateType gt)
1194{
1195    circuit_->LoadGatePtr(gate)->SetGateType(gt);
1196}
1197
1198UseIterator GateAccessor::ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state)
1199{
1200    ASSERT(GetOpCode(*useIt) == OpCode::IF_SUCCESS);
1201    auto uses = Uses(*useIt);
1202    for (auto it = uses.begin(); it != uses.end();) {
1203        if (IsStateIn(it)) {
1204            it = ReplaceIn(it, state);
1205        }
1206    }
1207    auto next = DeleteGate(useIt);
1208    return next;
1209}
1210
1211UseIterator GateAccessor::ReplaceHirIfException(const UseIterator &useIt, StateDepend replacement)
1212{
1213    ASSERT(GetOpCode(*useIt) == OpCode::IF_EXCEPTION);
1214    auto uses = Uses(*useIt);
1215    for (auto it = uses.begin(); it != uses.end();) {
1216        if (IsStateIn(it)) {
1217            it = ReplaceIn(it, replacement.State());
1218        } else if (IsDependIn(it)) {
1219            it = ReplaceIn(it, replacement.Depend());
1220        } else {
1221            ASSERT(!IsValueIn(it));
1222        }
1223    }
1224    UseIterator next = useIt;
1225    next++;
1226    return next;
1227}
1228
1229void GateAccessor::ExceptionReturn(GateRef state, GateRef depend)
1230{
1231    CircuitBuilder builder(circuit_);
1232    auto constant = builder.ExceptionConstant();
1233    builder.Return(state, depend, constant);
1234}
1235
1236void GateAccessor::ReplaceHirWithIfBranch(GateRef hirGate, StateDepend success,
1237                                          StateDepend exception, GateRef value)
1238{
1239    auto uses = Uses(hirGate);
1240    GateRef ifException = Circuit::NullGate();
1241    for (auto it = uses.begin(); it != uses.end();) {
1242        if (IsStateIn(it)) {
1243            const OpCode op = GetOpCode(*it);
1244            if (op == OpCode::IF_SUCCESS) {
1245                it = ReplaceHirIfSuccess(it, success.State());
1246            } else if (op == OpCode::IF_EXCEPTION) {
1247                ifException = *it;
1248                it = ReplaceHirIfException(it, exception);
1249            } else if (GetMetaData(*it)->IsVirtualState()) {
1250                it = ReplaceIn(it, success.State());
1251            } else {
1252                ExceptionReturn(exception.State(), exception.Depend());
1253                it = ReplaceIn(it, success.State());
1254            }
1255        } else if (IsDependIn(it)) {
1256            const OpCode op = GetOpCode(*it);
1257            if (op == OpCode::IF_EXCEPTION) {
1258                // ignore it now.
1259                it++;
1260            } else {
1261                it = ReplaceIn(it, success.Depend());
1262            }
1263        } else {
1264            ASSERT(IsValueIn(it));
1265            it = ReplaceIn(it, value);
1266        }
1267    }
1268
1269    if (ifException != Circuit::NullGate()) {
1270        DeleteGate(ifException);
1271    }
1272
1273    // delete old gate
1274    DeleteGate(hirGate);
1275}
1276
1277void GateAccessor::ReplaceHirDirectly(GateRef hirGate,
1278    StateDepend replacement, GateRef value)
1279{
1280    auto uses = Uses(hirGate);
1281    for (auto it = uses.begin(); it != uses.end();) {
1282        if (IsStateIn(it)) {
1283            ASSERT(GetOpCode(*it) != OpCode::IF_SUCCESS &&
1284                GetOpCode(*it) != OpCode::IF_EXCEPTION);
1285            it = ReplaceIn(it, replacement.State());
1286        } else if (IsDependIn(it)) {
1287            it = ReplaceIn(it, replacement.Depend());
1288        } else {
1289            ASSERT(IsValueIn(it));
1290            it = ReplaceIn(it, value);
1291        }
1292    }
1293
1294    // delete old gate
1295    DeleteGate(hirGate);
1296}
1297
1298void GateAccessor::ReplaceHirAndDeleteIfException(GateRef hirGate,
1299    StateDepend replacement, GateRef value)
1300{
1301    if (value != Circuit::NullGate()) {
1302        auto type = GetGateType(hirGate);
1303        if (!type.IsAnyType()) {
1304            SetGateType(value, type);
1305        }
1306    }
1307    GateRef ifException = Circuit::NullGate();
1308    auto uses = Uses(hirGate);
1309    for (auto it = uses.begin(); it != uses.end();) {
1310        if (IsStateIn(it)) {
1311            const OpCode op = GetOpCode(*it);
1312            if (op == OpCode::IF_SUCCESS) {
1313                it = ReplaceHirIfSuccess(it, replacement.State());
1314            } else if (op == OpCode::IF_EXCEPTION) {
1315                ifException = *it;
1316                it = ReplaceIn(it, circuit_->DeadGate());
1317            } else {
1318                it = ReplaceIn(it, replacement.State());
1319            }
1320        } else if (IsDependIn(it)) {
1321            const OpCode op = GetOpCode(*it);
1322            if (op == OpCode::IF_EXCEPTION) {
1323                it = ReplaceIn(it, circuit_->DeadGate());
1324            } else {
1325                it = ReplaceIn(it, replacement.Depend());
1326            }
1327        } else {
1328            ASSERT(IsValueIn(it));
1329            it = ReplaceIn(it, value);
1330        }
1331    }
1332
1333    // delete old gate
1334    DeleteGate(hirGate);
1335    if (ifException != Circuit::NullGate()) {
1336        ReplaceGate(ifException, circuit_->DeadGate());
1337    }
1338    #ifndef NDEBUG
1339        GetCircuit()->AddComment(value,  "old V " + std::to_string(GetId(hirGate)));
1340        GetCircuit()->AddComment(replacement.Depend(),  "old D " + std::to_string(GetId(hirGate)));
1341    #endif
1342}
1343
1344UseIterator GateAccessor::DeleteGate(const UseIterator &useIt)
1345{
1346    auto next = useIt;
1347    next++;
1348    circuit_->DeleteGate(*useIt);
1349    return next;
1350}
1351
1352void GateAccessor::DecreaseIn(const UseIterator &useIt)
1353{
1354    size_t idx = useIt.GetIndex();
1355    circuit_->DecreaseIn(*useIt, idx);
1356}
1357
1358void GateAccessor::DecreaseIn(GateRef gate, size_t index)
1359{
1360    circuit_->DecreaseIn(gate, index);
1361}
1362
1363void GateAccessor::NewIn(GateRef gate, size_t idx, GateRef in)
1364{
1365    circuit_->NewIn(gate, idx, in);
1366}
1367
1368size_t GateAccessor::GetStateCount(GateRef gate) const
1369{
1370    return circuit_->LoadGatePtr(gate)->GetStateCount();
1371}
1372
1373size_t GateAccessor::GetDependCount(GateRef gate) const
1374{
1375    return circuit_->LoadGatePtr(gate)->GetDependCount();
1376}
1377
1378size_t GateAccessor::GetInValueCount(GateRef gate) const
1379{
1380    return circuit_->LoadGatePtr(gate)->GetInValueCount();
1381}
1382
1383void GateAccessor::UpdateAllUses(GateRef oldIn, GateRef newIn)
1384{
1385    if (oldIn == newIn) {
1386        return;
1387    }
1388    auto uses = Uses(oldIn);
1389    for (auto useIt = uses.begin(); useIt != uses.end();) {
1390        useIt = ReplaceIn(useIt, newIn);
1391    }
1392}
1393
1394void GateAccessor::ReplaceIn(GateRef gate, size_t index, GateRef in)
1395{
1396    circuit_->ModifyIn(gate, index, in);
1397}
1398
1399void GateAccessor::DeleteIn(GateRef gate, size_t idx)
1400{
1401    ASSERT(idx < circuit_->LoadGatePtrConst(gate)->GetNumIns());
1402    ASSERT(!circuit_->IsInGateNull(gate, idx));
1403    circuit_->LoadGatePtr(gate)->DeleteIn(idx);
1404}
1405
1406void GateAccessor::ReplaceStateIn(GateRef gate, GateRef in, size_t index)
1407{
1408    ASSERT(index < GetStateCount(gate));
1409    circuit_->ModifyIn(gate, index, in);
1410}
1411
1412void GateAccessor::ReplaceDependIn(GateRef gate, GateRef in, size_t index)
1413{
1414    ASSERT(index < GetDependCount(gate));
1415    size_t stateCount = GetStateCount(gate);
1416    circuit_->ModifyIn(gate, stateCount + index, in);
1417}
1418
1419void GateAccessor::ReplaceOrNewDependIn(GateRef gate, GateRef in, size_t index)
1420{
1421    ASSERT(index < GetDependCount(gate));
1422    size_t stateCount = GetStateCount(gate);
1423    auto depend = GetDep(gate);
1424    if (depend == Circuit::NullGate()) {
1425        circuit_->NewIn(gate, stateCount + index, in);
1426    } else {
1427        circuit_->ModifyIn(gate, stateCount + index, in);
1428    }
1429}
1430
1431void GateAccessor::ReplaceValueIn(GateRef gate, GateRef in, size_t index)
1432{
1433    ASSERT(index < GetInValueCount(gate));
1434    size_t valueStartIndex = GetInValueStarts(gate);
1435    circuit_->ModifyIn(gate, valueStartIndex + index, in);
1436}
1437
1438void GateAccessor::DeleteGate(GateRef gate)
1439{
1440    circuit_->DeleteGate(gate);
1441}
1442
1443MachineType GateAccessor::GetMachineType(GateRef gate) const
1444{
1445    return circuit_->GetMachineType(gate);
1446}
1447
1448void GateAccessor::SetMachineType(GateRef gate, MachineType type)
1449{
1450    circuit_->SetMachineType(gate, type);
1451}
1452
1453GateRef GateAccessor::GetConstantGate(MachineType bitValue, BitField bitfield, GateType type) const
1454{
1455    return circuit_->GetConstantGate(bitValue, bitfield, type);
1456}
1457
1458GateRef GateAccessor::GetInitialEnvGate(GateRef depend, GateRef jsFunc) const
1459{
1460    return circuit_->GetInitialEnvGate(depend, jsFunc);
1461}
1462
1463bool GateAccessor::IsConstantNumber(GateRef gate) const
1464{
1465    DISALLOW_GARBAGE_COLLECTION;
1466    if (GetGateType(gate).IsNJSValueType() ||
1467        (GetOpCode(gate) != OpCode::CONSTANT)) {
1468        return false;
1469    }
1470    JSTaggedValue value(GetConstantValue(gate));
1471    return value.IsNumber();
1472}
1473
1474double GateAccessor::GetFloat64FromConstant(GateRef gate) const
1475{
1476    DISALLOW_GARBAGE_COLLECTION;
1477    ASSERT(GetOpCode(gate) == OpCode::CONSTANT);
1478    uint64_t rawValue = GetConstantValue(gate);
1479    if (GetGateType(gate).IsNJSValueType()) {
1480        ASSERT(GetMachineType(gate) == MachineType::F64);
1481        return base::bit_cast<double>(rawValue);
1482    }
1483    JSTaggedValue value(rawValue);
1484    return value.GetDouble();
1485}
1486
1487int GateAccessor::GetInt32FromConstant(GateRef gate) const
1488{
1489    DISALLOW_GARBAGE_COLLECTION;
1490    ASSERT(GetOpCode(gate) == OpCode::CONSTANT);
1491    uint64_t rawValue = GetConstantValue(gate);
1492    if (GetGateType(gate).IsNJSValueType()) {
1493        ASSERT(GetMachineType(gate) == MachineType::I32);
1494        return static_cast<int>(rawValue);
1495    }
1496    JSTaggedValue value(rawValue);
1497    return value.GetInt();
1498}
1499
1500bool GateAccessor::IsStateIn(const UseIterator &useIt) const
1501{
1502    size_t stateStartIndex = 0;
1503    size_t stateEndIndex = stateStartIndex + GetStateCount(*useIt);
1504    size_t index = useIt.GetIndex();
1505    return (index >= stateStartIndex && index < stateEndIndex);
1506}
1507
1508bool GateAccessor::IsDependIn(const UseIterator &useIt) const
1509{
1510    size_t dependStartIndex = GetStateCount(*useIt);
1511    size_t dependEndIndex = dependStartIndex + GetDependCount(*useIt);
1512    size_t index = useIt.GetIndex();
1513    return (index >= dependStartIndex && index < dependEndIndex);
1514}
1515
1516bool GateAccessor::IsValueIn(const UseIterator &useIt) const
1517{
1518    size_t valueStartIndex = GetInValueStarts(*useIt);
1519    size_t valueEndIndex = valueStartIndex + GetInValueCount(*useIt);
1520    size_t index = useIt.GetIndex();
1521    return (index >= valueStartIndex && index < valueEndIndex);
1522}
1523
1524bool GateAccessor::IsFrameStateIn(const UseIterator &useIt) const
1525{
1526    size_t index = useIt.GetIndex();
1527    return IsFrameStateIn(*useIt, index);
1528}
1529
1530bool GateAccessor::IsStateIn(GateRef gate, size_t index) const
1531{
1532    size_t stateStartIndex = 0;
1533    size_t stateEndIndex = stateStartIndex + GetStateCount(gate);
1534    return (index >= stateStartIndex && index < stateEndIndex);
1535}
1536
1537bool GateAccessor::IsDependIn(GateRef gate, size_t index) const
1538{
1539    size_t dependStartIndex = GetStateCount(gate);
1540    size_t dependEndIndex = dependStartIndex + GetDependCount(gate);
1541    return (index >= dependStartIndex && index < dependEndIndex);
1542}
1543
1544bool GateAccessor::IsValueIn(GateRef gate, size_t index) const
1545{
1546    size_t valueStartIndex = GetInValueStarts(gate);
1547    size_t valueEndIndex = valueStartIndex + GetInValueCount(gate);
1548    return (index >= valueStartIndex && index < valueEndIndex);
1549}
1550
1551bool GateAccessor::IsFrameStateIn(GateRef gate, size_t index) const
1552{
1553    Gate *gatePtr = circuit_->LoadGatePtr(gate);
1554    size_t frameStateStartIndex = gatePtr->GetInFrameStateStarts();
1555    size_t FrameStateEndIndex = frameStateStartIndex + gatePtr->GetInFrameStateCount();
1556    return (index >= frameStateStartIndex && index < FrameStateEndIndex);
1557}
1558
1559void GateAccessor::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value)
1560{
1561    if (value != Circuit::NullGate()) {
1562        GateType type = GetGateType(gate);
1563        GateType valueType = GetGateType(value);
1564        if (!type.IsAnyType() && !valueType.IsNJSValueType()) {
1565            SetGateType(value, type);
1566        }
1567    }
1568
1569    auto uses = Uses(gate);
1570    for (auto useIt = uses.begin(); useIt != uses.end();) {
1571        if (IsStateIn(useIt)) {
1572            ASSERT(state != Circuit::NullGate());
1573            useIt = ReplaceIn(useIt, state);
1574        } else if (IsDependIn(useIt)) {
1575            ASSERT(depend != Circuit::NullGate());
1576            useIt = ReplaceIn(useIt, depend);
1577        } else if (IsValueIn(useIt)) {
1578            ASSERT(value != Circuit::NullGate());
1579            useIt = ReplaceIn(useIt, value);
1580        } else {
1581            LOG_ECMA(FATAL) << "this branch is unreachable";
1582            UNREACHABLE();
1583        }
1584    }
1585#ifndef NDEBUG
1586    GetCircuit()->AddComment(value,  "old V " + std::to_string(GetId(gate)));
1587#endif
1588    DeleteGate(gate);
1589}
1590
1591void GateAccessor::ReplaceGate(GateRef gate, GateRef replacement)
1592{
1593    GateRef depend = Circuit::NullGate();
1594    if (GetDependCount(gate) > 0) {
1595        ASSERT(GetDependCount(gate) == 1); // 1: one dep
1596        depend = GetDep(gate);
1597    }
1598    GateRef state = Circuit::NullGate();
1599    if (GetStateCount(gate) > 0) {
1600        ASSERT(GetStateCount(gate) == 1);  // 1: one state
1601        state = GetState(gate);
1602    }
1603    return ReplaceGate(gate, StateDepend {state, depend}, replacement);
1604}
1605
1606void GateAccessor::ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement)
1607{
1608    ASSERT(gate != replacement);
1609    auto state = stateDepend.State();
1610    auto depend = stateDepend.Depend();
1611    auto uses = Uses(gate);
1612    for (auto it = uses.begin(); it != uses.end();) {
1613        if (IsStateIn(it)) {
1614            ASSERT(state != Circuit::NullGate());
1615            it = ReplaceIn(it, state);
1616        } else if (IsDependIn(it)) {
1617            ASSERT(depend != Circuit::NullGate());
1618            it = ReplaceIn(it, depend);
1619        } else {
1620            it = ReplaceIn(it, replacement);
1621        }
1622    }
1623#ifndef NDEBUG
1624    GetCircuit()->AddComment(replacement,  "old V " + std::to_string(GetId(gate)));
1625#endif
1626    DeleteGate(gate);
1627}
1628
1629void GateAccessor::ReplaceControlGate(GateRef gate, GateRef newState)
1630{
1631    auto uses = Uses(gate);
1632    for (auto useIt = uses.begin(); useIt != uses.end();) {
1633        if (IsStateIn(useIt)) {
1634            OpCode opcode = GetOpCode(*useIt);
1635            if (opcode == OpCode::VALUE_SELECTOR || opcode == OpCode::DEPEND_SELECTOR) {
1636                useIt++;
1637            } else {
1638                useIt = ReplaceIn(useIt, newState);
1639            }
1640        } else {
1641            LOG_ECMA(FATAL) << "this branch is unreachable";
1642            UNREACHABLE();
1643        }
1644    }
1645    // Do not delete this gate
1646}
1647
1648// When Insert newGate, all the stateIn from state and dependIn from depend can be replaced to newGate
1649void GateAccessor::ReplaceInAfterInsert(GateRef state, GateRef depend, GateRef newGate)
1650{
1651    auto uses = Uses(state);
1652    for (auto useIt = uses.begin(); useIt != uses.end();) {
1653        if (IsStateIn(useIt) && (*useIt != newGate)) {
1654            ASSERT(newGate != Circuit::NullGate());
1655            // Exception, for example, IF_TRUE / IF_FALSE -> DEPEND_RELAY,
1656            // or LOOP_BEGIN / MERGE -> DEPEND_SELECTOR cannot be replaced
1657            if (!IsState(*useIt)) {
1658                useIt++;
1659                continue;
1660            }
1661            useIt = ReplaceIn(useIt, newGate);
1662        } else {
1663            useIt++;
1664        }
1665    }
1666
1667    uses = Uses(depend);
1668    for (auto useIt = uses.begin(); useIt != uses.end();) {
1669        if (IsDependIn(useIt) && (*useIt != newGate)) {
1670            ASSERT(newGate != Circuit::NullGate());
1671            useIt = ReplaceIn(useIt, newGate);
1672        } else {
1673            useIt++;
1674        }
1675    }
1676}
1677
1678// When loopExit, find stateSplit after DEPEND_SELECTOR
1679void GateAccessor::GetFrameStateDependIn(GateRef gate, GateRef &dependIn)
1680{
1681    auto uses = Uses(gate);
1682    size_t stateSplitCount = 0;
1683    GateRef stateSplit = Circuit::NullGate();
1684    for (auto it = uses.begin(); it != uses.end();) {
1685        if (GetOpCode(*it) == OpCode::STATE_SPLIT) {
1686            ASSERT(stateSplitCount < 1); // only one state Split;
1687            stateSplitCount++;
1688            stateSplit = *it;
1689            break;
1690        } else {
1691            ++it;
1692        }
1693    }
1694
1695    ASSERT(stateSplitCount <= 1);
1696    if (stateSplitCount == 1 && stateSplit != Circuit::NullGate()) {
1697        dependIn = stateSplit;
1698    }
1699}
1700
1701// When ifOp or loopExit, insertAfter
1702// stateIn: IF_TRUE / IF_FALSE / MERGE
1703// dependIn: DEPEND_RELAY / DEPEND_SELECTOR, if stateSplit follow closely, after the stateSplit.
1704
1705void GateAccessor::GetStateInAndDependIn(GateRef insertAfter, GateRef &stateIn, GateRef &dependIn)
1706{
1707    if (GetOpCode(insertAfter) == OpCode::IF_TRUE || GetOpCode(insertAfter) == OpCode::IF_FALSE
1708        || GetOpCode(insertAfter) == OpCode::IF_SUCCESS) {
1709        auto uses = Uses(insertAfter);
1710        for (auto it = uses.begin(); it != uses.end();) {
1711            if (GetOpCode(*it) == OpCode::DEPEND_RELAY) {
1712                stateIn = insertAfter;
1713                dependIn = (*it);
1714                break;
1715            } else {
1716                ++it;
1717            }
1718        }
1719    } else if (GetOpCode(insertAfter) == OpCode::MERGE) {
1720        auto uses = Uses(insertAfter);
1721        for (auto it = uses.begin(); it != uses.end();) {
1722            if (GetOpCode(*it) == OpCode::DEPEND_SELECTOR) {
1723                stateIn = insertAfter;
1724                dependIn = (*it);
1725                GetFrameStateDependIn(*it, dependIn);
1726                break;
1727            } else {
1728                ++it;
1729            }
1730        }
1731    }
1732    ASSERT(GetDependCount(dependIn) > 0);
1733}
1734
1735size_t GateAccessor::GetFrameDepth(GateRef gate, OpCode op)
1736{
1737    if (GetOpCode(gate) != op) {
1738        return 0;
1739    }
1740    size_t depth = 0;
1741    GateRef prev = GetFrameState(gate);
1742    while ((GetOpCode(prev) == op)) {
1743        depth++;
1744        prev = GetFrameState(prev);
1745    }
1746    return depth;
1747}
1748
1749GateRef GateAccessor::GetFrameState(GateRef gate) const
1750{
1751    ASSERT(HasFrameState(gate));
1752    Gate *gatePtr = circuit_->LoadGatePtr(gate);
1753    size_t index = gatePtr->GetInFrameStateStarts();
1754    return circuit_->GetIn(gate, index);
1755}
1756
1757GateRef GateAccessor::FindNearestFrameState(GateRef gate) const
1758{
1759    auto statesplit = FindNearestStateSplit(gate);
1760    return GetFrameState(statesplit);
1761}
1762
1763GateRef GateAccessor::FindNearestStateSplit(GateRef gate) const
1764{
1765    auto statesplit = gate;
1766    while (GetOpCode(statesplit) != OpCode::STATE_SPLIT) {
1767        statesplit = GetDep(statesplit);
1768    }
1769    return statesplit;
1770}
1771
1772bool GateAccessor::HasFrameState(GateRef gate) const
1773{
1774    return GetMetaData(gate)->HasFrameState();
1775}
1776
1777void GateAccessor::ReplaceFrameStateIn(GateRef gate, GateRef in)
1778{
1779    ASSERT(HasFrameState(gate));
1780    Gate *gatePtr = circuit_->LoadGatePtr(gate);
1781    size_t index = gatePtr->GetInFrameStateStarts();
1782    circuit_->ModifyIn(gate, index, in);
1783}
1784
1785GateRef GateAccessor::GetRoot(OpCode opcode) const
1786{
1787    GateRef root = circuit_->GetRoot();
1788    if (opcode == OpCode::CIRCUIT_ROOT) {
1789        return root;
1790    }
1791
1792    auto uses = ConstUses(root);
1793    for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
1794        if (GetOpCode(*useIt) == opcode) {
1795            return *useIt;
1796        }
1797    }
1798    return Circuit::NullGate();
1799}
1800
1801GateRef GateAccessor::GetGlueFromArgList() const
1802{
1803    auto argRoot = GetArgRoot();
1804    ASSERT(static_cast<size_t>(CommonArgIdx::GLUE) == 0);
1805    const Gate *curGate = circuit_->LoadGatePtrConst(argRoot);
1806
1807    const Out *curOut = curGate->GetFirstOutConst();
1808    ASSERT(!curGate->IsFirstOutNull());
1809    while (!curOut->IsNextOutNull()) {
1810        curOut = curOut->GetNextOutConst();
1811    }
1812    return circuit_->GetGateRef(curOut->GetGateConst());
1813}
1814
1815void GateAccessor::GetArgsOuts(std::vector<GateRef>& outs) const
1816{
1817    auto argRoot = GetArgRoot();
1818    GetOuts(argRoot, outs);
1819}
1820
1821void GateAccessor::GetReturnOuts(std::vector<GateRef>& outs) const
1822{
1823    auto returnRoot = GetReturnRoot();
1824    GetOuts(returnRoot, outs);
1825}
1826
1827const GateMetaData *GateAccessor::GetMetaData(GateRef gate) const
1828{
1829    return circuit_->LoadGatePtrConst(gate)->GetMetaData();
1830}
1831
1832void GateAccessor::SetMetaData(GateRef gate, const GateMetaData* meta)
1833{
1834    return circuit_->LoadGatePtr(gate)->SetMetaData(meta);
1835}
1836
1837bool GateAccessor::IsFixed(GateRef g) const
1838{
1839    return GetMetaData(g)->IsFixed();
1840}
1841
1842bool GateAccessor::IsProlog(GateRef g) const
1843{
1844    return GetMetaData(g)->IsProlog();
1845}
1846
1847bool GateAccessor::IsCFGMerge(GateRef g) const
1848{
1849    return GetMetaData(g)->IsCFGMerge();
1850}
1851
1852bool GateAccessor::MetaDataEqu(GateRef g1, GateRef g2) const
1853{
1854    return GetMetaData(g1) == GetMetaData(g2);
1855}
1856
1857bool GateAccessor::MetaDataValueEqu(GateRef g1, GateRef g2) const
1858{
1859    const GateMetaData *g1Meta = GetMetaData(g1);
1860    const GateMetaData *g2Meta = GetMetaData(g2);
1861
1862    return g1Meta->equal(*g2Meta);
1863}
1864
1865bool GateAccessor::IsNop(GateRef g) const
1866{
1867    return GetMetaData(g)->IsNop();
1868}
1869
1870bool GateAccessor::IsDead(GateRef gate) const
1871{
1872    return GetMetaData(gate)->IsDead();
1873}
1874
1875bool GateAccessor::IsRoot(GateRef g) const
1876{
1877    return GetMetaData(g)->IsRoot();
1878}
1879
1880const GateMetaData *ConstGateAccessor::GetMetaData(GateRef g) const
1881{
1882    return circuit_->LoadGatePtrConst(g)->GetMetaData();
1883}
1884
1885bool ConstGateAccessor::IsFixed(GateRef g) const
1886{
1887    return GetMetaData(g)->IsFixed();
1888}
1889
1890bool ConstGateAccessor::IsProlog(GateRef g) const
1891{
1892    return GetMetaData(g)->IsProlog();
1893}
1894
1895bool ConstGateAccessor::IsSchedulable(GateRef g) const
1896{
1897    return GetMetaData(g)->IsSchedulable();
1898}
1899
1900GateRef GateAccessor::GetDependSelectorFromMerge(GateRef gate)
1901{
1902    GateRef depend = Circuit::NullGate();
1903    auto uses = Uses(gate);
1904    for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
1905        if (GetOpCode(*useIt) == OpCode::DEPEND_SELECTOR) {
1906            depend = *useIt;
1907            break;
1908        }
1909    }
1910    ASSERT(depend != Circuit::NullGate());
1911    return depend;
1912}
1913
1914bool GateAccessor::HasIfExceptionUse(GateRef gate) const
1915{
1916    ASSERT(GetStateCount(gate) > 0);
1917    auto uses = ConstUses(gate);
1918    for (auto it = uses.begin(); it != uses.end(); it++) {
1919        if (GetOpCode(*it) == OpCode::IF_EXCEPTION) {
1920            return true;
1921        }
1922    }
1923    return false;
1924}
1925
1926bool GateAccessor::IsHeapObjectFromElementsKind(GateRef gate)
1927{
1928    OpCode opcode = GetOpCode(gate);
1929    if (opcode == OpCode::JS_BYTECODE) {
1930        auto bc = GetByteCodeOpcode(gate);
1931        if (bc == EcmaOpcode::LDOBJBYVALUE_IMM8_V8 || bc == EcmaOpcode::LDOBJBYVALUE_IMM16_V8 ||
1932            bc == EcmaOpcode::LDTHISBYVALUE_IMM8 || bc == EcmaOpcode::LDTHISBYVALUE_IMM16) {
1933            ElementsKind kind = TryGetElementsKind(gate);
1934            return Elements::IsObject(kind);
1935        }
1936        return false;
1937    }
1938
1939    if (opcode == OpCode::LOAD_ELEMENT) {
1940        TypedLoadOp typedOp = GetTypedLoadOp(gate);
1941        return typedOp == TypedLoadOp::ARRAY_LOAD_OBJECT_ELEMENT;
1942    }
1943
1944    return false;
1945}
1946
1947bool GateAccessor::IsConstString(GateRef gate)
1948{
1949    OpCode op = GetOpCode(gate);
1950    if (op == OpCode::JS_BYTECODE) {
1951        EcmaOpcode ecmaOpcode = GetByteCodeOpcode(gate);
1952        return ecmaOpcode == EcmaOpcode::LDA_STR_ID16;
1953    }
1954    return false;
1955}
1956
1957bool GateAccessor::IsSingleCharGate(GateRef gate)
1958{
1959    OpCode op = GetOpCode(gate);
1960    if (op == OpCode::LOAD_ELEMENT) {
1961        return GetTypedLoadOp(gate) == TypedLoadOp::STRING_LOAD_ELEMENT;
1962    }
1963    return false;
1964}
1965
1966bool GateAccessor::UseForTypeOpProfilerGate(GateRef gate) const
1967{
1968    OpCode op = GetOpCode(gate);
1969    switch (op) {
1970#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) \
1971        case OpCode::OP:                          \
1972            return true;
1973
1974    MCR_IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)
1975    MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE)
1976    MCR_GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE)
1977    MCR_GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_OPCODE)
1978    MCR_GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE)
1979    MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_OPCODE)
1980    MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(DECLARE_GATE_OPCODE)
1981#undef DECLARE_GATE_OPCODE
1982        default:
1983            return false;
1984    }
1985}
1986
1987uint32_t GateAccessor::GetStringIdFromLdaStrGate(GateRef gate)
1988{
1989    ASSERT(GetByteCodeOpcode(gate) == EcmaOpcode::LDA_STR_ID16);
1990    GateRef stringId = GetValueIn(gate, 0);
1991    return GetConstantValue(stringId);
1992}
1993
1994bool GateAccessor::IsLoopBackUse(GateRef gate, const UseIterator &useIt) const
1995{
1996    if (IsLoopBack(gate) && IsStateIn(useIt)) {
1997        return IsLoopHead(*useIt);
1998    }
1999    if ((IsValueSelector(*useIt) && IsValueIn(useIt)) ||
2000        (IsDependSelector(*useIt) && IsDependIn(useIt))) {
2001        return IsLoopHead(GetState(*useIt));
2002    }
2003    return false;
2004}
2005
2006bool GateAccessor::IsCreateArray(GateRef gate) const
2007{
2008    if (GetOpCode(gate) != OpCode::JS_BYTECODE) {
2009        return false;
2010    }
2011    EcmaOpcode ecmaop = GetByteCodeOpcode(gate);
2012    switch (ecmaop) {
2013        case EcmaOpcode::CREATEEMPTYARRAY_IMM8:
2014        case EcmaOpcode::CREATEEMPTYARRAY_IMM16:
2015        case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
2016        case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
2017            return true;
2018        default:
2019            return false;
2020    }
2021    UNREACHABLE();
2022    return false;
2023}
2024
2025void GateAccessor::SetStoreNoBarrier(GateRef gate, bool isNoBarrier)
2026{
2027    ASSERT(GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO ||
2028           GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY);
2029    Gate *gatePtr = circuit_->LoadGatePtr(gate);
2030    const_cast<BoolMetaData *>(gatePtr->GetBoolMetaData())->SetBool(isNoBarrier);
2031}
2032
2033bool GateAccessor::IsNoBarrier(GateRef gate) const
2034{
2035    ASSERT(GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO ||
2036           GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY);
2037    Gate *gatePtr = circuit_->LoadGatePtr(gate);
2038    return gatePtr->GetBoolMetaData()->GetBool();
2039}
2040
2041uint32_t GateAccessor::GetConstpoolId(GateRef gate) const
2042{
2043    ASSERT(GetOpCode(gate) == OpCode::GET_SHARED_CONSTPOOL);
2044    Gate *gatePtr = circuit_->LoadGatePtr(gate);
2045    return gatePtr->GetOneParameterMetaData()->GetValue();
2046}
2047
2048GateRef GateAccessor::GetFrameValue(GateRef gate)
2049{
2050    ASSERT(GetOpCode(gate) == OpCode::FRAME_STATE);
2051    return GetValueIn(gate, 1);
2052}
2053
2054TypedBinOp GateAccessor::GetRevCompareOpForTypedBinOp(TypedBinOp op)
2055{
2056    switch (op) {
2057        case TypedBinOp::TYPED_LESS:
2058            return TypedBinOp::TYPED_GREATEREQ;
2059        case TypedBinOp::TYPED_LESSEQ:
2060            return TypedBinOp::TYPED_GREATER;
2061        case TypedBinOp::TYPED_GREATER:
2062            return TypedBinOp::TYPED_LESSEQ;
2063        case TypedBinOp::TYPED_GREATEREQ:
2064            return TypedBinOp::TYPED_LESS;
2065        case TypedBinOp::TYPED_EQ:
2066            return TypedBinOp::TYPED_NOTEQ;
2067        case TypedBinOp::TYPED_NOTEQ:
2068            return TypedBinOp::TYPED_EQ;
2069        default:
2070            UNREACHABLE();
2071            return op;
2072    }
2073}
2074
2075TypedBinOp GateAccessor::GetSwapCompareOpForTypedBinOp(TypedBinOp op)
2076{
2077    switch (op) {
2078        case TypedBinOp::TYPED_LESS:
2079            return TypedBinOp::TYPED_GREATER;
2080        case TypedBinOp::TYPED_LESSEQ:
2081            return TypedBinOp::TYPED_GREATEREQ;
2082        case TypedBinOp::TYPED_GREATER:
2083            return TypedBinOp::TYPED_LESS;
2084        case TypedBinOp::TYPED_GREATEREQ:
2085            return TypedBinOp::TYPED_LESSEQ;
2086        case TypedBinOp::TYPED_EQ:
2087            return TypedBinOp::TYPED_EQ;
2088        case TypedBinOp::TYPED_NOTEQ:
2089            return TypedBinOp::TYPED_NOTEQ;
2090        default:
2091            UNREACHABLE();
2092            return op;
2093    }
2094}
2095}  // namespace panda::ecmascript::kungfu
2096