1d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 2d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Copyright (C) 2009 The Android Open Source Project 3d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 4d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Licensed under the Apache License, Version 2.0 (the "License"); 5d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * you may not use this file except in compliance with the License. 6d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * You may obtain a copy of the License at 7d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 8d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * http://www.apache.org/licenses/LICENSE-2.0 9d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 10d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Unless required by applicable law or agreed to in writing, software 11d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * distributed under the License is distributed on an "AS IS" BASIS, 12d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * See the License for the specific language governing permissions and 14d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * limitations under the License. 15d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 16d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 17d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include <errno.h> 18d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include <limits.h> 19d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include <sys/mman.h> 20d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include "Dalvik.h" 22d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include "alloc/Heap.h" 23d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include "alloc/HeapBitmap.h" 24d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include "alloc/HeapInternal.h" 25d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include "alloc/HeapSource.h" 26d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#include "alloc/Verify.h" 27d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 28d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 29d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * A "mostly copying", generational, garbage collector. 30d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 31d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * TODO: we allocate our own contiguous tract of page frames to back 32d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * object allocations. To cooperate with other heaps active in the 33d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * virtual machine we need to move the responsibility of allocating 34d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * pages someplace outside of this code. 35d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 36d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The other major data structures that maintain the state of the heap 37d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * are the block space table and the block queue. 38d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 39d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The block space table records the state of a block. We must track 40d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * whether a block is: 41d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 42d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - Free or allocated in some space. 43d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 44d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - If the block holds part of a large object allocation, whether the 45d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * block is the initial or a continued block of the allocation. 46d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 47d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - Whether the block is pinned, that is to say whether at least one 48d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * object in the block must remain stationary. Only needed during a 49d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * GC. 50d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 51d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - Which space the object belongs to. At present this means 52d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * from-space or to-space. 53d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 54d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The block queue is used during garbage collection. Unlike Cheney's 55d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * algorithm, from-space and to-space are not contiguous. Therefore, 56d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * one cannot maintain the state of the copy with just two pointers. 57d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The block queue exists to thread lists of blocks from the various 58d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * spaces together. 59d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 60d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Additionally, we record the free space frontier of the heap, as 61d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * well as the address of the first object within a block, which is 62d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * required to copy objects following a large object (not currently 63d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * implemented). This is stored in the heap source structure. This 64d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * should be moved elsewhere to support in-line allocations from Java 65d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * threads. 66d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 67d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Allocation requests are satisfied by reserving storage from one or 68d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * more contiguous blocks. Objects that are small enough to fit 69d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * inside a block are packed together within a block. Objects that 70d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * are larger than a block are allocated from contiguous sequences of 71d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * blocks. When half the available blocks are filled, a garbage 72d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * collection occurs. We "flip" spaces (exchange from- and to-space), 73d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * copy live objects into to space, and perform pointer adjustment. 74d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 75d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Copying is made more complicated by the requirement that some 76d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * objects must not be moved. This property is known as "pinning". 77d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * These objects must be dealt with specially. We use Bartlett's 78d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * scheme; blocks containing such objects are grayed (promoted) at the 79952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * start of a garbage collection. By virtue of this trick, tracing 80d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * from the roots proceeds as usual but all objects on those pages are 81d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * considered promoted and therefore not moved. 82d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 83d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * TODO: there is sufficient information within the garbage collector 84d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * to implement Attardi's scheme for evacuating unpinned objects from 85d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * a page that is otherwise pinned. This would eliminate false 86d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * retention caused by the large pinning granularity. 87d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 88d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * We need a scheme for medium and large objects. Ignore that for 89d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * now, we can return to this later. 90d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 91d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Eventually we need to worry about promoting objects out of the 92d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * copy-collected heap (tenuring) into a less volatile space. Copying 93d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * may not always be the best policy for such spaces. We should 94d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * consider a variant of mark, sweep, compact. 95d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 96d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The block scheme allows us to use VM page faults to maintain a 97d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * write barrier. Consider having a special leaf state for a page. 98d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 99d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Bibliography: 100d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 101d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * C. J. Cheney. 1970. A non-recursive list compacting 102d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * algorithm. CACM. 13-11 pp677--678. 103d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 104d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Joel F. Bartlett. 1988. Compacting Garbage Collection with 105d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Ambiguous Roots. Digital Equipment Corporation. 106d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 107d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Joel F. Bartlett. 1989. Mostly-Copying Garbage Collection Picks Up 108d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Generations and C++. Digital Equipment Corporation. 109d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 110d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * G. May Yip. 1991. Incremental, Generational Mostly-Copying Garbage 111d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Collection in Uncooperative Environments. Digital Equipment 112d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Corporation. 113d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 114d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Giuseppe Attardi, Tito Flagella. 1994. A Customisable Memory 115d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Management Framework. TR-94-010 116d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 117d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Giuseppe Attardi, Tito Flagella, Pietro Iglio. 1998. A customisable 118d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * memory management framework for C++. Software -- Practice and 119d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Experience. 28(11), 1143-1183. 120d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 121d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 122d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 123d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0])) 124d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1258bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#if 0 1264308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_ALLOC ALOGI 1274308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_PIN ALOGI 1284308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_PROM ALOGI 1294308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_REF ALOGI 1304308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_SCAV ALOGI 1314308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_TRAN ALOGI 1324308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block#define LOG_VER ALOGI 133d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#else 1348bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_ALLOC(...) ((void)0) 1358bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_PIN(...) ((void)0) 1368bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_PROM(...) ((void)0) 1378bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_REF(...) ((void)0) 1388bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_SCAV(...) ((void)0) 1398bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_TRAN(...) ((void)0) 1408bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro#define LOG_VER(...) ((void)0) 141d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 142d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 143d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void enqueueBlock(HeapSource *heapSource, size_t block); 1442396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic void scavengeReference(Object **obj); 145952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic bool toSpaceContains(const void *addr); 146952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic bool fromSpaceContains(const void *addr); 147d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic size_t sumHeapBitmap(const HeapBitmap *bitmap); 1482396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic size_t objectSize(const Object *obj); 149952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic void scavengeDataObject(Object *obj); 1501e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void scavengeBlockQueue(); 151d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 152d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 153d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * We use 512-byte blocks. 154d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 155d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiroenum { BLOCK_SHIFT = 9 }; 156d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiroenum { BLOCK_SIZE = 1 << BLOCK_SHIFT }; 157d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 158d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 159d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Space identifiers, stored into the blockSpace array. 160d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 161d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiroenum { 162d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro BLOCK_FREE = 0, 163d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro BLOCK_FROM_SPACE = 1, 164d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro BLOCK_TO_SPACE = 2, 165d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro BLOCK_CONTINUED = 7 166d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro}; 167d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 168d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 169d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Alignment for all allocations, in bytes. 170d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 171d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiroenum { ALLOC_ALIGNMENT = 8 }; 172d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 173d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 174d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Sentinel value for the queue end. 175d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 176d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#define QUEUE_TAIL (~(size_t)0) 177d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 178d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostruct HeapSource { 179d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 180d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* The base address of backing store. */ 181d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *blockBase; 182d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 183d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Total number of blocks available for allocation. */ 184d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t totalBlocks; 185d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t allocBlocks; 186d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 187d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 188d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The scavenger work queue. Implemented as an array of index 189d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * values into the queue. 190d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 191d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t *blockQueue; 192d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 193d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 194d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Base and limit blocks. Basically the shifted start address of 195d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the block. We convert blocks to a relative number when 196d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * indexing in the block queue. TODO: make the block queue base 197d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * relative rather than the index into the block queue. 198d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 199d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t baseBlock, limitBlock; 200d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 201d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t queueHead; 202d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t queueTail; 203d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t queueSize; 204d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 205d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* The space of the current block 0 (free), 1 or 2. */ 206d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro char *blockSpace; 207d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 208d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Start of free space in the current block. */ 209d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *allocPtr; 210d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Exclusive limit of free space in the current block. */ 211d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *allocLimit; 212d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 213d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapBitmap allocBits; 214d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 215d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 216d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The starting size of the heap. This value is the same as the 217d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * value provided to the -Xms flag. 218d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 219d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t minimumSize; 220d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 221d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 222d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The maximum size of the heap. This value is the same as the 223d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * -Xmx flag. 224d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 225d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t maximumSize; 226d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 227d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 228d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The current, committed size of the heap. At present, this is 229d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * equivalent to the maximumSize. 230d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 231d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t currentSize; 232d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 233d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t bytesAllocated; 234d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro}; 235d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 236d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic unsigned long alignDown(unsigned long x, unsigned long n) 237d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 238d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return x & -n; 239d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 240d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 241d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic unsigned long alignUp(unsigned long x, unsigned long n) 242d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 243d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return alignDown(x + (n - 1), n); 244d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 245d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 246d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void describeBlocks(const HeapSource *heapSource) 247d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 248f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < heapSource->totalBlocks; ++i) { 249d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if ((i % 32) == 0) putchar('\n'); 250d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro printf("%d ", heapSource->blockSpace[i]); 251d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 252d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro putchar('\n'); 253d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 254d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 255d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 256d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Virtual memory interface. 257d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 258d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 259d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void *virtualAlloc(size_t length) 260d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 261f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro int flags = MAP_PRIVATE | MAP_ANONYMOUS; 262f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro int prot = PROT_READ | PROT_WRITE; 263f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro void *addr = mmap(NULL, length, prot, flags, -1, 0); 264d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (addr == MAP_FAILED) { 265d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro LOGE_HEAP("mmap: %s", strerror(errno)); 266d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro addr = NULL; 267d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 268d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return addr; 269d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 270d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 271d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void virtualFree(void *addr, size_t length) 272d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 273d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(addr != NULL); 274d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert((uintptr_t)addr % SYSTEM_PAGE_SIZE == 0); 275f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro int res = munmap(addr, length); 276d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (res == -1) { 277d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro LOGE_HEAP("munmap: %s", strerror(errno)); 278d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 279d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 280d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 281eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro#ifndef NDEBUG 282d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic int isValidAddress(const HeapSource *heapSource, const u1 *addr) 283d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 284d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t block; 285d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 286d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = (uintptr_t)addr >> BLOCK_SHIFT; 287d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return heapSource->baseBlock <= block && 288d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->limitBlock > block; 289d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 290eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro#endif 291d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 292d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 293d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Iterate over the block map looking for a contiguous run of free 294d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * blocks. 295d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 296d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void *allocateBlocks(HeapSource *heapSource, size_t blocks) 297d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 298f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t allocBlocks = heapSource->allocBlocks; 299f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t totalBlocks = heapSource->totalBlocks; 300d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Check underflow. */ 301d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(blocks != 0); 302d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Check overflow. */ 303d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (allocBlocks + blocks > totalBlocks / 2) { 304d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return NULL; 305d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 306d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scan block map. */ 307f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < totalBlocks; ++i) { 308d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Check fit. */ 309f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t j = 0; j < blocks; ++j) { /* runs over totalBlocks */ 310d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->blockSpace[i+j] != BLOCK_FREE) { 311d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro break; 312d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 313d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 314d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* No fit? */ 315d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (j != blocks) { 316d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro i += j; 317d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro continue; 318d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 319d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Fit, allocate. */ 320d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[i] = BLOCK_TO_SPACE; /* why to-space? */ 321f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t j = 1; j < blocks; ++j) { 322d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[i+j] = BLOCK_CONTINUED; 323d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 324d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocBlocks += blocks; 325f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro void *addr = &heapSource->blockBase[i*BLOCK_SIZE]; 326d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro memset(addr, 0, blocks*BLOCK_SIZE); 327d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Collecting? */ 328d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->queueHead != QUEUE_TAIL) { 329d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro LOG_ALLOC("allocateBlocks allocBlocks=%zu,block#=%zu", heapSource->allocBlocks, i); 330d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 331d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * This allocated was on behalf of the transporter when it 332d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * shaded a white object gray. We enqueue the block so 333d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the scavenger can further shade the gray objects black. 334d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 335d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro enqueueBlock(heapSource, i); 336d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 337d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 338d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return addr; 339d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 340d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Insufficient space, fail. */ 341c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Insufficient space, %zu blocks, %zu blocks allocated and %zu bytes allocated", 342d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->totalBlocks, 343d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocBlocks, 344d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->bytesAllocated); 345d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return NULL; 346d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 347d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 348d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* Converts an absolute address to a relative block number. */ 349d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic size_t addressToBlock(const HeapSource *heapSource, const void *addr) 350d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 351d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 352d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(isValidAddress(heapSource, addr)); 353d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return (((uintptr_t)addr) >> BLOCK_SHIFT) - heapSource->baseBlock; 354d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 355d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 356d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* Converts a relative block number to an absolute address. */ 357d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic u1 *blockToAddress(const HeapSource *heapSource, size_t block) 358d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 359d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *addr; 360d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 361d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro addr = (u1 *) (((uintptr_t) heapSource->baseBlock + block) * BLOCK_SIZE); 362d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(isValidAddress(heapSource, addr)); 363d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return addr; 364d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 365d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 366d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void clearBlock(HeapSource *heapSource, size_t block) 367d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 368d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 369d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(block < heapSource->totalBlocks); 370f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro u1 *addr = heapSource->blockBase + block*BLOCK_SIZE; 371d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro memset(addr, 0xCC, BLOCK_SIZE); 372f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < BLOCK_SIZE; i += 8) { 373d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHeapBitmapClearObjectBit(&heapSource->allocBits, addr + i); 374d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 375d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 376d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 377d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void clearFromSpace(HeapSource *heapSource) 378d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 379d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 380f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t i = 0; 381f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t count = 0; 382d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (i < heapSource->totalBlocks) { 383d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->blockSpace[i] != BLOCK_FROM_SPACE) { 384d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++i; 385d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro continue; 386d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 387d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[i] = BLOCK_FREE; 388d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro clearBlock(heapSource, i); 389d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++i; 390d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++count; 391d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (i < heapSource->totalBlocks && 392d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[i] == BLOCK_CONTINUED) { 393d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[i] = BLOCK_FREE; 394d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro clearBlock(heapSource, i); 395d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++i; 396d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++count; 397d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 398d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 3998bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("freed %zu blocks (%zu bytes)", count, count*BLOCK_SIZE); 400d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 401d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 402d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 403d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Appends the given block to the block queue. The block queue is 404d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * processed in-order by the scavenger. 405d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 406d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void enqueueBlock(HeapSource *heapSource, size_t block) 407d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 408d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 409d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(block < heapSource->totalBlocks); 410d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->queueHead != QUEUE_TAIL) { 411d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockQueue[heapSource->queueTail] = block; 412d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 413d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->queueHead = block; 414d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 415d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockQueue[block] = QUEUE_TAIL; 416d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->queueTail = block; 417d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++heapSource->queueSize; 418d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 419d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 420d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 421d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Grays all objects within the block corresponding to the given 422d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * address. 423d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 424d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void promoteBlockByAddr(HeapSource *heapSource, const void *addr) 425d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 426d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t block; 427d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 428d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = addressToBlock(heapSource, (const u1 *)addr); 429d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->blockSpace[block] != BLOCK_TO_SPACE) { 4308bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_PROM("promoting block %zu %d @ %p", block, heapSource->blockSpace[block], obj); 431d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[block] = BLOCK_TO_SPACE; 432d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro enqueueBlock(heapSource, block); 433d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* TODO(cshapiro): count continued blocks?*/ 434d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocBlocks += 1; 435d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 4368bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_PROM("NOT promoting block %zu %d @ %p", block, heapSource->blockSpace[block], obj); 437d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 438d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 439d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 440d28668cf8740d1f913b4e9140a8c685013c1ad18Carl ShapiroGcHeap *dvmHeapSourceStartup(size_t startSize, size_t absoluteMaxSize) 441d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 442d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro GcHeap* gcHeap; 443d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapSource *heapSource; 444d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 445d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(startSize <= absoluteMaxSize); 446d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 447b74e7190e86d559712747e5cdb31a0d390b7af7dIliyan Malchev heapSource = calloc(1, sizeof(*heapSource)); 448d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 449d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 450d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->minimumSize = alignUp(startSize, BLOCK_SIZE); 451d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->maximumSize = alignUp(absoluteMaxSize, BLOCK_SIZE); 452d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 453d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->currentSize = heapSource->maximumSize; 454d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 455d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Allocate underlying storage for blocks. */ 456d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockBase = virtualAlloc(heapSource->maximumSize); 457d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->blockBase != NULL); 458d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->baseBlock = (uintptr_t) heapSource->blockBase >> BLOCK_SHIFT; 459d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->limitBlock = ((uintptr_t) heapSource->blockBase + heapSource->maximumSize) >> BLOCK_SHIFT; 460d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 461d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocBlocks = 0; 462d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->totalBlocks = (heapSource->limitBlock - heapSource->baseBlock); 463d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 464d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->totalBlocks = heapSource->maximumSize / BLOCK_SIZE); 465d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 466d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro { 467d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t size = sizeof(heapSource->blockQueue[0]); 468d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockQueue = malloc(heapSource->totalBlocks*size); 469d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->blockQueue != NULL); 470d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro memset(heapSource->blockQueue, 0xCC, heapSource->totalBlocks*size); 471d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->queueHead = QUEUE_TAIL; 472d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 473d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 474d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Byte indicating space residence or free status of block. */ 475d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro { 476d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t size = sizeof(heapSource->blockSpace[0]); 477b74e7190e86d559712747e5cdb31a0d390b7af7dIliyan Malchev heapSource->blockSpace = calloc(1, heapSource->totalBlocks*size); 478d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->blockSpace != NULL); 479d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 480d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 481d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHeapBitmapInit(&heapSource->allocBits, 482d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockBase, 483d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->maximumSize, 484d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro "blockBase"); 485d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 486d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Initialize allocation pointers. */ 487d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocPtr = allocateBlocks(heapSource, 1); 488d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocLimit = heapSource->allocPtr + BLOCK_SIZE; 489d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 490b74e7190e86d559712747e5cdb31a0d390b7af7dIliyan Malchev gcHeap = calloc(1, sizeof(*gcHeap)); 491d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(gcHeap != NULL); 492d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro gcHeap->heapSource = heapSource; 493d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 494d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return gcHeap; 495d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 496d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 497d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 498d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Perform any required heap initializations after forking from the 499d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * zygote process. This is a no-op for the time being. Eventually 500d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * this will demarcate the shared region of the heap. 501d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 5021e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmHeapSourceStartupAfterZygote() 503d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 504d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return true; 505d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 506d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 5071e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmHeapSourceStartupBeforeFork() 508d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 509d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 510d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return false; 511d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 512d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 513d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmHeapSourceShutdown(GcHeap **gcHeap) 514d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 515d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (*gcHeap == NULL || (*gcHeap)->heapSource == NULL) 516d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return; 51788b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro free((*gcHeap)->heapSource->blockQueue); 51888b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro free((*gcHeap)->heapSource->blockSpace); 519d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro virtualFree((*gcHeap)->heapSource->blockBase, 520d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro (*gcHeap)->heapSource->maximumSize); 521d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro free((*gcHeap)->heapSource); 522d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro (*gcHeap)->heapSource = NULL; 523d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro free(*gcHeap); 524d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *gcHeap = NULL; 525d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 526d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 527d862faa2ceae186da5518607505eb942d634ced9Carl Shapirosize_t dvmHeapSourceGetValue(HeapSourceValueSpec spec, 528d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t perHeapStats[], 529d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t arrayLen) 530d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 531d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapSource *heapSource; 532d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t value; 533d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 534d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource = gDvm.gcHeap->heapSource; 535d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro switch (spec) { 536d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case HS_FOOTPRINT: 537d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro value = heapSource->maximumSize; 538d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro break; 539d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case HS_ALLOWED_FOOTPRINT: 540d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro value = heapSource->maximumSize; 541d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro break; 542d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case HS_BYTES_ALLOCATED: 543d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro value = heapSource->bytesAllocated; 544d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro break; 545d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case HS_OBJECTS_ALLOCATED: 546d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro value = sumHeapBitmap(&heapSource->allocBits); 547d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro break; 548d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro default: 549d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 550d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro value = 0; 551d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 552d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (perHeapStats) { 553d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *perHeapStats = value; 554d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 555d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return value; 556d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 557d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 558d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 559d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Performs a shallow copy of the allocation bitmap into the given 560d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * vector of heap bitmaps. 561d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 562d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmHeapSourceGetObjectBitmaps(HeapBitmap objBits[], HeapBitmap markBits[], 563d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t numHeaps) 564d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 565d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 566d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 567d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 5681e1433e78f560a01744e870c19c162ab88df9dc1Carl ShapiroHeapBitmap *dvmHeapSourceGetLiveBits() 569d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 570603469a4258a1daf35841449e29f34639115f35eCarl Shapiro return &gDvm.gcHeap->heapSource->allocBits; 571d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 572d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 573d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 574d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Allocate the specified number of bytes from the heap. The 575d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * allocation cursor points into a block of free storage. If the 576d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * given allocation fits in the remaining space of the block, we 577d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * advance the cursor and return a pointer to the free storage. If 578d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the allocation cannot fit in the current block but is smaller than 579d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * a block we request a new block and allocate from it instead. If 580d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the allocation is larger than a block we must allocate from a span 581d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * of contiguous blocks. 582d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 583d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid *dvmHeapSourceAlloc(size_t length) 584d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 585d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapSource *heapSource; 586d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro unsigned char *addr; 587d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t aligned, available, blocks; 588d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 589d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource = gDvm.gcHeap->heapSource; 590d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 591d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->allocPtr != NULL); 592d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->allocLimit != NULL); 593d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 594d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro aligned = alignUp(length, ALLOC_ALIGNMENT); 595d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro available = heapSource->allocLimit - heapSource->allocPtr; 596d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 597d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Try allocating inside the current block. */ 598d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (aligned <= available) { 599d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro addr = heapSource->allocPtr; 600d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocPtr += aligned; 601d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->bytesAllocated += aligned; 602d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHeapBitmapSetObjectBit(&heapSource->allocBits, addr); 603d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return addr; 604d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 605d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 606d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Try allocating in a new block. */ 607d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (aligned <= BLOCK_SIZE) { 608d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro addr = allocateBlocks(heapSource, 1); 609d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (addr != NULL) { 610d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocLimit = addr + BLOCK_SIZE; 611d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocPtr = addr + aligned; 612d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->bytesAllocated += aligned; 613d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHeapBitmapSetObjectBit(&heapSource->allocBits, addr); 614d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* TODO(cshapiro): pad out the current block. */ 615d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 616d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return addr; 617d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 618d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 619d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Try allocating in a span of blocks. */ 620d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro blocks = alignUp(aligned, BLOCK_SIZE) / BLOCK_SIZE; 621d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 622d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro addr = allocateBlocks(heapSource, blocks); 623d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Propagate failure upward. */ 624d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (addr != NULL) { 625d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->bytesAllocated += aligned; 626d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHeapBitmapSetObjectBit(&heapSource->allocBits, addr); 627d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* TODO(cshapiro): pad out free space in the last block. */ 628d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 629d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return addr; 630d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 631d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 632d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid *dvmHeapSourceAllocAndGrow(size_t size) 633d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 634d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return dvmHeapSourceAlloc(size); 635d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 636d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 637d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* TODO: refactor along with dvmHeapSourceAlloc */ 638d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid *allocateGray(size_t size) 639d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 6407800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro HeapSource *heapSource; 6417800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro void *addr; 6427800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro size_t block; 6437800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro 644952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* TODO: add a check that we are in a GC. */ 6457800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro heapSource = gDvm.gcHeap->heapSource; 6467800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro addr = dvmHeapSourceAlloc(size); 647703a2f3f1acc3ecc23d37970af2638463587a40fCarl Shapiro assert(addr != NULL); 6487800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro block = addressToBlock(heapSource, (const u1 *)addr); 6497800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro if (heapSource->queueHead == QUEUE_TAIL) { 6507800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro /* 6517800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro * Forcibly append the underlying block to the queue. This 6527800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro * condition occurs when referents are transported following 6537800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro * the initial trace. 6547800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro */ 6557800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro enqueueBlock(heapSource, block); 6567800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro LOG_PROM("forced promoting block %zu %d @ %p", block, heapSource->blockSpace[block], addr); 6577800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro } 6587800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro return addr; 659d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 660d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 661eff0df741d2b1537cf1010328000c1369559b628Carl Shapirobool dvmHeapSourceContainsAddress(const void *ptr) 662eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro{ 663eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro HeapSource *heapSource = gDvm.gcHeap->heapSource; 664eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro return dvmHeapBitmapCoversAddress(&heapSource->allocBits, ptr); 665eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro} 666eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro 667d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 668d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Returns true if the given address is within the heap and points to 669d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the header of a live object. 670d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 671d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirobool dvmHeapSourceContains(const void *addr) 672d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 673d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapSource *heapSource; 674d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapBitmap *bitmap; 675d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 676d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource = gDvm.gcHeap->heapSource; 677d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro bitmap = &heapSource->allocBits; 678dc1e4f1499994dca0b6796c32acaa66e436a02daCarl Shapiro if (!dvmHeapBitmapCoversAddress(bitmap, addr)) { 679dc1e4f1499994dca0b6796c32acaa66e436a02daCarl Shapiro return false; 680dc1e4f1499994dca0b6796c32acaa66e436a02daCarl Shapiro } else { 681dc1e4f1499994dca0b6796c32acaa66e436a02daCarl Shapiro return dvmHeapBitmapIsObjectBitSet(bitmap, addr); 682dc1e4f1499994dca0b6796c32acaa66e436a02daCarl Shapiro } 683d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 684d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 6855cdd4a3f91d3fc25c8eeca8f58e35bb6c4e908caCarl Shapirobool dvmHeapSourceGetPtrFlag(const void *ptr, HeapSourcePtrFlag flag) 686d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 687d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 688d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return false; 689d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 690d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 691d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirosize_t dvmHeapSourceChunkSize(const void *ptr) 692d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 693d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 694d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return 0; 695d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 696d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 6971e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirosize_t dvmHeapSourceFootprint() 698d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 699d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 700d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return 0; 701d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 702d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 703d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 704d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Returns the "ideal footprint" which appears to be the number of 705d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * bytes currently committed to the heap. This starts out at the 706d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * start size of the heap and grows toward the maximum size. 707d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 7081e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirosize_t dvmHeapSourceGetIdealFootprint() 709d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 710d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return gDvm.gcHeap->heapSource->currentSize; 711d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 712d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 7131e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirofloat dvmGetTargetHeapUtilization() 714d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 715603469a4258a1daf35841449e29f34639115f35eCarl Shapiro return 0.5f; 716d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 717d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 718d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmSetTargetHeapUtilization(float newTarget) 719d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 720603469a4258a1daf35841449e29f34639115f35eCarl Shapiro assert(newTarget > 0.0f && newTarget < 1.0f); 721d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 722d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 723d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 724d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Expands the size of the heap after a collection. At present we 725d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * commit the pages for maximum size of the heap so this routine is 726d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * just a no-op. Eventually, we will either allocate or commit pages 727d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * on an as-need basis. 728d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 7291e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapSourceGrowForUtilization() 730d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 731d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* do nothing */ 732d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 733d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 734808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogersvoid dvmHeapSourceWalk(void(*callback)(void* start, void* end, 735808a7c0e7e39b7ca3c7db1366e6e4089166052bbIan Rogers size_t used_bytes, void* arg), 736d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro void *arg) 737d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 738d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 739d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 740d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 7411e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirosize_t dvmHeapSourceGetNumHeaps() 742d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 743d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return 1; 744d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 745d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 746d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirobool dvmTrackExternalAllocation(size_t n) 747d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 748528f381bbecd4ee90018f5e0cb2a28388790f82fCarl Shapiro /* do nothing */ 749528f381bbecd4ee90018f5e0cb2a28388790f82fCarl Shapiro return true; 750d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 751d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 752d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmTrackExternalFree(size_t n) 753d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 754528f381bbecd4ee90018f5e0cb2a28388790f82fCarl Shapiro /* do nothing */ 755d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 756d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 7571e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirosize_t dvmGetExternalBytesAllocated() 758d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 759d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 760d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return 0; 761d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 762d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 7631e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapSourceFlip() 764d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 765f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HeapSource *heapSource = gDvm.gcHeap->heapSource; 766d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 767d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Reset the block queue. */ 768d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocBlocks = 0; 769d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->queueSize = 0; 770d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->queueHead = QUEUE_TAIL; 771d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 772d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* TODO(cshapiro): pad the current (prev) block. */ 773d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 774d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocPtr = NULL; 775d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->allocLimit = NULL; 776d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 777d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Whiten all allocated blocks. */ 778f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < heapSource->totalBlocks; ++i) { 779d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->blockSpace[i] == BLOCK_TO_SPACE) { 780d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->blockSpace[i] = BLOCK_FROM_SPACE; 781d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 782d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 783d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 784d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 785d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void room(size_t *alloc, size_t *avail, size_t *total) 786d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 787f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HeapSource *heapSource = gDvm.gcHeap->heapSource; 788d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *total = heapSource->totalBlocks*BLOCK_SIZE; 789d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *alloc = heapSource->allocBlocks*BLOCK_SIZE; 790d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *avail = *total - *alloc; 791d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 792d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 793d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic bool isSpaceInternal(u1 *addr, int space) 794d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 795d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapSource *heapSource; 796d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *base, *limit; 797d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t offset; 798d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro char space2; 799d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 800d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource = gDvm.gcHeap->heapSource; 801d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro base = heapSource->blockBase; 802d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(addr >= base); 803d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro limit = heapSource->blockBase + heapSource->maximumSize; 804d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(addr < limit); 805d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro offset = addr - base; 806d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro space2 = heapSource->blockSpace[offset >> BLOCK_SHIFT]; 807d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return space == space2; 808d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 809d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 810952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic bool fromSpaceContains(const void *addr) 811d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 812d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return isSpaceInternal((u1 *)addr, BLOCK_FROM_SPACE); 813d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 814d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 815952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic bool toSpaceContains(const void *addr) 816d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 817d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return isSpaceInternal((u1 *)addr, BLOCK_TO_SPACE); 818d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 819d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 820d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 821d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Notifies the collector that the object at the given address must 822d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * remain stationary during the current collection. 823d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 824d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void pinObject(const Object *obj) 825d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 826d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro promoteBlockByAddr(gDvm.gcHeap->heapSource, obj); 827d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 828d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 829d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic size_t sumHeapBitmap(const HeapBitmap *bitmap) 830d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 831f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t sum = 0; 832f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < bitmap->bitsLen >> 2; ++i) { 833603469a4258a1daf35841449e29f34639115f35eCarl Shapiro sum += CLZ(bitmap->bits[i]); 834d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 835d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return sum; 836d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 837d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 838d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 839d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Miscellaneous functionality. 840d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 841d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 842d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic int isForward(const void *addr) 843d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 844d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return (uintptr_t)addr & 0x1; 845d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 846d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 847d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void setForward(const void *toObj, void *fromObj) 848d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 849d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *(unsigned long *)fromObj = (uintptr_t)toObj | 0x1; 850d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 851d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 852d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void* getForward(const void *fromObj) 853d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 854d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return (void *)((uintptr_t)fromObj & ~0x1); 855d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 856d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 857d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* Beware, uses the same encoding as a forwarding pointers! */ 858d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic int isPermanentString(const StringObject *obj) { 859d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return (uintptr_t)obj & 0x1; 860d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 861d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 862d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void* getPermanentString(const StringObject *obj) 863d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 864d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return (void *)((uintptr_t)obj & ~0x1); 865d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 866d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 867d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 868d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 869d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Scavenging and transporting routines follow. A transporter grays 870d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * an object. A scavenger blackens an object. We define these 871d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * routines for each fundamental object type. Dispatch is performed 872d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * in scavengeObject. 873d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 874d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 875d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 8762396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * Class object scavenging. 877d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 8782396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic void scavengeClassObject(ClassObject *obj) 879d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 8808bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeClassObject(obj=%p)", obj); 8812396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(obj != NULL); 882d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj->obj.clazz != NULL); 883d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj->obj.clazz->descriptor != NULL); 884d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!strcmp(obj->obj.clazz->descriptor, "Ljava/lang/Class;")); 885d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj->descriptor != NULL); 8868bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeClassObject: descriptor='%s',vtableCount=%zu", 8878bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro obj->descriptor, obj->vtableCount); 888703a2f3f1acc3ecc23d37970af2638463587a40fCarl Shapiro /* Delegate class object and instance field scavenging. */ 889703a2f3f1acc3ecc23d37970af2638463587a40fCarl Shapiro scavengeDataObject((Object *)obj); 890d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge the array element class object. */ 891d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (IS_CLASS_FLAG_SET(obj, CLASS_ISARRAY)) { 892d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **)(void *)&obj->elementClass); 893d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 894d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge the superclass. */ 895d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **)(void *)&obj->super); 896d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge the class loader. */ 897d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&obj->classLoader); 898d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge static fields. */ 899f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < obj->sfieldCount; ++i) { 900d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro char ch = obj->sfields[i].field.signature[0]; 901d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (ch == '[' || ch == 'L') { 902d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **)(void *)&obj->sfields[i].value.l); 903d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 904d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 905d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge interface class objects. */ 906f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < obj->interfaceCount; ++i) { 907d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **) &obj->interfaces[i]); 908d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 909d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 910d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 911d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 912d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Array object scavenging. 913d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 914d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic size_t scavengeArrayObject(ArrayObject *array) 915d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 9168bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeArrayObject(array=%p)", array); 917d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge the class object. */ 918952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(toSpaceContains(array)); 919d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(array != NULL); 920d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(array->obj.clazz != NULL); 921d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **) array); 922f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t length = dvmArrayObjectSize(array); 923d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge the array contents. */ 924d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (IS_CLASS_FLAG_SET(array->obj.clazz, CLASS_ISOBJECTARRAY)) { 925d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro Object **contents = (Object **)array->contents; 926f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < array->length; ++i) { 927d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&contents[i]); 928d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 929d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 930d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return length; 931d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 932d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 933d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 934d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Reference object scavenging. 935d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 936d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 937952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic int getReferenceFlags(const Object *obj) 938d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 939d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro int flags; 940d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 941d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro flags = CLASS_ISREFERENCE | 942d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro CLASS_ISWEAKREFERENCE | 943d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro CLASS_ISPHANTOMREFERENCE; 944952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro return GET_CLASS_FLAG_GROUP(obj->clazz, flags); 945d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 946d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 947952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic int isSoftReference(const Object *obj) 948d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 949d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return getReferenceFlags(obj) == CLASS_ISREFERENCE; 950d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 951d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 952952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic int isWeakReference(const Object *obj) 953d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 954d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return getReferenceFlags(obj) & CLASS_ISWEAKREFERENCE; 955d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 956d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 957eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro#ifndef NDEBUG 958952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic bool isPhantomReference(const Object *obj) 959d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 960d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return getReferenceFlags(obj) & CLASS_ISPHANTOMREFERENCE; 961d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 962eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro#endif 963d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 964952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro/* 965952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Returns true if the reference was registered with a reference queue 966952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * but has not yet been appended to it. 967952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 968952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic bool isReferenceEnqueuable(const Object *ref) 969d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 970952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *queue, *queueNext; 971d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 972952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro queue = dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queue); 973952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro queueNext = dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queueNext); 974952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (queue == NULL || queueNext != NULL) { 975952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 976952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * There is no queue, or the reference has already 977952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * been enqueued. The Reference.enqueue() method 978952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * will do nothing even if we call it. 979952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 980952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro return false; 981952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 982952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 983952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 984952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * We need to call enqueue(), but if we called it from 985952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * here we'd probably deadlock. Schedule a call. 986952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 987952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro return true; 988d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 989d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 990952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro/* 991952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Schedules a reference to be appended to its reference queue. 992952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 993eff0df741d2b1537cf1010328000c1369559b628Carl Shapirostatic void enqueueReference(Object *ref) 994d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 995646ba0996da817deddb509b2130a6ad432096691Carl Shapiro assert(ref != NULL); 996952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queue) != NULL); 997952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(dvmGetFieldObject(ref, gDvm.offJavaLangRefReference_queueNext) == NULL); 998646ba0996da817deddb509b2130a6ad432096691Carl Shapiro if (!dvmHeapAddRefToLargeTable(&gDvm.gcHeap->referenceOperations, ref)) { 999c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("no room for any more reference operations"); 1000952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmAbort(); 1001952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1002d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1003d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1004952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro/* 1005952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Sets the referent field of a reference object to NULL. 1006952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1007952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic void clearReference(Object *obj) 1008d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1009952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmSetFieldObject(obj, gDvm.offJavaLangRefReference_referent, NULL); 1010952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro} 1011d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1012952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro/* 1013952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Clears reference objects with white referents. 1014952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1015952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirovoid clearWhiteReferences(Object **list) 1016952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro{ 1017697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes size_t referentOffset, queueNextOffset; 1018952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro bool doSignal; 1019952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1020697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes queueNextOffset = gDvm.offJavaLangRefReference_queueNext; 1021952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro referentOffset = gDvm.offJavaLangRefReference_referent; 1022952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro doSignal = false; 1023952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro while (*list != NULL) { 1024952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *ref = *list; 1025952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro JValue *field = dvmFieldPtr(ref, referentOffset); 1026952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *referent = field->l; 1027697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes *list = dvmGetFieldObject(ref, queueNextOffset); 1028697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes dvmSetFieldObject(ref, queueNextOffset, NULL); 1029952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(referent != NULL); 1030952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (isForward(referent->clazz)) { 1031952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro field->l = referent = getForward(referent->clazz); 1032952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro continue; 1033952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1034952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (fromSpaceContains(referent)) { 1035952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Referent is white, clear it. */ 1036952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro clearReference(ref); 1037952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (isReferenceEnqueuable(ref)) { 1038952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro enqueueReference(ref); 1039952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro doSignal = true; 1040952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1041952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1042952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1043952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 1044952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * If we cleared a reference with a reference queue we must notify 1045952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * the heap worker to append the reference. 1046952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1047952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (doSignal) { 1048952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmSignalHeapWorker(false); 1049d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1050952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(*list == NULL); 1051952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro} 1052952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1053952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro/* 1054952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Blackens referents subject to the soft reference preservation 1055952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * policy. 1056952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1057952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirovoid preserveSoftReferences(Object **list) 1058952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro{ 1059952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *ref; 1060952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *prev, *next; 1061697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes size_t referentOffset, queueNextOffset; 1062952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro unsigned counter; 1063952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro bool white; 1064952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1065697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes queueNextOffset = gDvm.offJavaLangRefReference_queueNext; 1066952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro referentOffset = gDvm.offJavaLangRefReference_referent; 1067952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro counter = 0; 1068952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro prev = next = NULL; 1069952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro ref = *list; 1070952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro while (ref != NULL) { 1071952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro JValue *field = dvmFieldPtr(ref, referentOffset); 1072952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *referent = field->l; 1073697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes next = dvmGetFieldObject(ref, queueNextOffset); 1074952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(referent != NULL); 1075952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (isForward(referent->clazz)) { 1076952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Referent is black. */ 1077952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro field->l = referent = getForward(referent->clazz); 1078952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro white = false; 1079952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } else { 1080952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro white = fromSpaceContains(referent); 1081952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1082952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (!white && ((++counter) & 1)) { 1083952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Referent is white and biased toward saving, gray it. */ 1084952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro scavengeReference((Object **)(void *)&field->l); 1085952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro white = true; 1086952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1087952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (white) { 1088952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Referent is black, unlink it. */ 1089952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (prev != NULL) { 1090697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes dvmSetFieldObject(ref, queueNextOffset, NULL); 1091697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes dvmSetFieldObject(prev, queueNextOffset, next); 1092952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1093952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } else { 1094952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Referent is white, skip over it. */ 1095952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro prev = ref; 1096952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1097952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro ref = next; 1098952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1099952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 1100952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Restart the trace with the newly gray references added to the 1101952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * root set. 1102952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1103952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro scavengeBlockQueue(); 1104952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro} 1105952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 11061e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid processFinalizableReferences() 1107952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro{ 1108952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro HeapRefTable newPendingRefs; 1109952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro LargeHeapRefTable *finRefs = gDvm.gcHeap->finalizableRefs; 1110952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object **ref; 1111952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object **lastRef; 1112952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro size_t totalPendCount; 1113952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1114952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 1115952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * All strongly, reachable objects are black. 1116952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Any white finalizable objects need to be finalized. 1117952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1118952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1119952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Create a table that the new pending refs will 1120952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * be added to. 1121952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1122eff0df741d2b1537cf1010328000c1369559b628Carl Shapiro if (!dvmHeapInitHeapRefTable(&newPendingRefs)) { 1123952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro //TODO: mark all finalizable refs and hope that 1124952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro // we can schedule them next time. Watch out, 1125952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro // because we may be expecting to free up space 1126952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro // by calling finalizers. 112760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_REF("no room for pending finalizations"); 1128952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmAbort(); 1129952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1130952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1131952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 1132952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Walk through finalizableRefs and move any white references to 1133952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * the list of new pending refs. 1134952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1135952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro totalPendCount = 0; 1136952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro while (finRefs != NULL) { 1137952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object **gapRef; 1138952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro size_t newPendCount = 0; 1139952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1140952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro gapRef = ref = finRefs->refs.table; 1141952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro lastRef = finRefs->refs.nextEntry; 1142952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro while (ref < lastRef) { 1143952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (fromSpaceContains(*ref)) { 1144952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (!dvmHeapAddToHeapRefTable(&newPendingRefs, *ref)) { 1145952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro //TODO: add the current table and allocate 1146952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro // a new, smaller one. 114760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_REF("no room for any more pending finalizations: %zd", 1148952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmHeapNumHeapRefTableEntries(&newPendingRefs)); 1149952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmAbort(); 1150952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1151952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro newPendCount++; 1152952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } else { 1153952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* This ref is black, so will remain on finalizableRefs. 1154952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1155952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (newPendCount > 0) { 1156952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Copy it up to fill the holes. 1157952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1158952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro *gapRef++ = *ref; 1159952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } else { 1160952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* No holes yet; don't bother copying. 1161952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1162952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro gapRef++; 1163952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1164952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1165952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro ref++; 1166952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1167952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro finRefs->refs.nextEntry = gapRef; 1168952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro //TODO: if the table is empty when we're done, free it. 1169952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro totalPendCount += newPendCount; 1170952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro finRefs = finRefs->next; 1171952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 117260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_REF("%zd finalizers triggered.", totalPendCount); 1173952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (totalPendCount == 0) { 1174952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* No objects required finalization. 1175952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Free the empty temporary table. 1176952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1177952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmClearReferenceTable(&newPendingRefs); 1178952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro return; 1179952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1180952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1181952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Add the new pending refs to the main list. 1182952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1183952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (!dvmHeapAddTableToLargeTable(&gDvm.gcHeap->pendingFinalizationRefs, 1184952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro &newPendingRefs)) 1185952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro { 118660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_REF("can't insert new pending finalizations"); 1187952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmAbort(); 1188952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1189952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1190952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro //TODO: try compacting the main list with a memcpy loop 1191952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1192952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* Blacken the refs we just moved; we don't want them or their 1193952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * children to get swept yet. 1194952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 1195952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro ref = newPendingRefs.table; 1196952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro lastRef = newPendingRefs.nextEntry; 1197952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(ref < lastRef); 1198952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_FINALIZING, 0); 1199952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro while (ref < lastRef) { 1200952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro scavengeReference(ref); 1201952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro ref++; 1202952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1203952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro HPROF_CLEAR_GC_SCAN_STATE(); 1204952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro scavengeBlockQueue(); 1205952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro dvmSignalHeapWorker(false); 1206d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1207d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1208d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1209d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * If a reference points to from-space and has been forwarded, we snap 1210d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the pointer to its new to-space address. If the reference points 1211d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * to an unforwarded from-space address we must enqueue the reference 1212d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * for later processing. TODO: implement proper reference processing 1213d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * and move the referent scavenging elsewhere. 1214d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1215952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic void scavengeReferenceObject(Object *obj) 1216d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1217952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object *referent; 1218952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro Object **queue; 1219697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes size_t referentOffset, queueNextOffset; 1220952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 1221d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj != NULL); 12228bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeReferenceObject(obj=%p),'%s'", obj, obj->clazz->descriptor); 12232396fda0f5907178632a14d70a94257023e33d42Carl Shapiro scavengeDataObject(obj); 1224952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro referentOffset = gDvm.offJavaLangRefReference_referent; 1225952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro referent = dvmGetFieldObject(obj, referentOffset); 1226952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (referent == NULL || toSpaceContains(referent)) { 1227952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro return; 1228952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } 1229952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (isSoftReference(obj)) { 1230952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro queue = &gDvm.gcHeap->softReferences; 1231952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } else if (isWeakReference(obj)) { 1232952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro queue = &gDvm.gcHeap->weakReferences; 1233952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro } else { 1234952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(isPhantomReference(obj)); 1235952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro queue = &gDvm.gcHeap->phantomReferences; 1236d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1237697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes queueNextOffset = gDvm.offJavaLangRefReference_queueNext; 1238697b5a942503b14fcd537d528edfc05460f144ebBarry Hayes dvmSetFieldObject(obj, queueNextOffset, *queue); 1239952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro *queue = obj; 12408bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeReferenceObject: enqueueing %p", obj); 1241d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1242d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1243d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1244d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Data object scavenging. 1245d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1246952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapirostatic void scavengeDataObject(Object *obj) 1247d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 12488bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("scavengeDataObject(obj=%p)", obj); 1249d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj != NULL); 1250952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(obj->clazz != NULL); 1251952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(obj->clazz->objectSize != 0); 1252952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(toSpaceContains(obj)); 1253d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge the class object. */ 1254f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro ClassObject *clazz = obj->clazz; 1255d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **) obj); 1256d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Scavenge instance fields. */ 1257d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (clazz->refOffsets != CLASS_WALK_SUPER) { 1258d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t refOffsets = clazz->refOffsets; 1259d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (refOffsets != 0) { 1260d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t rshift = CLZ(refOffsets); 1261d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t offset = CLASS_OFFSET_FROM_CLZ(rshift); 1262d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro Object **ref = (Object **)((u1 *)obj + offset); 1263d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(ref); 1264d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro refOffsets &= ~(CLASS_HIGH_BIT >> rshift); 1265d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1266d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1267d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro for (; clazz != NULL; clazz = clazz->super) { 1268d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro InstField *field = clazz->ifields; 1269f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < clazz->ifieldRefCount; ++i, ++field) { 1270d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t offset = field->byteOffset; 1271d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro Object **ref = (Object **)((u1 *)obj + offset); 1272d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(ref); 1273d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1274d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1275d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 12762396fda0f5907178632a14d70a94257023e33d42Carl Shapiro} 12772396fda0f5907178632a14d70a94257023e33d42Carl Shapiro 12782396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic Object *transportObject(const Object *fromObj) 12792396fda0f5907178632a14d70a94257023e33d42Carl Shapiro{ 12802396fda0f5907178632a14d70a94257023e33d42Carl Shapiro Object *toObj; 12812396fda0f5907178632a14d70a94257023e33d42Carl Shapiro size_t allocSize, copySize; 12822396fda0f5907178632a14d70a94257023e33d42Carl Shapiro 12838bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_TRAN("transportObject(fromObj=%p) allocBlocks=%zu", 12842396fda0f5907178632a14d70a94257023e33d42Carl Shapiro fromObj, 12852396fda0f5907178632a14d70a94257023e33d42Carl Shapiro gDvm.gcHeap->heapSource->allocBlocks); 12862396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(fromObj != NULL); 1287952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(fromSpaceContains(fromObj)); 12882396fda0f5907178632a14d70a94257023e33d42Carl Shapiro allocSize = copySize = objectSize(fromObj); 12892396fda0f5907178632a14d70a94257023e33d42Carl Shapiro if (LW_HASH_STATE(fromObj->lock) != LW_HASH_STATE_UNHASHED) { 12902396fda0f5907178632a14d70a94257023e33d42Carl Shapiro /* 12912396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * The object has been hashed or hashed and moved. We must 12922396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * reserve an additional word for a hash code. 12932396fda0f5907178632a14d70a94257023e33d42Carl Shapiro */ 12942396fda0f5907178632a14d70a94257023e33d42Carl Shapiro allocSize += sizeof(u4); 12952396fda0f5907178632a14d70a94257023e33d42Carl Shapiro } 12962396fda0f5907178632a14d70a94257023e33d42Carl Shapiro if (LW_HASH_STATE(fromObj->lock) == LW_HASH_STATE_HASHED_AND_MOVED) { 12972396fda0f5907178632a14d70a94257023e33d42Carl Shapiro /* 12982396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * The object has its hash code allocated. Ensure the hash 12992396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * code is copied along with the instance data. 13002396fda0f5907178632a14d70a94257023e33d42Carl Shapiro */ 13012396fda0f5907178632a14d70a94257023e33d42Carl Shapiro copySize += sizeof(u4); 13022396fda0f5907178632a14d70a94257023e33d42Carl Shapiro } 13032396fda0f5907178632a14d70a94257023e33d42Carl Shapiro /* TODO(cshapiro): don't copy, re-map large data objects. */ 13042396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(copySize <= allocSize); 13052396fda0f5907178632a14d70a94257023e33d42Carl Shapiro toObj = allocateGray(allocSize); 13062396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(toObj != NULL); 1307952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(toSpaceContains(toObj)); 13082396fda0f5907178632a14d70a94257023e33d42Carl Shapiro memcpy(toObj, fromObj, copySize); 13092396fda0f5907178632a14d70a94257023e33d42Carl Shapiro if (LW_HASH_STATE(fromObj->lock) == LW_HASH_STATE_HASHED) { 13102396fda0f5907178632a14d70a94257023e33d42Carl Shapiro /* 13112396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * The object has had its hash code exposed. Append it to the 13122396fda0f5907178632a14d70a94257023e33d42Carl Shapiro * instance and set a bit so we know to look for it there. 13132396fda0f5907178632a14d70a94257023e33d42Carl Shapiro */ 13142396fda0f5907178632a14d70a94257023e33d42Carl Shapiro *(u4 *)(((char *)toObj) + copySize) = (u4)fromObj >> 3; 13152396fda0f5907178632a14d70a94257023e33d42Carl Shapiro toObj->lock |= LW_HASH_STATE_HASHED_AND_MOVED << LW_HASH_STATE_SHIFT; 13162396fda0f5907178632a14d70a94257023e33d42Carl Shapiro } 13178bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_TRAN("transportObject: from %p/%zu to %p/%zu (%zu,%zu) %s", 13188bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro fromObj, addressToBlock(gDvm.gcHeap->heapSource,fromObj), 13198bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro toObj, addressToBlock(gDvm.gcHeap->heapSource,toObj), 13208bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro copySize, allocSize, copySize < allocSize ? "DIFFERENT" : ""); 13212396fda0f5907178632a14d70a94257023e33d42Carl Shapiro return toObj; 1322d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1323d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1324d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1325d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Generic reference scavenging. 1326d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1327d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1328d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1329d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Given a reference to an object, the scavenge routine will gray the 1330d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * reference. Any objects pointed to by the scavenger object will be 1331d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * transported to new space and a forwarding pointer will be installed 1332d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * in the header of the object. 1333d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1334d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1335d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1336d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Blacken the given pointer. If the pointer is in from space, it is 1337d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * transported to new space. If the object has a forwarding pointer 1338d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * installed it has already been transported and the referent is 1339d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * snapped to the new address. 1340d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 13412396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic void scavengeReference(Object **obj) 1342d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1343d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ClassObject *clazz; 13442396fda0f5907178632a14d70a94257023e33d42Carl Shapiro Object *fromObj, *toObj; 1345d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1346d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj); 1347d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 13482396fda0f5907178632a14d70a94257023e33d42Carl Shapiro if (*obj == NULL) return; 1349d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1350d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(dvmIsValidObject(*obj)); 1351d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1352d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* The entire block is black. */ 1353952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro if (toSpaceContains(*obj)) { 13548bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeReference skipping pinned object @ %p", *obj); 13552396fda0f5907178632a14d70a94257023e33d42Carl Shapiro return; 1356d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 13578bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeReference(*obj=%p)", *obj); 1358d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1359952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(fromSpaceContains(*obj)); 1360d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1361d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro clazz = (*obj)->clazz; 1362d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1363d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (isForward(clazz)) { 13648bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("forwarding %p @ %p to %p", *obj, obj, (void *)((uintptr_t)clazz & ~0x1)); 1365d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro *obj = (Object *)getForward(clazz); 13662396fda0f5907178632a14d70a94257023e33d42Carl Shapiro return; 13672396fda0f5907178632a14d70a94257023e33d42Carl Shapiro } 13682396fda0f5907178632a14d70a94257023e33d42Carl Shapiro fromObj = *obj; 13692396fda0f5907178632a14d70a94257023e33d42Carl Shapiro if (clazz == NULL) { 13708bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("scavangeReference %p has a NULL class object", fromObj); 1371d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!"implemented"); 13722396fda0f5907178632a14d70a94257023e33d42Carl Shapiro toObj = NULL; 1373d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 13742396fda0f5907178632a14d70a94257023e33d42Carl Shapiro toObj = transportObject(fromObj); 1375d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 13762396fda0f5907178632a14d70a94257023e33d42Carl Shapiro setForward(toObj, fromObj); 13772396fda0f5907178632a14d70a94257023e33d42Carl Shapiro *obj = (Object *)toObj; 1378d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1379d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1380d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1381d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Generic object scavenging. 1382d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 13832396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic void scavengeObject(Object *obj) 1384d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1385d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ClassObject *clazz; 1386d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1387d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(obj != NULL); 1388952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(obj->clazz != NULL); 1389952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro assert(!((uintptr_t)obj->clazz & 0x1)); 1390d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro clazz = obj->clazz; 1391c6d2470eec726ae0ad95e4fd2d9d7da7cb2cdcbaDan Bornstein if (dvmIsTheClassClass(clazz)) { 13922396fda0f5907178632a14d70a94257023e33d42Carl Shapiro scavengeClassObject((ClassObject *)obj); 1393d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISARRAY)) { 13942396fda0f5907178632a14d70a94257023e33d42Carl Shapiro scavengeArrayObject((ArrayObject *)obj); 1395d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else if (IS_CLASS_FLAG_SET(clazz, CLASS_ISREFERENCE)) { 1396952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro scavengeReferenceObject(obj); 1397d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1398952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro scavengeDataObject(obj); 1399d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1400d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1401d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1402d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1403d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * External root scavenging routines. 1404d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1405d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1406d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void pinHashTableEntries(HashTable *table) 1407d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 14088bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN(">>> pinHashTableEntries(table=%p)", table); 1409d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (table == NULL) { 1410d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return; 1411d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1412d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHashTableLock(table); 1413f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < table->tableSize; ++i) { 1414f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HashEntry *entry = &table->pEntries[i]; 1415f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro void *obj = entry->data; 1416d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (obj == NULL || obj == HASH_TOMBSTONE) { 1417d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro continue; 1418d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1419d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinObject(entry->data); 1420d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1421d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHashTableUnlock(table); 14228bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN("<<< pinHashTableEntries(table=%p)", table); 1423d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1424d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 14251e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void pinPrimitiveClasses() 1426d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1427f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t length = ARRAYSIZE(gDvm.primitiveClass); 1428f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < length; i++) { 1429d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (gDvm.primitiveClass[i] != NULL) { 1430d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinObject((Object *)gDvm.primitiveClass[i]); 1431d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1432d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1433d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1434d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1435d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1436d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Scavenge interned strings. Permanent interned strings will have 1437d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * been pinned and are therefore ignored. Non-permanent strings that 1438d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * have been forwarded are snapped. All other entries are removed. 1439d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 14401e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void scavengeInternedStrings() 1441d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1442f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HashTable *table = gDvm.internedStrings; 1443d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (table == NULL) { 1444d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return; 1445d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1446d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHashTableLock(table); 1447f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < table->tableSize; ++i) { 1448f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HashEntry *entry = &table->pEntries[i]; 1449f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro Object *obj = (Object *)entry->data; 1450d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (obj == NULL || obj == HASH_TOMBSTONE) { 1451d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro continue; 1452d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else if (!isPermanentString((StringObject *)obj)) { 14538bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("entry->data=%p", entry->data); 14548bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV(">>> string obj=%p", entry->data); 1455d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* TODO(cshapiro): detach white string objects */ 1456d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **)(void *)&entry->data); 14578bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("<<< string obj=%p", entry->data); 1458d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1459d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1460d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHashTableUnlock(table); 1461d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1462d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 14631e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void pinInternedStrings() 1464d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1465f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HashTable *table = gDvm.internedStrings; 1466d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (table == NULL) { 1467d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return; 1468d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1469d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHashTableLock(table); 1470f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < table->tableSize; ++i) { 1471f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HashEntry *entry = &table->pEntries[i]; 1472f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro Object *obj = (Object *)entry->data; 1473d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (obj == NULL || obj == HASH_TOMBSTONE) { 1474d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro continue; 1475d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else if (isPermanentString((StringObject *)obj)) { 1476d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro obj = (Object *)getPermanentString((StringObject*)obj); 14778bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PROM(">>> pin string obj=%p", obj); 1478d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinObject(obj); 14798bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PROM("<<< pin string obj=%p", obj); 1480d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1481d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1482d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHashTableUnlock(table); 1483d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1484d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1485d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1486d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * At present, reference tables contain references that must not be 1487d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * moved by the collector. Instead of scavenging each reference in 1488d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the table we pin each referenced object. 1489d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1490583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapirostatic void pinReferenceTable(const ReferenceTable *table) 1491d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1492d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(table != NULL); 1493d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(table->table != NULL); 1494d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(table->nextEntry != NULL); 1495f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (Object **entry = table->table; entry < table->nextEntry; ++entry) { 1496d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(entry != NULL); 1497d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(!isForward(*entry)); 1498d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinObject(*entry); 1499d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1500d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1501d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1502646ba0996da817deddb509b2130a6ad432096691Carl Shapirostatic void scavengeLargeHeapRefTable(LargeHeapRefTable *table) 1503d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 15047800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro for (; table != NULL; table = table->next) { 15057800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro Object **ref = table->refs.table; 15067800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro for (; ref < table->refs.nextEntry; ++ref) { 1507646ba0996da817deddb509b2130a6ad432096691Carl Shapiro scavengeReference(ref); 15087800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro } 15097800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro } 15107800c097fe06c046a1f6bed8650dd546d7b7a886Carl Shapiro} 1511d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1512d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* This code was copied from Thread.c */ 1513d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void scavengeThreadStack(Thread *thread) 1514d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1515d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro const u4 *framePtr; 1516d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#if WITH_EXTRA_GC_CHECKS > 1 1517d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro bool first = true; 1518d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 1519d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 152030bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee framePtr = (const u4 *)thread->interpSave.curFrame; 1521d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (framePtr != NULL) { 1522d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro const StackSaveArea *saveArea; 1523d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro const Method *method; 1524d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1525d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro saveArea = SAVEAREA_FROM_FP(framePtr); 1526d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro method = saveArea->method; 1527583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro if (method != NULL && !dvmIsNativeMethod(method)) { 1528d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#ifdef COUNT_PRECISE_METHODS 1529d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* the GC is running, so no lock required */ 1530d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (dvmPointerSetAddEntry(gDvm.preciseMethods, method)) 153160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_SCAV("PGC: added %s.%s %p", 15328bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro method->clazz->descriptor, method->name, method); 1533d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 1534d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#if WITH_EXTRA_GC_CHECKS > 1 1535d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1536d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * May also want to enable the memset() in the "invokeMethod" 1537d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * goto target in the portable interpreter. That sets the stack 1538d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * to a pattern that makes referring to uninitialized data 1539d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * very obvious. 1540d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1541d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1542d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (first) { 1543d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1544d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * First frame, isn't native, check the "alternate" saved PC 1545d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * as a sanity check. 1546d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 1547d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * It seems like we could check the second frame if the first 1548d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * is native, since the PCs should be the same. It turns out 1549d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * this doesn't always work. The problem is that we could 1550d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * have calls in the sequence: 1551d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * interp method #2 1552d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * native method 1553d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * interp method #1 1554d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 1555d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * and then GC while in the native method after returning 1556d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * from interp method #2. The currentPc on the stack is 1557d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * for interp method #1, but thread->currentPc2 is still 1558d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * set for the last thing interp method #2 did. 1559d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 1560d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * This can also happen in normal execution: 1561d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - sget-object on not-yet-loaded class 1562d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - class init updates currentPc2 1563d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * - static field init is handled by parsing annotations; 1564d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * static String init requires creation of a String object, 1565d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * which can cause a GC 1566d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 1567d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Essentially, any pattern that involves executing 1568d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * interpreted code and then causes an allocation without 1569d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * executing instructions in the original method will hit 1570d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * this. These are rare enough that the test still has 1571d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * some value. 1572d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1573d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (saveArea->xtra.currentPc != thread->currentPc2) { 1574e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("PGC: savedPC(%p) != current PC(%p), %s.%s ins=%p", 1575d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro saveArea->xtra.currentPc, thread->currentPc2, 1576d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro method->clazz->descriptor, method->name, method->insns); 1577d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (saveArea->xtra.currentPc != NULL) 1578c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE(" pc inst = 0x%04x", *saveArea->xtra.currentPc); 1579d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (thread->currentPc2 != NULL) 1580c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE(" pc2 inst = 0x%04x", *thread->currentPc2); 1581d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmDumpThread(thread, false); 1582d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1583d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1584d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1585d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * It's unusual, but not impossible, for a non-first frame 1586d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * to be at something other than a method invocation. For 1587d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * example, if we do a new-instance on a nonexistent class, 1588d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * we'll have a lot of class loader activity on the stack 1589d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * above the frame with the "new" operation. Could also 1590d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * happen while we initialize a Throwable when an instruction 1591d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * fails. 1592d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 1593d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * So there's not much we can do here to verify the PC, 1594d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * except to verify that it's a GC point. 1595d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1596d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1597d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(saveArea->xtra.currentPc != NULL); 1598d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 1599d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1600d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro const RegisterMap* pMap; 1601d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro const u1* regVector; 1602d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1603d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro Method* nonConstMethod = (Method*) method; // quiet gcc 1604d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pMap = dvmGetExpandedRegisterMap(nonConstMethod); 1605d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 160660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein //LOG_SCAV("PGC: %s.%s", method->clazz->descriptor, method->name); 1607d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1608d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (pMap != NULL) { 1609d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* found map, get registers for this address */ 1610d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro int addr = saveArea->xtra.currentPc - method->insns; 1611d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro regVector = dvmRegisterMapGetLine(pMap, addr); 1612d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1613d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (regVector == NULL) { 161460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_SCAV("PGC: map but no entry for %s.%s addr=0x%04x", 16158bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro method->clazz->descriptor, method->name, addr); 1616d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 161760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_SCAV("PGC: found map for %s.%s 0x%04x (t=%d)", 16188bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro method->clazz->descriptor, method->name, addr, 16198bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro thread->threadId); 1620d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1621d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1622d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1623d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1624d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * No map found. If precise GC is disabled this is 1625d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * expected -- we don't create pointers to the map data even 1626d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * if it's present -- but if it's enabled it means we're 1627d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * unexpectedly falling back on a conservative scan, so it's 1628d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * worth yelling a little. 1629d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1630d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (gDvm.preciseGc) { 163160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_SCAV("PGC: no map for %s.%s", method->clazz->descriptor, method->name); 1632d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1633d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro regVector = NULL; 1634d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1635d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (regVector == NULL) { 163688b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro /* 163788b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro * There are no roots to scavenge. Skip over the entire frame. 163888b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro */ 163988b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro framePtr += method->registersSize; 1640d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1641d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1642d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Precise scan. v0 is at the lowest address on the 1643d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * interpreted stack, and is the first bit in the register 1644d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * vector, so we can walk through the register map and 1645d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * memory in the same direction. 1646d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * 1647d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * A '1' bit indicates a live reference. 1648d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1649d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u2 bits = 1 << 1; 1650f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = method->registersSize - 1; i >= 0; i--) { 1651d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u4 rval = *framePtr; 1652d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1653d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro bits >>= 1; 1654d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (bits == 1) { 1655d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* set bit 9 so we can tell when we're empty */ 1656d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro bits = *regVector++ | 0x0100; 1657d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1658d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1659d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (rval != 0 && (bits & 0x01) != 0) { 1660d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1661d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Non-null, register marked as live reference. This 1662d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * should always be a valid object. 1663d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1664d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#if WITH_EXTRA_GC_CHECKS > 0 1665d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if ((rval & 0x3) != 0 || !dvmIsValidObject((Object*) rval)) { 1666d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* this is very bad */ 1667c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("PGC: invalid ref in reg %d: 0x%08x", 1668d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro method->registersSize-1 - i, rval); 1669d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else 1670d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 1671d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro { 1672d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 16738bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("stack reference %u@%p", *framePtr, framePtr); 1674d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* dvmMarkObjectNonNull((Object *)rval); */ 1675d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference((Object **) framePtr); 1676d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1677d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1678d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 1679d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Null or non-reference, do nothing at all. 1680d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1681d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#if WITH_EXTRA_GC_CHECKS > 1 1682d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (dvmIsValidObject((Object*) rval)) { 1683d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* this is normal, but we feel chatty */ 1684062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("PGC: ignoring valid ref in reg %d: 0x%08x", 1685d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro method->registersSize-1 - i, rval); 1686d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1687d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 1688d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1689d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++framePtr; 1690d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1691d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmReleaseRegisterMapLine(pMap, regVector); 1692d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1693d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1694952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* else this is a break frame and there is nothing to gray, or 1695d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * this is a native method and the registers are just the "ins", 1696d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * copied from various registers in the caller's set. 1697d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1698d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1699d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#if WITH_EXTRA_GC_CHECKS > 1 1700d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro first = false; 1701d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro#endif 1702d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1703d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Don't fall into an infinite loop if things get corrupted. 1704d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1705d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr || 1706d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro saveArea->prevFrame == NULL); 1707d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro framePtr = saveArea->prevFrame; 1708d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1709d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1710d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1711d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void scavengeThread(Thread *thread) 1712d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 17138bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("scavengeThread(thread=%p)", thread); 1714d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 17158bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("Scavenging threadObj=%p", thread->threadObj); 1716d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&thread->threadObj); 1717d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 17188bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("Scavenging exception=%p", thread->exception); 1719d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&thread->exception); 1720d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1721d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeThreadStack(thread); 1722d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1723d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 17241e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void scavengeThreadList() 1725d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1726d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro Thread *thread; 1727d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1728d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmLockThreadList(dvmThreadSelf()); 1729d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro thread = gDvm.threadList; 1730d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (thread) { 1731d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeThread(thread); 1732d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro thread = thread->next; 1733d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1734d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmUnlockThreadList(); 1735d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1736d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 173788b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapirostatic void pinThreadStack(const Thread *thread) 1738583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro{ 1739583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro const u4 *framePtr; 1740583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro const StackSaveArea *saveArea; 174188b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro Method *method; 1742583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro const char *shorty; 1743583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro Object *obj; 1744583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro 1745583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro saveArea = NULL; 174630bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee framePtr = (const u4 *)thread->interpSave.curFrame; 1747583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro for (; framePtr != NULL; framePtr = saveArea->prevFrame) { 1748583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro saveArea = SAVEAREA_FROM_FP(framePtr); 174988b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro method = (Method *)saveArea->method; 1750583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro if (method != NULL && dvmIsNativeMethod(method)) { 1751583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro /* 175288b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro * This is native method, pin its arguments. 175388b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro * 1754952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * For purposes of graying references, we don't need to do 1755583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * anything here, because all of the native "ins" were copied 1756583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * from registers in the caller's stack frame and won't be 1757583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * changed (an interpreted method can freely use registers 1758583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * with parameters like any other register, but natives don't 1759583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * work that way). 1760583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * 1761583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * However, we need to ensure that references visible to 1762583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * native methods don't move around. We can do a precise scan 1763583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * of the arguments by examining the method signature. 1764583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro */ 176560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_PIN("+++ native scan %s.%s", 17668bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro method->clazz->descriptor, method->name); 1767583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro assert(method->registersSize == method->insSize); 1768583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro if (!dvmIsStaticMethod(method)) { 1769583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro /* grab the "this" pointer */ 1770583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro obj = (Object *)*framePtr++; 1771583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro if (obj == NULL) { 1772583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro /* 1773583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * This can happen for the "fake" entry frame inserted 1774583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * for threads created outside the VM. There's no actual 1775583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * call so there's no object. If we changed the fake 1776583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * entry method to be declared "static" then this 1777583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * situation should never occur. 1778583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro */ 1779583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } else { 1780583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro assert(dvmIsValidObject(obj)); 1781583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro pinObject(obj); 1782583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1783583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1784583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro shorty = method->shorty+1; // skip return value 1785f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = method->registersSize - 1; i >= 0; i--, framePtr++) { 1786583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro switch (*shorty++) { 1787583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro case 'L': 1788583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro obj = (Object *)*framePtr; 1789583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro if (obj != NULL) { 1790583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro assert(dvmIsValidObject(obj)); 1791583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro pinObject(obj); 1792583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1793583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro break; 1794583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro case 'D': 1795583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro case 'J': 1796583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro framePtr++; 1797583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro break; 1798583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro default: 1799583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro /* 32-bit non-reference value */ 1800583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro obj = (Object *)*framePtr; // debug, remove 1801583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro if (dvmIsValidObject(obj)) { // debug, remove 1802583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro /* if we see a lot of these, our scan might be off */ 180360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_PIN("+++ did NOT pin obj %p", obj); 1804583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1805583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro break; 1806583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1807583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 180888b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro } else if (method != NULL && !dvmIsNativeMethod(method)) { 180988b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro const RegisterMap* pMap = dvmGetExpandedRegisterMap(method); 181088b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro const u1* regVector = NULL; 181188b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro 18124308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("conservative : %s.%s", method->clazz->descriptor, method->name); 181388b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro 181488b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro if (pMap != NULL) { 181588b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro int addr = saveArea->xtra.currentPc - method->insns; 181688b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro regVector = dvmRegisterMapGetLine(pMap, addr); 181788b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro } 181888b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro if (regVector == NULL) { 181988b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro /* 182088b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro * No register info for this frame, conservatively pin. 182188b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro */ 1822f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (int i = 0; i < method->registersSize; ++i) { 182388b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro u4 regValue = framePtr[i]; 182488b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro if (regValue != 0 && (regValue & 0x3) == 0 && dvmIsValidObject((Object *)regValue)) { 182588b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro pinObject((Object *)regValue); 182688b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro } 182788b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro } 182888b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro } 1829583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1830583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro /* 1831583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro * Don't fall into an infinite loop if things get corrupted. 1832583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro */ 1833583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr || 1834583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro saveArea->prevFrame == NULL); 1835583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro } 1836583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro} 1837583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro 1838583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapirostatic void pinThread(const Thread *thread) 1839d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1840d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(thread != NULL); 18418bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN("pinThread(thread=%p)", thread); 1842d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 18438bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN("Pin native method arguments"); 184488b0035c26d6281fd6f07e35b52433c5b410ed26Carl Shapiro pinThreadStack(thread); 1845583d64c0b51ea2036bf235281adb85cc0d67ae92Carl Shapiro 18468bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN("Pin internalLocalRefTable"); 1847d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinReferenceTable(&thread->internalLocalRefTable); 1848d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 18498bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN("Pin jniLocalRefTable"); 1850d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinReferenceTable(&thread->jniLocalRefTable); 1851d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1852d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Can the check be pushed into the promote routine? */ 1853d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (thread->jniMonitorRefTable.table) { 18548bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_PIN("Pin jniMonitorRefTable"); 1855d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinReferenceTable(&thread->jniMonitorRefTable); 1856d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1857d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1858d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 18591e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void pinThreadList() 1860d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1861d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro Thread *thread; 1862d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1863d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmLockThreadList(dvmThreadSelf()); 1864d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro thread = gDvm.threadList; 1865d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (thread) { 1866d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinThread(thread); 1867d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro thread = thread->next; 1868d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1869d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmUnlockThreadList(); 1870d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1871d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1872d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1873d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Heap block scavenging. 1874d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1875d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1876d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 1877d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Scavenge objects in the current block. Scavenging terminates when 1878d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * the pointer reaches the highest address in the block or when a run 1879d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * of zero words that continues to the highest address is reached. 1880d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 1881d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void scavengeBlock(HeapSource *heapSource, size_t block) 1882d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1883d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *cursor; 1884d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *end; 1885d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t size; 1886d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 18878bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeBlock(heapSource=%p,block=%zu)", heapSource, block); 1888d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1889d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 1890d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(block < heapSource->totalBlocks); 1891d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->blockSpace[block] == BLOCK_TO_SPACE); 1892d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1893d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro cursor = blockToAddress(heapSource, block); 1894d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro end = cursor + BLOCK_SIZE; 18958bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("scavengeBlock start=%p, end=%p", cursor, end); 1896d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1897d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Parse and scavenge the current block. */ 1898d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = 0; 1899d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (cursor < end) { 1900d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u4 word = *(u4 *)cursor; 1901d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (word != 0) { 19022396fda0f5907178632a14d70a94257023e33d42Carl Shapiro scavengeObject((Object *)cursor); 19032396fda0f5907178632a14d70a94257023e33d42Carl Shapiro size = objectSize((Object *)cursor); 1904d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = alignUp(size, ALLOC_ALIGNMENT); 1905d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro cursor += size; 1906d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1907d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Check for padding. */ 1908d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (*(u4 *)cursor == 0) { 1909d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro cursor += 4; 1910d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (cursor == end) break; 1911d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1912d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Punt if something went wrong. */ 1913d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(cursor == end); 1914d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1915d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1916d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1917d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 19182396fda0f5907178632a14d70a94257023e33d42Carl Shapirostatic size_t objectSize(const Object *obj) 1919d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1920d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t size; 1921d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 19222396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(obj != NULL); 19232396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(obj->clazz != NULL); 1924c49db8554956f8d43eb487709bc1dccfe0496ad2Barry Hayes if (obj->clazz == gDvm.classJavaLangClass) { 1925d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = dvmClassObjectSize((ClassObject *)obj); 1926d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) { 1927d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = dvmArrayObjectSize((ArrayObject *)obj); 1928d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 19292396fda0f5907178632a14d70a94257023e33d42Carl Shapiro assert(obj->clazz->objectSize != 0); 1930d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = obj->clazz->objectSize; 1931d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 19322396fda0f5907178632a14d70a94257023e33d42Carl Shapiro if (LW_HASH_STATE(obj->lock) == LW_HASH_STATE_HASHED_AND_MOVED) { 19332396fda0f5907178632a14d70a94257023e33d42Carl Shapiro size += sizeof(u4); 19342396fda0f5907178632a14d70a94257023e33d42Carl Shapiro } 1935d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return size; 1936d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1937d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1938d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void verifyBlock(HeapSource *heapSource, size_t block) 1939d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1940d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *cursor; 1941d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u1 *end; 1942d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t size; 1943d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 19448bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_VER("verifyBlock(heapSource=%p,block=%zu)", heapSource, block); 1945d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1946d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource != NULL); 1947d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(block < heapSource->totalBlocks); 1948d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(heapSource->blockSpace[block] == BLOCK_TO_SPACE); 1949d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1950d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro cursor = blockToAddress(heapSource, block); 1951d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro end = cursor + BLOCK_SIZE; 19528bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_VER("verifyBlock start=%p, end=%p", cursor, end); 1953d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1954d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Parse and scavenge the current block. */ 1955d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = 0; 1956d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (cursor < end) { 1957d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro u4 word = *(u4 *)cursor; 1958d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (word != 0) { 1959d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmVerifyObject((Object *)cursor); 1960d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = objectSize((Object *)cursor); 1961d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size = alignUp(size, ALLOC_ALIGNMENT); 1962d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro cursor += size; 1963d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } else { 1964d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Check for padding. */ 1965d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (*(unsigned long *)cursor == 0) { 1966d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro cursor += 4; 1967d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (cursor == end) break; 1968d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1969d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Punt if something went wrong. */ 1970d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(cursor == end); 1971d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1972d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1973d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1974d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1975d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirostatic void describeBlockQueue(const HeapSource *heapSource) 1976d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 1977d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t block, count; 1978d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro char space; 1979d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 1980d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = heapSource->queueHead; 1981d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro count = 0; 19828bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV(">>> describeBlockQueue(heapSource=%p)", heapSource); 1983d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Count the number of blocks enqueued. */ 1984d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (block != QUEUE_TAIL) { 1985d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = heapSource->blockQueue[block]; 1986d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro ++count; 1987d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 19888bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("blockQueue %zu elements, enqueued %zu", 1989d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro count, heapSource->queueSize); 1990d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = heapSource->queueHead; 1991d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (block != QUEUE_TAIL) { 1992d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro space = heapSource->blockSpace[block]; 19938bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("block=%zu@%p,space=%zu", block, blockToAddress(heapSource,block), space); 1994d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = heapSource->blockQueue[block]; 1995d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 1996d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 19978bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("<<< describeBlockQueue(heapSource=%p)", heapSource); 1998d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 1999d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2000d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 2001d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Blackens promoted objects. 2002d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 20031e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void scavengeBlockQueue() 2004d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2005d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro HeapSource *heapSource; 2006d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t block; 2007d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 20088bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV(">>> scavengeBlockQueue()"); 2009d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource = gDvm.gcHeap->heapSource; 2010d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro describeBlockQueue(heapSource); 2011d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro while (heapSource->queueHead != QUEUE_TAIL) { 2012d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro block = heapSource->queueHead; 201360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_SCAV("Dequeueing block %zu", block); 2014d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeBlock(heapSource, block); 2015d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro heapSource->queueHead = heapSource->blockQueue[block]; 201660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOG_SCAV("New queue head is %zu", heapSource->queueHead); 2017d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 20188bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("<<< scavengeBlockQueue()"); 2019d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2020d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2021d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 2022d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Scan the block list and verify all blocks that are marked as being 2023d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * in new space. This should be parametrized so we can invoke this 2024d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * routine outside of the context of a collection. 2025d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 20261e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirostatic void verifyNewSpace() 2027d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2028f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HeapSource *heapSource = gDvm.gcHeap->heapSource; 2029f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro size_t c0 = 0, c1 = 0, c2 = 0, c7 = 0; 2030f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < heapSource->totalBlocks; ++i) { 2031d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro switch (heapSource->blockSpace[i]) { 2032d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case BLOCK_FREE: ++c0; break; 2033d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case BLOCK_TO_SPACE: ++c1; break; 2034d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case BLOCK_FROM_SPACE: ++c2; break; 2035d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro case BLOCK_CONTINUED: ++c7; break; 2036d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro default: assert(!"reached"); 2037d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 2038d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 20398bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_VER("Block Demographics: " 20408bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro "Free=%zu,ToSpace=%zu,FromSpace=%zu,Continued=%zu", 20418bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro c0, c1, c2, c7); 2042f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro for (size_t i = 0; i < heapSource->totalBlocks; ++i) { 2043d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro if (heapSource->blockSpace[i] != BLOCK_TO_SPACE) { 2044d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro continue; 2045d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 2046d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro verifyBlock(heapSource, i); 2047d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 2048d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2049d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 20501e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid describeHeap() 2051d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2052f9fa8c14c7ef87b4318d606bfc5132df7b77b17cCarl Shapiro HeapSource *heapSource = gDvm.gcHeap->heapSource; 2053d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro describeBlocks(heapSource); 2054d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2055d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2056d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 2057d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The collection interface. Collection has a few distinct phases. 2058d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * The first is flipping AKA condemning AKA whitening the heap. The 2059d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * second is to promote all objects which are pointed to by pinned or 2060d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * ambiguous references. The third phase is tracing from the stacks, 2061d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * registers and various globals. Lastly, a verification of the heap 2062d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * is performed. The last phase should be optional. 2063d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 20641e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmScavengeRoots() /* Needs a new name badly */ 2065d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2066d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro GcHeap *gcHeap; 2067d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2068d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro { 2069d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t alloc, unused, total; 2070d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2071d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro room(&alloc, &unused, &total); 20728bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("BEFORE GC: %zu alloc, %zu free, %zu total.", 20738bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro alloc, unused, total); 2074d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 2075d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2076d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro gcHeap = gDvm.gcHeap; 2077d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmHeapSourceFlip(); 2078d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2079d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 2080d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Promote blocks with stationary objects. 2081d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 2082d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinThreadList(); 2083d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinReferenceTable(&gDvm.jniGlobalRefTable); 2084d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinReferenceTable(&gDvm.jniPinRefTable); 2085d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinHashTableEntries(gDvm.loadedClasses); 2086427bf463f1afa080908bbed7319f585cce9e6db2Carl Shapiro pinHashTableEntries(gDvm.dbgRegistry); 2087d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinPrimitiveClasses(); 2088d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro pinInternedStrings(); 2089d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2090d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro // describeBlocks(gcHeap->heapSource); 2091d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2092d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 2093d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Create first, open new-space page right here. 2094d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 2095d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2096d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* Reset allocation to an unallocated block. */ 2097d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro gDvm.gcHeap->heapSource->allocPtr = allocateBlocks(gDvm.gcHeap->heapSource, 1); 2098d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro gDvm.gcHeap->heapSource->allocLimit = gDvm.gcHeap->heapSource->allocPtr + BLOCK_SIZE; 2099d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 2100d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Hack: promote the empty block allocated above. If the 2101d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * promotions that occurred above did not actually gray any 2102d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * objects, the block queue may be empty. We must force a 2103d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * promotion to be safe. 2104d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 2105d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro promoteBlockByAddr(gDvm.gcHeap->heapSource, gDvm.gcHeap->heapSource->allocPtr); 2106d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2107d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 2108d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Scavenge blocks and relocate movable objects. 2109d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 2110d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21118bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("Scavenging gDvm.threadList"); 2112d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeThreadList(); 2113d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21148bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("Scavenging gDvm.gcHeap->referenceOperations"); 2115646ba0996da817deddb509b2130a6ad432096691Carl Shapiro scavengeLargeHeapRefTable(gcHeap->referenceOperations); 2116d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21178bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("Scavenging gDvm.gcHeap->pendingFinalizationRefs"); 2118646ba0996da817deddb509b2130a6ad432096691Carl Shapiro scavengeLargeHeapRefTable(gcHeap->pendingFinalizationRefs); 2119d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21208bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("Scavenging random global stuff"); 2121d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&gDvm.outOfMemoryObj); 2122d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&gDvm.internalErrorObj); 2123d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeReference(&gDvm.noClassDefFoundErrorObj); 2124d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21258bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro // LOG_SCAV("Scavenging gDvm.internedString"); 2126d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeInternedStrings(); 2127d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21288bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("Root scavenge has completed."); 2129d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2130d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro scavengeBlockQueue(); 2131d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 213206d3da57d53d63bd49f14bffbd54972819c9b79cDan Bornstein // LOG_SCAV("Re-snap global class pointers."); 213306d3da57d53d63bd49f14bffbd54972819c9b79cDan Bornstein // scavengeGlobals(); 2134d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 21358bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("New space scavenge has completed."); 2136d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2137d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* 2138952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro * Process reference objects in strength order. 2139952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro */ 2140952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 21418bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_REF("Processing soft references..."); 2142952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro preserveSoftReferences(&gDvm.gcHeap->softReferences); 2143952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro clearWhiteReferences(&gDvm.gcHeap->softReferences); 2144952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 21458bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_REF("Processing weak references..."); 2146952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro clearWhiteReferences(&gDvm.gcHeap->weakReferences); 2147952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 21488bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_REF("Finding finalizations..."); 2149952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro processFinalizableReferences(); 2150952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 21518bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_REF("Processing f-reachable soft references..."); 2152952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro clearWhiteReferences(&gDvm.gcHeap->softReferences); 2153952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 21548bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_REF("Processing f-reachable weak references..."); 2155952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro clearWhiteReferences(&gDvm.gcHeap->weakReferences); 2156952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 21578bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_REF("Processing phantom references..."); 2158952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro clearWhiteReferences(&gDvm.gcHeap->phantomReferences); 2159952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro 2160952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* 2161d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Verify the stack and heap. 2162d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 2163f571825e42a0daa957b99f8cf7598f517b504fa3Carl Shapiro dvmVerifyRoots(); 2164d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro verifyNewSpace(); 2165d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2166d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro //describeBlocks(gcHeap->heapSource); 2167d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2168d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro clearFromSpace(gcHeap->heapSource); 2169d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2170d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro { 2171d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro size_t alloc, rem, total; 2172d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2173d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro room(&alloc, &rem, &total); 21748bb533e726c477d4982b30d01d19c0cda5fa7fb6Carl Shapiro LOG_SCAV("AFTER GC: %zu alloc, %zu free, %zu total.", alloc, rem, total); 2175d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro } 2176d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2177d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2178d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro/* 2179d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro * Interface compatibility routines. 2180d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro */ 2181d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2182d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmClearWhiteRefs(Object **list) 2183d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2184952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* do nothing */ 2185d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(*list == NULL); 2186d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2187d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2188d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmHandleSoftRefs(Object **list) 2189d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2190952e84a2716643a7c70dc8370b49db12ef9cce4eCarl Shapiro /* do nothing */ 2191d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro assert(*list == NULL); 2192d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2193d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2194d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirobool dvmHeapBeginMarkStep(GcMode mode) 2195d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2196d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* do nothing */ 2197d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro return true; 2198d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2199d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 22001e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapFinishMarkStep() 2201d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2202d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* do nothing */ 2203d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2204d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 22051e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapMarkRootSet() 2206d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2207d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* do nothing */ 2208d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2209d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 22101e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapScanMarkedObjects() 2211d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2212d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro dvmScavengeRoots(); 2213d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2214d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 22151e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapScheduleFinalizations() 2216d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2217d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* do nothing */ 2218d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2219d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 2220d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapirovoid dvmHeapSweepUnmarkedObjects(GcMode mode, int *numFreed, size_t *sizeFreed) 2221d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro{ 2222703a2f3f1acc3ecc23d37970af2638463587a40fCarl Shapiro *numFreed = 0; 2223703a2f3f1acc3ecc23d37970af2638463587a40fCarl Shapiro *sizeFreed = 0; 2224d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro /* do nothing */ 2225d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro} 2226d28668cf8740d1f913b4e9140a8c685013c1ad18Carl Shapiro 22271e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmMarkDirtyObjects() 2228791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro{ 2229791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro assert(!"implemented"); 2230791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro} 2231791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro 22321e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmHeapSourceThreadShutdown() 2233791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro{ 2234791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro /* do nothing */ 2235791802c9408e6506d8382bee74c250d169c88d2aCarl Shapiro} 2236