!9078 Add asm shared barrier

Merge pull request !9078 from zhouguangyuan0718/master-asm-share-barrier
This commit is contained in:
openharmony_ci 2024-09-05 17:46:07 +00:00 committed by Gitee
commit 02edc6ddb0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
15 changed files with 377 additions and 31 deletions

View File

@ -1019,6 +1019,11 @@ void AssemblerAarch64::Tbnz(const Register &rt, int32_t bitPos, int32_t imm)
EmitU32(code);
}
void AssemblerAarch64::Tst(const Register& rn, const Operand& operand)
{
Ands(Register(Zero, rn.GetType()), rn, operand);
}
void AssemblerAarch64::Tst(const Register &rn, const LogicalImmediate &imm)
{
Ands(Register(Zero, rn.GetType()), rn, imm);

View File

@ -866,6 +866,14 @@ void AssemblerX64::Movl(const Operand &src, Register dst)
EmitOperand(dst, src);
}
void AssemblerX64::Movl(Register src, const Operand& dst)
{
EmitRexPrefixl(src, dst);
// 0x89: Move r32 to r/m64
EmitU8(0x89);
EmitOperand(src, dst);
}
void AssemblerX64::Testq(Immediate src, Register dst)
{
if (InRange8(src.Value())) {
@ -1011,6 +1019,16 @@ void AssemblerX64::Shrq(Immediate src, Register dst)
EmitI8(static_cast<int8_t>(src.Value()));
}
void AssemblerX64::Shrl(Immediate src, Register dst)
{
EmitRexPrefix(dst);
// C1 : Shr r/m32, imm8;
EmitU8(0xc1);
// 5: C1 /5 id
EmitModrm(5, dst);
EmitI8(static_cast<int8_t>(src.Value()));
}
void AssemblerX64::Shr(Immediate src, Register dst)
{
Shrq(src, dst);
@ -1278,6 +1296,16 @@ void AssemblerX64::Movzbl(const Operand &src, Register dst)
EmitOperand(dst, src);
}
void AssemblerX64::Movzbl(Register src, Register dst)
{
EmitRexPrefixl(dst, src);
// 0F B6 : Movzx r64, r/m16
EmitU8(0x0F);
EmitU8(0xB6);
// 0F B6 /r: Movzx r64, r/m16
EmitModrm(dst, src);
}
void AssemblerX64::Btq(Immediate src, Register dst)
{
EmitRexPrefixW(dst);
@ -1327,6 +1355,16 @@ void AssemblerX64::Shlq(Immediate src, Register dst)
EmitI8(static_cast<int8_t>(src.Value()));
}
void AssemblerX64::Btsl(Register src, Register dst)
{
EmitRexPrefixl(src, dst);
// 0F AB: bts r32, r32;
EmitU8(0x0F);
EmitU8(0xAB);
EmitModrm(src, dst);
}
void AssemblerX64::Int3()
{
// CC :: INT3

View File

@ -143,13 +143,17 @@ public:
void Leal(const Operand &src, Register dst);
void Movl(Register src, Register dst);
void Movl(const Operand &src, Register dst);
void Movl(Register dst, const Operand& src);
void Movzbq(const Operand &src, Register dst);
void Movzbl(const Operand &src, Register dst);
void Movzbl(Register src, Register dst);
void Movabs(uint64_t src, Register dst);
void Shrq(Immediate src, Register dst);
void Shrl(Immediate src, Register dst);
void Shr(Immediate src, Register dst);
void Shll(Immediate src, Register dst);
void Shlq(Immediate src, Register dst);
void Btsl(Register src, Register dst);
void Testq(Immediate src, Register dst);
void Testb(Immediate src, Register dst);
void Int3();

View File

@ -840,6 +840,11 @@ DEF_CALL_SIGNATURE(ASMWriteBarrierWithEden)
callSign->SetTargetKind(CallSignature::TargetKind::ASM_CALL_BARRIER_STUB);
}
DEF_CALL_SIGNATURE(VerifyBarrier)
{
SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(VerifyBarrier);
}
#undef SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON
DEF_CALL_SIGNATURE(NewThisObjectChecked)

View File

@ -629,7 +629,8 @@ private:
V(ConvertCharToInt32) \
V(ConvertCharToDouble) \
V(ASMFastWriteBarrier) \
V(ASMWriteBarrierWithEden)
V(ASMWriteBarrierWithEden) \
V(VerifyBarrier)
#define DECL_CALL_SIGNATURE(name) \
class name##CallSignature final { \

View File

@ -117,7 +117,8 @@ namespace panda::ecmascript::kungfu {
V(ConvertCharToDouble) \
V(DeleteObjectProperty) \
V(SameValue) \
V(StringIteratorNext)
V(StringIteratorNext) \
V(VerifyBarrier)
#define COMMON_STUB_ID_LIST(V) \
COMMON_STUB_LIST(V)

View File

@ -889,6 +889,16 @@ void SetSValueWithBarrierStubBuilder::GenerateCircuit()
Return();
}
void VerifyBarrierStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
GateRef obj = TaggedArgument(1);
GateRef offset = PtrArgument(2); // 2 : 3rd para
GateRef value = TaggedArgument(3); // 3 : 4th para
VerifyBarrier(glue, obj, offset, value);
Return();
}
void NewThisObjectCheckedStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);

View File

@ -750,8 +750,7 @@ public:
bool enableLog = data->GetLog()->EnableMethodCIRLog();
Scheduler::Run(data->GetCircuit(), data->GetCfg(), data->GetMethodName(), enableLog);
Chunk chunk(data->GetNativeAreaAllocator());
// disable fast barrier for stub, need fix for local2share barrier.
PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, false).Run(data->GetCfg());
PostSchedule(data->GetCircuit(), enableLog, data->GetMethodName(), &chunk, true).Run(data->GetCfg());
return true;
}
};

View File

@ -539,6 +539,14 @@ void PostSchedule::LoweringStoreUnknownBarrierAndPrepareScheduleGate(GateRef gat
GateRef target = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, index, GateType::NJSValue());
GateRef reseverdFrameArgs = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
GateRef reseverdPc = circuit_->GetConstantGateWithoutCache(MachineType::I64, 0, GateType::NJSValue());
#ifndef NDEBUG
GateRef verifyTarget = circuit_->GetConstantGateWithoutCache(MachineType::ARCH, CommonStubCSigns::VerifyBarrier,
GateType::NJSValue());
const CallSignature* verifyBarrierCs = CommonStubCSigns::Get(CommonStubCSigns::VerifyBarrier);
GateRef verifyBarrier = builder_.Call(verifyBarrierCs, glue, verifyTarget, builder_.GetDepend(),
{glue, base, offset, value, reseverdFrameArgs, reseverdPc},
Circuit::NullGate(), "verify barrier");
#endif
GateRef storeBarrier = builder_.Call(cs, glue, target, builder_.GetDepend(),
{ glue, base, offset, value, reseverdFrameArgs, reseverdPc },
Circuit::NullGate(), comment.data());
@ -547,6 +555,9 @@ void PostSchedule::LoweringStoreUnknownBarrierAndPrepareScheduleGate(GateRef gat
GateRef ordinaryBlock = isHeapObject.GetControl();
PrepareToScheduleNewGate(ordinaryBlock, barrierBBGates);
PrepareToScheduleNewGate(storeBarrier, barrierBBGates);
#ifndef NDEBUG
PrepareToScheduleNewGate(verifyBarrier, barrierBBGates);
#endif
PrepareToScheduleNewGate(reseverdFrameArgs, barrierBBGates);
PrepareToScheduleNewGate(reseverdPc, barrierBBGates);
PrepareToScheduleNewGate(ifTrue, barrierBBGates);

View File

@ -1786,6 +1786,28 @@ void StubBuilder::SetValueWithRep(
return;
}
void StubBuilder::VerifyBarrier(GateRef glue, GateRef obj, [[maybe_unused]] GateRef offset, GateRef value)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
// ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj.
GateRef objectRegion = ObjectAddressToRange(obj);
GateRef valueRegion = ObjectAddressToRange(value);
Label fatal(env);
Label noFatal(env);
int msgId = GET_MESSAGE_STRING_ID(SharedObjectRefersLocalObject);
BRANCH(BoolAnd(InSharedHeap(objectRegion), BoolNot(InSharedHeap(valueRegion))), &fatal, &exit);
Bind(&fatal);
{
FatalPrint(glue, {Int32(msgId)});
Jump(&exit);
}
Bind(&exit);
env->SubCfgExit();
}
void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, bool withEden,
MemoryAttribute::ShareFlag share)
{

View File

@ -731,6 +731,7 @@ ShortcutBoolOr([&]{ return first; }, [&]{ return second; })
GateRef IntPtrEuqal(GateRef x, GateRef y);
void SetValueWithAttr(GateRef glue, GateRef obj, GateRef offset, GateRef key, GateRef value, GateRef attr);
void SetValueWithRep(GateRef glue, GateRef obj, GateRef offset, GateRef value, GateRef rep, Label *repChange);
void VerifyBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value);
void SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, bool withEden = false,
MemoryAttribute::ShareFlag share = MemoryAttribute::UNKNOWN);
GateRef GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index,

View File

@ -1195,7 +1195,7 @@ void AsmInterpreterCall::PreserveMostCall(ExtendedAssembler* assembler)
// Skip x0 slot and frametype slot
__ Add(SP, SP, Immediate(DOUBLE_SLOT_SIZE * PreserveRegPairIndex +
FRAME_SLOT_SIZE + FRAME_SLOT_SIZE));
__ Ldp(X29, X30, MemoryOperand(SP, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
__ Ldp(FP, X30, MemoryOperand(SP, DOUBLE_SLOT_SIZE, AddrMode::POSTINDEX));
__ Ret();
}
}
@ -1214,7 +1214,7 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
// region flag: 0x08, 0x09, [0x0A, 0x11], [0x12, 0x15], 0x16
// value is share: [0x12, 0x16] => valueMaybeSweepableShare
// readonly share: 0x16 => return
// sweepable share: [0x12, 0x15] => needCallShare
// sweepable share: [0x12, 0x15] => needShareBarrier
// value is not share: 0x08, 0x09, [0x0A, 0x11], => valueNotShare
// value is young : 0x09 => needCallNotShare
// value is not young : 0x08, [0x0A, 0x11], => checkMark
@ -1225,7 +1225,7 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
Label needCall;
Label checkMark;
Label needCallNotShare;
Label needCallShare;
Label needShareBarrier;
Label valueNotShare;
Label valueMaybeSweepableShare;
{
@ -1289,21 +1289,14 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
{
// valueMaybeSweepableShare:
// if (valueFlag != IN_SHARED_READ_ONLY_SPACE){
// goto needCallShare
// goto needShareBarrier
// }
// return
__ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::IN_SHARED_READ_ONLY_SPACE));
__ B(NE, &needCallShare);
__ B(NE, &needShareBarrier);
__ Ret();
}
__ Bind(&needCallShare);
{
int32_t SValueBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
kungfu::CommonStubCSigns::SetSValueWithBarrier * FRAME_SLOT_SIZE;
__ Mov(X15, SValueBarrierOffset);
__ B(&needCall);
}
__ Bind(&needCallNotShare);
{
int32_t NonSValueBarrier = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
@ -1315,6 +1308,10 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
__ Ldr(X15, MemoryOperand(X0, Register(X15), UXTX));
PreserveMostCall(assembler);
}
__ Bind(&needShareBarrier);
{
ASMFastSharedWriteBarrier(assembler, needCall);
}
}
// ASMWriteBarrierWithEden(GateRef glue, GateRef obj, GateRef offset, GateRef value)
@ -1334,6 +1331,128 @@ void AsmInterpreterCall::ASMWriteBarrierWithEden(ExtendedAssembler* assembler)
PreserveMostCall(assembler);
}
// %x0 - glue
// %x1 - obj
// %x2 - offset
// %x3 - value
void AsmInterpreterCall::ASMFastSharedWriteBarrier(ExtendedAssembler* assembler, Label& needCall)
{
Label checkBarrierForSharedValue;
Label restoreScratchRegister;
Label callSharedBarrier;
{
// int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
// int8_t objFlag = *objRegion
// if (objFlag >= SHARED_SPACE_BEGIN){
// // share to share, just check the barrier
// goto checkBarrierForSharedValue
// }
__ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize));
__ Ldrb(Register(X15, W), MemoryOperand(X15, 0));
// X15 is the flag load from region of obj.
__ Cmp(Register(X15, W), Immediate(RegionSpaceFlag::SHARED_SPACE_BEGIN));
__ B(GE, &checkBarrierForSharedValue); // if objflag >= SHARED_SPACE_BEGIN => checkBarrierForSharedValue
}
{
// int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
// int8_t *localToShareSet = *(objRegion + LocalToShareSetOffset)
// if (localToShareSet == 0){
// goto callSharedBarrier
// }
__ And(X15, X1, LogicalImmediate::Create(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), RegXSize));
__ Ldr(X15, MemoryOperand(X15, Region::PackedData::GetLocalToShareSetOffset(false)));
// X15 is localToShareSet for obj region.
__ Cbz({X15, X}, &callSharedBarrier); // if localToShareSet == 0 => callSharedBarrier
}
{
// X16, X17 will be used as scratch register, spill them.
// the caller will call this function with inline asm, it will not save any registers except x15.
// So we need spill and restore x16, x17 when we need them as scratch register.
{
__ Stp(X16, X17, MemoryOperand(SP, -DOUBLE_SLOT_SIZE, PREINDEX));
}
// int64_t objOffset = obj & DEFAULT_REGION_MASK
// int64_t slotOffset = objOffset + offset
__ And(X16, X1, LogicalImmediate::Create(DEFAULT_REGION_MASK, RegXSize));
__ Add(X16, X16, Operand(Register(X2)));
// the logic to get mask in stub_builder.cpp
// [63-------------------------35][34------------------------8][7---3][2-0]
// bitOffset: bbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc
// bitPerWordMask: 11 111
// indexInWord = And bitoffset bitPerWordMask
// indexInWord: cc ccc
// mask = 1 << indexInWord
// the logic to test bit set value here:
// [63-------------------------35][34------------------------8][7---3][2-0]
// slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd
// Ubfm X16 slotOffset 3 7
// indexInWord: cc ccc
__ Ubfm(X17, X16, TAGGED_TYPE_SIZE_LOG, TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2 - 1);
// the logic to get byteIndex in stub_builder.cpp
// [63-------------------------35][34------------------------8][7---3][2-0]
// slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd
// 1. bitOffsetPtr = LSR TAGGED_TYPE_SIZE_LOG(3) slotOffset
// bitOffsetPtr: aaaaaaaaaaaaaaaaaaaaaaaaaa aaabbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc
// 2. bitOffset = TruncPtrToInt32 bitOffsetPtr
// bitOffset: bbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc
// 3. index = LSR BIT_PER_WORD_LOG2(5) bitOffset
// index: bbbbbbbbbbbbbbbbbbb bbbbb bbb
// 4. byteIndex = Mul index BYTE_PER_WORD(4)
// byteIndex: bbbbbbbbbbbbbbbbbbbbb bbbbb b00
// the logic to get byteIndex here:
// [63-------------------------35][34------------------------8][7---3][2-0]
// slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd
// Ubfm X16 slotOffset 8 34
// index: bbbbbbbbbbbbbbbbbbb bbbbb bbb
__ Ubfm(X16, X16, TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2,
sizeof(uint32_t) * GCBitset::BIT_PER_BYTE + TAGGED_TYPE_SIZE_LOG - 1);
__ Add(X15, X15, Operand(Register(X16), LSL, GCBitset::BYTE_PER_WORD_LOG2));
__ Add(X15, X15, Immediate(RememberedSet::GCBITSET_DATA_OFFSET));
// X15 is the address of bitset value. X15 = X15 + X16 << BYTE_PER_WORD_LOG2 + GCBITSET_DATA_OFFSET
// mask = 1 << indexInWord
__ Mov(Register(X16, W), 1);
__ Lsl(Register(X17, W), Register(X16, W), Register(X17, W)); // X17 is the mask
__ Ldr(Register(X16, W), MemoryOperand(X15, 0)); // x16: oldsetValue
__ Tst(Register(X16, W), Register(X17, W));
__ B(NE, &restoreScratchRegister);
__ Orr(Register(X16, W), Register(X16, W), Register(X17, W));
__ Str(Register(X16, W), MemoryOperand(X15, 0));
}
__ Bind(&restoreScratchRegister);
{
__ Ldp(X16, X17, MemoryOperand(SP, DOUBLE_SLOT_SIZE, POSTINDEX));
}
__ Bind(&checkBarrierForSharedValue);
{
// checkBarrierForSharedValue:
// int8_t GCStateBitField = *(glue+SharedGCStateBitFieldOffset)
// if (GCStateBitField & JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK != 0) {
// goto callSharedBarrier
// }
// return
__ Mov(X15, JSThread::GlueData::GetSharedGCStateBitFieldOffset(false));
__ Ldrb(Register(X15, W), MemoryOperand(X0, Register(X15), UXTX));
static_assert(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK == 1 && "Tbnz can't handle other bit mask");
__ Tbnz(Register(X15, W), 0, &callSharedBarrier);
// if GCState is not READY_TO_MARK, go to needCallNotShare.
__ Ret();
}
__ Bind(&callSharedBarrier);
{
int32_t SValueBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
kungfu::CommonStubCSigns::SetSValueWithBarrier * FRAME_SLOT_SIZE;
__ Mov(X15, SValueBarrierOffset);
__ B(&needCall);
}
}
// Generate code for generator re-entering asm interpreter
// c++ calling convention
// Input: %X0 - glue

View File

@ -217,6 +217,8 @@ public:
static void ASMFastWriteBarrier(ExtendedAssembler *assembler);
static void ASMWriteBarrierWithEden(ExtendedAssembler *assembler);
static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label& needCall);
private:
static void PushCallThis(ExtendedAssembler *assembler, JSCallMode mode,
Label *stackOverflow, FrameTransitionType type);

View File

@ -1495,7 +1495,7 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
// region flag: 0x08, 0x09, [0x0A, 0x11], [0x12, 0x14], 0x15
// value is share: [0x12, 0x15] => valueMaybeSweepableShare
// readonly share: 0x15 => return
// sweepable share: [0x12, 0x14] => needCallShare
// sweepable share: [0x12, 0x14] => needShareBarrier
// value is not share: 0x08, 0x09, [0x0A, 0x11], => valueNotShare
// value is young : 0x09 => needCallNotShare
// value is not young : 0x08, [0x0A, 0x11], => checkMark
@ -1506,7 +1506,7 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
Label needCall;
Label checkMark;
Label needCallNotShare;
Label needCallShare;
Label needShareBarrier;
Label valueNotShare;
Label valueMaybeSweepableShare;
{
@ -1567,21 +1567,14 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
{
// valueMaybeSweepableShare:
// if (valueFlag != IN_SHARED_READ_ONLY_SPACE){
// goto needCallShare
// goto needShareBarrier
// }
// return
__ Cmpl(Immediate(RegionSpaceFlag::IN_SHARED_READ_ONLY_SPACE), r11);
__ Jne(&needCallShare);
__ Jne(&needShareBarrier);
__ Ret();
}
__ Bind(&needCallShare);
{
int32_t SValueBarrierOffset = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
kungfu::CommonStubCSigns::SetSValueWithBarrier * FRAME_SLOT_SIZE;
__ Movq(Operand(rdi, SValueBarrierOffset), r11);
__ Jmp(&needCall);
}
__ Bind(&needCallNotShare);
{
int32_t NonSValueBarrier = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
@ -1592,14 +1585,18 @@ void AsmInterpreterCall::ASMFastWriteBarrier(ExtendedAssembler* assembler)
{
PreserveMostCall(assembler);
}
__ Bind(&needShareBarrier);
{
ASMFastSharedWriteBarrier(assembler, needCall);
}
}
// ASMWriteBarrierWithEden(GateRef glue, GateRef obj, GateRef offset, GateRef value)
// c calling convention, but preserve all general registers except %x15
// %x0 - glue
// %x1 - obj
// %x2 - offset
// %x3 - value
// %rd1 - glue
// %rsi - obj
// %rdx - offset
// %rcx - value
void AsmInterpreterCall::ASMWriteBarrierWithEden(ExtendedAssembler* assembler)
{
__ BindAssemblerStub(RTSTUB_ID(ASMWriteBarrierWithEden));
@ -1610,6 +1607,136 @@ void AsmInterpreterCall::ASMWriteBarrierWithEden(ExtendedAssembler* assembler)
PreserveMostCall(assembler);
}
// %rd1 - glue
// %rsi - obj
// %rdx - offset
// %rcx - value
void AsmInterpreterCall::ASMFastSharedWriteBarrier(ExtendedAssembler* assembler, Label& needcall)
{
Label checkBarrierForSharedValue;
Label restoreScratchRegister;
Label callSharedBarrier;
{
// int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
// int8_t objFlag = *objRegion
// if (objFlag >= SHARED_SPACE_BEGIN){
// // share to share, just check the barrier
// goto checkBarrierForSharedValue
// }
__ Movabs(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), r11); // r11 is the mask to get the region.
__ And(rsi, r11); // r11: region address of obj.
__ Movzbl(Operand(r11, 0), r11); // r11: the flag load from region of obj.
__ Cmpl(Immediate(RegionSpaceFlag::SHARED_SPACE_BEGIN), r11);
__ Jae(&checkBarrierForSharedValue); // if objflag >= SHARED_SPACE_BEGIN => checkBarrierForSharedValue
}
{
// int8_t *objRegion = obj & (~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK))
// int8_t *localToShareSet = *(objRegion + LocalToShareSetOffset)
// if (localToShareSet == 0){
// goto callSharedBarrier
// }
__ Movabs(~(JSTaggedValue::TAG_MARK | DEFAULT_REGION_MASK), r11); // r11 is the mask to get the region.
__ And(rsi, r11); // r11: region address of obj.
__ Movq(Operand(r11, Region::PackedData::GetLocalToShareSetOffset(false)), r11);
// r11 is localToShareSet for obj region.
__ Cmpq(Immediate(0), r11);
__ Je(&callSharedBarrier); // if localToShareSet == 0 => callSharedBarrier
}
{
// r12, r13 will be used as scratch register, spill them.
{
__ Pushq(r12);
__ Pushq(r13);
}
// int64_t objOffset = obj & DEFAULT_REGION_MASK
// int64_t slotOffset = objOffset + offset
// int8_t lowSlotOffset = slotOffset & 0xff
__ Movabs(DEFAULT_REGION_MASK, r12);
__ And(rsi, r12); // obj & DEFAULT_REGION_MASK => r12 is obj's offset to region
__ Addq(rdx, r12); // r12 is slotAddr's offset to region
__ Movzbl(r12, r13); // r13 is low 8 bit of slotAddr's offset to region
// the logic to get byteIndex in stub_builder.cpp
// [63-------------------------35][34------------------------8][7---3][2-0]
// slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd
// 1. bitOffsetPtr = LSR TAGGED_TYPE_SIZE_LOG(3) slotOffset
// bitOffsetPtr: aaaaaaaaaaaaaaaaaaaaaaaaaa aaabbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc
// 2. bitOffset = TruncPtrToInt32 bitOffsetPtr
// bitOffset: bbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc
// 3. index = LSR BIT_PER_WORD_LOG2(5) bitOffset
// index: bbbbbbbbbbbbbbbbbbb bbbbb bbb
// 4. byteIndex = Mul index BYTE_PER_WORD(4)
// byteIndex: bbbbbbbbbbbbbbbbbbbbb bbbbb b00
// the logic to get byteIndex here:
// [63-------------------------35][34------------------------8][7---3][2-0]
// slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd
// 1. LSR (TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2 - GCBitset::BYTE_PER_WORD_LOG2)(6) slotOffset
// r12: aaaaaaaaaaaaaaaaaaaaaaa aaaaaabbbbbbbbbbbbbbbbbbbbb bbbbb bcc
// indexMask: 00000000000000000000000000000 000000111111111111111111111 11111 100
// 2. And r12 indexMask
// byteIndex: bbbbbbbbbbbbbbbbbbbbb bbbbb b00
constexpr uint32_t byteIndexMask = static_cast<uint32_t>(0xffffffffffffffff >> TAGGED_TYPE_SIZE_LOG) >>
GCBitset::BIT_PER_WORD_LOG2 << GCBitset::BYTE_PER_WORD_LOG2;
static_assert(byteIndexMask == 0x1ffffffc && "LocalToShareSet is changed?");
__ Shrq(TAGGED_TYPE_SIZE_LOG + GCBitset::BIT_PER_WORD_LOG2 - GCBitset::BYTE_PER_WORD_LOG2, r12);
__ Andq(byteIndexMask, r12); // r12 is byteIndex
__ Addq(RememberedSet::GCBITSET_DATA_OFFSET, r11); // r11 is bitsetData addr
__ Addq(r12, r11); // r11 is the addr of bitset value
__ Movl(Operand(r11, 0), r12); // r12: oldsetValue
// the logic to get mask in stub_builder.cpp
// [63-------------------------35][34------------------------8][7---3][2-0]
// bitOffset: bbbbbbbbbbbbbbbbbbbbbbbb bbbcc ccc
// bitPerWordMask: 11 111
// indexInWord = And bitoffset bitPerWordMask
// indexInWord: cc ccc
// mask = 1 << indexInWord
// the logic to test bit set value here:
// [63-------------------------35][34------------------------8][7---3][2-0]
// slotOffset: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbb ccccc ddd
// lowSlotOffset: ccccc ddd
// indexInWord = Shrl TAGGED_TYPE_SIZE_LOG lowSlotOffset
// indexInWord: cc ccc
__ Shrl(TAGGED_TYPE_SIZE_LOG, r13);
// if "r13" position in r12 is 1, goto restoreScratchRegister;
// if "r13" position in r12 is 0, set it to 1 and store r12 to r11(addr of bitset value)
__ Btsl(r13, r12);
__ Jb(&restoreScratchRegister);
__ Movl(r12, Operand(r11, 0));
}
__ Bind(&restoreScratchRegister);
{
__ Popq(r13);
__ Popq(r12);
}
__ Bind(&checkBarrierForSharedValue);
{
// checkBarrierForSharedValue:
// int8_t GCStateBitField = *(glue+SharedGCStateBitFieldOffset)
// if (GCStateBitField & JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK != 0) {
// goto callSharedBarrier
// }
// return
__ Movl(Operand(rdi, JSThread::GlueData::GetSharedGCStateBitFieldOffset(false)), r11);
__ Testb(Immediate(JSThread::SHARED_CONCURRENT_MARKING_BITFIELD_MASK), r11);
__ Jne(&callSharedBarrier);
// if GCState is not READY_TO_MARK, go to needCallNotShare.
__ Ret();
}
__ Bind(&callSharedBarrier);
{
int32_t NonSValueBarrier = static_cast<int32_t>(JSThread::GlueData::GetCOStubEntriesOffset(false)) +
kungfu::CommonStubCSigns::SetSValueWithBarrier * FRAME_SLOT_SIZE;
__ Movq(Operand(rdi, NonSValueBarrier), r11);
__ Jmp(&needcall);
}
}
void AsmInterpreterCall::PushUndefinedWithArgcAndCheckStack(ExtendedAssembler *assembler, Register glue, Register argc,
Register op1, Register op2, Label *stackOverflow)
{

View File

@ -220,6 +220,7 @@ private:
static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode,
Label *fastPathEntry, Label *pushCallThis, Label *stackOverflow);
static void PreserveMostCall(ExtendedAssembler* assembler);
static void ASMFastSharedWriteBarrier(ExtendedAssembler *assembler, Label &needcall);
friend class OptimizedCall;
friend class BaselineCall;
};