1/*
2    Title:  scanaddrs.h - Scan addresses in objects
3
4    Copyright (c) 2006-8, 2012, 2015, 2018 David C.J. Matthews
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License version 2.1 as published by the Free Software Foundation.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
19*/
20
21#ifndef SCANADDRS_H_INCLUDED
22#define SCANADDRS_H_INCLUDED
23
24#include "globals.h"
25
26// Type of relocations.
27typedef enum {
28    PROCESS_RELOC_DIRECT = 0,           // 32 or 64 bit address of target
29    PROCESS_RELOC_I386RELATIVE         // 32 or 64 bit relative address
30} ScanRelocationKind;
31
32class StackSpace;
33
34class ScanAddress {
35public:
36    virtual ~ScanAddress() {} // Keeps gcc happy
37
38protected:
39    // Scan an address in the memory.  "pt" always points into an object.
40    // It is not called with pt pointing at a C++ automatic variable.
41    // Tagged integers have already been filtered out.
42    // The result is the length word of the object to use if the object
43    // is to be processed recursively or 0 if it should not be.
44    // Default action - call ScanObjectAddress for the base object address of
45    // the address.
46    virtual POLYUNSIGNED ScanAddressAt(PolyWord *pt);
47
48    // As for ScanAddressAt except that the value is a pointer to the first word in a closure object.
49    // In most cases we're just scanning the heap we don't need to do anything and we scan
50    // the code area separately.
51    virtual POLYUNSIGNED ScanCodeAddressAt(PolyObject **pt) { return 0; }
52
53public:
54    // The fundamental overridable for this class.  Takes the object address and returns
55    // the updated address.  If nothing else is overridden everything eventually comes here.
56    virtual PolyObject *ScanObjectAddress(PolyObject *base) = 0;// { return base; }
57
58    typedef enum { STRENGTH_STRONG = 0, STRENGTH_WEAK = 1 } RtsStrength;
59
60    // Scan an address in the run-time system.  This normally just applies ScanObjectAddress
61    // but if this is a weak reference it can set *pt to NULL
62    virtual void ScanRuntimeAddress(PolyObject **pt, RtsStrength weak)
63        { *pt = ScanObjectAddress(*pt); }
64
65    // Scan a word in the run-time system.  This is the preferred call for non-weak
66    // references and deals with the general case of a word.
67    void ScanRuntimeWord(PolyWord *w);
68
69    // Process a constant within the code.
70    // The default action is to call the DEFAULT ScanAddressAt NOT the virtual which means that it calls
71    // ScanObjectAddress for the base address of the object referred to.
72    virtual void ScanConstant(PolyObject *base, byte *addressOfConstant, ScanRelocationKind code);
73
74    // Scan the objects in the region and process their addresses.  Applies ScanAddressesInObject
75    // to each of the objects.  The "region" argument points AT the first length word.
76    // Typically used to scan or update addresses in the mutable area.
77    void ScanAddressesInRegion(PolyWord *region, PolyWord *endOfRegion);
78
79    // General object processor.
80    // If the object is a word object calls ScanAddressesAt for all the addresses.
81    //
82    // If the object is a code object calls ScanAddressesAt for the constant area and
83    // calls (indirectly) ScanConstant, and by default ScanObjectAddress for addresses within
84    // the code
85    //
86    // If the object is a stack calls ScanStackAddress which calls ScanObjectAddress for
87    // addresses within the code.
88    virtual void ScanAddressesInObject(PolyObject *base, POLYUNSIGNED lengthWord);
89
90    void ScanAddressesInObject(PolyObject *base) { ScanAddressesInObject(base, base->LengthWord()); }
91
92    // Extract a constant from the code.
93#ifdef POLYML32IN64
94    static PolyObject *GetConstantValue(byte *addressOfConstant, ScanRelocationKind code, PolyWord *base = globalHeapBase);
95#else
96    static PolyObject *GetConstantValue(byte *addressOfConstant, ScanRelocationKind code, PolyWord *base = 0);
97#endif
98    // Store a constant in the code.
99    static void SetConstantValue(byte *addressOfConstant, PolyObject *p, ScanRelocationKind code);
100};
101
102#endif
103