mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 06:20:13 +00:00
[vm, gc] Implement the incremental marking barrier for IA32.
Enable concurrent marking for IA32. This removes the last write barrier relying on different alignment offsets for old and new space. TEST=ci Change-Id: Ib1c13124002392cf1c3ec264643325ec471a6918 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262280 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
c515938ee4
commit
1bff4bead9
12 changed files with 285 additions and 217 deletions
|
@ -1289,6 +1289,19 @@ void Assembler::testl(Register reg, const Immediate& immediate) {
|
|||
}
|
||||
}
|
||||
|
||||
void Assembler::testl(const Address& address, const Immediate& immediate) {
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
EmitUint8(0xF7);
|
||||
EmitOperand(0, address);
|
||||
EmitImmediate(immediate);
|
||||
}
|
||||
|
||||
void Assembler::testl(const Address& address, Register reg) {
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
EmitUint8(0x85);
|
||||
EmitOperand(reg, address);
|
||||
}
|
||||
|
||||
void Assembler::testb(const Address& address, const Immediate& imm) {
|
||||
ASSERT(imm.is_int8());
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
|
@ -1297,6 +1310,12 @@ void Assembler::testb(const Address& address, const Immediate& imm) {
|
|||
EmitUint8(imm.value() & 0xFF);
|
||||
}
|
||||
|
||||
void Assembler::testb(const Address& address, ByteRegister reg) {
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
EmitUint8(0x84);
|
||||
EmitOperand(reg, address);
|
||||
}
|
||||
|
||||
void Assembler::Alu(int bytes, uint8_t opcode, Register dst, Register src) {
|
||||
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
|
||||
if (bytes == 2) {
|
||||
|
@ -2003,49 +2022,12 @@ void Assembler::CompareObject(Register reg, const Object& object) {
|
|||
}
|
||||
}
|
||||
|
||||
// Destroys the value register.
|
||||
void Assembler::StoreIntoObjectFilter(Register object,
|
||||
Register value,
|
||||
Label* label,
|
||||
CanBeSmi can_be_smi,
|
||||
BarrierFilterMode how_to_jump) {
|
||||
if (can_be_smi == kValueIsNotSmi) {
|
||||
#if defined(DEBUG)
|
||||
Label okay;
|
||||
BranchIfNotSmi(value, &okay);
|
||||
Stop("Unexpected Smi!");
|
||||
Bind(&okay);
|
||||
#endif
|
||||
COMPILE_ASSERT((target::ObjectAlignment::kNewObjectAlignmentOffset ==
|
||||
target::kWordSize) &&
|
||||
(target::ObjectAlignment::kOldObjectAlignmentOffset == 0));
|
||||
// Write-barrier triggers if the value is in the new space (has bit set) and
|
||||
// the object is in the old space (has bit cleared).
|
||||
// To check that we could compute value & ~object and skip the write barrier
|
||||
// if the bit is not set. However we can't destroy the object.
|
||||
// However to preserve the object we compute negated expression
|
||||
// ~value | object instead and skip the write barrier if the bit is set.
|
||||
notl(value);
|
||||
orl(value, object);
|
||||
testl(value, Immediate(target::ObjectAlignment::kNewObjectAlignmentOffset));
|
||||
} else {
|
||||
ASSERT(target::ObjectAlignment::kNewObjectAlignmentOffset == 4);
|
||||
ASSERT(kHeapObjectTag == 1);
|
||||
// Detect value being ...101 and object being ...001.
|
||||
andl(value, Immediate(7));
|
||||
leal(value, Address(value, object, TIMES_2, 9));
|
||||
testl(value, Immediate(0xf));
|
||||
}
|
||||
Condition condition = how_to_jump == kJumpToNoUpdate ? NOT_ZERO : ZERO;
|
||||
auto const distance = how_to_jump == kJumpToNoUpdate ? kNearJump : kFarJump;
|
||||
j(condition, label, distance);
|
||||
}
|
||||
|
||||
void Assembler::StoreIntoObject(Register object,
|
||||
const Address& dest,
|
||||
Register value,
|
||||
CanBeSmi can_be_smi,
|
||||
MemoryOrder memory_order) {
|
||||
MemoryOrder memory_order,
|
||||
Register scratch) {
|
||||
// x.slot = x. Barrier should have be removed at the IL level.
|
||||
ASSERT(object != value);
|
||||
|
||||
|
@ -2054,18 +2036,65 @@ void Assembler::StoreIntoObject(Register object,
|
|||
} else {
|
||||
movl(dest, value);
|
||||
}
|
||||
Label done;
|
||||
StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
|
||||
// A store buffer update is required.
|
||||
if (object != EDX) {
|
||||
if (value != EDX) {
|
||||
pushl(EDX); // Preserve EDX.
|
||||
|
||||
bool spill_scratch = false;
|
||||
if (scratch == kNoRegister) {
|
||||
spill_scratch = true;
|
||||
if (object != EAX && value != EAX) {
|
||||
scratch = EAX;
|
||||
} else if (object != EBX && value != EBX) {
|
||||
scratch = EBX;
|
||||
} else {
|
||||
scratch = ECX;
|
||||
}
|
||||
movl(EDX, object);
|
||||
}
|
||||
call(Address(THR, target::Thread::write_barrier_entry_point_offset()));
|
||||
if ((object != EDX) && (value != EDX)) {
|
||||
popl(EDX); // Restore EDX.
|
||||
ASSERT(scratch != object);
|
||||
ASSERT(scratch != value);
|
||||
|
||||
// In parallel, test whether
|
||||
// - object is old and not remembered and value is new, or
|
||||
// - object is old and value is old and not marked and concurrent marking is
|
||||
// in progress
|
||||
// If so, call the WriteBarrier stub, which will either add object to the
|
||||
// store buffer (case 1) or add value to the marking stack (case 2).
|
||||
// Compare UntaggedObject::StorePointer.
|
||||
Label done;
|
||||
if (can_be_smi == kValueCanBeSmi) {
|
||||
BranchIfSmi(value, &done, kNearJump);
|
||||
}
|
||||
if (spill_scratch) {
|
||||
pushl(scratch);
|
||||
}
|
||||
movl(scratch, FieldAddress(object, target::Object::tags_offset()));
|
||||
shrl(scratch, Immediate(target::UntaggedObject::kBarrierOverlapShift));
|
||||
andl(scratch, Address(THR, target::Thread::write_barrier_mask_offset()));
|
||||
testl(FieldAddress(value, target::Object::tags_offset()), scratch);
|
||||
if (spill_scratch) {
|
||||
popl(scratch);
|
||||
}
|
||||
j(ZERO, &done, kNearJump);
|
||||
|
||||
Register object_for_call = object;
|
||||
if (value != kWriteBarrierValueReg) {
|
||||
// Unlikely. Only non-graph intrinsics.
|
||||
// TODO(rmacnak): Shuffle registers in intrinsics.
|
||||
pushl(kWriteBarrierValueReg);
|
||||
if (object == kWriteBarrierValueReg) {
|
||||
COMPILE_ASSERT(EAX != kWriteBarrierValueReg);
|
||||
COMPILE_ASSERT(ECX != kWriteBarrierValueReg);
|
||||
object_for_call = (value == EAX) ? ECX : EAX;
|
||||
pushl(object_for_call);
|
||||
movl(object_for_call, object);
|
||||
}
|
||||
movl(kWriteBarrierValueReg, value);
|
||||
}
|
||||
call(Address(THR, target::Thread::write_barrier_wrappers_thread_offset(
|
||||
object_for_call)));
|
||||
if (value != kWriteBarrierValueReg) {
|
||||
if (object == kWriteBarrierValueReg) {
|
||||
popl(object_for_call);
|
||||
}
|
||||
popl(kWriteBarrierValueReg);
|
||||
}
|
||||
Bind(&done);
|
||||
}
|
||||
|
@ -2096,48 +2125,46 @@ void Assembler::StoreIntoObjectNoBarrier(Register object,
|
|||
Stop("Write barrier is required");
|
||||
Bind(&done);
|
||||
#endif // defined(DEBUG)
|
||||
// No store buffer update.
|
||||
}
|
||||
|
||||
// Destroys the value register.
|
||||
void Assembler::StoreIntoArray(Register object,
|
||||
Register slot,
|
||||
Register value,
|
||||
CanBeSmi can_be_smi) {
|
||||
CanBeSmi can_be_smi,
|
||||
Register scratch) {
|
||||
ASSERT(object != value);
|
||||
movl(Address(slot, 0), value);
|
||||
|
||||
ASSERT(scratch != kNoRegister);
|
||||
ASSERT(scratch != object);
|
||||
ASSERT(scratch != value);
|
||||
ASSERT(scratch != slot);
|
||||
|
||||
// In parallel, test whether
|
||||
// - object is old and not remembered and value is new, or
|
||||
// - object is old and value is old and not marked and concurrent marking is
|
||||
// in progress
|
||||
// If so, call the WriteBarrier stub, which will either add object to the
|
||||
// store buffer (case 1) or add value to the marking stack (case 2).
|
||||
// Compare UntaggedObject::StorePointer.
|
||||
Label done;
|
||||
StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
|
||||
// A store buffer update is required.
|
||||
if (value != kWriteBarrierObjectReg) {
|
||||
pushl(kWriteBarrierObjectReg); // Preserve kWriteBarrierObjectReg.
|
||||
if (can_be_smi == kValueCanBeSmi) {
|
||||
BranchIfSmi(value, &done, kNearJump);
|
||||
}
|
||||
if (value != kWriteBarrierSlotReg && slot != kWriteBarrierSlotReg) {
|
||||
pushl(kWriteBarrierSlotReg); // Preserve kWriteBarrierSlotReg.
|
||||
}
|
||||
if (object != kWriteBarrierObjectReg && slot != kWriteBarrierSlotReg) {
|
||||
if (slot == kWriteBarrierObjectReg && object == kWriteBarrierSlotReg) {
|
||||
xchgl(slot, object);
|
||||
} else if (slot == kWriteBarrierObjectReg) {
|
||||
movl(kWriteBarrierSlotReg, slot);
|
||||
movl(kWriteBarrierObjectReg, object);
|
||||
} else {
|
||||
movl(kWriteBarrierObjectReg, object);
|
||||
movl(kWriteBarrierSlotReg, slot);
|
||||
}
|
||||
} else if (object != kWriteBarrierObjectReg) {
|
||||
movl(kWriteBarrierObjectReg, object);
|
||||
} else if (slot != kWriteBarrierSlotReg) {
|
||||
movl(kWriteBarrierSlotReg, slot);
|
||||
movl(scratch, FieldAddress(object, target::Object::tags_offset()));
|
||||
shrl(scratch, Immediate(target::UntaggedObject::kBarrierOverlapShift));
|
||||
andl(scratch, Address(THR, target::Thread::write_barrier_mask_offset()));
|
||||
testl(FieldAddress(value, target::Object::tags_offset()), scratch);
|
||||
j(ZERO, &done, kNearJump);
|
||||
|
||||
if ((object != kWriteBarrierObjectReg) || (value != kWriteBarrierValueReg) ||
|
||||
(slot != kWriteBarrierSlotReg)) {
|
||||
// Spill and shuffle unimplemented. Currently StoreIntoArray is only used
|
||||
// from StoreIndexInstr, which gets these exact registers from the register
|
||||
// allocator.
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
call(Address(THR, target::Thread::array_write_barrier_entry_point_offset()));
|
||||
if (value != kWriteBarrierSlotReg && slot != kWriteBarrierSlotReg) {
|
||||
popl(kWriteBarrierSlotReg); // Restore kWriteBarrierSlotReg.
|
||||
}
|
||||
if (value != kWriteBarrierObjectReg) {
|
||||
popl(kWriteBarrierObjectReg); // Restore kWriteBarrierObjectReg.
|
||||
}
|
||||
Bind(&done);
|
||||
}
|
||||
|
||||
|
|
|
@ -463,7 +463,10 @@ class Assembler : public AssemblerBase {
|
|||
|
||||
void testl(Register reg1, Register reg2);
|
||||
void testl(Register reg, const Immediate& imm);
|
||||
void testl(const Address& address, const Immediate& imm);
|
||||
void testl(const Address& address, Register reg);
|
||||
void testb(const Address& address, const Immediate& imm);
|
||||
void testb(const Address& address, ByteRegister reg);
|
||||
|
||||
// clang-format off
|
||||
// Macro for handling common ALU instructions. Arguments to F:
|
||||
|
@ -820,11 +823,21 @@ class Assembler : public AssemblerBase {
|
|||
const Address& dest, // Where we are storing into.
|
||||
Register value, // Value we are storing.
|
||||
CanBeSmi can_value_be_smi = kValueCanBeSmi,
|
||||
MemoryOrder memory_order = kRelaxedNonAtomic) override;
|
||||
MemoryOrder memory_order = kRelaxedNonAtomic) override {
|
||||
StoreIntoObject(object, dest, value, can_value_be_smi, memory_order,
|
||||
kNoRegister);
|
||||
}
|
||||
void StoreIntoObject(Register object, // Object we are storing into.
|
||||
const Address& dest, // Where we are storing into.
|
||||
Register value, // Value we are storing.
|
||||
CanBeSmi can_value_be_smi,
|
||||
MemoryOrder memory_order,
|
||||
Register scratch);
|
||||
void StoreIntoArray(Register object, // Object we are storing into.
|
||||
Register slot, // Where we are storing into.
|
||||
Register value, // Value we are storing.
|
||||
CanBeSmi can_value_be_smi = kValueCanBeSmi);
|
||||
CanBeSmi can_value_be_smi = kValueCanBeSmi,
|
||||
Register scratch = kNoRegister);
|
||||
void StoreIntoObjectNoBarrier(
|
||||
Register object,
|
||||
const Address& dest,
|
||||
|
@ -839,9 +852,10 @@ class Assembler : public AssemblerBase {
|
|||
int32_t offset, // Where we are storing into.
|
||||
Register value, // Value we are storing.
|
||||
CanBeSmi can_value_be_smi = kValueCanBeSmi,
|
||||
MemoryOrder memory_order = kRelaxedNonAtomic) {
|
||||
MemoryOrder memory_order = kRelaxedNonAtomic,
|
||||
Register scratch = kNoRegister) {
|
||||
StoreIntoObject(object, FieldAddress(object, offset), value,
|
||||
can_value_be_smi, memory_order);
|
||||
can_value_be_smi, memory_order, scratch);
|
||||
}
|
||||
void StoreIntoObjectOffsetNoBarrier(
|
||||
Register object,
|
||||
|
@ -1197,22 +1211,6 @@ class Assembler : public AssemblerBase {
|
|||
void EmitGenericShift(int rm, Register reg, const Immediate& imm);
|
||||
void EmitGenericShift(int rm, const Operand& operand, Register shifter);
|
||||
|
||||
enum BarrierFilterMode {
|
||||
// Filter falls through into the barrier update code. Target label
|
||||
// is a "after-store" label.
|
||||
kJumpToNoUpdate,
|
||||
|
||||
// Filter falls through to the "after-store" code. Target label
|
||||
// is barrier update code label.
|
||||
kJumpToBarrier,
|
||||
};
|
||||
|
||||
void StoreIntoObjectFilter(Register object,
|
||||
Register value,
|
||||
Label* label,
|
||||
CanBeSmi can_be_smi,
|
||||
BarrierFilterMode barrier_filter_mode);
|
||||
|
||||
int32_t jit_cookie();
|
||||
|
||||
int32_t jit_cookie_;
|
||||
|
|
|
@ -6949,7 +6949,11 @@ void RawStoreFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
LocationSummary* StoreFieldInstr::MakeLocationSummary(Zone* zone,
|
||||
bool opt) const {
|
||||
const intptr_t kNumInputs = 2;
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
const intptr_t kNumTemps = ShouldEmitStoreBarrier() ? 1 : 0;
|
||||
#else
|
||||
const intptr_t kNumTemps = 0;
|
||||
#endif
|
||||
LocationSummary* summary = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
|
||||
|
@ -6973,9 +6977,7 @@ LocationSummary* StoreFieldInstr::MakeLocationSummary(Zone* zone,
|
|||
Location value_loc;
|
||||
if (ShouldEmitStoreBarrier()) {
|
||||
summary->set_in(kValuePos,
|
||||
kWriteBarrierValueReg != kNoRegister
|
||||
? Location::RegisterLocation(kWriteBarrierValueReg)
|
||||
: Location::WritableRegister());
|
||||
Location::RegisterLocation(kWriteBarrierValueReg));
|
||||
} else {
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
// IA32 supports emitting `mov mem, Imm32` even for heap
|
||||
|
@ -7004,6 +7006,11 @@ LocationSummary* StoreFieldInstr::MakeLocationSummary(Zone* zone,
|
|||
#endif
|
||||
}
|
||||
}
|
||||
if (kNumTemps == 1) {
|
||||
summary->set_temp(0, Location::RequiresRegister());
|
||||
} else {
|
||||
ASSERT(kNumTemps == 0);
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
@ -7057,8 +7064,14 @@ void StoreFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
if (ShouldEmitStoreBarrier()) {
|
||||
Register value_reg = locs()->in(kValuePos).reg();
|
||||
if (!compressed) {
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
|
||||
CanValueBeSmi(), memory_order_,
|
||||
locs()->temp(0).reg());
|
||||
#else
|
||||
__ StoreIntoObjectOffset(instance_reg, offset_in_bytes, value_reg,
|
||||
CanValueBeSmi(), memory_order_);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(DART_COMPRESSED_POINTERS)
|
||||
__ StoreCompressedIntoObjectOffset(instance_reg, offset_in_bytes,
|
||||
|
|
|
@ -1705,7 +1705,7 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
|
|||
bool opt) const {
|
||||
const intptr_t kNumInputs = 3;
|
||||
const intptr_t kNumTemps =
|
||||
class_id() == kArrayCid && ShouldEmitStoreBarrier() ? 1 : 0;
|
||||
class_id() == kArrayCid && ShouldEmitStoreBarrier() ? 2 : 0;
|
||||
LocationSummary* locs = new (zone)
|
||||
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
||||
locs->set_in(0, Location::RequiresRegister());
|
||||
|
@ -1720,12 +1720,12 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone,
|
|||
}
|
||||
switch (class_id()) {
|
||||
case kArrayCid:
|
||||
locs->set_in(2, ShouldEmitStoreBarrier()
|
||||
? Location::WritableRegister()
|
||||
: LocationRegisterOrConstant(value()));
|
||||
locs->set_in(2, LocationRegisterOrConstant(value()));
|
||||
if (ShouldEmitStoreBarrier()) {
|
||||
locs->set_in(0, Location::RegisterLocation(kWriteBarrierObjectReg));
|
||||
locs->set_in(2, Location::RegisterLocation(kWriteBarrierValueReg));
|
||||
locs->set_temp(0, Location::RegisterLocation(kWriteBarrierSlotReg));
|
||||
locs->set_temp(1, Location::RequiresRegister());
|
||||
}
|
||||
break;
|
||||
case kExternalTypedDataUint8ArrayCid:
|
||||
|
@ -1791,8 +1791,9 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
if (ShouldEmitStoreBarrier()) {
|
||||
Register value = locs()->in(2).reg();
|
||||
Register slot = locs()->temp(0).reg();
|
||||
Register scratch = locs()->temp(1).reg();
|
||||
__ leal(slot, element_address);
|
||||
__ StoreIntoArray(array, slot, value, CanValueBeSmi());
|
||||
__ StoreIntoArray(array, slot, value, CanValueBeSmi(), scratch);
|
||||
} else if (locs()->in(2).IsConstant()) {
|
||||
const Object& constant = locs()->in(2).constant();
|
||||
__ StoreIntoObjectNoBarrier(array, element_address, constant);
|
||||
|
|
|
@ -1614,9 +1614,9 @@ static constexpr dart::compiler::target::word
|
|||
static constexpr dart::compiler::target::word
|
||||
Thread_AllocateArray_entry_point_offset = 408;
|
||||
static constexpr dart::compiler::target::word Thread_active_exception_offset =
|
||||
832;
|
||||
852;
|
||||
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
|
||||
836;
|
||||
856;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_array_write_barrier_entry_point_offset = 300;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -1639,7 +1639,7 @@ static constexpr dart::compiler::target::word
|
|||
Thread_allocate_object_slow_entry_point_offset = 324;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_allocate_object_slow_stub_offset = 208;
|
||||
static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 872;
|
||||
static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 892;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_async_exception_handler_stub_offset = 212;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -1652,13 +1652,13 @@ static constexpr dart::compiler::target::word
|
|||
Thread_call_to_runtime_entry_point_offset = 304;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_call_to_runtime_stub_offset = 140;
|
||||
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 904;
|
||||
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 928;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_dispatch_table_array_offset = 44;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_double_truncate_round_supported_offset = 876;
|
||||
Thread_double_truncate_round_supported_offset = 896;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_service_extension_stream_offset = 908;
|
||||
Thread_service_extension_stream_offset = 932;
|
||||
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
|
||||
344;
|
||||
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 256;
|
||||
|
@ -1674,7 +1674,7 @@ static constexpr dart::compiler::target::word Thread_end_offset = 52;
|
|||
static constexpr dart::compiler::target::word
|
||||
Thread_enter_safepoint_stub_offset = 280;
|
||||
static constexpr dart::compiler::target::word Thread_execution_state_offset =
|
||||
852;
|
||||
872;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_exit_safepoint_stub_offset = 284;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -1696,13 +1696,13 @@ static constexpr dart::compiler::target::word Thread_float_not_address_offset =
|
|||
static constexpr dart::compiler::target::word
|
||||
Thread_float_zerow_address_offset = 404;
|
||||
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
|
||||
840;
|
||||
860;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_invoke_dart_code_stub_offset = 136;
|
||||
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
|
||||
868;
|
||||
888;
|
||||
static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
|
||||
static constexpr dart::compiler::target::word Thread_isolate_group_offset = 912;
|
||||
static constexpr dart::compiler::target::word Thread_isolate_group_offset = 936;
|
||||
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
|
||||
64;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -1755,11 +1755,11 @@ static constexpr dart::compiler::target::word Thread_return_async_stub_offset =
|
|||
static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_predefined_symbols_address_offset = 376;
|
||||
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 844;
|
||||
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 864;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_saved_shadow_call_stack_offset = 848;
|
||||
Thread_saved_shadow_call_stack_offset = 868;
|
||||
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
|
||||
856;
|
||||
876;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_slow_type_test_stub_offset = 272;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -1780,25 +1780,25 @@ static constexpr dart::compiler::target::word
|
|||
static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
|
||||
76;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_await_entry_point_offset = 796;
|
||||
Thread_suspend_state_await_entry_point_offset = 816;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_init_async_entry_point_offset = 792;
|
||||
Thread_suspend_state_init_async_entry_point_offset = 812;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_return_async_entry_point_offset = 800;
|
||||
Thread_suspend_state_return_async_entry_point_offset = 820;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_return_async_not_future_entry_point_offset = 804;
|
||||
Thread_suspend_state_return_async_not_future_entry_point_offset = 824;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_init_async_star_entry_point_offset = 808;
|
||||
Thread_suspend_state_init_async_star_entry_point_offset = 828;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_yield_async_star_entry_point_offset = 812;
|
||||
Thread_suspend_state_yield_async_star_entry_point_offset = 832;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_return_async_star_entry_point_offset = 816;
|
||||
Thread_suspend_state_return_async_star_entry_point_offset = 836;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_init_sync_star_entry_point_offset = 820;
|
||||
Thread_suspend_state_init_sync_star_entry_point_offset = 840;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_suspend_sync_star_at_start_entry_point_offset = 824;
|
||||
Thread_suspend_state_suspend_sync_star_at_start_entry_point_offset = 844;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_handle_exception_entry_point_offset = 828;
|
||||
Thread_suspend_state_handle_exception_entry_point_offset = 848;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_top_exit_frame_info_offset = 72;
|
||||
static constexpr dart::compiler::target::word Thread_top_offset = 48;
|
||||
|
@ -1811,14 +1811,14 @@ static constexpr dart::compiler::target::word
|
|||
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
|
||||
32;
|
||||
static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
|
||||
static constexpr dart::compiler::target::word Thread_callback_code_offset = 860;
|
||||
static constexpr dart::compiler::target::word Thread_callback_code_offset = 880;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_callback_stack_return_offset = 864;
|
||||
static constexpr dart::compiler::target::word Thread_next_task_id_offset = 880;
|
||||
static constexpr dart::compiler::target::word Thread_random_offset = 888;
|
||||
Thread_callback_stack_return_offset = 884;
|
||||
static constexpr dart::compiler::target::word Thread_next_task_id_offset = 904;
|
||||
static constexpr dart::compiler::target::word Thread_random_offset = 912;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_jump_to_frame_entry_point_offset = 356;
|
||||
static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 896;
|
||||
static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 920;
|
||||
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
|
||||
0;
|
||||
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
|
||||
|
@ -1901,6 +1901,9 @@ static constexpr dart::compiler::target::word
|
|||
WeakReference_type_arguments_offset = 8;
|
||||
static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
|
||||
4, 12, 8, 16};
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_write_barrier_wrappers_thread_offset[] = {792, 796, 800, 804,
|
||||
-1, -1, -1, 808};
|
||||
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 16;
|
||||
static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word Array_header_size = 12;
|
||||
|
@ -6907,9 +6910,9 @@ static constexpr dart::compiler::target::word
|
|||
static constexpr dart::compiler::target::word
|
||||
Thread_AllocateArray_entry_point_offset = 408;
|
||||
static constexpr dart::compiler::target::word Thread_active_exception_offset =
|
||||
832;
|
||||
852;
|
||||
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
|
||||
836;
|
||||
856;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_array_write_barrier_entry_point_offset = 300;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -6932,7 +6935,7 @@ static constexpr dart::compiler::target::word
|
|||
Thread_allocate_object_slow_entry_point_offset = 324;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_allocate_object_slow_stub_offset = 208;
|
||||
static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 872;
|
||||
static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 892;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_async_exception_handler_stub_offset = 212;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -6945,13 +6948,13 @@ static constexpr dart::compiler::target::word
|
|||
Thread_call_to_runtime_entry_point_offset = 304;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_call_to_runtime_stub_offset = 140;
|
||||
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 904;
|
||||
static constexpr dart::compiler::target::word Thread_dart_stream_offset = 928;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_dispatch_table_array_offset = 44;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_double_truncate_round_supported_offset = 876;
|
||||
Thread_double_truncate_round_supported_offset = 896;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_service_extension_stream_offset = 908;
|
||||
Thread_service_extension_stream_offset = 932;
|
||||
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
|
||||
344;
|
||||
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 256;
|
||||
|
@ -6967,7 +6970,7 @@ static constexpr dart::compiler::target::word Thread_end_offset = 52;
|
|||
static constexpr dart::compiler::target::word
|
||||
Thread_enter_safepoint_stub_offset = 280;
|
||||
static constexpr dart::compiler::target::word Thread_execution_state_offset =
|
||||
852;
|
||||
872;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_exit_safepoint_stub_offset = 284;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -6989,13 +6992,13 @@ static constexpr dart::compiler::target::word Thread_float_not_address_offset =
|
|||
static constexpr dart::compiler::target::word
|
||||
Thread_float_zerow_address_offset = 404;
|
||||
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
|
||||
840;
|
||||
860;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_invoke_dart_code_stub_offset = 136;
|
||||
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
|
||||
868;
|
||||
888;
|
||||
static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
|
||||
static constexpr dart::compiler::target::word Thread_isolate_group_offset = 912;
|
||||
static constexpr dart::compiler::target::word Thread_isolate_group_offset = 936;
|
||||
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
|
||||
64;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -7048,11 +7051,11 @@ static constexpr dart::compiler::target::word Thread_return_async_stub_offset =
|
|||
static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_predefined_symbols_address_offset = 376;
|
||||
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 844;
|
||||
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 864;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_saved_shadow_call_stack_offset = 848;
|
||||
Thread_saved_shadow_call_stack_offset = 868;
|
||||
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
|
||||
856;
|
||||
876;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_slow_type_test_stub_offset = 272;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -7073,25 +7076,25 @@ static constexpr dart::compiler::target::word
|
|||
static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
|
||||
76;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_await_entry_point_offset = 796;
|
||||
Thread_suspend_state_await_entry_point_offset = 816;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_init_async_entry_point_offset = 792;
|
||||
Thread_suspend_state_init_async_entry_point_offset = 812;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_return_async_entry_point_offset = 800;
|
||||
Thread_suspend_state_return_async_entry_point_offset = 820;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_return_async_not_future_entry_point_offset = 804;
|
||||
Thread_suspend_state_return_async_not_future_entry_point_offset = 824;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_init_async_star_entry_point_offset = 808;
|
||||
Thread_suspend_state_init_async_star_entry_point_offset = 828;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_yield_async_star_entry_point_offset = 812;
|
||||
Thread_suspend_state_yield_async_star_entry_point_offset = 832;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_return_async_star_entry_point_offset = 816;
|
||||
Thread_suspend_state_return_async_star_entry_point_offset = 836;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_init_sync_star_entry_point_offset = 820;
|
||||
Thread_suspend_state_init_sync_star_entry_point_offset = 840;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_suspend_sync_star_at_start_entry_point_offset = 824;
|
||||
Thread_suspend_state_suspend_sync_star_at_start_entry_point_offset = 844;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_suspend_state_handle_exception_entry_point_offset = 828;
|
||||
Thread_suspend_state_handle_exception_entry_point_offset = 848;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_top_exit_frame_info_offset = 72;
|
||||
static constexpr dart::compiler::target::word Thread_top_offset = 48;
|
||||
|
@ -7104,14 +7107,14 @@ static constexpr dart::compiler::target::word
|
|||
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
|
||||
32;
|
||||
static constexpr dart::compiler::target::word Thread_heap_base_offset = 36;
|
||||
static constexpr dart::compiler::target::word Thread_callback_code_offset = 860;
|
||||
static constexpr dart::compiler::target::word Thread_callback_code_offset = 880;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_callback_stack_return_offset = 864;
|
||||
static constexpr dart::compiler::target::word Thread_next_task_id_offset = 880;
|
||||
static constexpr dart::compiler::target::word Thread_random_offset = 888;
|
||||
Thread_callback_stack_return_offset = 884;
|
||||
static constexpr dart::compiler::target::word Thread_next_task_id_offset = 904;
|
||||
static constexpr dart::compiler::target::word Thread_random_offset = 912;
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_jump_to_frame_entry_point_offset = 356;
|
||||
static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 896;
|
||||
static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 920;
|
||||
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
|
||||
0;
|
||||
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
|
||||
|
@ -7194,6 +7197,9 @@ static constexpr dart::compiler::target::word
|
|||
WeakReference_type_arguments_offset = 8;
|
||||
static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
|
||||
4, 12, 8, 16};
|
||||
static constexpr dart::compiler::target::word
|
||||
Thread_write_barrier_wrappers_thread_offset[] = {792, 796, 800, 804,
|
||||
-1, -1, -1, 808};
|
||||
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 16;
|
||||
static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word Array_header_size = 12;
|
||||
|
|
|
@ -384,10 +384,10 @@
|
|||
RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal, \
|
||||
CodeEntryKind::kMonomorphicUnchecked, \
|
||||
[](CodeEntryKind value) { return true; }) \
|
||||
NOT_IN_IA32(RANGE(Thread, write_barrier_wrappers_thread_offset, Register, 0, \
|
||||
kNumberOfCpuRegisters - 1, [](Register reg) { \
|
||||
return (kDartAvailableCpuRegs & (1 << reg)) != 0; \
|
||||
})) \
|
||||
RANGE(Thread, write_barrier_wrappers_thread_offset, Register, 0, \
|
||||
kNumberOfCpuRegisters - 1, [](Register reg) { \
|
||||
return (kDartAvailableCpuRegs & (1 << reg)) != 0; \
|
||||
}) \
|
||||
\
|
||||
SIZEOF(AbstractType, InstanceSize, UntaggedAbstractType) \
|
||||
SIZEOF(ApiError, InstanceSize, UntaggedApiError) \
|
||||
|
|
|
@ -1340,60 +1340,60 @@ void StubCodeCompiler::GenerateCloneContextStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
|
||||
// Not used on IA32.
|
||||
__ Breakpoint();
|
||||
for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
|
||||
if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
|
||||
|
||||
Register reg = static_cast<Register>(i);
|
||||
intptr_t start = __ CodeSize();
|
||||
__ pushl(kWriteBarrierObjectReg);
|
||||
__ movl(kWriteBarrierObjectReg, reg);
|
||||
__ call(Address(THR, target::Thread::write_barrier_entry_point_offset()));
|
||||
__ popl(kWriteBarrierObjectReg);
|
||||
__ ret();
|
||||
intptr_t end = __ CodeSize();
|
||||
|
||||
ASSERT_EQUAL(end - start, kStoreBufferWrapperSize);
|
||||
RELEASE_ASSERT(end - start == kStoreBufferWrapperSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper stub to implement Assembler::StoreIntoObject/Array.
|
||||
// Input parameters:
|
||||
// EDX: Object (old)
|
||||
// EBX: Value (old or new)
|
||||
// EDI: Slot
|
||||
// If EDX is not remembered, mark as remembered and add to the store buffer.
|
||||
// If EAX is new, add EDX to the store buffer. Otherwise EAX is old, mark EAX
|
||||
// and add it to the mark list.
|
||||
COMPILE_ASSERT(kWriteBarrierObjectReg == EDX);
|
||||
COMPILE_ASSERT(kWriteBarrierValueReg == kNoRegister);
|
||||
COMPILE_ASSERT(kWriteBarrierValueReg == EBX);
|
||||
COMPILE_ASSERT(kWriteBarrierSlotReg == EDI);
|
||||
static void GenerateWriteBarrierStubHelper(Assembler* assembler,
|
||||
bool cards) {
|
||||
Label remember_card;
|
||||
|
||||
// Save values being destroyed.
|
||||
__ pushl(EAX);
|
||||
__ pushl(ECX);
|
||||
|
||||
Label add_to_buffer;
|
||||
// Check whether this object has already been remembered. Skip adding to the
|
||||
// store buffer if the object is in the store buffer already.
|
||||
// Spilled: EAX, ECX
|
||||
// EDX: Address being stored
|
||||
__ movl(EAX, FieldAddress(EDX, target::Object::tags_offset()));
|
||||
__ testl(EAX,
|
||||
Immediate(1 << target::UntaggedObject::kOldAndNotRememberedBit));
|
||||
__ j(NOT_EQUAL, &add_to_buffer, Assembler::kNearJump);
|
||||
__ popl(ECX);
|
||||
__ popl(EAX);
|
||||
__ ret();
|
||||
|
||||
// Update the tags that this object has been remembered.
|
||||
// EDX: Address being stored
|
||||
// EAX: Current tag value
|
||||
__ Bind(&add_to_buffer);
|
||||
Label add_to_mark_stack, remember_card, lost_race;
|
||||
__ testl(EBX, Immediate(1 << target::ObjectAlignment::kNewObjectBitPosition));
|
||||
__ j(ZERO, &add_to_mark_stack);
|
||||
|
||||
if (cards) {
|
||||
// Check if this object is using remembered cards.
|
||||
__ testl(EAX, Immediate(1 << target::UntaggedObject::kCardRememberedBit));
|
||||
__ j(NOT_EQUAL, &remember_card, Assembler::kFarJump); // Unlikely.
|
||||
__ testl(FieldAddress(EDX, target::Object::tags_offset()),
|
||||
Immediate(1 << target::UntaggedObject::kCardRememberedBit));
|
||||
__ j(NOT_ZERO, &remember_card, Assembler::kFarJump); // Unlikely.
|
||||
} else {
|
||||
#if defined(DEBUG)
|
||||
Label ok;
|
||||
__ testl(EAX, Immediate(1 << target::UntaggedObject::kCardRememberedBit));
|
||||
__ j(ZERO, &ok, Assembler::kFarJump); // Unlikely.
|
||||
__ testl(FieldAddress(EDX, target::Object::tags_offset()),
|
||||
Immediate(1 << target::UntaggedObject::kCardRememberedBit));
|
||||
__ j(ZERO, &ok, Assembler::kFarJump);
|
||||
__ Stop("Wrong barrier");
|
||||
__ Bind(&ok);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Atomically clear kOldAndNotRememberedBit.
|
||||
Label retry, lost_race;
|
||||
Label retry;
|
||||
__ movl(EAX, FieldAddress(EDX, target::Object::tags_offset()));
|
||||
__ Bind(&retry);
|
||||
__ movl(ECX, EAX);
|
||||
|
@ -1443,6 +1443,43 @@ static void GenerateWriteBarrierStubHelper(Assembler* assembler,
|
|||
}
|
||||
__ ret();
|
||||
|
||||
__ Bind(&add_to_mark_stack);
|
||||
// Atomically clear kOldAndNotMarkedBit.
|
||||
Label retry_marking, marking_overflow;
|
||||
__ movl(EAX, FieldAddress(EBX, target::Object::tags_offset()));
|
||||
__ Bind(&retry_marking);
|
||||
__ movl(ECX, EAX);
|
||||
__ testl(ECX, Immediate(1 << target::UntaggedObject::kOldAndNotMarkedBit));
|
||||
__ j(ZERO, &lost_race); // Marked by another thread.
|
||||
__ andl(ECX, Immediate(~(1 << target::UntaggedObject::kOldAndNotMarkedBit)));
|
||||
// Cmpxchgq: compare value = implicit operand EAX, new value = ECX.
|
||||
// On failure, EAX is updated with the current value.
|
||||
__ LockCmpxchgl(FieldAddress(EBX, target::Object::tags_offset()), ECX);
|
||||
__ j(NOT_EQUAL, &retry_marking, Assembler::kNearJump);
|
||||
|
||||
__ movl(EAX, Address(THR, target::Thread::marking_stack_block_offset()));
|
||||
__ movl(ECX, Address(EAX, target::MarkingStackBlock::top_offset()));
|
||||
__ movl(
|
||||
Address(EAX, ECX, TIMES_4, target::MarkingStackBlock::pointers_offset()),
|
||||
EBX);
|
||||
__ incl(ECX);
|
||||
__ movl(Address(EAX, target::MarkingStackBlock::top_offset()), ECX);
|
||||
__ cmpl(ECX, Immediate(target::MarkingStackBlock::kSize));
|
||||
__ popl(ECX); // Unspill.
|
||||
__ popl(EAX); // Unspill.
|
||||
__ j(EQUAL, &marking_overflow, Assembler::kNearJump);
|
||||
__ ret();
|
||||
|
||||
__ Bind(&marking_overflow);
|
||||
{
|
||||
LeafRuntimeScope rt(assembler,
|
||||
/*frame_size=*/1 * target::kWordSize,
|
||||
/*preserve_registers=*/true);
|
||||
__ movl(Address(ESP, 0), THR); // Push the thread as the only argument.
|
||||
rt.Call(kMarkingStackBlockProcessRuntimeEntry, 1);
|
||||
}
|
||||
__ ret();
|
||||
|
||||
__ Bind(&lost_race);
|
||||
__ popl(ECX); // Unspill.
|
||||
__ popl(EAX); // Unspill.
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "platform/assert.h"
|
||||
#include "platform/globals.h"
|
||||
#include "platform/utils.h"
|
||||
|
||||
#include "vm/constants_base.h"
|
||||
|
||||
|
@ -101,7 +102,7 @@ const Register kStackTraceObjectReg = EDX;
|
|||
|
||||
// ABI for write barrier stub.
|
||||
const Register kWriteBarrierObjectReg = EDX;
|
||||
const Register kWriteBarrierValueReg = kNoRegister;
|
||||
const Register kWriteBarrierValueReg = EBX;
|
||||
const Register kWriteBarrierSlotReg = EDI;
|
||||
|
||||
// Common ABI for shared slow path stubs.
|
||||
|
@ -352,11 +353,16 @@ const RegList kAllCpuRegistersList = 0xFF;
|
|||
const RegList kAllFpuRegistersList = (1 << kNumberOfFpuRegisters) - 1;
|
||||
|
||||
const intptr_t kReservedCpuRegisters = (1 << SPREG) | (1 << FPREG) | (1 << THR);
|
||||
constexpr intptr_t kNumberOfReservedCpuRegisters =
|
||||
Utils::CountOneBits32(kReservedCpuRegisters);
|
||||
// CPU registers available to Dart allocator.
|
||||
const RegList kDartAvailableCpuRegs =
|
||||
kAllCpuRegistersList & ~kReservedCpuRegisters;
|
||||
constexpr int kNumberOfDartAvailableCpuRegs =
|
||||
kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
|
||||
// No reason to prefer certain registers on IA32.
|
||||
constexpr int kRegisterAllocationBias = 0;
|
||||
constexpr int kStoreBufferWrapperSize = 11;
|
||||
|
||||
const RegList kAbiPreservedCpuRegs = (1 << EDI) | (1 << ESI) | (1 << EBX);
|
||||
|
||||
|
|
|
@ -936,12 +936,8 @@ void PageSpace::CollectGarbage(Thread* thread, bool compact, bool finalize) {
|
|||
ASSERT(!Thread::Current()->force_growth());
|
||||
|
||||
if (!finalize) {
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
return; // Barrier not implemented.
|
||||
#else
|
||||
if (!enable_concurrent_mark()) return; // Disabled.
|
||||
if (FLAG_marker_tasks == 0) return; // Disabled.
|
||||
#endif
|
||||
}
|
||||
|
||||
GcSafepointOperationScope safepoint_scope(thread);
|
||||
|
@ -1498,11 +1494,7 @@ void PageSpaceController::RecordUpdate(SpaceUsage before,
|
|||
intptr_t threshold =
|
||||
after.CombinedUsedInWords() + (kPageSizeInWords * growth_in_pages);
|
||||
|
||||
#if defined(TARGET_ARCH_IA32)
|
||||
bool concurrent_mark = false;
|
||||
#else
|
||||
bool concurrent_mark = FLAG_concurrent_mark && (FLAG_marker_tasks != 0);
|
||||
#endif
|
||||
if (concurrent_mark) {
|
||||
soft_gc_threshold_in_words_ = threshold;
|
||||
hard_gc_threshold_in_words_ = kIntptrMax / kWordSize;
|
||||
|
|
|
@ -688,13 +688,11 @@ class UntaggedObject {
|
|||
// Incremental barrier: record when a store creates an
|
||||
// old -> old-and-not-marked reference.
|
||||
ASSERT(value->IsOldObject());
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
if (ClassIdTag::decode(target_tags) == kInstructionsCid) {
|
||||
// Instruction pages may be non-writable. Defer marking.
|
||||
thread->DeferredMarkingStackAddObject(value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (value->untag()->TryAcquireMarkBit()) {
|
||||
thread->MarkingStackAddObject(value);
|
||||
}
|
||||
|
@ -722,13 +720,11 @@ class UntaggedObject {
|
|||
// Incremental barrier: record when a store creates an
|
||||
// old -> old-and-not-marked reference.
|
||||
ASSERT(value->IsOldObject());
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
if (ClassIdTag::decode(target_tags) == kInstructionsCid) {
|
||||
// Instruction pages may be non-writable. Defer marking.
|
||||
thread->DeferredMarkingStackAddObject(value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (value->untag()->TryAcquireMarkBit()) {
|
||||
thread->MarkingStackAddObject(value);
|
||||
}
|
||||
|
|
|
@ -122,11 +122,9 @@ Thread::Thread(bool is_vm_isolate)
|
|||
CACHED_CONSTANTS_LIST(DEFAULT_INIT)
|
||||
#undef DEFAULT_INIT
|
||||
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
for (intptr_t i = 0; i < kNumberOfDartAvailableCpuRegs; ++i) {
|
||||
write_barrier_wrappers_entry_points_[i] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEFAULT_INIT(name) name##_entry_point_ = 0;
|
||||
RUNTIME_ENTRY_LIST(DEFAULT_INIT)
|
||||
|
@ -205,13 +203,11 @@ void Thread::InitVMConstants() {
|
|||
CACHED_CONSTANTS_LIST(INIT_VALUE)
|
||||
#undef INIT_VALUE
|
||||
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
for (intptr_t i = 0; i < kNumberOfDartAvailableCpuRegs; ++i) {
|
||||
write_barrier_wrappers_entry_points_[i] =
|
||||
StubCode::WriteBarrierWrappers().EntryPoint() +
|
||||
i * kStoreBufferWrapperSize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define INIT_VALUE(name) \
|
||||
ASSERT(name##_entry_point_ == 0); \
|
||||
|
|
|
@ -701,7 +701,6 @@ class Thread : public ThreadState {
|
|||
CACHED_CONSTANTS_LIST(DEFINE_OFFSET_METHOD)
|
||||
#undef DEFINE_OFFSET_METHOD
|
||||
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
static intptr_t write_barrier_wrappers_thread_offset(Register reg) {
|
||||
ASSERT((kDartAvailableCpuRegs & (1 << reg)) != 0);
|
||||
intptr_t index = 0;
|
||||
|
@ -726,7 +725,6 @@ class Thread : public ThreadState {
|
|||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEFINE_OFFSET_METHOD(name) \
|
||||
static intptr_t name##_entry_point_offset() { \
|
||||
|
@ -1195,9 +1193,7 @@ class Thread : public ThreadState {
|
|||
LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
|
||||
#undef DECLARE_MEMBERS
|
||||
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
uword write_barrier_wrappers_entry_points_[kNumberOfDartAvailableCpuRegs];
|
||||
#endif
|
||||
|
||||
#define DECLARE_MEMBERS(name) uword name##_entry_point_ = 0;
|
||||
CACHED_FUNCTION_ENTRY_POINTS_LIST(DECLARE_MEMBERS)
|
||||
|
|
Loading…
Reference in a new issue