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, ¬InYoung);
69 Bind(¬InYoung);
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, ©LocalToShare);
330 Bind(©LocalToShare);
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, ©LocalToShare);
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(©LocalToShare);
430 {
431 dstBitSetAddr = localToShareBitSetAddr;
432 srcBitSetAddr = srcLocalToShareBitSetAddr;
433 Jump(©BitSet);
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)), ©Both, &tryBatchBarrier);
448 Bind(©Both);
449 {
450 dstBitSetAddr = localToShareBitSetAddr;
451 srcBitSetAddr = srcLocalToShareBitSetAddr;
452 dstBitSetAddr2 = oldToNewBitSetAddr;
453 srcBitSetAddr2 = srcOldToNewBitSetAddr;
454 Jump(©BitSet);
455 }
456 Bind(&tryBatchBarrier);
457 {
458 Label copyOne(env);
459 BRANCH_UNLIKELY(BitAnd(localToShareSwapped, oldToNewSwapped), &batchBarrier, ©One);
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(©One);
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(©BitSet);
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(©BitSet);
489 }
490 }
491 }
492 }
493 Bind(©BitSet);
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(©BitSet);
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)), ©Both, &tryBatchBarrier);
795 Bind(©Both);
796 {
797 bitSetAddr = localToShareBitSetAddr;
798 bitSetAddr2 = oldToNewBitSetAddr;
799 Jump(©BitSet);
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(©BitSet);
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(©BitSet);
832 }
833 }
834 }
835 }
836 Bind(©BitSet);
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