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 frame->verifier()->update_furthest_jump(target); 138 } 139 140 void StackMapTable::check_new_object( 141 const StackMapFrame* frame, int32_t target, TRAPS) const { 142 if (frame->offset() > target && frame->has_new_object()) { 143 frame->verifier()->verify_error( 144 ErrorContext::bad_code(frame->offset()), 145 "Uninitialized object exists on backward branch %d", target); 146 return; 147 } 148 } 149 150 void StackMapTable::print_on(outputStream* str) const { 151 str->indent().print_cr("StackMapTable: frame_count = %d", _frame_count); 152 str->indent().print_cr("table = { "); 153 { 154 streamIndentor si(str); 155 for (int32_t i = 0; i < _frame_count; ++i) { 156 _frame_array[i]->print_on(str); 157 } | 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, bool handler, ErrorContext* ctx, TRAPS) const { 74 int index = get_index_from_offset(target); 75 return match_stackmap(frame, target, index, match, update, handler, 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 // handler is true if the frame in stackmap_table is for an exception handler. 81 // 82 // The values of match and update are: _match__update__handler 83 // 84 // checking a branch target: true false false 85 // checking an exception handler: true false true 86 // linear bytecode verification following an 87 // unconditional branch: false true false 88 // linear bytecode verification not following an 89 // unconditional branch: true true false 90 bool StackMapTable::match_stackmap( 91 StackMapFrame* frame, int32_t target, int32_t frame_index, 92 bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { 93 if (frame_index < 0 || frame_index >= _frame_count) { 94 *ctx = ErrorContext::missing_stackmap(frame->offset()); 95 frame->verifier()->verify_error( 96 *ctx, "Expecting a stackmap frame at branch target %d", target); 97 return false; 98 } 99 100 StackMapFrame *stackmap_frame = _frame_array[frame_index]; 101 bool result = true; 102 if (match) { 103 // Has direct control flow from last instruction, need to match the two 104 // frames. 105 result = frame->is_assignable_to(stackmap_frame, 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, 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_on(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_on(str); 156 } |