68 return i; // frame with offset doesn't exist in the array |
68 return i; // frame with offset doesn't exist in the array |
69 } |
69 } |
70 |
70 |
71 bool StackMapTable::match_stackmap( |
71 bool StackMapTable::match_stackmap( |
72 StackMapFrame* frame, int32_t target, |
72 StackMapFrame* frame, int32_t target, |
73 bool match, bool update, ErrorContext* ctx, TRAPS) const { |
73 bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { |
74 int index = get_index_from_offset(target); |
74 int index = get_index_from_offset(target); |
75 return match_stackmap(frame, target, index, match, update, ctx, THREAD); |
75 return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD); |
76 } |
76 } |
77 |
77 |
78 // Match and/or update current_frame to the frame in stackmap table with |
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. |
79 // specified offset and frame index. Return true if the two frames match. |
|
80 // handler is true if the frame in stackmap_table is for an exception handler. |
80 // |
81 // |
81 // The values of match and update are: _match__update_ |
82 // The values of match and update are: _match__update__handler |
82 // |
83 // |
83 // checking a branch target/exception handler: true false |
84 // checking a branch target: true false false |
|
85 // checking an exception handler: true false true |
84 // linear bytecode verification following an |
86 // linear bytecode verification following an |
85 // unconditional branch: false true |
87 // unconditional branch: false true false |
86 // linear bytecode verification not following an |
88 // linear bytecode verification not following an |
87 // unconditional branch: true true |
89 // unconditional branch: true true false |
88 bool StackMapTable::match_stackmap( |
90 bool StackMapTable::match_stackmap( |
89 StackMapFrame* frame, int32_t target, int32_t frame_index, |
91 StackMapFrame* frame, int32_t target, int32_t frame_index, |
90 bool match, bool update, ErrorContext* ctx, TRAPS) const { |
92 bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { |
91 if (frame_index < 0 || frame_index >= _frame_count) { |
93 if (frame_index < 0 || frame_index >= _frame_count) { |
92 *ctx = ErrorContext::missing_stackmap(frame->offset()); |
94 *ctx = ErrorContext::missing_stackmap(frame->offset()); |
93 frame->verifier()->verify_error( |
95 frame->verifier()->verify_error( |
94 *ctx, "Expecting a stackmap frame at branch target %d", target); |
96 *ctx, "Expecting a stackmap frame at branch target %d", target); |
95 return false; |
97 return false; |
96 } |
98 } |
97 |
99 |
98 StackMapFrame *stackmap_frame = _frame_array[frame_index]; |
100 StackMapFrame *stackmap_frame = _frame_array[frame_index]; |
99 bool result = true; |
101 bool result = true; |
100 if (match) { |
102 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 |
103 // Has direct control flow from last instruction, need to match the two |
104 // frames. |
104 // frames. |
105 result = frame->is_assignable_to(stackmap_frame, is_exception_handler, |
105 result = frame->is_assignable_to(stackmap_frame, handler, |
106 ctx, CHECK_VERIFY_(frame->verifier(), result)); |
106 ctx, CHECK_VERIFY_(frame->verifier(), result)); |
107 } |
107 } |
108 if (update) { |
108 if (update) { |
109 // Use the frame in stackmap table as current frame |
109 // Use the frame in stackmap table as current frame |
110 int lsize = stackmap_frame->locals_size(); |
110 int lsize = stackmap_frame->locals_size(); |
124 |
124 |
125 void StackMapTable::check_jump_target( |
125 void StackMapTable::check_jump_target( |
126 StackMapFrame* frame, int32_t target, TRAPS) const { |
126 StackMapFrame* frame, int32_t target, TRAPS) const { |
127 ErrorContext ctx; |
127 ErrorContext ctx; |
128 bool match = match_stackmap( |
128 bool match = match_stackmap( |
129 frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); |
129 frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier())); |
130 if (!match || (target < 0 || target >= _code_length)) { |
130 if (!match || (target < 0 || target >= _code_length)) { |
131 frame->verifier()->verify_error(ctx, |
131 frame->verifier()->verify_error(ctx, |
132 "Inconsistent stackmap frames at branch target %d", target); |
132 "Inconsistent stackmap frames at branch target %d", target); |
133 return; |
133 return; |
134 } |
134 } |
135 // check if uninitialized objects exist on backward branches |
135 // check if uninitialized objects exist on backward branches |
136 check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); |
136 check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); |
137 frame->verifier()->update_furthest_jump(target); |
|
138 } |
137 } |
139 |
138 |
140 void StackMapTable::check_new_object( |
139 void StackMapTable::check_new_object( |
141 const StackMapFrame* frame, int32_t target, TRAPS) const { |
140 const StackMapFrame* frame, int32_t target, TRAPS) const { |
142 if (frame->offset() > target && frame->has_new_object()) { |
141 if (frame->offset() > target && frame->has_new_object()) { |