Chromium Code Reviews| Index: src/heap/spaces.h |
| diff --git a/src/heap/spaces.h b/src/heap/spaces.h |
| index 69a8d89fccba5c5aa06f91d2a1995870b70ef033..c23748a11aba5729a1ed3cf3ebb8db7396df2ae1 100644 |
| --- a/src/heap/spaces.h |
| +++ b/src/heap/spaces.h |
| @@ -2460,6 +2460,50 @@ class NewSpacePageIterator BASE_EMBEDDED { |
| NewSpacePage* last_page_; |
| }; |
| +// ----------------------------------------------------------------------------- |
| +// Allows observation of inline allocation in the new space. This class is not |
| +// publicly instantiable; use NewSpace::AddInlineAllocationObserver. |
| +class InlineAllocationObserver { |
| + public: |
| + typedef void (*callback_t)(int bytes_allocated, void* arg); |
| + |
| + InlineAllocationObserver(const InlineAllocationObserver&) = default; |
| + InlineAllocationObserver& operator=(const InlineAllocationObserver&) = |
| + default; |
| + |
| + private: |
| + explicit InlineAllocationObserver(intptr_t step_size, callback_t callback, |
| + void* callback_arg) |
| + : step_size_(step_size), |
| + callback_(callback), |
| + callback_arg_(callback_arg), |
| + bytes_to_next_step_(step_size) { |
| + DCHECK(step_size >= kPointerSize); |
| + } |
| + |
| + intptr_t step_size() const { return step_size_; } |
| + callback_t callback() const { return callback_; } |
| + |
| + // Called each time the new space does an inline allocation step. This may be |
| + // more frequently than the step_size we are monitoring (e.g. when there are |
| + // multiple observers, or when page or space boundary is encountered.) The |
| + // callback is only called once at least step_size bytes have been allocated. |
| + void step(int bytes_allocated) { |
| + bytes_to_next_step_ -= bytes_allocated; |
| + if (bytes_to_next_step_ <= 0) { |
| + callback_(static_cast<int>(step_size_ - bytes_to_next_step_), |
| + callback_arg_); |
| + bytes_to_next_step_ = step_size_; |
| + } |
| + } |
| + |
| + intptr_t step_size_; |
| + callback_t callback_; |
| + void* callback_arg_; |
| + intptr_t bytes_to_next_step_; |
| + |
| + friend class NewSpace; |
| +}; |
| // ----------------------------------------------------------------------------- |
| // The young generation space. |
| @@ -2649,10 +2693,25 @@ class NewSpace : public Space { |
| void ResetAllocationInfo(); |
| void UpdateInlineAllocationLimit(int size_in_bytes); |
| - void LowerInlineAllocationLimit(intptr_t step) { |
| - inline_allocation_limit_step_ = step; |
| + |
| + // Allows observation of inline allocation. The callback gets after every |
|
ulan
2015/10/21 09:06:12
The callback gets called
ofrobots
2015/10/22 02:42:22
Done.
|
| + // step_size bytes have been allocated (approximately). This works by |
| + // adjusting the allocation limit to a lower value and adjusting it |
| + // after each step. The callback_arg argument is passed to the callback each |
| + // time it is called. |
| + void AddInlineAllocationObserver( |
| + intptr_t step_size, InlineAllocationObserver::callback_t callback, |
| + void* callback_arg); |
| + |
| + // Removes a previously installed callback function. For duplicate functions |
| + // they are removed in the order of insertion (one at a time.) |
| + void RemoveInlineAllocationObserver( |
| + InlineAllocationObserver::callback_t callback); |
| + |
| + void DisableInlineAllocationSteps() { |
| + inline_allocation_limit_step_ = 0; |
| + top_on_previous_step_ = 0; |
| UpdateInlineAllocationLimit(0); |
| - top_on_previous_step_ = step ? allocation_info_.top() : 0; |
| } |
| // Get the extent of the inactive semispace (for use as a marking stack, |
| @@ -2728,6 +2787,8 @@ class NewSpace : public Space { |
| // Update allocation info to match the current to-space page. |
| void UpdateAllocationInfo(); |
| + void UpdateInlineAllocationLimitStep(); |
| + |
| Address chunk_base_; |
| uintptr_t chunk_size_; |
| @@ -2747,11 +2808,13 @@ class NewSpace : public Space { |
| // mark-compact collection. |
| AllocationInfo allocation_info_; |
| - // When incremental marking is active we will set allocation_info_.limit |
| - // to be lower than actual limit and then will gradually increase it |
| - // in steps to guarantee that we do incremental marking steps even |
| - // when all allocation is performed from inlined generated code. |
| + // When inline allocation stepping is active, either because of incremental |
| + // marking or because of idle scavenge, we 'interrupt' inline allocation every |
| + // once in a while. This is done by setting allocation_info_.limit to be lower |
| + // than the actual limit and and increasing it in steps to guarantee that the |
| + // observers are notified periodically. |
| intptr_t inline_allocation_limit_step_; |
| + List<InlineAllocationObserver> inline_allocation_observers_; |
| Address top_on_previous_step_; |
| @@ -2761,8 +2824,7 @@ class NewSpace : public Space { |
| bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment); |
| // If we are doing inline allocation in steps, this method performs the 'step' |
| - // operation. Right now incremental marking is the only consumer of inline |
| - // allocation steps. top is the memory address of the bump pointer at the last |
| + // operation. top is the memory address of the bump pointer at the last |
| // inline allocation (i.e. it determines the numbers of bytes actually |
| // allocated since the last step.) new_top is the address of the bump pointer |
| // where the next byte is going to be allocated from. top and new_top may be |