20 * or visit www.oracle.com if you need additional information or have any |
20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
21 * questions. |
22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 define_array(ciObjectArray, ciObject*); |
|
26 define_stack(ciObjectList, ciObjectArray); |
|
27 |
|
28 // This class implements a fast, conservative analysis of effect of methods |
25 // This class implements a fast, conservative analysis of effect of methods |
29 // on the escape state of their arguments. The analysis is at the bytecode |
26 // on the escape state of their arguments. The analysis is at the bytecode |
30 // level. |
27 // level. |
31 |
28 |
32 class ciMethodBlocks; |
29 class ciMethodBlocks; |
33 class ciBlock; |
30 class ciBlock; |
34 |
31 |
35 class BCEscapeAnalyzer : public ResourceObj { |
32 class BCEscapeAnalyzer : public ResourceObj { |
36 private: |
33 private: |
|
34 Arena* _arena; // ciEnv arena |
|
35 |
37 bool _conservative; // If true, return maximally |
36 bool _conservative; // If true, return maximally |
38 // conservative results. |
37 // conservative results. |
39 ciMethod* _method; |
38 ciMethod* _method; |
40 ciMethodData* _methodData; |
39 ciMethodData* _methodData; |
41 int _arg_size; |
40 int _arg_size; |
42 |
41 VectorSet _arg_local; |
43 intStack _stack; |
42 VectorSet _arg_stack; |
44 |
43 VectorSet _arg_returned; |
45 BitMap _arg_local; |
44 VectorSet _dirty; |
46 BitMap _arg_stack; |
|
47 BitMap _arg_returned; |
|
48 BitMap _dirty; |
|
49 enum{ ARG_OFFSET_MAX = 31}; |
45 enum{ ARG_OFFSET_MAX = 31}; |
50 uint *_arg_modified; |
46 uint *_arg_modified; |
51 |
47 |
52 bool _return_local; |
48 bool _return_local; |
53 bool _return_allocated; |
49 bool _return_allocated; |
54 bool _allocated_escapes; |
50 bool _allocated_escapes; |
55 bool _unknown_modified; |
51 bool _unknown_modified; |
56 |
52 |
57 ciObjectList _dependencies; |
53 GrowableArray<ciObject *> _dependencies; |
58 |
54 |
59 ciMethodBlocks *_methodBlocks; |
55 ciMethodBlocks *_methodBlocks; |
60 |
56 |
61 BCEscapeAnalyzer* _parent; |
57 BCEscapeAnalyzer* _parent; |
62 int _level; |
58 int _level; |
66 class StateInfo; |
62 class StateInfo; |
67 |
63 |
68 private: |
64 private: |
69 // helper functions |
65 // helper functions |
70 bool is_argument(int i) { return i >= 0 && i < _arg_size; } |
66 bool is_argument(int i) { return i >= 0 && i < _arg_size; } |
71 |
|
72 void raw_push(int i) { _stack.push(i); } |
|
73 int raw_pop() { return _stack.is_empty() ? -1 : _stack.pop(); } |
|
74 void apush(int i) { raw_push(i); } |
|
75 void spush() { raw_push(-1); } |
|
76 void lpush() { spush(); spush(); } |
|
77 int apop() { return raw_pop(); } |
|
78 void spop() { assert(_stack.is_empty() || _stack.top() == -1, ""); raw_pop(); } |
|
79 void lpop() { spop(); spop(); } |
|
80 |
|
81 void set_returned(ArgumentMap vars); |
67 void set_returned(ArgumentMap vars); |
82 bool is_argument(ArgumentMap vars); |
68 bool is_argument(ArgumentMap vars); |
83 bool is_arg_stack(ArgumentMap vars); |
69 bool is_arg_stack(ArgumentMap vars); |
84 void clear_bits(ArgumentMap vars, BitMap &bs); |
70 void clear_bits(ArgumentMap vars, VectorSet &bs); |
85 void set_method_escape(ArgumentMap vars); |
71 void set_method_escape(ArgumentMap vars); |
86 void set_global_escape(ArgumentMap vars); |
72 void set_global_escape(ArgumentMap vars); |
87 void set_dirty(ArgumentMap vars); |
73 void set_dirty(ArgumentMap vars); |
88 void set_modified(ArgumentMap vars, int offs, int size); |
74 void set_modified(ArgumentMap vars, int offs, int size); |
89 |
75 |
114 // accessors |
100 // accessors |
115 ciMethod* method() const { return _method; } |
101 ciMethod* method() const { return _method; } |
116 ciMethodData* methodData() const { return _methodData; } |
102 ciMethodData* methodData() const { return _methodData; } |
117 BCEscapeAnalyzer* parent() const { return _parent; } |
103 BCEscapeAnalyzer* parent() const { return _parent; } |
118 int level() const { return _level; } |
104 int level() const { return _level; } |
119 ciObjectList* dependencies() { return &_dependencies; } |
105 GrowableArray<ciObject *>* dependencies() { return &_dependencies; } |
120 bool has_dependencies() const { return !_dependencies.is_empty(); } |
106 bool has_dependencies() const { return !_dependencies.is_empty(); } |
121 |
107 |
122 // retrieval of interprocedural escape information |
108 // retrieval of interprocedural escape information |
123 |
109 |
124 // The given argument does not escape the callee. |
110 // The given argument does not escape the callee. |
125 bool is_arg_local(int i) const { |
111 bool is_arg_local(int i) const { |
126 return !_conservative && _arg_local.at(i); |
112 return !_conservative && _arg_local.test(i); |
127 } |
113 } |
128 |
114 |
129 // The given argument escapes the callee, but does not become globally |
115 // The given argument escapes the callee, but does not become globally |
130 // reachable. |
116 // reachable. |
131 bool is_arg_stack(int i) const { |
117 bool is_arg_stack(int i) const { |
132 return !_conservative && _arg_stack.at(i); |
118 return !_conservative && _arg_stack.test(i); |
133 } |
119 } |
134 |
120 |
135 // The given argument does not escape globally, and may be returned. |
121 // The given argument does not escape globally, and may be returned. |
136 bool is_arg_returned(int i) const { |
122 bool is_arg_returned(int i) const { |
137 return !_conservative && _arg_returned.at(i); } |
123 return !_conservative && _arg_returned.test(i); } |
138 |
124 |
139 // True iff only input arguments are returned. |
125 // True iff only input arguments are returned. |
140 bool is_return_local() const { |
126 bool is_return_local() const { |
141 return !_conservative && _return_local; |
127 return !_conservative && _return_local; |
142 } |
128 } |