1697 } |
1697 } |
1698 } |
1698 } |
1699 } |
1699 } |
1700 |
1700 |
1701 |
1701 |
1702 const void* ClassFileParser::parse_exception_table(const ClassFileStream* const cfs, |
1702 const ClassFileParser::unsafe_u2* ClassFileParser::parse_exception_table(const ClassFileStream* const cfs, |
1703 u4 code_length, |
1703 u4 code_length, |
1704 u4 exception_table_length, |
1704 u4 exception_table_length, |
1705 TRAPS) { |
1705 TRAPS) { |
1706 assert(cfs != NULL, "invariant"); |
1706 assert(cfs != NULL, "invariant"); |
1707 |
1707 |
1708 const void* const exception_table_start = cfs->current(); |
1708 const unsafe_u2* const exception_table_start = cfs->current(); |
1709 assert(exception_table_start != NULL, "null exception table"); |
1709 assert(exception_table_start != NULL, "null exception table"); |
1710 |
1710 |
1711 cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, |
1711 cfs->guarantee_more(8 * exception_table_length, CHECK_NULL); // start_pc, |
1712 // end_pc, |
1712 // end_pc, |
1713 // handler_pc, |
1713 // handler_pc, |
1821 lvt->slot = Bytes::get_Java_u2((u1*) &src->slot); |
1821 lvt->slot = Bytes::get_Java_u2((u1*) &src->slot); |
1822 } |
1822 } |
1823 |
1823 |
1824 // Function is used to parse both attributes: |
1824 // Function is used to parse both attributes: |
1825 // LocalVariableTable (LVT) and LocalVariableTypeTable (LVTT) |
1825 // LocalVariableTable (LVT) and LocalVariableTypeTable (LVTT) |
1826 const void* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs, |
1826 const ClassFileParser::unsafe_u2* ClassFileParser::parse_localvariable_table(const ClassFileStream* cfs, |
1827 u4 code_length, |
1827 u4 code_length, |
1828 u2 max_locals, |
1828 u2 max_locals, |
1829 u4 code_attribute_length, |
1829 u4 code_attribute_length, |
1830 u2* const localvariable_table_length, |
1830 u2* const localvariable_table_length, |
1831 bool isLVTT, |
1831 bool isLVTT, |
1832 TRAPS) { |
1832 TRAPS) { |
1833 const char* const tbl_name = (isLVTT) ? "LocalVariableTypeTable" : "LocalVariableTable"; |
1833 const char* const tbl_name = (isLVTT) ? "LocalVariableTypeTable" : "LocalVariableTable"; |
1834 *localvariable_table_length = cfs->get_u2(CHECK_NULL); |
1834 *localvariable_table_length = cfs->get_u2(CHECK_NULL); |
1835 const unsigned int size = |
1835 const unsigned int size = |
1836 (*localvariable_table_length) * sizeof(Classfile_LVT_Element) / sizeof(u2); |
1836 (*localvariable_table_length) * sizeof(Classfile_LVT_Element) / sizeof(u2); |
1837 |
1837 |
1841 if (_need_verify) { |
1841 if (_need_verify) { |
1842 guarantee_property(code_attribute_length == (sizeof(*localvariable_table_length) + size * sizeof(u2)), |
1842 guarantee_property(code_attribute_length == (sizeof(*localvariable_table_length) + size * sizeof(u2)), |
1843 "%s has wrong length in class file %s", tbl_name, CHECK_NULL); |
1843 "%s has wrong length in class file %s", tbl_name, CHECK_NULL); |
1844 } |
1844 } |
1845 |
1845 |
1846 const void* const localvariable_table_start = cfs->current(); |
1846 const unsafe_u2* const localvariable_table_start = cfs->current(); |
1847 assert(localvariable_table_start != NULL, "null local variable table"); |
1847 assert(localvariable_table_start != NULL, "null local variable table"); |
1848 if (!_need_verify) { |
1848 if (!_need_verify) { |
1849 cfs->skip_u2_fast(size); |
1849 cfs->skip_u2_fast(size); |
1850 } else { |
1850 } else { |
1851 cfs->guarantee_more(size * 2, CHECK_NULL); |
1851 cfs->guarantee_more(size * 2, CHECK_NULL); |
1957 return NULL; |
1957 return NULL; |
1958 } |
1958 } |
1959 return stackmap_table_start; |
1959 return stackmap_table_start; |
1960 } |
1960 } |
1961 |
1961 |
1962 const void* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const cfs, |
1962 const ClassFileParser::unsafe_u2* ClassFileParser::parse_checked_exceptions(const ClassFileStream* const cfs, |
1963 u2* const checked_exceptions_length, |
1963 u2* const checked_exceptions_length, |
1964 u4 method_attribute_length, |
1964 u4 method_attribute_length, |
1965 TRAPS) { |
1965 TRAPS) { |
1966 assert(cfs != NULL, "invariant"); |
1966 assert(cfs != NULL, "invariant"); |
1967 assert(checked_exceptions_length != NULL, "invariant"); |
1967 assert(checked_exceptions_length != NULL, "invariant"); |
1968 |
1968 |
1969 cfs->guarantee_more(2, CHECK_NULL); // checked_exceptions_length |
1969 cfs->guarantee_more(2, CHECK_NULL); // checked_exceptions_length |
1970 *checked_exceptions_length = cfs->get_u2_fast(); |
1970 *checked_exceptions_length = cfs->get_u2_fast(); |
1971 const unsigned int size = |
1971 const unsigned int size = |
1972 (*checked_exceptions_length) * sizeof(CheckedExceptionElement) / sizeof(u2); |
1972 (*checked_exceptions_length) * sizeof(CheckedExceptionElement) / sizeof(u2); |
1973 const void* const checked_exceptions_start = cfs->current(); |
1973 const unsafe_u2* const checked_exceptions_start = cfs->current(); |
1974 assert(checked_exceptions_start != NULL, "null checked exceptions"); |
1974 assert(checked_exceptions_start != NULL, "null checked exceptions"); |
1975 if (!_need_verify) { |
1975 if (!_need_verify) { |
1976 cfs->skip_u2_fast(size); |
1976 cfs->skip_u2_fast(size); |
1977 } else { |
1977 } else { |
1978 // Verify each value in the checked exception table |
1978 // Verify each value in the checked exception table |
2135 * - HotSpot internal LVT keeps natural ordering of class file LVT entries. |
2135 * - HotSpot internal LVT keeps natural ordering of class file LVT entries. |
2136 */ |
2136 */ |
2137 void ClassFileParser::copy_localvariable_table(const ConstMethod* cm, |
2137 void ClassFileParser::copy_localvariable_table(const ConstMethod* cm, |
2138 int lvt_cnt, |
2138 int lvt_cnt, |
2139 u2* const localvariable_table_length, |
2139 u2* const localvariable_table_length, |
2140 const void** const localvariable_table_start, |
2140 const unsafe_u2** const localvariable_table_start, |
2141 int lvtt_cnt, |
2141 int lvtt_cnt, |
2142 u2* const localvariable_type_table_length, |
2142 u2* const localvariable_type_table_length, |
2143 const void** const localvariable_type_table_start, |
2143 const unsafe_u2** const localvariable_type_table_start, |
2144 TRAPS) { |
2144 TRAPS) { |
2145 |
2145 |
2146 ResourceMark rm(THREAD); |
2146 ResourceMark rm(THREAD); |
2147 |
2147 |
2148 typedef ResourceHashtable<LocalVariableTableElement, LocalVariableTableElement*, |
2148 typedef ResourceHashtable<LocalVariableTableElement, LocalVariableTableElement*, |
2333 u2 max_stack = 0; |
2333 u2 max_stack = 0; |
2334 u2 max_locals = 0; |
2334 u2 max_locals = 0; |
2335 u4 code_length = 0; |
2335 u4 code_length = 0; |
2336 const u1* code_start = 0; |
2336 const u1* code_start = 0; |
2337 u2 exception_table_length = 0; |
2337 u2 exception_table_length = 0; |
2338 const void* exception_table_start = NULL; // (potentially unaligned) pointer to array of u2 elements |
2338 const unsafe_u2* exception_table_start = NULL; // (potentially unaligned) pointer to array of u2 elements |
2339 Array<int>* exception_handlers = Universe::the_empty_int_array(); |
2339 Array<int>* exception_handlers = Universe::the_empty_int_array(); |
2340 u2 checked_exceptions_length = 0; |
2340 u2 checked_exceptions_length = 0; |
2341 const void* checked_exceptions_start = NULL; // (potentially unaligned) pointer to array of u2 elements |
2341 const unsafe_u2* checked_exceptions_start = NULL; // (potentially unaligned) pointer to array of u2 elements |
2342 CompressedLineNumberWriteStream* linenumber_table = NULL; |
2342 CompressedLineNumberWriteStream* linenumber_table = NULL; |
2343 int linenumber_table_length = 0; |
2343 int linenumber_table_length = 0; |
2344 int total_lvt_length = 0; |
2344 int total_lvt_length = 0; |
2345 u2 lvt_cnt = 0; |
2345 u2 lvt_cnt = 0; |
2346 u2 lvtt_cnt = 0; |
2346 u2 lvtt_cnt = 0; |
2347 bool lvt_allocated = false; |
2347 bool lvt_allocated = false; |
2348 u2 max_lvt_cnt = INITIAL_MAX_LVT_NUMBER; |
2348 u2 max_lvt_cnt = INITIAL_MAX_LVT_NUMBER; |
2349 u2 max_lvtt_cnt = INITIAL_MAX_LVT_NUMBER; |
2349 u2 max_lvtt_cnt = INITIAL_MAX_LVT_NUMBER; |
2350 u2* localvariable_table_length = NULL; |
2350 u2* localvariable_table_length = NULL; |
2351 const void** localvariable_table_start = NULL; // (potentially unaligned) pointer to array of LVT attributes |
2351 const unsafe_u2** localvariable_table_start = NULL; // (potentially unaligned) pointer to array of LVT attributes |
2352 u2* localvariable_type_table_length = NULL; |
2352 u2* localvariable_type_table_length = NULL; |
2353 const void** localvariable_type_table_start = NULL; // (potentially unaligned) pointer to LVTT attributes |
2353 const unsafe_u2** localvariable_type_table_start = NULL; // (potentially unaligned) pointer to LVTT attributes |
2354 int method_parameters_length = -1; |
2354 int method_parameters_length = -1; |
2355 const u1* method_parameters_data = NULL; |
2355 const u1* method_parameters_data = NULL; |
2356 bool method_parameters_seen = false; |
2356 bool method_parameters_seen = false; |
2357 bool parsed_code_attribute = false; |
2357 bool parsed_code_attribute = false; |
2358 bool parsed_checked_exceptions_attribute = false; |
2358 bool parsed_checked_exceptions_attribute = false; |
2489 // Parse local variable table |
2489 // Parse local variable table |
2490 if (!lvt_allocated) { |
2490 if (!lvt_allocated) { |
2491 localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2491 localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2492 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2492 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2493 localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2493 localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2494 THREAD, const void*, INITIAL_MAX_LVT_NUMBER); |
2494 THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER); |
2495 localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2495 localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2496 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2496 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2497 localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2497 localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2498 THREAD, const void*, INITIAL_MAX_LVT_NUMBER); |
2498 THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER); |
2499 lvt_allocated = true; |
2499 lvt_allocated = true; |
2500 } |
2500 } |
2501 if (lvt_cnt == max_lvt_cnt) { |
2501 if (lvt_cnt == max_lvt_cnt) { |
2502 max_lvt_cnt <<= 1; |
2502 max_lvt_cnt <<= 1; |
2503 localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt); |
2503 localvariable_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_table_length, lvt_cnt, max_lvt_cnt); |
2504 localvariable_table_start = REALLOC_RESOURCE_ARRAY(const void*, localvariable_table_start, lvt_cnt, max_lvt_cnt); |
2504 localvariable_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_table_start, lvt_cnt, max_lvt_cnt); |
2505 } |
2505 } |
2506 localvariable_table_start[lvt_cnt] = |
2506 localvariable_table_start[lvt_cnt] = |
2507 parse_localvariable_table(cfs, |
2507 parse_localvariable_table(cfs, |
2508 code_length, |
2508 code_length, |
2509 max_locals, |
2509 max_locals, |
2518 cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) { |
2518 cp->symbol_at(code_attribute_name_index) == vmSymbols::tag_local_variable_type_table()) { |
2519 if (!lvt_allocated) { |
2519 if (!lvt_allocated) { |
2520 localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2520 localvariable_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2521 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2521 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2522 localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2522 localvariable_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2523 THREAD, const void*, INITIAL_MAX_LVT_NUMBER); |
2523 THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER); |
2524 localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2524 localvariable_type_table_length = NEW_RESOURCE_ARRAY_IN_THREAD( |
2525 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2525 THREAD, u2, INITIAL_MAX_LVT_NUMBER); |
2526 localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2526 localvariable_type_table_start = NEW_RESOURCE_ARRAY_IN_THREAD( |
2527 THREAD, const void*, INITIAL_MAX_LVT_NUMBER); |
2527 THREAD, const unsafe_u2*, INITIAL_MAX_LVT_NUMBER); |
2528 lvt_allocated = true; |
2528 lvt_allocated = true; |
2529 } |
2529 } |
2530 // Parse local variable type table |
2530 // Parse local variable type table |
2531 if (lvtt_cnt == max_lvtt_cnt) { |
2531 if (lvtt_cnt == max_lvtt_cnt) { |
2532 max_lvtt_cnt <<= 1; |
2532 max_lvtt_cnt <<= 1; |
2533 localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt); |
2533 localvariable_type_table_length = REALLOC_RESOURCE_ARRAY(u2, localvariable_type_table_length, lvtt_cnt, max_lvtt_cnt); |
2534 localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const void*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt); |
2534 localvariable_type_table_start = REALLOC_RESOURCE_ARRAY(const unsafe_u2*, localvariable_type_table_start, lvtt_cnt, max_lvtt_cnt); |
2535 } |
2535 } |
2536 localvariable_type_table_start[lvtt_cnt] = |
2536 localvariable_type_table_start[lvtt_cnt] = |
2537 parse_localvariable_table(cfs, |
2537 parse_localvariable_table(cfs, |
2538 code_length, |
2538 code_length, |
2539 max_locals, |
2539 max_locals, |