--- old/src/share/vm/gc/g1/g1ConcurrentMark.hpp 2017-02-23 10:57:56.791706895 +0100 +++ new/src/share/vm/gc/g1/g1ConcurrentMark.hpp 2017-02-23 10:57:56.676703445 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,55 @@ class ConcurrentGCTimer; class G1OldTracer; class G1SurvivorRegions; -typedef GenericTaskQueue G1CMTaskQueue; + +#ifdef _MSC_VER +#pragma warning(push) +// warning C4522: multiple assignment operators specified +#pragma warning(disable:4522) +#endif + +// This is a container class for either an oop or a continuation address for +// mark stack entries. Both are pushed onto the mark stack. +class G1TaskQueueEntry VALUE_OBJ_CLASS_SPEC { +private: + void* _holder; + + static const uintptr_t ArraySliceBit = 1; +public: + G1TaskQueueEntry() : _holder(NULL) { } + G1TaskQueueEntry(oop obj) : _holder(obj) { } + G1TaskQueueEntry(HeapWord* addr) : _holder((void*)((uintptr_t)addr | ArraySliceBit)) { } + + G1TaskQueueEntry& operator=(const G1TaskQueueEntry& t) { + _holder = t._holder; + return *this; + } + + volatile G1TaskQueueEntry& operator=(const volatile G1TaskQueueEntry& t) volatile { + _holder = t._holder; + return *this; + } + + oop obj() const { + assert(!is_array_slice(), "Trying to read array slice " PTR_FORMAT " as oop", p2i(_holder)); + return (oop)_holder; + } + + HeapWord* slice() const { + assert(is_array_slice(), "Trying to read oop " PTR_FORMAT " as array slice", p2i(_holder)); + return (HeapWord*)((uintptr_t)_holder &~ ArraySliceBit); + } + + bool is_oop() const { return !is_array_slice(); } + bool is_array_slice() const { return ((uintptr_t)_holder & ArraySliceBit) != 0; } + bool is_null() const { return _holder == NULL; } +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +typedef GenericTaskQueue G1CMTaskQueue; typedef GenericTaskQueueSet G1CMTaskQueueSet; // Closure used by CM during concurrent reference discovery @@ -166,11 +214,11 @@ class G1CMMarkStack VALUE_OBJ_CLASS_SPEC { public: // Number of oops that can fit in a single chunk. - static const size_t OopsPerChunk = 1024 - 1 /* One reference for the next pointer */; + static const size_t EntriesPerChunk = 1024 - 1 /* One reference for the next pointer */; private: struct OopChunk { OopChunk* next; - oop data[OopsPerChunk]; + G1TaskQueueEntry data[EntriesPerChunk]; }; size_t _max_chunk_capacity; // Maximum number of OopChunk elements on the stack. @@ -227,12 +275,12 @@ // be terminated with a NULL. // Returns whether the buffer contents were successfully pushed to the global mark // stack. - bool par_push_chunk(oop* buffer); + bool par_push_chunk(G1TaskQueueEntry* buffer); // Pops a chunk from this mark stack, copying them into the given buffer. This // chunk may contain up to OopsPerChunk elements. If there are less, the last // element in the array is a NULL pointer. - bool par_pop_chunk(oop* buffer); + bool par_pop_chunk(G1TaskQueueEntry* buffer); // Return whether the chunk list is empty. Racy due to unsynchronized access to // _chunk_list. @@ -251,7 +299,7 @@ // Return the approximate number of oops on this mark stack. Racy due to // unsynchronized access to _chunks_in_chunk_list. - size_t size() const { return _chunks_in_chunk_list * OopsPerChunk; } + size_t size() const { return _chunks_in_chunk_list * EntriesPerChunk; } void set_empty(); @@ -531,14 +579,14 @@ // Manipulation of the global mark stack. // The push and pop operations are used by tasks for transfers // between task-local queues and the global mark stack. - bool mark_stack_push(oop* arr) { + bool mark_stack_push(G1TaskQueueEntry* arr) { if (!_global_mark_stack.par_push_chunk(arr)) { set_has_overflown(); return false; } return true; } - bool mark_stack_pop(oop* arr) { + bool mark_stack_pop(G1TaskQueueEntry* arr) { return _global_mark_stack.par_pop_chunk(arr); } size_t mark_stack_size() { return _global_mark_stack.size(); } @@ -573,7 +621,7 @@ } // Attempts to steal an object from the task queues of other tasks - bool try_stealing(uint worker_id, int* hash_seed, oop& obj); + bool try_stealing(uint worker_id, int* hash_seed, G1TaskQueueEntry& task_entry); G1ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, @@ -828,7 +876,7 @@ // mark bitmap scan, and so needs to be pushed onto the mark stack. bool is_below_finger(oop obj, HeapWord* global_finger) const; - template void process_grey_object(oop obj); + template void process_grey_object(G1TaskQueueEntry task_entry); public: // Apply the closure on the given area of the objArray. Return the number of words // scanned. @@ -893,10 +941,10 @@ inline void deal_with_reference(oop obj); // It scans an object and visits its children. - inline void scan_object(oop obj); + inline void scan_object(G1TaskQueueEntry task_entry); // It pushes an object on the local queue. - inline void push(oop obj); + inline void push(G1TaskQueueEntry task_entry); // Move entries to the global stack. void move_entries_to_global_stack();