1 /*
2 * Copyright (c) 2023 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/early_elimination.h"
17
18 namespace panda::ecmascript::kungfu {
19
Initialize()20 void EarlyElimination::Initialize()
21 {
22 dependChains_.resize(circuit_->GetMaxGateId() + 1, nullptr); // 1: +1 for size
23 renames_.resize(circuit_->GetMaxGateId() + 1, Circuit::NullGate()); // 1: +1 for size
24 GateRef entry = acc_.GetDependRoot();
25 VisitDependEntry(entry);
26 }
27
GetLoopDependInfo(GateRef depend)28 DependInfoNode* EarlyElimination::GetLoopDependInfo(GateRef depend)
29 {
30 auto depIn = acc_.GetDep(depend);
31 auto dependChain = GetDependChain(depIn);
32 if (dependChain == nullptr) {
33 return nullptr;
34 }
35 auto newChain = new (chunk_) DependInfoNode(chunk_);
36 newChain->CopyFrom(dependChain);
37 ChunkSet<GateRef> visited(chunk_);
38 ChunkQueue<GateRef> workList(chunk_);
39 workList.push(depend);
40 visited.insert(acc_.GetDep(depend));
41 while (!workList.empty()) {
42 auto curDep = workList.front();
43 workList.pop();
44 if (visited.count(curDep)) {
45 continue;
46 }
47 if (!acc_.IsNotWrite(curDep)) {
48 newChain = UpdateWrite(curDep, newChain);
49 }
50 visited.insert(curDep);
51 auto depCount = acc_.GetDependCount(curDep);
52 for (size_t i = 0; i < depCount; ++i) {
53 workList.push(acc_.GetDep(curDep, i));
54 }
55 }
56 return newChain;
57 }
58
VisitDependEntry(GateRef gate)59 GateRef EarlyElimination::VisitDependEntry(GateRef gate)
60 {
61 auto empty = new (chunk_) DependInfoNode(chunk_);
62 return UpdateDependChain(gate, empty);
63 }
64
VisitGate(GateRef gate)65 GateRef EarlyElimination::VisitGate(GateRef gate)
66 {
67 auto opcode = acc_.GetOpCode(gate);
68 switch (opcode) {
69 case OpCode::LOAD_PROPERTY:
70 case OpCode::LOAD_ELEMENT:
71 case OpCode::LOAD_ARRAY_LENGTH:
72 case OpCode::LOAD_TYPED_ARRAY_LENGTH:
73 case OpCode::TYPED_ARRAY_CHECK:
74 case OpCode::OBJECT_TYPE_CHECK:
75 case OpCode::STABLE_ARRAY_CHECK:
76 case OpCode::INDEX_CHECK:
77 case OpCode::ELEMENTSKIND_CHECK:
78 case OpCode::TYPED_CALL_CHECK:
79 case OpCode::LOAD_CONST_OFFSET:
80 case OpCode::LOAD_HCLASS_CONST_OFFSET:
81 case OpCode::LOAD_HCLASS_FROM_CONSTPOOL:
82 case OpCode::TYPED_BINARY_OP:
83 case OpCode::TYPED_UNARY_OP:
84 case OpCode::JSINLINETARGET_TYPE_CHECK:
85 case OpCode::JSINLINETARGET_HEAPCONSTANT_CHECK:
86 case OpCode::PROTOTYPE_CHECK:
87 case OpCode::LOAD_GETTER:
88 case OpCode::LOAD_SETTER:
89 case OpCode::ECMA_STRING_CHECK:
90 case OpCode::INTERN_STRING_CHECK:
91 case OpCode::BUILTIN_INSTANCE_HCLASS_CHECK:
92 case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK:
93 case OpCode::TYPE_OF_CHECK:
94 case OpCode::TYPED_CONSTRUCTOR_CHECK:
95 case OpCode::ARRAY_CONSTRUCTOR_CHECK:
96 case OpCode::FLOAT32_ARRAY_CONSTRUCTOR_CHECK:
97 case OpCode::OBJECT_CONSTRUCTOR_CHECK:
98 case OpCode::BOOLEAN_CONSTRUCTOR_CHECK:
99 case OpCode::PROTO_CHANGE_MARKER_CHECK:
100 case OpCode::PRIMTYPE_PROTO_CHANGE_MARKER_CHECK:
101 case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
102 case OpCode::PRIMITIVE_TYPE_CHECK:
103 case OpCode::LOAD_BUILTIN_OBJECT:
104 case OpCode::LOOK_UP_HOLDER:
105 case OpCode::IS_CALLABLE_CHECK:
106 case OpCode::MATH_HCLASS_CONSISTENCY_CHECK:
107 return TryEliminateGate(gate);
108 case OpCode::STATE_SPLIT:
109 if (enableFrameStateElimination_) {
110 return TryEliminateFrameState(gate);
111 }
112 break;
113 case OpCode::DEPEND_SELECTOR:
114 return TryEliminateDependSelector(gate);
115 default:
116 if (acc_.GetDependCount(gate) == 1) { // 1: depend in is 1
117 return TryEliminateOther(gate);
118 }
119 break;
120 }
121 return Circuit::NullGate();
122 }
123
TryEliminateOther(GateRef gate)124 GateRef EarlyElimination::TryEliminateOther(GateRef gate)
125 {
126 ASSERT(acc_.GetDependCount(gate) >= 1);
127 auto depIn = acc_.GetDep(gate);
128 auto dependChain = GetDependChain(depIn);
129 if (dependChain == nullptr) {
130 return Circuit::NullGate();
131 }
132
133 if (!acc_.IsNotWrite(gate)) {
134 dependChain = UpdateWrite(gate, dependChain);
135 }
136
137 return UpdateDependChain(gate, dependChain);
138 }
139
TryEliminateGate(GateRef gate)140 GateRef EarlyElimination::TryEliminateGate(GateRef gate)
141 {
142 ASSERT(acc_.GetDependCount(gate) == 1);
143 auto depIn = acc_.GetDep(gate);
144 auto dependChain = GetDependChain(depIn);
145 // dependChain is null
146 if (dependChain == nullptr) {
147 return Circuit::NullGate();
148 }
149
150 if (!acc_.IsNotWrite(gate)) {
151 dependChain = UpdateWrite(gate, dependChain);
152 return UpdateDependChain(gate, dependChain);
153 }
154
155 auto numIns = acc_.GetNumValueIn(gate);
156 for (size_t i = 0; i < numIns; ++i) {
157 auto origin = acc_.GetValueIn(gate, i);
158 auto checkd = dependChain->LookupCheckedNode(this, origin);
159 if (origin != checkd) {
160 acc_.ReplaceValueIn(gate, checkd, i);
161 }
162 }
163
164 // lookup gate, replace
165 auto preGate = dependChain->LookupNode(this, gate);
166 if (preGate != Circuit::NullGate()) {
167 return preGate;
168 }
169 // update gate, for others elimination
170 dependChain = dependChain->UpdateNode(gate);
171 return UpdateDependChain(gate, dependChain);
172 }
173
TryEliminateFrameState(GateRef gate)174 GateRef EarlyElimination::TryEliminateFrameState(GateRef gate)
175 {
176 ASSERT(acc_.GetOpCode(gate) == OpCode::STATE_SPLIT);
177 auto depIn = acc_.GetDep(gate);
178 auto dependChain = GetDependChain(depIn);
179 // dependChain is null
180 if (dependChain == nullptr) {
181 return Circuit::NullGate();
182 }
183 // lookup gate, replace
184 auto preFrame = dependChain->LookupFrameState();
185 auto curFrame = acc_.GetFrameState(gate);
186 if ((preFrame != Circuit::NullGate()) && (preFrame != curFrame) &&
187 acc_.GetFrameState(preFrame) == acc_.GetFrameState(curFrame)) {
188 acc_.UpdateAllUses(curFrame, preFrame);
189 auto frameValues = acc_.GetValueIn(curFrame, 1); // 1: frameValues
190 acc_.DeleteGate(frameValues);
191 acc_.DeleteGate(curFrame);
192 return depIn;
193 } else {
194 dependChain = dependChain->UpdateFrameState(curFrame);
195 }
196 // update gate, for others elimination
197
198 return UpdateDependChain(gate, dependChain);
199 }
200
TryEliminateDependSelector(GateRef gate)201 GateRef EarlyElimination::TryEliminateDependSelector(GateRef gate)
202 {
203 auto state = acc_.GetState(gate);
204 if (acc_.IsLoopHead(state)) {
205 auto dependChain = GetLoopDependInfo(gate);
206 if (dependChain == nullptr) {
207 return Circuit::NullGate();
208 }
209 return UpdateDependChain(gate, dependChain);
210 }
211
212 auto dependCount = acc_.GetDependCount(gate);
213 for (size_t i = 0; i < dependCount; ++i) {
214 auto depend = acc_.GetDep(gate, i);
215 auto dependChain = GetDependChain(depend);
216 if (dependChain == nullptr) {
217 return Circuit::NullGate();
218 }
219 }
220
221 // all depend done.
222 auto depend = acc_.GetDep(gate);
223 auto dependChain = GetDependChain(depend);
224 DependInfoNode* copy = new (chunk_) DependInfoNode(chunk_);
225 copy->CopyFrom(dependChain);
226 for (size_t i = 1; i < dependCount; ++i) { // 1: second in
227 auto dependIn = acc_.GetDep(gate, i);
228 auto tempChain = GetDependChain(dependIn);
229 copy->Merge(this, tempChain);
230 }
231 return UpdateDependChain(gate, copy);
232 }
233
UpdateDependChain(GateRef gate,DependInfoNode * dependChain)234 GateRef EarlyElimination::UpdateDependChain(GateRef gate, DependInfoNode* dependChain)
235 {
236 ASSERT(dependChain != nullptr);
237 auto oldDependChain = GetDependChain(gate);
238 if (dependChain->Equals(oldDependChain)) {
239 return Circuit::NullGate();
240 }
241 dependChains_[acc_.GetId(gate)] = dependChain;
242 return gate;
243 }
244
UpdateWrite(GateRef gate,DependInfoNode * dependInfo)245 DependInfoNode* EarlyElimination::UpdateWrite(GateRef gate, DependInfoNode* dependInfo)
246 {
247 if (!enableMemoryAnalysis_) {
248 return new (chunk_) DependInfoNode(chunk_);
249 }
250 auto op = acc_.GetOpCode(gate);
251 switch (op) {
252 case OpCode::STORE_PROPERTY:
253 case OpCode::STORE_PROPERTY_NO_BARRIER:
254 case OpCode::STORE_CONST_OFFSET:
255 case OpCode::STORE_HCLASS_CONST_OFFSET:
256 case OpCode::STORE_ELEMENT:
257 case OpCode::STORE_MEMORY:
258 case OpCode::MIGRATE_ARRAY_WITH_KIND:
259 case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
260 case OpCode::MONO_STORE_PROPERTY:
261 return dependInfo->UpdateStoreProperty(this, gate);
262 default:
263 return new (chunk_) DependInfoNode(chunk_);
264 }
265 }
266
MayAccessOneMemory(GateRef lhs,GateRef rhs)267 bool EarlyElimination::MayAccessOneMemory(GateRef lhs, GateRef rhs)
268 {
269 auto rop = acc_.GetOpCode(rhs);
270 auto lop = acc_.GetOpCode(lhs);
271 switch (rop) {
272 case OpCode::STORE_MEMORY:
273 ASSERT(acc_.GetMemoryType(rhs) == MemoryType::ELEMENT_TYPE);
274 return acc_.GetOpCode(lhs) == OpCode::LOAD_ELEMENT;
275 case OpCode::MIGRATE_ARRAY_WITH_KIND: {
276 if (lop == OpCode::LOAD_ELEMENT) {
277 GateRef lopValueIn = acc_.GetValueIn(lhs, 0); // loadelement receiver
278 GateRef ropValueIn = acc_.GetValueIn(rhs, 0); // migrate receiver
279 return lopValueIn == ropValueIn;
280 }
281 return false;
282 }
283 case OpCode::STORE_ELEMENT: {
284 if (lop == OpCode::LOAD_ELEMENT) {
285 bool lopIsTypedArray = acc_.TypedOpIsTypedArray(lhs, TypedOpKind::TYPED_LOAD_OP);
286 bool ropIsTypedArray = acc_.TypedOpIsTypedArray(rhs, TypedOpKind::TYPED_STORE_OP);
287 return lopIsTypedArray == ropIsTypedArray;
288 }
289 return false;
290 }
291 case OpCode::STORE_PROPERTY:
292 case OpCode::STORE_PROPERTY_NO_BARRIER: {
293 if (lop == OpCode::LOAD_PROPERTY) {
294 auto loff = acc_.GetValueIn(lhs, 1);
295 auto roff = acc_.GetValueIn(rhs, 1);
296 ASSERT(acc_.GetOpCode(loff) == OpCode::CONSTANT);
297 ASSERT(acc_.GetOpCode(roff) == OpCode::CONSTANT);
298 return loff == roff;
299 } else if (lop == OpCode::PROTOTYPE_CHECK) {
300 auto lindex = acc_.GetHClassIndex(lhs);
301 auto rindex = acc_.GetHClassIndex(rhs);
302 return (lindex == 0) || (rindex == 0) || (lindex != rindex);
303 }
304 break;
305 }
306 case OpCode::STORE_CONST_OFFSET:
307 case OpCode::STORE_HCLASS_CONST_OFFSET: {
308 if (lop == OpCode::LOAD_CONST_OFFSET || lop == OpCode::LOAD_HCLASS_CONST_OFFSET) {
309 auto loff = acc_.GetOffset(lhs);
310 auto roff = acc_.GetOffset(rhs);
311 return loff == roff;
312 }
313 break;
314 }
315 case OpCode::LOAD_PROPERTY:
316 case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
317 if (acc_.GetGateType(lhs).Value() != acc_.GetGateType(rhs).Value()) {
318 return false;
319 }
320 break;
321 default:
322 break;
323 }
324 return false;
325 }
326
CompareOrder(GateRef lhs,GateRef rhs)327 bool EarlyElimination::CompareOrder(GateRef lhs, GateRef rhs)
328 {
329 return visitor_->GetGateOrder(lhs) < visitor_->GetGateOrder(rhs);
330 }
331
CheckReplacement(GateRef lhs,GateRef rhs)332 bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs)
333 {
334 if (!acc_.MetaDataEqu(lhs, rhs)) {
335 if (acc_.GetOpCode(lhs) != acc_.GetOpCode(rhs)) {
336 return false;
337 }
338 }
339
340 if (acc_.GetNumValueIn(lhs) != acc_.GetNumValueIn(rhs)) {
341 return false;
342 }
343
344 size_t valueCount = acc_.GetNumValueIn(lhs);
345 for (size_t i = 0; i < valueCount; i++) {
346 if (Rename(acc_.GetValueIn(lhs, i)) != Rename(acc_.GetValueIn(rhs, i))) {
347 return false;
348 }
349 }
350
351 auto opcode = acc_.GetOpCode(lhs);
352 switch (opcode) {
353 case OpCode::LOAD_ELEMENT: {
354 if (acc_.GetTypedLoadOp(lhs) != acc_.GetTypedLoadOp(rhs)) {
355 return false;
356 }
357 break;
358 }
359 case OpCode::TYPED_BINARY_OP: {
360 auto lhsOp = acc_.GetTypedBinaryOp(lhs);
361 auto rhsOp = acc_.GetTypedBinaryOp(rhs);
362 if (lhsOp != rhsOp) {
363 return false;
364 }
365 break;
366 }
367 case OpCode::TYPED_UNARY_OP: {
368 auto lhsOp = acc_.GetTypedUnAccessor(lhs).GetTypedUnOp();
369 auto rhsOp = acc_.GetTypedUnAccessor(rhs).GetTypedUnOp();
370 if (lhsOp != rhsOp) {
371 return false;
372 }
373 break;
374 }
375 case OpCode::TYPED_ARRAY_CHECK: {
376 TypedArrayMetaDataAccessor lhsAccessor = acc_.GetTypedArrayMetaDataAccessor(lhs);
377 TypedArrayMetaDataAccessor rhsAccessor = acc_.GetTypedArrayMetaDataAccessor(rhs);
378 if ((lhsAccessor.GetParamType() != rhsAccessor.GetParamType())) {
379 return false;
380 }
381
382 OnHeapMode lMode = lhsAccessor.GetOnHeapMode();
383 OnHeapMode rMode = rhsAccessor.GetOnHeapMode();
384 // When the onheapmode types of the two checks are inconsistent and one type is none, the none type will be
385 // updated to another type. Because there is no side effect between the two checks, the onheapmode types are
386 // also consistent.
387 if (lMode != rMode) {
388 if (OnHeap::IsNone(lMode)) {
389 acc_.UpdateOnHeapMode(lhs, rMode);
390 return true;
391 } else if (OnHeap::IsNone(rMode)) {
392 acc_.UpdateOnHeapMode(rhs, lMode);
393 return true;
394 }
395 return false;
396 }
397 break;
398 }
399 case OpCode::TYPE_OF_CHECK: {
400 if (acc_.GetParamType(lhs) != acc_.GetParamType(rhs)) {
401 return false;
402 }
403 break;
404 }
405 case OpCode::PROTOTYPE_CHECK: {
406 if (acc_.GetHClassIndex(lhs) != acc_.GetHClassIndex(rhs)) {
407 return false;
408 }
409 break;
410 }
411 case OpCode::LOAD_CONST_OFFSET:
412 case OpCode::LOAD_HCLASS_CONST_OFFSET: {
413 if (acc_.GetOffset(lhs) != acc_.GetOffset(rhs)) {
414 return false;
415 }
416 if (acc_.GetMachineType(lhs) != acc_.GetMachineType(rhs)) {
417 return false;
418 }
419 if (acc_.GetMemoryAttribute(lhs).Value() != acc_.GetMemoryAttribute(rhs).Value()) {
420 return false;
421 }
422 break;
423 }
424 case OpCode::LOAD_HCLASS_FROM_CONSTPOOL: {
425 if (acc_.GetIndex(lhs) != acc_.GetIndex(rhs)) {
426 return false;
427 }
428 break;
429 }
430 case OpCode::JSINLINETARGET_HEAPCONSTANT_CHECK: {
431 if (acc_.GetFuncGT(lhs) != acc_.GetFuncGT(rhs)) {
432 return false;
433 }
434 break;
435 }
436 case OpCode::JSINLINETARGET_TYPE_CHECK: {
437 if (acc_.GetFuncGT(lhs) != acc_.GetFuncGT(rhs)) {
438 return false;
439 }
440 break;
441 }
442 case OpCode::TYPED_CONSTRUCTOR_CHECK:
443 case OpCode::ARRAY_CONSTRUCTOR_CHECK:
444 case OpCode::FLOAT32_ARRAY_CONSTRUCTOR_CHECK:
445 case OpCode::OBJECT_CONSTRUCTOR_CHECK:
446 case OpCode::BOOLEAN_CONSTRUCTOR_CHECK: {
447 if (acc_.GetValueIn(lhs) != acc_.GetValueIn(rhs)) {
448 return false;
449 }
450 break;
451 }
452 case OpCode::LOAD_BUILTIN_OBJECT: {
453 if (acc_.GetIndex(lhs) != acc_.GetIndex(rhs)) {
454 return false;
455 }
456 break;
457 }
458 default:
459 break;
460 }
461 return true;
462 }
463
CheckRenameReplacement(GateRef lhs,GateRef rhs)464 bool EarlyElimination::CheckRenameReplacement(GateRef lhs, GateRef rhs)
465 {
466 auto opcode = acc_.GetOpCode(lhs);
467 switch (opcode) {
468 case OpCode::INDEX_CHECK: {
469 auto index = acc_.GetValueIn(lhs, 1);
470 if (Rename(index) == Rename(rhs)) {
471 return true;
472 }
473 break;
474 }
475 default:
476 break;
477 }
478 return false;
479 }
480
Rename(GateRef gate)481 GateRef EarlyElimination::Rename(GateRef gate)
482 {
483 ChunkStack<GateRef> gateStack(chunk_);
484 while (true) {
485 auto op = acc_.GetOpCode(gate);
486 bool renamed = false;
487 switch (op) {
488 case OpCode::INDEX_CHECK: {
489 GateRef ans = renames_[acc_.GetId(gate)];
490 if (ans == Circuit::NullGate()) {
491 renamed = true;
492 gateStack.push(gate);
493 gate = acc_.GetValueIn(gate, 1);
494 } else {
495 gate = ans;
496 }
497 break;
498 }
499 default:
500 break;
501 }
502 if (!renamed) {
503 break;
504 }
505 }
506 while (!gateStack.empty()) {
507 auto topGate = gateStack.top();
508 gateStack.pop();
509 renames_[acc_.GetId(topGate)] = gate;
510 }
511 return gate;
512 }
513
Merge(EarlyElimination * elimination,DependInfoNode * that)514 void DependInfoNode::Merge(EarlyElimination* elimination, DependInfoNode* that)
515 {
516 auto siz = this->size_; // size of lhs-chain
517 auto lhs = this->head_;
518 auto rhs = that->head_;
519 ChunkStack<GateRef> gateStack(chunk_);
520 while (lhs != rhs) {
521 if (lhs == nullptr || rhs == nullptr) {
522 siz = 0;
523 lhs = nullptr;
524 break;
525 } else if (lhs->gate == rhs->gate) {
526 gateStack.push(lhs->gate);
527 siz--;
528 lhs = lhs->next;
529 rhs = rhs->next;
530 } else if (elimination->CompareOrder(lhs->gate, rhs->gate)) {
531 rhs = rhs->next;
532 } else {
533 siz--;
534 lhs = lhs->next;
535 }
536 }
537 // lhs : common suffix of lhs-chain and rhs-chain
538 this->head_ = lhs;
539 this->size_ = siz;
540 while (!gateStack.empty()) {
541 Node* node = chunk_->New<Node>(gateStack.top(), head_);
542 gateStack.pop();
543 this->size_++;
544 this->head_ = node;
545 }
546 if (this->frameState_ != that->frameState_) {
547 this->frameState_ = Circuit::NullGate();
548 }
549 }
550
Equals(DependInfoNode * that)551 bool DependInfoNode::Equals(DependInfoNode* that)
552 {
553 if (that == nullptr) {
554 return false;
555 }
556 if (size_ != that->size_ || frameState_ != that->frameState_) {
557 return false;
558 }
559 auto lhs = this->head_;
560 auto rhs = that->head_;
561 while (lhs != rhs) {
562 if (lhs->gate != rhs->gate) {
563 return false;
564 }
565 lhs = lhs->next;
566 rhs = rhs->next;
567 }
568 return true;
569 }
570
LookupFrameState() const571 GateRef DependInfoNode::LookupFrameState() const
572 {
573 return frameState_;
574 }
575
LookupCheckedNode(EarlyElimination * elimination,GateRef gate)576 GateRef DependInfoNode::LookupCheckedNode(EarlyElimination* elimination, GateRef gate)
577 {
578 for (Node* node = head_; node != nullptr; node = node->next) {
579 if (elimination->CheckRenameReplacement(node->gate, gate)) {
580 return node->gate;
581 }
582 }
583 return gate;
584 }
585
GetGates(std::vector<GateRef> & gates) const586 void DependInfoNode::GetGates(std::vector<GateRef>& gates) const
587 {
588 ChunkStack<GateRef> st(chunk_);
589 for (Node* node = head_; node != nullptr; node = node->next) {
590 st.push(node->gate);
591 }
592 while (!st.empty()) {
593 gates.emplace_back(st.top());
594 st.pop();
595 }
596 }
597
LookupNode(EarlyElimination * elimination,GateRef gate)598 GateRef DependInfoNode::LookupNode(EarlyElimination* elimination, GateRef gate)
599 {
600 for (Node* node = head_; node != nullptr; node = node->next) {
601 if (elimination->CheckReplacement(node->gate, gate)) {
602 return node->gate;
603 }
604 }
605 return Circuit::NullGate();
606 }
607
UpdateNode(GateRef gate)608 DependInfoNode* DependInfoNode::UpdateNode(GateRef gate)
609 {
610 // assign node->next to head
611 Node* node = chunk_->New<Node>(gate, head_);
612 DependInfoNode* that = new (chunk_) DependInfoNode(chunk_);
613 // assign head to node
614 that->head_ = node;
615 that->size_ = size_ + 1;
616 that->frameState_ = frameState_;
617 return that;
618 }
619
UpdateFrameState(GateRef framestate)620 DependInfoNode* DependInfoNode::UpdateFrameState(GateRef framestate)
621 {
622 // assign node->next to head
623 DependInfoNode* that = new (chunk_) DependInfoNode(chunk_);
624 // assign head to node
625 that->head_ = head_;
626 that->size_ = size_;
627 that->frameState_ = framestate;
628 return that;
629 }
630
UpdateStoreProperty(EarlyElimination * elimination,GateRef gate)631 DependInfoNode* DependInfoNode::UpdateStoreProperty(EarlyElimination* elimination, GateRef gate)
632 {
633 DependInfoNode* that = new (chunk_) DependInfoNode(chunk_);
634 ChunkStack<GateRef> gateStack(chunk_);
635 for (Node* node = head_; node != nullptr; node = node->next) {
636 if (!elimination->MayAccessOneMemory(node->gate, gate)) {
637 gateStack.push(node->gate);
638 }
639 }
640 while (!gateStack.empty()) {
641 that = that->UpdateNode(gateStack.top());
642 gateStack.pop();
643 }
644 return that;
645 }
646 } // namespace panda::ecmascript::kungfu
647