summaryrefslogtreecommitdiff
path: root/src/vm/gcenv.ee.cpp
diff options
context:
space:
mode:
authorSean Gillespie <sean@swgillespie.me>2016-12-10 17:50:06 -0800
committerGitHub <noreply@github.com>2016-12-10 17:50:06 -0800
commit04d6bd105ade5f6189a15a6dbb59b082613429a1 (patch)
tree9209ba4b53eca61cad3a2fc94c585b6a66ff4618 /src/vm/gcenv.ee.cpp
parentd42b3935eaa056712e09a0f83b38e211bdb451d9 (diff)
downloadcoreclr-04d6bd105ade5f6189a15a6dbb59b082613429a1.tar.gz
coreclr-04d6bd105ade5f6189a15a6dbb59b082613429a1.tar.bz2
coreclr-04d6bd105ade5f6189a15a6dbb59b082613429a1.zip
Local GC: Decouple write barrier operations between the GC and EE (#8568)
* Decouple write barrier operations between the GC and EE * Address code review feedback * Address code review feedback * Repair the standalone GC build
Diffstat (limited to 'src/vm/gcenv.ee.cpp')
-rw-r--r--src/vm/gcenv.ee.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/vm/gcenv.ee.cpp b/src/vm/gcenv.ee.cpp
index 604ac297aa..3be8384b3d 100644
--- a/src/vm/gcenv.ee.cpp
+++ b/src/vm/gcenv.ee.cpp
@@ -1214,3 +1214,57 @@ void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext)
#endif //GC_PROFILING || FEATURE_EVENT_TRACE
}
+void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
+{
+ assert(args != nullptr);
+ switch (args->operation)
+ {
+ case WriteBarrierOp::StompResize:
+ // StompResize requires a new card table, a new lowest address, and
+ // a new highest address
+ assert(args->card_table != nullptr);
+ assert(args->lowest_address != nullptr);
+ assert(args->highest_address != nullptr);
+ g_card_table = args->card_table;
+ ::StompWriteBarrierResize(args->is_runtime_suspended, args->requires_upper_bounds_check);
+
+ // We need to make sure that other threads executing checked write barriers
+ // will see the g_card_table update before g_lowest/highest_address updates.
+ // Otherwise, the checked write barrier may AV accessing the old card table
+ // with address that it does not cover. Write barriers access card table
+ // without memory barriers for performance reasons, so we need to flush
+ // the store buffers here.
+ FlushProcessWriteBuffers();
+
+ g_lowest_address = args->lowest_address;
+ VolatileStore(&g_highest_address, args->highest_address);
+ return;
+ case WriteBarrierOp::StompEphemeral:
+ // StompEphemeral requires a new ephemeral low and a new ephemeral high
+ assert(args->ephemeral_lo != nullptr);
+ assert(args->ephemeral_hi != nullptr);
+ g_ephemeral_low = args->ephemeral_lo;
+ g_ephemeral_high = args->ephemeral_hi;
+ ::StompWriteBarrierEphemeral(args->is_runtime_suspended);
+ return;
+ case WriteBarrierOp::Initialize:
+ // This operation should only be invoked once, upon initialization.
+ assert(g_card_table == nullptr);
+ assert(g_lowest_address == nullptr);
+ assert(g_highest_address == nullptr);
+ assert(args->card_table != nullptr);
+ assert(args->lowest_address != nullptr);
+ assert(args->highest_address != nullptr);
+ assert(args->is_runtime_suspended && "the runtime must be suspended here!");
+ assert(!args->requires_upper_bounds_check && "the ephemeral generation must be at the top of the heap!");
+
+ g_card_table = args->card_table;
+ FlushProcessWriteBuffers();
+ g_lowest_address = args->lowest_address;
+ VolatileStore(&g_highest_address, args->highest_address);
+ ::StompWriteBarrierResize(true, false);
+ return;
+ default:
+ assert(!"unknown WriteBarrierOp enum");
+ }
+}