1/*
2 * Copyright (c) 2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20/*
21    ThreadLocalCollector.h
22    Thread Local Collector
23    Copyright (c) 2008-2011 Apple Inc. All rights reserved.
24 */
25
26#pragma once
27#ifndef __AUTO_THREAD_LOCAL_COLLECTOR__
28#define __AUTO_THREAD_LOCAL_COLLECTOR__
29
30#include "Definitions.h"
31#include "Range.h"
32#include "SubZone.h"
33#include "Zone.h"
34
35namespace Auto {
36
37    //----- Collector -----//
38
39    //
40    // Responsible for garbage collection.
41    //
42
43    class ThreadLocalCollector {
44    public:
45
46    private:
47        Zone *_zone;
48        Range _coverage;
49        void *_stack_bottom;
50        Sentinel _localsGuard;
51        LocalBlocksHash &_localBlocks;
52        void **_tlcBuffer; // local_allocations_size_limit entries, backing lives in Thread. Used for several purposes in TLC.
53        size_t _tlcBufferCount;
54        Thread &_thread;
55
56        PtrHashSet *_zombies;
57
58        void scan_stack_range(const Range &range);
59        void mark_push_block(void *block);
60        void scan_range(const Range &range);
61        void scan_with_layout(const Range &range, const unsigned char* map);
62        void scan_local_block(Subzone *subzone, usword_t q, void *block);
63        void scan_pending_until_done();
64        void scan_marked_blocks();
65        void scavenge_local(size_t count, void *garbage[]);
66        void process_local_garbage(void (*garbage_list_handler)(ThreadLocalCollector *));
67
68        friend class thread_local_scanner_helper;
69
70        static void finalize_local_garbage_now(ThreadLocalCollector *tlc);
71        static void finalize_local_garbage_later(ThreadLocalCollector *tlc);
72        static void unmark_local_garbage(ThreadLocalCollector *tlc);
73        static void mark_local_garbage(void **garbage_list, size_t garbage_count);
74        void trace_scanning_phase_end();
75        void append_block(void *block);
76
77    public:
78
79        ThreadLocalCollector(Zone *zone, void *current_stack_bottom, Thread &thread)
80            : _zone(zone), _coverage(zone->coverage()), _stack_bottom(current_stack_bottom), _localsGuard(thread.localsGuard()), _localBlocks(thread.locals()),
81        _tlcBuffer(thread.tlc_buffer()), _tlcBufferCount(0), _thread(thread), _zombies(NULL)
82        {
83        }
84
85        ~ThreadLocalCollector()
86        {
87            if (_zombies)
88                delete _zombies;
89        }
90
91        //
92        // should_collect
93        //
94        static bool should_collect(Zone *zone, Thread &thread, bool canFinalizeNow);
95
96        //
97        // should_collect_suspended
98        //
99        static bool should_collect_suspended(Thread &thread);
100
101        //
102        // collect
103        //
104        void collect(bool finalizeNow);
105
106        //
107        // collect_suspended
108        //
109        void collect_suspended(Range &registers, Range &stack);
110
111        //
112        // reap_all
113        //
114        void reap_all();
115
116        //
117        // eject_local_block
118        //
119        // removes block and all referenced stack local blocks
120        //
121        void eject_local_block(void *startingBlock);
122
123        //
124        // block_in_garbage_list
125        //
126        // searches the garbage list and returns true if block is in it
127        bool block_in_garbage_list(void *block);
128
129        //
130        // evict_local_garbage
131        //
132        // scans the list of garbage blocks. any non-garbage local blocks which are reachable are made global
133        void evict_local_garbage();
134
135        //
136        // add_zombie
137        //
138        // adds block as a thread local zombie
139        void add_zombie(void *block);
140
141        //
142        // is_zombie
143        //
144        // test if a block is a thread local zombie
145        inline bool is_zombie(void *block);
146    };
147};
148
149#endif
150