made a copy
[strongtalk-kjk.git] / vm / code / nmethodScopes.hpp
blobf68a70ffc001a79268ee54bee2ed04dacc4e364b
1 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.22 $ */
2 /* Copyright (c) 2006, Sun Microsystems, Inc.
3 All rights reserved.
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6 following conditions are met:
8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
10 disclaimer in the documentation and/or other materials provided with the distribution.
11 * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived
12 from this software without specific prior written permission.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
15 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
16 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
18 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
19 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
24 #ifdef DELTA_COMPILER
26 // UnpackClosure is used for iteration over a string of nameDescs with different pc values.
28 class UnpackClosure: public StackObj {
29 public:
30 virtual void nameDescAt(NameDesc* nameDesc, char* pc) = 0;
34 // nmethodScopes represent the compressed nmethod source-level debugging information generated by the scopeDescRecorder.
35 // Whenever the debugging information is needed, it is uncompressed into ScopeDescs.
36 // Compression works mainly by putting all "large" data (e.g., oops) into an array and
37 // using small (8-bit) indices to refer to this array from the actual scope data structures.
39 # define FOR_EACH_SCOPE(SCOPES, VAR)\
40 for(ScopeDesc* VAR = SCOPES->getNext(NULL); \
41 VAR != NULL; VAR = SCOPES->getNext(VAR) )
43 class nmethodScopes : public ValueObj {
44 private:
45 int _nmethod_offset;
46 uint16 _length;
47 // Implements the compact version of nmethod scopes
48 // with byte codes, shared oop array, and value array.
49 uint16 _oops_offset; // word offset to the oops array
50 uint16 _value_offset; // word offset to the value array
51 uint16 _pcs_offset; // word offset to PcDesc array
52 int _dependants_end; // size of dependants
54 private:
55 static uint16 pack_word_aligned(int value) {
56 assert(value % BytesPerWord == 0, "value should be word aligned");
57 assert(value >> BytesPerWord <= nthMask(BitsPerByte*sizeof(uint16)),
58 "value exceeds limit");
59 return value >> LogBytesPerWord;
62 static int unpack_word_aligned(uint16 v) { return v << LogBytesPerWord; }
64 int oops_offset() const { return unpack_word_aligned(_oops_offset); }
65 int value_offset() const { return unpack_word_aligned(_value_offset); }
66 int pcs_offset() const { return unpack_word_aligned(_pcs_offset); }
68 // Return the address after the struct header
69 u_char* start() const { return (u_char*) (this+1); }
71 public: // for debugging
72 oop* oops() const { return (oop*) (start() + oops_offset()); }
73 int oops_size() const { return (value_offset() - oops_offset())/sizeof(oop); }
74 oop oop_at(int index) const {
75 assert( index < oops_size(), "oops index out of range");
76 return oops()[index];
78 private:
79 int* values() const { return (int*) (start() + value_offset()); }
80 int value_size() const { return (pcs_offset() - value_offset())/sizeof(int); }
81 int value_at(int index) const {
82 assert( index < value_size(), "oops index out of range");
83 return values()[index];
86 inline u_char getIndexAt(int& offset) const;
87 inline oop unpackOopFromIndex(u_char index, int& offset) const;
88 inline int unpackValueFromIndex(u_char index, int& offset) const;
90 private:
91 friend class ScopeDescRecorder;
92 void set_nmethod_offset(int v) { _nmethod_offset = v; }
93 void set_length(int v) { _length = pack_word_aligned(v); }
94 void set_oops_offset(int v) { _oops_offset = pack_word_aligned(v); }
95 void set_value_offset(int v) { _value_offset = pack_word_aligned(v); }
96 void set_pcs_offset(int v) { _pcs_offset = pack_word_aligned(v); }
97 void set_dependants_end(int v) { _dependants_end = v; }
99 public:
100 klassOop dependant_at(int index) const {
101 assert(index >= 0 && index < dependent_length(), "must be within bounds");
102 oop result = oop_at(index);
103 assert(result->is_klass(), "must be klass");
104 return klassOop(result);
106 int dependent_length() const { return _dependants_end; }
108 void* pcs() const { return (void*) (start() + pcs_offset()); }
109 void* pcsEnd() const { return (void*) end(); }
111 int length() const { return unpack_word_aligned(_length); }
113 nmethod* my_nmethod() const { return (nmethod*) (((char*) this) - _nmethod_offset); };
115 // returns the address following this nmethodScopes.
116 ScopeDesc* end() const { return (ScopeDesc*) (start() + length()); }
118 bool includes(ScopeDesc* d) const { return this == d->_scopes; }
120 // Returns the root scope without pc specific information.
121 // The returned scope cannot be used for retrieving name desc information.
122 ScopeDesc *root() const { return at(0, ScopeDesc::invalid_pc); }
124 int size() const { return sizeof(nmethodScopes) + length(); }
126 // Returns a scope located at offset.
127 ScopeDesc* at(int offset, char* pc) const;
129 NonInlinedBlockScopeDesc* noninlined_block_scope_at(int offset) const ;
131 // used in iterator macro FOR_EACH_SCOPE
132 ScopeDesc *getNext(ScopeDesc *s) const {
133 if (!s) return root();
134 int offset = s->next_offset();
136 if (offset + (sizeof(int) - (offset%sizeof(int))) % sizeof(int)
137 >= (_oops_offset)*sizeof(oop)) return NULL;
138 return at(offset, ScopeDesc::invalid_pc);
141 u_char get_next_char(int& offset) const { return *(start() + offset++); }
143 int16 get_next_half(int& offset) const;
145 u_char peek_next_char(int offset) const { return *(start() + offset); }
147 oop unpackOopAt(int& offset) const;
148 int unpackValueAt(int& offset) const;
150 void iterate(int& offset, UnpackClosure* closure) const; // iterates over a string of NameDescs (iterator is not called at termination)
151 NameDesc* unpackNameDescAt(int& offset, char* pc) const; // Unpacks a string of name descs and returns one matching the pc
153 private:
154 NameDesc* unpackNameDescAt(int& offset, bool& is_last, char* pc) const; // Unpacks a single name desc at offset
155 public:
157 // Support for garbage collection.
158 void oops_do(void f(oop*));
159 void scavenge_contents();
160 void switch_pointers(oop from, oop to, GrowableArray<nmethod*>* nmethods_to_invalidate);
162 bool is_new() const;
164 void relocate();
166 void verify();
167 void print();
169 // Prints (dep d% oops %d bytes %d pcs %d)
170 void print_partition();
174 #endif