• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/compiler/barrier_stub_builder.h"
17 #include "ecmascript/compiler/rt_call_signature.h"
18 #include "ecmascript/compiler/stub_builder-inl.h"
19 #include "ecmascript/js_thread.h"
20 
21 /*  LOCAL_TO_SHARE_SWAPPED 和 OLD_TO_NEW_SWAPPED_MASK标记读取并发场景分析:
22 *   设置标记:CollectGarbage->RunPhases->Sweep->PrepareSweeping这条路径会设置这两个标记, CollectGarbage只会在当前线程local gc时使用。
23 *   清除标记:(1)由CreateXXXXRememberedSet清除标记,这个调用点有两种情况:
24 *                a. js主线程在需要读rset时会调用的方法,一定在js线程。
25 *                b. gc时移动对象时从gc线程调用,此时主线程是被suspendAll停下来的等待gc线程的状态。
26 *           (2)CollectGarbage -> RunPhases -> Evacuate -> UpdateReference ->
27 *               并行UpdateReferenceTask -> UpdateRSet -> Merge:
28 *               其中有并行任务,会主线程会等待并行任务结束,有同步的保证,可以保证清除能够被主线程观察到。
29 *
30 *   LOCAL_TO_SHARE_COLLECTED_MASK标记读取并发场景分析:
31 *   设置标记:SharedGCMarkBase::MarkRoots-> CollectLocalVMRSet(访问多个线程的heap) -> EnumerateRegions -> ExtractLocalToShareRSet,
32 *           这里会有跨线程,但是已经在SuspendAll的保证之下了。
33 *   清除标记:(1)入口在MergeBackAndResetRSetWorkListHandler,这个函数调用点有5个,可能不在当前线程,但是调用点处都有SuspendAll的保证。
34 *           (2)js线程在local gc结束时,会把自己线程被Collect的rset拿回来,这里只处理当前线程的,没有并发问题。
35 */
36 
37 namespace panda::ecmascript::kungfu {
DoBatchBarrier()38 void BarrierStubBuilder::DoBatchBarrier()
39 {
40     auto env = GetEnvironment();
41     Label entry(env);
42     env->SubCfgEntry(&entry);
43     Label exit(env);
44     Label handleMark(env);
45     Label handleBitSet(env);
46     BRANCH_NO_WEIGHT(InSharedHeap(objectRegion_), &handleMark, &handleBitSet);
47     Bind(&handleBitSet);
48     {
49         DoBatchBarrierInternal();
50         Jump(&handleMark);
51     }
52 
53     Bind(&handleMark);
54     HandleMark();
55     Jump(&exit);
56     Bind(&exit);
57     env->SubCfgExit();
58 }
59 
DoBatchBarrierInternal()60 void BarrierStubBuilder::DoBatchBarrierInternal()
61 {
62     auto env = GetEnvironment();
63     Label entry(env);
64     env->SubCfgEntry(&entry);
65     Label exit(env);
66     Label inYoung(env);
67     Label notInYoung(env);
68     BRANCH_NO_WEIGHT(InYoungGeneration(objectRegion_), &inYoung, &notInYoung);
69     Bind(&notInYoung);
70     {
71         BarrierBatchBitSet(LocalToShared | OldToNew);
72         Jump(&exit);
73     }
74     Bind(&inYoung);
75     {
76         BarrierBatchBitSet(LocalToShared);
77         Jump(&exit);
78     }
79     Bind(&exit);
80     env->SubCfgExit();
81 }
82 
GetBitSetDataAddr(GateRef objectRegion,GateRef loadOffset,int32_t createFunID)83 GateRef BarrierStubBuilder::GetBitSetDataAddr(GateRef objectRegion, GateRef loadOffset, int32_t createFunID)
84 {
85     auto env = GetEnvironment();
86     Label entry(env);
87     env->SubCfgEntry(&entry);
88     Label exit(env);
89 
90     DEFVARIABLE(oldBitSet, VariableType::NATIVE_POINTER(),
91                 Load(VariableType::NATIVE_POINTER(), objectRegion, loadOffset));
92 
93     Label createRset(env);
94     BRANCH_UNLIKELY(IntPtrEqual(*oldBitSet, IntPtr(0)), &createRset, &exit);
95     Bind(&createRset);
96     {
97         oldBitSet = CallNGCRuntime(glue_, createFunID, {objectRegion});
98         Jump(&exit);
99     }
100 
101     Bind(&exit);
102     GateRef bitSetDataAddr = PtrAdd(*oldBitSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
103     env->SubCfgExit();
104     return bitSetDataAddr;
105 }
106 
HandleMark()107 void BarrierStubBuilder::HandleMark()
108 {
109     auto env = GetEnvironment();
110     Label entry(env);
111     env->SubCfgEntry(&entry);
112     Label exit(env);
113 
114     bool isArch32 = GetEnvironment()->Is32Bit();
115     GateRef gcStateBitField = Load(VariableType::INT64(), glue_,
116                                    Int64(JSThread::GlueData::GetGCStateBitFieldOffset(isArch32)));
117     GateRef gcState = Int64And(gcStateBitField, Int64(JSThread::CONCURRENT_MARKING_BITFIELD_MASK));
118     GateRef sharedGCStateBitField = Load(VariableType::INT64(), glue_,
119                                          Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(isArch32)));
120     GateRef sharedGCState = Int64And(sharedGCStateBitField, Int64(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK));
121     Label needMarking(env);
122     GateRef marking = Int64NotEqual(gcState, Int64(static_cast<int64_t>(MarkStatus::READY_TO_MARK)));
123     GateRef sharedMarking = Int64NotEqual(sharedGCState,
124                                           Int64(static_cast<int64_t>(SharedMarkStatus::READY_TO_CONCURRENT_MARK)));
125     BRANCH_LIKELY(BitAnd(BoolNot(marking), BoolNot(sharedMarking)), &exit, &needMarking);
126     Bind(&needMarking);
127     Label begin(env);
128     Label body(env);
129     Label endLoop(env);
130     DEFVARIABLE(index, VariableType::INT32(), Int32(0));
131     Jump(&begin);
132     LoopBegin(&begin);
133     {
134         BRANCH_LIKELY(Int32UnsignedLessThan(*index, slotCount_), &body, &exit);
135         Bind(&body);
136         {
137             GateRef offset = PtrMul(ZExtInt32ToPtr(*index), IntPtr(JSTaggedValue::TaggedTypeSize()));
138             GateRef value = Load(VariableType::JS_ANY(), dstAddr_, offset);
139             Label doMarking(env);
140             BRANCH_NO_WEIGHT(TaggedIsHeapObject(value), &doMarking, &endLoop);
141             Bind(&doMarking);
142 
143             GateRef valueRegion = ObjectAddressToRange(value);
144             Label callMarking(env);
145             Label doSharedMarking(env);
146             BRANCH_NO_WEIGHT(LogicAndBuilder(env).And(marking).And(BoolNot(InSharedHeap(valueRegion))).Done(),
147                              &callMarking, &doSharedMarking);
148             Bind(&callMarking);
149             {
150                 CallNGCRuntime(glue_, RTSTUB_ID(MarkingBarrier), {glue_, dstAddr_, offset, value});
151                 Jump(&endLoop);
152             }
153             Bind(&doSharedMarking);
154             {
155                 Label callSharedMarking(env);
156                 BRANCH_NO_WEIGHT(
157                     LogicAndBuilder(env).And(sharedMarking).And(InSharedSweepableSpace(valueRegion)).Done(),
158                     &callSharedMarking, &endLoop);
159                 Bind(&callSharedMarking);
160                 {
161                     CallNGCRuntime(glue_, RTSTUB_ID(SharedGCMarkingBarrier), {glue_, dstAddr_, offset, value});
162                     Jump(&endLoop);
163                 }
164             }
165         }
166     }
167     Bind(&endLoop);
168     index = Int32Add(*index, Int32(1));
169     LoopEnd(&begin);
170     Bind(&exit);
171     env->SubCfgExit();
172 }
173 
BarrierBatchBitSet(uint8_t bitSetSelect)174 void BarrierStubBuilder::BarrierBatchBitSet(uint8_t bitSetSelect)
175 {
176     auto env = GetEnvironment();
177     Label entry(env);
178     env->SubCfgEntry(&entry);
179 
180     Label beforeExit(env);
181     Label exit(env);
182     Label begin(env);
183     Label loopBody(env);
184     Label endLoop(env);
185     GateRef initByteIdx = TruncPtrToInt32(IntPtrLSR(PtrSub(TaggedCastToIntPtr(dstAddr_), objectRegion_),
186                                                     IntPtr(TAGGED_TYPE_SIZE_LOG)));
187     GateRef initQuadIdx = Int32LSR(initByteIdx, Int32(BIT_PER_QUAD_LOG2));
188     DEFVARIABLE(quadIdx, VariableType::INT32(), initQuadIdx);
189     DEFVARIABLE(localToShareBitSet, VariableType::INT64(), Int64(0));
190     DEFVARIABLE(oldToNewBitSet, VariableType::INT64(), Int64(0));
191     DEFVARIABLE(index, VariableType::INT32(), initByteIdx);
192 
193     Jump(&begin);
194     LoopBegin(&begin);
195     {
196         BRANCH_NO_WEIGHT(Int32UnsignedLessThan(*index, Int32Add(initByteIdx, slotCount_)), &loopBody, &beforeExit);
197         Bind(&loopBody);
198         {
199             Label checkLocalRegion(env);
200             Label updateLocalToShared(env);
201             Label updateOldToNew(env);
202             GateRef offset = PtrMul(ZExtInt32ToPtr(*index), IntPtr(JSTaggedValue::TaggedTypeSize()));
203             GateRef value = Load(VariableType::JS_ANY(), objectRegion_, offset);
204             Label doUpdate(env);
205             BRANCH_NO_WEIGHT(TaggedIsHeapObject(value), &doUpdate, &endLoop);
206             Bind(&doUpdate);
207             {
208                 GateRef valueRegion = ObjectAddressToRange(value);
209                 Label flushLast(env);
210                 Label curCheck(env);
211                 GateRef curQuadIdx = Int32LSR(*index, Int32(BIT_PER_QUAD_LOG2));
212                 GateRef bitOffset = Int32And(*index, Int32(BIT_PER_QUAD_MASK));
213                 GateRef mask = Int64LSL(Int64(1), ZExtInt32ToInt64(bitOffset));
214                 BRANCH_LIKELY(Int32Equal(curQuadIdx, *quadIdx), &curCheck, &flushLast);
215                 Bind(&flushLast);
216                 {
217                     Label updateIdx(env);
218                     FlushBatchBitSet(bitSetSelect, *quadIdx,  localToShareBitSet, oldToNewBitSet, &updateIdx);
219                     Bind(&updateIdx);
220                     quadIdx = curQuadIdx;
221                     Jump(&curCheck);
222                 }
223                 Bind(&curCheck);
224                 if ((bitSetSelect & LocalToShared) != 0) {
225                     BRANCH_NO_WEIGHT(InSharedSweepableSpace(valueRegion), &updateLocalToShared, &checkLocalRegion);
226                     Bind(&updateLocalToShared);
227                     {
228                         localToShareBitSet = Int64Or(*localToShareBitSet, mask);
229                         Jump(&endLoop);
230                     }
231                     Bind(&checkLocalRegion);
232                 }
233                 if ((bitSetSelect & OldToNew) != 0) {
234                     BRANCH_NO_WEIGHT(InYoungGeneration(valueRegion), &updateOldToNew, &endLoop);
235                     Bind(&updateOldToNew);
236                     {
237                         oldToNewBitSet = Int64Or(*oldToNewBitSet, mask);
238                     }
239                 }
240                 Jump(&endLoop);
241             }
242         }
243         Bind(&endLoop);
244         index = Int32Add(*index, Int32(1));
245         LoopEnd(&begin);
246     }
247     Bind(&beforeExit);
248     FlushBatchBitSet(bitSetSelect, *quadIdx, localToShareBitSet, oldToNewBitSet, &exit);
249     Bind(&exit);
250     env->SubCfgExit();
251 }
252 
FlushBatchBitSet(uint8_t bitSetSelect,GateRef quadIdx,Variable & localToShareBitSetVar,Variable & oldToNewBitSetVar,Label * next)253 void BarrierStubBuilder::FlushBatchBitSet(uint8_t bitSetSelect, GateRef quadIdx,
254                                           Variable &localToShareBitSetVar, Variable &oldToNewBitSetVar, Label* next)
255 {
256     auto env = GetEnvironment();
257     Label batchUpdateLocalToShare(env);
258     Label checkNext(env);
259     Label batchUpdateOldToNew(env);
260     if ((bitSetSelect & LocalToShared) != 0) {
261         BRANCH_LIKELY(Int64NotEqual(*localToShareBitSetVar, Int64(0)), &batchUpdateLocalToShare, &checkNext);
262         Bind(&batchUpdateLocalToShare);
263         {
264             GateRef loadOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env->Is32Bit()));
265             GateRef bitSetAddr = GetBitSetDataAddr(objectRegion_, loadOffset, RTSTUB_ID(CreateLocalToShare));
266 
267             GateRef byteIndex = Int32LSL(quadIdx, Int32(BYTE_PER_QUAD_LOG2));
268             GateRef oldValue = Load(VariableType::INT64(), bitSetAddr, ZExtInt32ToInt64(byteIndex));
269             Store(VariableType::INT64(), glue_, bitSetAddr, ZExtInt32ToInt64(byteIndex),
270                   Int64Or(oldValue, *localToShareBitSetVar), MemoryAttribute::NoBarrier());
271             localToShareBitSetVar = Int64(0);
272             Jump(&checkNext);
273         }
274         Bind(&checkNext);
275     }
276     if ((bitSetSelect & OldToNew) != 0) {
277         BRANCH_LIKELY(Int64NotEqual(*oldToNewBitSetVar, Int64(0)), &batchUpdateOldToNew, next);
278         Bind(&batchUpdateOldToNew);
279         {
280             GateRef loadOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env->Is32Bit()));
281             GateRef bitSetAddr = GetBitSetDataAddr(objectRegion_, loadOffset, RTSTUB_ID(CreateOldToNew));
282             GateRef byteIndex = Int32LSL(quadIdx, Int32(BYTE_PER_QUAD_LOG2));
283             GateRef oldValue = Load(VariableType::INT64(), bitSetAddr, ZExtInt32ToInt64(byteIndex));
284             Store(VariableType::INT64(), glue_, bitSetAddr, ZExtInt32ToInt64(byteIndex),
285                   Int64Or(oldValue, *oldToNewBitSetVar), MemoryAttribute::NoBarrier());
286             oldToNewBitSetVar = Int64(0);
287         }
288     }
289     Jump(next);
290 }
291 
DoMoveBarrierCrossRegion(GateRef srcAddr,GateRef srcObj)292 void BarrierStubBuilder::DoMoveBarrierCrossRegion(GateRef srcAddr, GateRef srcObj)
293 {
294     auto env = GetEnvironment();
295     Label entry(env);
296     env->SubCfgEntry(&entry);
297     Label exit(env);
298     Label handleMark(env);
299     Label handleBitSet(env);
300     Label doMove(env);
301     BRANCH_NO_WEIGHT(Int32Equal(slotCount_, Int32(0)), &exit, &doMove);
302     Bind(&doMove);
303     BRANCH_NO_WEIGHT(InSharedHeap(objectRegion_), &handleMark, &handleBitSet);
304     Bind(&handleBitSet);
305     {
306         GateRef srcRegion = ObjectAddressToRange(srcObj);
307         Label batchBarrier(env);
308         Label srcNotInSharedHeap(env);
309         // copy shared array to local heap, there is no bitset can be copied, do batch barrier for dst object.
310         BRANCH_UNLIKELY(InSharedHeap(srcRegion), &batchBarrier, &srcNotInSharedHeap);
311         Bind(&srcNotInSharedHeap);
312         {
313             GateRef sameKind = LogicOrBuilder(env)
314                                .Or(BitAnd(InYoungGeneration(objectRegion_), InYoungGeneration(srcRegion)))
315                                .Or(BitAnd(InGeneralOldGeneration(objectRegion_), InGeneralOldGeneration(srcRegion)))
316                                .Done();
317             Label sameRegionKind(env);
318             Label crossRegion(env);
319             BRANCH_NO_WEIGHT(sameKind, &sameRegionKind, &crossRegion);
320             Bind(&sameRegionKind);
321             {
322                 // dst and src are in same kind region, copy the bitset of them.
323                 DoMoveBarrierSameRegionKind(srcAddr, srcRegion, CrossRegion);
324                 Jump(&handleMark);
325             }
326             Bind(&crossRegion);
327             {
328                 Label copyLocalToShare(env);
329                 BRANCH_UNLIKELY(IsLocalToShareSwapped(srcRegion), &batchBarrier, &copyLocalToShare);
330                 Bind(&copyLocalToShare);
331                 {
332                     // dst and src are in different kind region, localToShare bitset can be copied unconditionally,
333                     GateRef srcBitStartIdx = Int64LSR(Int64Sub(srcAddr, srcRegion), Int64(TAGGED_TYPE_SIZE_LOG));
334                     GateRef dstBitStartIdx = Int64LSR(Int64Sub(dstAddr_, objectRegion_), Int64(TAGGED_TYPE_SIZE_LOG));
335 
336                     GateRef localToShareOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env->Is32Bit()));
337                     GateRef localToShareBitSetAddr =
338                         GetBitSetDataAddr(objectRegion_, localToShareOffset, RTSTUB_ID(CreateLocalToShare));
339                     GateRef srcLocalToShareBitSetAddr =
340                         GetBitSetDataAddr(srcRegion, localToShareOffset, RTSTUB_ID(CreateLocalToShare));
341                     BitSetRangeMoveForward(srcLocalToShareBitSetAddr, localToShareBitSetAddr, srcBitStartIdx,
342                                            dstBitStartIdx, ZExtInt32ToInt64(slotCount_));
343                     Label inOld(env);
344                     BRANCH_NO_WEIGHT(InYoungGeneration(objectRegion_), &handleMark, &inOld);
345                     Bind(&inOld);
346                     {
347                         // copy young object to old region, do BarrierBatchBitSet bitset for oldToNew bitset.
348                         BarrierBatchBitSet(OldToNew);
349                         Jump(&handleMark);
350                     }
351                 }
352             }
353         }
354         Bind(&batchBarrier);
355         {
356             DoBatchBarrierInternal();
357             Jump(&handleMark);
358         }
359     }
360     Bind(&handleMark);
361     HandleMark();
362     Jump(&exit);
363     Bind(&exit);
364     env->SubCfgExit();
365 }
366 
DoMoveBarrierInRegion(GateRef srcAddr)367 void BarrierStubBuilder::DoMoveBarrierInRegion(GateRef srcAddr)
368 {
369     auto env = GetEnvironment();
370     Label entry(env);
371     env->SubCfgEntry(&entry);
372     Label exit(env);
373     Label handleMark(env);
374     Label handleBitSet(env);
375     Label doMove(env);
376     BRANCH_NO_WEIGHT(Int32Equal(slotCount_, Int32(0)), &exit, &doMove);
377     Bind(&doMove);
378     BRANCH_NO_WEIGHT(InSharedHeap(objectRegion_), &handleMark, &handleBitSet);
379     Bind(&handleBitSet);
380     {
381         DoMoveBarrierSameRegionKind(srcAddr, objectRegion_, InSameRegion);
382         Jump(&handleMark);
383     }
384     Bind(&handleMark);
385     HandleMark();
386     Jump(&exit);
387     Bind(&exit);
388     env->SubCfgExit();
389 }
390 
DoMoveBarrierSameRegionKind(GateRef srcAddr,GateRef srcRegion,RegionKind regionKind)391 void BarrierStubBuilder::DoMoveBarrierSameRegionKind(GateRef srcAddr, GateRef srcRegion, RegionKind regionKind)
392 {
393     auto env = GetEnvironment();
394     Label entry(env);
395     env->SubCfgEntry(&entry);
396     Label exit(env);
397     Label inYoung(env);
398     Label inOld(env);
399     Label copyBitSet(env);
400 
401     DEFVARIABLE(dstBitSetAddr, VariableType::NATIVE_POINTER(), IntPtr(0));
402     DEFVARIABLE(dstBitSetAddr2, VariableType::NATIVE_POINTER(), IntPtr(0));
403     DEFVARIABLE(srcBitSetAddr, VariableType::NATIVE_POINTER(), IntPtr(0));
404     DEFVARIABLE(srcBitSetAddr2, VariableType::NATIVE_POINTER(), IntPtr(0));
405 
406     GateRef localToShareOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env->Is32Bit()));
407     GateRef localToShareBitSetAddr =
408         GetBitSetDataAddr(objectRegion_, localToShareOffset, RTSTUB_ID(CreateLocalToShare));
409     GateRef srcLocalToShareBitSetAddr = Gate::InvalidGateRef;
410     if (regionKind == InSameRegion) {
411         srcLocalToShareBitSetAddr = localToShareBitSetAddr;
412     } else {
413         ASSERT(regionKind == CrossRegion);
414         srcLocalToShareBitSetAddr = GetBitSetDataAddr(srcRegion, localToShareOffset, RTSTUB_ID(CreateLocalToShare));
415     }
416     GateRef localToShareSwapped = IsLocalToShareSwapped(srcRegion);
417     BRANCH_NO_WEIGHT(InYoungGeneration(objectRegion_), &inYoung, &inOld);
418     Bind(&inYoung);
419     {
420         Label batchBarrier(env);
421         Label copyLocalToShare(env);
422         BRANCH_UNLIKELY(localToShareSwapped, &batchBarrier, &copyLocalToShare);
423         Bind(&batchBarrier);
424         {
425             // slowpath, localToShareRSet is swapped, it can't be copied, just set the bitset bit by bit.
426             BarrierBatchBitSet(LocalToShared);
427             Jump(&exit);
428         }
429         Bind(&copyLocalToShare);
430         {
431             dstBitSetAddr = localToShareBitSetAddr;
432             srcBitSetAddr = srcLocalToShareBitSetAddr;
433             Jump(&copyBitSet);
434         }
435     }
436     Bind(&inOld);
437     {
438         GateRef oldToNewOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env->Is32Bit()));
439         GateRef oldToNewBitSetAddr = GetBitSetDataAddr(objectRegion_, oldToNewOffset, RTSTUB_ID(CreateOldToNew));
440         GateRef srcOldToNewBitSetAddr = GetBitSetDataAddr(srcRegion, oldToNewOffset, RTSTUB_ID(CreateOldToNew));
441         // CreateOldToNew may change the RSetFlag, so load it again.
442         GateRef oldToNewSwapped = IsOldToNewSwapped(srcRegion);
443         Label batchBarrier(env);
444         Label tryBatchBarrier(env);
445         Label copyBoth(env);
446         // both localToShareSwapped and oldToNewSwapped are not swapped.
447         BRANCH_LIKELY(BitAnd(BoolNot(localToShareSwapped), BoolNot(oldToNewSwapped)), &copyBoth, &tryBatchBarrier);
448         Bind(&copyBoth);
449         {
450             dstBitSetAddr = localToShareBitSetAddr;
451             srcBitSetAddr = srcLocalToShareBitSetAddr;
452             dstBitSetAddr2 = oldToNewBitSetAddr;
453             srcBitSetAddr2 = srcOldToNewBitSetAddr;
454             Jump(&copyBitSet);
455         }
456         Bind(&tryBatchBarrier);
457         {
458             Label copyOne(env);
459             BRANCH_UNLIKELY(BitAnd(localToShareSwapped, oldToNewSwapped), &batchBarrier, &copyOne);
460             Bind(&batchBarrier);
461             {
462                 // slowpath, localToShareRSet and oldToNewRSet are swapped,
463                 // it can't be copied, just set the bitset bit by bit.
464                 BarrierBatchBitSet(LocalToShared | OldToNew);
465                 Jump(&exit);
466             }
467             Bind(&copyOne);
468             {
469                 Label localToShareBatchBarrier(env);
470                 Label oldToNewBatchBarrier(env);
471                 BRANCH_NO_WEIGHT(localToShareSwapped, &localToShareBatchBarrier, &oldToNewBatchBarrier);
472                 Bind(&localToShareBatchBarrier);
473                 {
474                     // slowpath, localToShareRSet is swapped, it can't be copied, just set the bitset bit by bit.
475                     // And copy oldToNewRSet.
476                     BarrierBatchBitSet(LocalToShared);
477                     dstBitSetAddr = oldToNewBitSetAddr;
478                     srcBitSetAddr = srcOldToNewBitSetAddr;
479                     Jump(&copyBitSet);
480                 }
481                 Bind(&oldToNewBatchBarrier);
482                 {
483                     // slowpath, oldToNewRSet is swapped, it can't be copied, just set the bitset bit by bit.
484                     // And copy localToShareRSet.
485                     BarrierBatchBitSet(OldToNew);
486                     dstBitSetAddr = localToShareBitSetAddr;
487                     srcBitSetAddr = srcLocalToShareBitSetAddr;
488                     Jump(&copyBitSet);
489                 }
490             }
491         }
492     }
493     Bind(&copyBitSet);
494     {
495         GateRef srcBitStartIdx = Int64LSR(Int64Sub(srcAddr, srcRegion), Int64(TAGGED_TYPE_SIZE_LOG));
496         GateRef dstBitStartIdx = Int64LSR(Int64Sub(dstAddr_, objectRegion_), Int64(TAGGED_TYPE_SIZE_LOG));
497         Label begin(env);
498         Label endLoop(env);
499         Label next(env);
500         Jump(&begin);
501         LoopBegin(&begin);
502         {
503             if (regionKind == InSameRegion) {
504                 BitSetRangeMove(*srcBitSetAddr, *dstBitSetAddr, srcBitStartIdx, dstBitStartIdx,
505                                 ZExtInt32ToInt64(slotCount_));
506             } else {
507                 ASSERT(regionKind == CrossRegion);
508                 BitSetRangeMoveForward(*srcBitSetAddr, *dstBitSetAddr, srcBitStartIdx, dstBitStartIdx,
509                                        ZExtInt32ToInt64(slotCount_));
510             }
511             BRANCH_UNLIKELY(IntPtrEqual(*dstBitSetAddr2, IntPtr(0)), &exit, &next);
512             Bind(&next);
513             {
514                 dstBitSetAddr = *dstBitSetAddr2;
515                 srcBitSetAddr = *srcBitSetAddr2;
516                 dstBitSetAddr2 = IntPtr(0);
517                 srcBitSetAddr2 = IntPtr(0);
518                 Jump(&endLoop);
519             }
520         }
521         Bind(&endLoop);
522         LoopEnd(&begin);
523     }
524     Bind(&exit);
525     env->SubCfgExit();
526 }
527 
BitSetRangeMove(GateRef srcBitSet,GateRef dstBitSet,GateRef srcStart,GateRef dstStart,GateRef length)528 void BarrierStubBuilder::BitSetRangeMove(GateRef srcBitSet, GateRef dstBitSet, GateRef srcStart, GateRef dstStart,
529                                          GateRef length)
530 {
531     auto env = GetEnvironment();
532     Label entry(env);
533     env->SubCfgEntry(&entry);
534     Label exit(env);
535     length = ZExtInt32ToInt64(length);
536 
537     GateRef forward = LogicOrBuilder(env)
538                       .Or(Int64LessThan(dstStart, srcStart))
539                       .Or(Int64GreaterThanOrEqual(dstStart, Int64Add(srcStart, length))).Done();
540     Label moveForward(env);
541     Label moveBackward(env);
542     BRANCH_NO_WEIGHT(forward, &moveForward, &moveBackward);
543     Bind(&moveForward);
544     {
545         BitSetRangeMoveForward(srcBitSet, dstBitSet, srcStart, dstStart, length);
546         Jump(&exit);
547     }
548     Bind(&moveBackward);
549     {
550         BitSetRangeMoveBackward(srcBitSet, dstBitSet, srcStart, dstStart, length);
551         Jump(&exit);
552     }
553     Bind(&exit);
554     env->SubCfgExit();
555 }
556 
BitSetRangeMoveForward(GateRef srcBitSet,GateRef dstBitSet,GateRef srcStart,GateRef dstStart,GateRef length)557 void BarrierStubBuilder::BitSetRangeMoveForward(GateRef srcBitSet, GateRef dstBitSet, GateRef srcStart,
558                                                 GateRef dstStart, GateRef length)
559 {
560     auto env = GetEnvironment();
561     Label entry(env);
562     env->SubCfgEntry(&entry);
563     Label exit(env);
564 
565     DEFVARIABLE(remainLength, VariableType::INT64(), length);
566     // srcQuad <- srcStart / 64;  // 源起始 uint64_t 元素索引
567     // dstQuad <- dstStart / 64; // 目标起始 uint64_t 元素索引
568     // srcBitOffset <- srcStart % 64; // 源起始元素的位偏移
569     // dstBitOffset <- dstStart % 64; // 目标起始元素的位偏移
570     DEFVARIABLE(srcQuad, VariableType::INT64(), Int64LSR(srcStart, Int64(BIT_PER_QUAD_LOG2)));
571     DEFVARIABLE(dstQuad, VariableType::INT64(), Int64LSR(dstStart, Int64(BIT_PER_QUAD_LOG2)));
572     DEFVARIABLE(srcBitOffset, VariableType::INT64(), Int64And(srcStart, Int64(BIT_PER_QUAD_MASK)));
573     DEFVARIABLE(dstBitOffset, VariableType::INT64(), Int64And(dstStart, Int64(BIT_PER_QUAD_MASK)));
574 
575     Label begin(env);
576     Label body(env);
577     Label endLoop(env);
578     Jump(&begin);
579     LoopBegin(&begin);
580 
581     // while remainLength > 0
582     // do
583     BRANCH_LIKELY(Int64GreaterThan(*remainLength, Int64(0)), &body, &exit);
584     Bind(&body);
585     {
586         Label beforeEndLoop(env);
587         // bitsInCurrentQuad <- min of {64 - srcBitOffset, 64 - dstBitOffset, remainLength};
588         GateRef bitsInCurrentQuad = ThreeInt64Min(Int64Sub(Int64(BIT_PER_QUAD), *srcBitOffset),
589                                                   Int64Sub(Int64(BIT_PER_QUAD), *dstBitOffset),
590                                                   *remainLength);
591         GateRef srcQuadData = Load(VariableType::INT64(), srcBitSet, Int64LSL(*srcQuad, Int64(BYTE_PER_QUAD_LOG2)));
592         Label setValue(env);
593         BRANCH_NO_WEIGHT(Int64Equal(srcQuadData, Int64(0)), &beforeEndLoop, &setValue);
594         Bind(&setValue);
595         {
596             // srcMask <- 0xFFFFFFFFFFFFFFFF >> (64 - bitsInCurrentQuad);
597             GateRef srcMask = Int64LSR(Int64(ALL_ONE_MASK), Int64Sub(Int64(BIT_PER_QUAD), bitsInCurrentQuad));
598             // srcData <- (srcBitSet[srcQuad * 8] >> srcBitOffset) & srcMask;
599             GateRef srcData = Int64And(Int64LSR(srcQuadData, *srcBitOffset), srcMask);
600             // zeroMask <- ~(srcMask << dstBitOffset);
601             GateRef zeroMask = Int64Not(Int64LSL(srcMask, *dstBitOffset));
602             // dstData <- load from dstBitSet offset dstQuad * 8;
603             GateRef dstData = Load(VariableType::INT64(), dstBitSet, Int64LSL(*dstQuad, Int64(BYTE_PER_QUAD_LOG2)));
604             // newDataMask <- (srcData << dstBitOffset);
605             GateRef newDataMask = Int64LSL(srcData, *dstBitOffset);
606             // newData <- dstData & zeroMask | newDataMask;
607             GateRef newData = Int64Or(Int64And(dstData, zeroMask), newDataMask);
608             // bitSet[dstQuad * 8] <- newData;
609             Store(VariableType::INT64(), glue_, dstBitSet, Int64LSL(*dstQuad, Int64(BYTE_PER_QUAD_LOG2)), newData);
610             Jump(&beforeEndLoop);
611         }
612         Bind(&beforeEndLoop);
613         {
614             // remainLength <- remainLength - bitsInCurrentQuad;
615             remainLength = Int64Sub(*remainLength, bitsInCurrentQuad);
616             //  srcBitOffset <- srcBitOffset + bitsInCurrentQuad;
617             srcBitOffset = Int64Add(*srcBitOffset, bitsInCurrentQuad);
618             //  dstBitOffset <- dstBitOffset + bitsInCurrentQuad;
619             dstBitOffset = Int64Add(*dstBitOffset, bitsInCurrentQuad);
620             Label srcAdd(env);
621             Label dstAdd(env);
622             Label checkDst(env);
623             BRANCH_NO_WEIGHT(Int64Equal(*srcBitOffset, Int64(BIT_PER_QUAD)), &srcAdd, &checkDst);
624             Bind(&srcAdd);
625             {
626                 //  if srcBitOffset == 64
627                 //  then srcQuad <- srcQuad + 1; srcBitOffset <- 0
628                 srcQuad = Int64Add(*srcQuad, Int64(1));
629                 srcBitOffset = Int64(0);
630                 Jump(&checkDst);
631             }
632             Bind(&checkDst);
633             BRANCH_NO_WEIGHT(Int64Equal(*dstBitOffset, Int64(BIT_PER_QUAD)), &dstAdd, &endLoop);
634             Bind(&dstAdd);
635             {
636                 // if dstBitOffset == 64
637                 // then dstQuad <- dstQuad + 1; dstBitOffset <- 0}
638                 dstQuad = Int64Add(*dstQuad, Int64(1));
639                 dstBitOffset = Int64(0);
640                 Jump(&endLoop);
641             }
642         }
643         Bind(&endLoop);
644         LoopEnd(&begin);
645     }
646     Bind(&exit);
647     env->SubCfgExit();
648 }
649 
BitSetRangeMoveBackward(GateRef srcBitSet,GateRef dstBitSet,GateRef srcStart,GateRef dstStart,GateRef length)650 void BarrierStubBuilder::BitSetRangeMoveBackward(GateRef srcBitSet, GateRef dstBitSet, GateRef srcStart,
651                                                  GateRef dstStart, GateRef length)
652 {
653     auto env = GetEnvironment();
654     Label entry(env);
655     env->SubCfgEntry(&entry);
656     Label exit(env);
657     DEFVARIABLE(remainLength, VariableType::INT64(), length);
658     // srcEnd <- srcStart + remainLength - 1;
659     // dstEnd <- dstStart + remainLength - 1;
660     DEFVARIABLE(srcEnd, VariableType::INT64(), Int64Sub(Int64Add(srcStart, length), Int64(1)));
661     DEFVARIABLE(dstEnd, VariableType::INT64(), Int64Sub(Int64Add(dstStart, length), Int64(1)));
662 
663     Label begin(env);
664     Label body(env);
665     Label endLoop(env);
666     Jump(&begin);
667     LoopBegin(&begin);
668     //  while remainLength > 0
669     BRANCH_LIKELY(Int64GreaterThan(*remainLength, Int64(0)), &body, &exit);
670     Bind(&body);
671     {
672         Label beforeEndLoop(env);
673         // srcBitOffset <- srcEnd % 64;
674         GateRef srcBitOffset = Int64And(*srcEnd, Int64(BIT_PER_QUAD_MASK));
675         // dstBitOffset <- dstEnd % 64;
676         GateRef dstBitOffset = Int64And(*dstEnd, Int64(BIT_PER_QUAD_MASK));
677         // bitsInCurrentQuad <- min of {srcBitOffset + 1, dstBitOffset + 1, remainLength};
678         GateRef bitsInCurrentQuad = ThreeInt64Min(Int64Add(srcBitOffset, Int64(1)),
679                                                   Int64Add(dstBitOffset, Int64(1)),
680                                                   *remainLength);
681         // srcQuadIndex <- srcEnd / 64;
682         GateRef srcQuadIndex = Int64LSR(*srcEnd, Int64(BIT_PER_QUAD_LOG2));
683         GateRef srcQuadData = Load(VariableType::INT64(), srcBitSet, Int64LSL(srcQuadIndex, Int64(BYTE_PER_QUAD_LOG2)));
684         Label setValue(env);
685         BRANCH_NO_WEIGHT(Int64Equal(srcQuadData, Int64(0)), &beforeEndLoop, &setValue);
686         Bind(&setValue);
687         {
688             // mask <- 0xFFFFFFFFFFFFFFFF >> (64 - bitsInCurrentQuad);
689             GateRef mask = Int64LSR(Int64(ALL_ONE_MASK), Int64Sub(Int64(BIT_PER_QUAD), bitsInCurrentQuad));
690             //  srcData <- (srcBitSet[srcQuadIndex * 8] >> (srcBitOffset - bitsInCurrentQuad + 1)) & mask;
691             GateRef srcData = Int64And(
692                 Int64LSR(srcQuadData, Int64Add(Int64Sub(srcBitOffset, bitsInCurrentQuad), Int64(1))), mask);
693             // zeroMask <- ~(mask << (dstBitOffset - bitsInCurrentQuad + 1));
694             GateRef zeroMask = Int64Not(Int64LSL(mask, Int64Add(Int64Sub(dstBitOffset, bitsInCurrentQuad), Int64(1))));
695             // dstWordIndex <- dstEnd / 64;
696             GateRef dstQuadIndex = Int64LSR(*dstEnd, Int64(BIT_PER_QUAD_LOG2));
697             // dstData <- load from dstBitSet offset dstQuadIndex * 8
698             GateRef dstData = Load(VariableType::INT64(), dstBitSet, Int64LSL(dstQuadIndex, Int64(BYTE_PER_QUAD_LOG2)));
699             // newDataMask <- (srcData << (dstBitOffset - bitsInCurrentQuad + 1))
700             GateRef newDataMask = Int64LSL(srcData, Int64Add(Int64Sub(dstBitOffset, bitsInCurrentQuad), Int64(1)));
701             // newData <- dstData & zeroMask | newDataMask;
702             GateRef newData = Int64Or(Int64And(dstData, zeroMask), newDataMask);
703             // bitSet[dstQuadIndex * 8] <- newData;
704             Store(VariableType::INT64(), glue_, dstBitSet, Int64LSL(dstQuadIndex, Int64(BYTE_PER_QUAD_LOG2)), newData);
705             Jump(&beforeEndLoop);
706         }
707         Bind(&beforeEndLoop);
708         {
709             // remainLength <- remainLength - bitsInCurrentQuad;
710             remainLength = Int64Sub(*remainLength, bitsInCurrentQuad);
711             // srcEnd <- srcEnd - bitsInCurrentQuad;
712             srcEnd = Int64Sub(*srcEnd, bitsInCurrentQuad);
713             // dstEnd <- dstEnd - bitsInCurrentQuad;
714             dstEnd = Int64Sub(*dstEnd, bitsInCurrentQuad);
715             Jump(&endLoop);
716         }
717         Bind(&endLoop);
718         LoopEnd(&begin);
719     }
720     Bind(&exit);
721     env->SubCfgExit();
722 }
723 
DoReverseBarrier()724 void BarrierStubBuilder::DoReverseBarrier()
725 {
726     auto env = GetEnvironment();
727     Label entry(env);
728     env->SubCfgEntry(&entry);
729     Label exit(env);
730     Label handleMark(env);
731     Label handleBitSet(env);
732     Label doReverse(env);
733     BRANCH_NO_WEIGHT(Int32Equal(slotCount_, Int32(0)), &exit, &doReverse);
734     Bind(&doReverse);
735     BRANCH_NO_WEIGHT(InSharedHeap(objectRegion_), &handleMark, &handleBitSet);
736     Bind(&handleBitSet);
737     {
738         DoReverseBarrierInternal();
739         Jump(&handleMark);
740     }
741     Bind(&handleMark);
742     HandleMark();
743     Jump(&exit);
744     Bind(&exit);
745     env->SubCfgExit();
746 }
747 
DoReverseBarrierInternal()748 void BarrierStubBuilder::DoReverseBarrierInternal()
749 {
750     auto env = GetEnvironment();
751     Label entry(env);
752     env->SubCfgEntry(&entry);
753     Label exit(env);
754     Label inYoung(env);
755     Label inOld(env);
756     Label copyBitSet(env);
757 
758     DEFVARIABLE(bitSetAddr, VariableType::NATIVE_POINTER(), IntPtr(0));
759     DEFVARIABLE(bitSetAddr2, VariableType::NATIVE_POINTER(), IntPtr(0));
760 
761     GateRef localToShareOffset = IntPtr(Region::PackedData::GetLocalToShareSetOffset(env->Is32Bit()));
762     GateRef localToShareBitSetAddr =
763         GetBitSetDataAddr(objectRegion_, localToShareOffset, RTSTUB_ID(CreateLocalToShare));
764 
765     GateRef localToShareSwapped = IsLocalToShareSwapped(objectRegion_);
766     BRANCH_NO_WEIGHT(InYoungGeneration(objectRegion_), &inYoung, &inOld);
767     Bind(&inYoung);
768     {
769         Label batchBarrier(env);
770         Label reverseLocalToShare(env);
771         BRANCH_UNLIKELY(localToShareSwapped, &batchBarrier, &reverseLocalToShare);
772         Bind(&batchBarrier);
773         {
774             // slowpath, localToShareRSet is swapped, it can't be reversed, just set the bitset bit by bit.
775             BarrierBatchBitSet(LocalToShared);
776             Jump(&exit);
777         }
778         Bind(&reverseLocalToShare);
779         {
780             bitSetAddr = localToShareBitSetAddr;
781             Jump(&copyBitSet);
782         }
783     }
784     Bind(&inOld);
785     {
786         GateRef oldToNewOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env->Is32Bit()));
787         GateRef oldToNewBitSetAddr = GetBitSetDataAddr(objectRegion_, oldToNewOffset, RTSTUB_ID(CreateOldToNew));
788         // CreateOldToNew may change the RSetFlag, so load it again.
789         GateRef oldToNewSwapped = IsOldToNewSwapped(objectRegion_);
790         Label batchBarrier(env);
791         Label tryBatchBarrier(env);
792         Label copyBoth(env);
793         // both localToShareSwapped and oldToNewSwapped are not swapped.
794         BRANCH_LIKELY(BitAnd(BoolNot(localToShareSwapped), BoolNot(oldToNewSwapped)), &copyBoth, &tryBatchBarrier);
795         Bind(&copyBoth);
796         {
797             bitSetAddr = localToShareBitSetAddr;
798             bitSetAddr2 = oldToNewBitSetAddr;
799             Jump(&copyBitSet);
800         }
801         Bind(&tryBatchBarrier);
802         {
803             Label reverseOne(env);
804             BRANCH_UNLIKELY(BitAnd(localToShareSwapped, oldToNewSwapped), &batchBarrier, &reverseOne);
805             Bind(&batchBarrier);
806             {
807                 // slowpath, localToShareRSet and oldToNewRSet are swapped,
808                 // it can't be reversed, just set the bitset bit by bit.
809                 BarrierBatchBitSet(LocalToShared | OldToNew);
810                 Jump(&exit);
811             }
812             Bind(&reverseOne);
813             {
814                 Label localToShareBatchBarrier(env);
815                 Label oldToNewBatchBarrier(env);
816                 BRANCH_NO_WEIGHT(localToShareSwapped, &localToShareBatchBarrier, &oldToNewBatchBarrier);
817                 Bind(&localToShareBatchBarrier);
818                 {
819                     // slowpath, localToShareRSet is swapped, it can't be reversed, just set the bitset bit by bit.
820                     // And copy oldToNewRSet.
821                     BarrierBatchBitSet(LocalToShared);
822                     bitSetAddr = oldToNewBitSetAddr;
823                     Jump(&copyBitSet);
824                 }
825                 Bind(&oldToNewBatchBarrier);
826                 {
827                     // slowpath, oldToNewRSet is swapped, it can't be reversed, just set the bitset bit by bit.
828                     // And copy localToShareRSet.
829                     BarrierBatchBitSet(OldToNew);
830                     bitSetAddr = localToShareBitSetAddr;
831                     Jump(&copyBitSet);
832                 }
833             }
834         }
835     }
836     Bind(&copyBitSet);
837     {
838         GateRef dstBitStartIdx = Int64LSR(Int64Sub(dstAddr_, objectRegion_), Int64(TAGGED_TYPE_SIZE_LOG));
839         Label begin(env);
840         Label endLoop(env);
841         Label next(env);
842         Jump(&begin);
843         LoopBegin(&begin);
844         {
845             BitSetRangeReverse(*bitSetAddr, dstBitStartIdx, ZExtInt32ToInt64(slotCount_));
846             BRANCH_UNLIKELY(IntPtrEqual(*bitSetAddr2, IntPtr(0)), &exit, &next);
847             Bind(&next);
848             {
849                 bitSetAddr = *bitSetAddr2;
850                 bitSetAddr2 = IntPtr(0);
851                 Jump(&endLoop);
852             }
853         }
854         Bind(&endLoop);
855         LoopEnd(&begin);
856     }
857     Bind(&exit);
858     env->SubCfgExit();
859 }
860 
BitSetRangeReverse(GateRef bitSet,GateRef startIdx,GateRef length)861 void BarrierStubBuilder::BitSetRangeReverse(GateRef bitSet, GateRef startIdx, GateRef length)
862 {
863     auto env = GetEnvironment();
864     Label entry(env);
865     env->SubCfgEntry(&entry);
866     Label exit(env);
867     // startOf <- startIdx % 64
868     GateRef startOf = Int64And(startIdx, Int64(BIT_PER_QUAD_MASK));
869     // endOf <- (startIdx + len) % 64
870     GateRef endOf = Int64And(Int64Add(startIdx, length), Int64(BIT_PER_QUAD_MASK));
871 
872     // startItemIndex <- startIdx / 64
873     GateRef startItemIndex = Int64LSR(startIdx, Int64(BIT_PER_QUAD_LOG2));
874     // endItemIndex <- (startIdx + len - 1) / 64
875     GateRef endItemIndex = Int64LSR(Int64Sub(Int64Add(startIdx, length), Int64(1)), Int64(BIT_PER_QUAD_LOG2));
876 
877     GateRef dstOffset = startIdx;
878     // srcOffset <- startIdx + ((64 - endOf) % 64 - startOf)
879     GateRef srcOffset = Int64Add(startIdx,
880         Int64Sub(Int64And(Int64Sub(Int64(BIT_PER_QUAD), endOf), Int64(BIT_PER_QUAD_MASK)), startOf));
881 
882     // startByteIndex <- startItemIndex * 8
883     GateRef startByteIndex = Int64LSL(startItemIndex, Int64(BIT_PER_BYTE_LOG2));
884     // endByteIndex <- endItemIndex * 8
885     GateRef endByteIndex = Int64LSL(endItemIndex, Int64(BIT_PER_BYTE_LOG2));
886 
887     GateRef startItem = Load(VariableType::INT64(), bitSet, startByteIndex);
888     GateRef endItem = Load(VariableType::INT64(), bitSet, endByteIndex);
889 
890     // startMask <- (1 << startOf) - 1
891     GateRef startMask = Int64Sub(Int64LSL(Int64(1), startOf), Int64(1));
892     // endMask <- ~((1 << endOf) - 1)
893     GateRef endMask = Int64Not(Int64Sub(Int64LSL(Int64(1), endOf), Int64(1)));
894 
895     DEFVARIABLE(vstartByteIndex, VariableType::INT64(), startByteIndex);
896     DEFVARIABLE(vendByteIndex, VariableType::INT64(), endByteIndex);
897 
898     Label loopBegin1(env);
899     Label loopEnd1(env);
900     Label loopExit1(env);
901     Label startReverse(env);
902     Jump(&loopBegin1);
903     LoopBegin(&loopBegin1);
904     {
905         BRANCH_LIKELY(Int64LessThanOrEqual(*vstartByteIndex, *vendByteIndex), &startReverse, &loopExit1);
906         Bind(&startReverse);
907         {
908             GateRef item1 = Load(VariableType::INT64(), bitSet, *vstartByteIndex);
909             GateRef item2 = Load(VariableType::INT64(), bitSet, *vendByteIndex);
910 
911             // revStart <- Int64BitReverse(bitSet[vstartByteIndex])
912             // revEnd <- Int64BitReverse(bitSet[vendByteIndex])
913             GateRef revStart = Int64BitReverse(item1);
914             GateRef revEnd = Int64BitReverse(item2);
915 
916             // bitSet[vstartByteIndex] <- revEnd
917             // bitSet[vendByteIndex] <- revStart
918             Store(VariableType::INT64(), glue_, bitSet, *vstartByteIndex, revEnd, MemoryAttribute::NoBarrier());
919             Store(VariableType::INT64(), glue_, bitSet, *vendByteIndex, revStart, MemoryAttribute::NoBarrier());
920 
921             // vstartByteIndex <- vstartByteIndex + 8
922             // vendByteIndex <- vendByteIndex - 8
923             vstartByteIndex = Int64Add(*vstartByteIndex, Int64(BYTE_PER_QUAD));
924             vendByteIndex = Int64Sub(*vendByteIndex, Int64(BYTE_PER_QUAD));
925             Jump(&loopEnd1);
926         }
927     }
928     Bind(&loopEnd1);
929     LoopEnd(&loopBegin1);
930     Bind(&loopExit1);
931     BitSetRangeMove(bitSet, bitSet, srcOffset, dstOffset, length);
932 
933     GateRef neStartMask = Int64Not(startMask);
934     GateRef neEndMask = Int64Not(endMask);
935 
936     // bitSet[startByteIndex] <- (startItem & startMask) | (startItem1 & neStartMask);
937     GateRef startItem1 = Load(VariableType::INT64(), bitSet, startByteIndex);
938     GateRef resStartItem = Int64Or(Int64And(startItem, startMask), Int64And(startItem1, neStartMask));
939     Store(VariableType::INT64(), glue_, bitSet, startByteIndex, resStartItem, MemoryAttribute::NoBarrier());
940 
941     // bitSet[endByteIndex] <- (resEndItem & endMask) | (endItem1 & neStartMask);
942     GateRef endItem1 = Load(VariableType::INT64(), bitSet, endByteIndex);
943     GateRef resEndItem = Int64Or(Int64And(endItem, endMask), Int64And(endItem1, neEndMask));
944     Store(VariableType::INT64(), glue_, bitSet, endByteIndex, resEndItem, MemoryAttribute::NoBarrier());
945     Jump(&exit);
946     Bind(&exit);
947     env->SubCfgExit();
948 }
949 
IsLocalToShareSwapped(GateRef region)950 GateRef BarrierStubBuilder::IsLocalToShareSwapped(GateRef region)
951 {
952     auto env = GetEnvironment();
953     GateRef RSetSwapFlagOffset = IntPtr(Region::PackedData::GetRSetSwapFlagOffset(env->Is32Bit()));
954     GateRef RSetFlag = Load(VariableType::INT8(), region, RSetSwapFlagOffset);
955     return NotEqual(Int8And(RSetFlag, Int8(LOCAL_TO_SHARE_SWAPPED_MASK)), Int8(0));
956 }
957 
IsOldToNewSwapped(GateRef region)958 GateRef BarrierStubBuilder::IsOldToNewSwapped(GateRef region)
959 {
960     auto env = GetEnvironment();
961     GateRef RSetSwapFlagOffset = IntPtr(Region::PackedData::GetRSetSwapFlagOffset(env->Is32Bit()));
962     GateRef RSetFlag = Load(VariableType::INT8(), region, RSetSwapFlagOffset);
963     return NotEqual(Int8And(RSetFlag, Int8(OLD_TO_NEW_SWAPPED_MASK)), Int8(0));
964 }
965 }
966