29 #include "oops/oop.inline.hpp"
30 #include "runtime/fieldType.hpp"
31 #include "runtime/handles.inline.hpp"
32
33 StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
34 u2 max_locals, u2 max_stack,
35 char* code_data, int code_len, TRAPS) {
36 _code_length = code_len;
37 _frame_count = reader->get_frame_count();
38 if (_frame_count > 0) {
39 _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
40 StackMapFrame*, _frame_count);
41 StackMapFrame* pre_frame = init_frame;
42 for (int32_t i = 0; i < _frame_count; i++) {
43 StackMapFrame* frame = reader->next(
44 pre_frame, i == 0, max_locals, max_stack,
45 CHECK_VERIFY(pre_frame->verifier()));
46 _frame_array[i] = frame;
47 int offset = frame->offset();
48 if (offset >= code_len || code_data[offset] == 0) {
49 frame->verifier()->verify_error("StackMapTable error: bad offset");
50 return;
51 }
52 pre_frame = frame;
53 }
54 }
55 reader->check_end(CHECK);
56 }
57
58 // This method is only called by method in StackMapTable.
59 int StackMapTable::get_index_from_offset(int32_t offset) const {
60 int i = 0;
61 for (; i < _frame_count; i++) {
62 if (_frame_array[i]->offset() == offset) {
63 return i;
64 }
65 }
66 return i; // frame with offset doesn't exist in the array
67 }
68
69 bool StackMapTable::match_stackmap(
70 StackMapFrame* frame, int32_t target,
71 bool match, bool update, TRAPS) const {
72 int index = get_index_from_offset(target);
73
74 return match_stackmap(
75 frame, target, index, match,
76 update, CHECK_VERIFY_(frame->verifier(), false));
77 }
78
79 // Match and/or update current_frame to the frame in stackmap table with
80 // specified offset and frame index. Return true if the two frames match.
81 //
82 // The values of match and update are: _match__update_
83 //
84 // checking a branch target/exception handler: true false
85 // linear bytecode verification following an
86 // unconditional branch: false true
87 // linear bytecode verification not following an
88 // unconditional branch: true true
89 bool StackMapTable::match_stackmap(
90 StackMapFrame* frame, int32_t target, int32_t frame_index,
91 bool match, bool update, TRAPS) const {
92 if (frame_index < 0 || frame_index >= _frame_count) {
93 frame->verifier()->verify_error(frame->offset(),
94 "Expecting a stackmap frame at branch target %d", target);
95 return false;
96 }
97
98 bool result = true;
99 StackMapFrame *stackmap_frame = _frame_array[frame_index];
100 if (match) {
101 // when checking handler target, match == true && update == false
102 bool is_exception_handler = !update;
103 // Has direct control flow from last instruction, need to match the two
104 // frames.
105 result = frame->is_assignable_to(
106 stackmap_frame, is_exception_handler,
107 CHECK_VERIFY_(frame->verifier(), false));
108 }
109 if (update) {
110 // Use the frame in stackmap table as current frame
111 int lsize = stackmap_frame->locals_size();
112 int ssize = stackmap_frame->stack_size();
113 if (frame->locals_size() > lsize || frame->stack_size() > ssize) {
114 // Make sure unused type array items are all _bogus_type.
115 frame->reset();
116 }
117 frame->set_locals_size(lsize);
118 frame->copy_locals(stackmap_frame);
119 frame->set_stack_size(ssize);
120 frame->copy_stack(stackmap_frame);
121 frame->set_flags(stackmap_frame->flags());
122 }
123 return result;
124 }
125
126 void StackMapTable::check_jump_target(
127 StackMapFrame* frame, int32_t target, TRAPS) const {
128 bool match = match_stackmap(
129 frame, target, true, false, CHECK_VERIFY(frame->verifier()));
130 if (!match || (target < 0 || target >= _code_length)) {
131 frame->verifier()->verify_error(frame->offset(),
132 "Inconsistent stackmap frames at branch target %d", target);
133 return;
134 }
135 // check if uninitialized objects exist on backward branches
136 check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
137 }
138
139 void StackMapTable::check_new_object(
140 const StackMapFrame* frame, int32_t target, TRAPS) const {
141 if (frame->offset() > target && frame->has_new_object()) {
142 frame->verifier()->verify_error(frame->offset(),
143 "Uninitialized object exists on backward branch %d", target);
144 return;
145 }
146 }
147
148 #ifndef PRODUCT
149
150 void StackMapTable::print() const {
151 tty->print_cr("StackMapTable: frame_count = %d", _frame_count);
152 tty->print_cr("table = { ");
153 for (int32_t i = 0; i < _frame_count; i++) {
154 _frame_array[i]->print();
155 }
156 tty->print_cr(" }");
157 }
158
159 #endif
160
161 int32_t StackMapReader::chop(
162 VerificationType* locals, int32_t length, int32_t chops) {
163 if (locals == NULL) return -1;
164 int32_t pos = length - 1;
165 for (int32_t i=0; i<chops; i++) {
166 if (locals[pos].is_category2_2nd()) {
167 pos -= 2;
168 } else {
169 pos --;
170 }
171 if (pos<0 && i<(chops-1)) return -1;
172 }
173 return pos+1;
174 }
175
176 VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) {
177 u1 tag = _stream->get_u1(THREAD);
178 if (tag < (u1)ITEM_UninitializedThis) {
179 return VerificationType::from_tag(tag);
|
29 #include "oops/oop.inline.hpp"
30 #include "runtime/fieldType.hpp"
31 #include "runtime/handles.inline.hpp"
32
33 StackMapTable::StackMapTable(StackMapReader* reader, StackMapFrame* init_frame,
34 u2 max_locals, u2 max_stack,
35 char* code_data, int code_len, TRAPS) {
36 _code_length = code_len;
37 _frame_count = reader->get_frame_count();
38 if (_frame_count > 0) {
39 _frame_array = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD,
40 StackMapFrame*, _frame_count);
41 StackMapFrame* pre_frame = init_frame;
42 for (int32_t i = 0; i < _frame_count; i++) {
43 StackMapFrame* frame = reader->next(
44 pre_frame, i == 0, max_locals, max_stack,
45 CHECK_VERIFY(pre_frame->verifier()));
46 _frame_array[i] = frame;
47 int offset = frame->offset();
48 if (offset >= code_len || code_data[offset] == 0) {
49 frame->verifier()->verify_error(
50 ErrorContext::bad_stackmap(i, frame),
51 "StackMapTable error: bad offset");
52 return;
53 }
54 pre_frame = frame;
55 }
56 }
57 reader->check_end(CHECK);
58 }
59
60 // This method is only called by method in StackMapTable.
61 int StackMapTable::get_index_from_offset(int32_t offset) const {
62 int i = 0;
63 for (; i < _frame_count; i++) {
64 if (_frame_array[i]->offset() == offset) {
65 return i;
66 }
67 }
68 return i; // frame with offset doesn't exist in the array
69 }
70
71 bool StackMapTable::match_stackmap(
72 StackMapFrame* frame, int32_t target,
73 bool match, bool update, ErrorContext* ctx, TRAPS) const {
74 int index = get_index_from_offset(target);
75 return match_stackmap(frame, target, index, match, update, ctx, THREAD);
76 }
77
78 // Match and/or update current_frame to the frame in stackmap table with
79 // specified offset and frame index. Return true if the two frames match.
80 //
81 // The values of match and update are: _match__update_
82 //
83 // checking a branch target/exception handler: true false
84 // linear bytecode verification following an
85 // unconditional branch: false true
86 // linear bytecode verification not following an
87 // unconditional branch: true true
88 bool StackMapTable::match_stackmap(
89 StackMapFrame* frame, int32_t target, int32_t frame_index,
90 bool match, bool update, ErrorContext* ctx, TRAPS) const {
91 if (frame_index < 0 || frame_index >= _frame_count) {
92 *ctx = ErrorContext::missing_stackmap(frame->offset());
93 frame->verifier()->verify_error(
94 *ctx, "Expecting a stackmap frame at branch target %d", target);
95 return false;
96 }
97
98 StackMapFrame *stackmap_frame = _frame_array[frame_index];
99 bool result = true;
100 if (match) {
101 // when checking handler target, match == true && update == false
102 bool is_exception_handler = !update;
103 // Has direct control flow from last instruction, need to match the two
104 // frames.
105 result = frame->is_assignable_to(stackmap_frame, is_exception_handler,
106 ctx, CHECK_VERIFY_(frame->verifier(), result));
107 }
108 if (update) {
109 // Use the frame in stackmap table as current frame
110 int lsize = stackmap_frame->locals_size();
111 int ssize = stackmap_frame->stack_size();
112 if (frame->locals_size() > lsize || frame->stack_size() > ssize) {
113 // Make sure unused type array items are all _bogus_type.
114 frame->reset();
115 }
116 frame->set_locals_size(lsize);
117 frame->copy_locals(stackmap_frame);
118 frame->set_stack_size(ssize);
119 frame->copy_stack(stackmap_frame);
120 frame->set_flags(stackmap_frame->flags());
121 }
122 return result;
123 }
124
125 void StackMapTable::check_jump_target(
126 StackMapFrame* frame, int32_t target, TRAPS) const {
127 ErrorContext ctx;
128 bool match = match_stackmap(
129 frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
130 if (!match || (target < 0 || target >= _code_length)) {
131 frame->verifier()->verify_error(ctx,
132 "Inconsistent stackmap frames at branch target %d", target);
133 return;
134 }
135 // check if uninitialized objects exist on backward branches
136 check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
137 }
138
139 void StackMapTable::check_new_object(
140 const StackMapFrame* frame, int32_t target, TRAPS) const {
141 if (frame->offset() > target && frame->has_new_object()) {
142 frame->verifier()->verify_error(
143 ErrorContext::bad_code(frame->offset()),
144 "Uninitialized object exists on backward branch %d", target);
145 return;
146 }
147 }
148
149 void StackMapTable::print(outputStream* str) const {
150 str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count);
151 str->indent().print_cr("table = { ");
152 {
153 streamIndentor si(str);
154 for (int32_t i = 0; i < _frame_count; i++) {
155 _frame_array[i]->print(str);
156 }
157 }
158 tty->print_cr(" }");
159 }
160
161 int32_t StackMapReader::chop(
162 VerificationType* locals, int32_t length, int32_t chops) {
163 if (locals == NULL) return -1;
164 int32_t pos = length - 1;
165 for (int32_t i=0; i<chops; i++) {
166 if (locals[pos].is_category2_2nd()) {
167 pos -= 2;
168 } else {
169 pos --;
170 }
171 if (pos<0 && i<(chops-1)) return -1;
172 }
173 return pos+1;
174 }
175
176 VerificationType StackMapReader::parse_verification_type(u1* flags, TRAPS) {
177 u1 tag = _stream->get_u1(THREAD);
178 if (tag < (u1)ITEM_UninitializedThis) {
179 return VerificationType::from_tag(tag);
|