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