8219860: Cleanup ClassFileParser::parse_linenumber_table
Reviewed-by: rehn, lfoltan, hseigel
This commit is contained in:
parent
69a6a6c4a0
commit
d2c205bb59
@ -52,7 +52,7 @@
|
||||
#include "oops/klass.inline.hpp"
|
||||
#include "oops/klassVtable.hpp"
|
||||
#include "oops/metadata.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/method.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
@ -1974,46 +1974,6 @@ const ClassFileParser::unsafe_u2* ClassFileParser::parse_localvariable_table(con
|
||||
return localvariable_table_start;
|
||||
}
|
||||
|
||||
|
||||
void ClassFileParser::parse_type_array(u2 array_length,
|
||||
u4 code_length,
|
||||
u4* const u1_index,
|
||||
u4* const u2_index,
|
||||
u1* const u1_array,
|
||||
u2* const u2_array,
|
||||
TRAPS) {
|
||||
const ClassFileStream* const cfs = _stream;
|
||||
u2 index = 0; // index in the array with long/double occupying two slots
|
||||
u4 i1 = *u1_index;
|
||||
u4 i2 = *u2_index + 1;
|
||||
for(int i = 0; i < array_length; i++) {
|
||||
const u1 tag = u1_array[i1++] = cfs->get_u1(CHECK);
|
||||
index++;
|
||||
if (tag == ITEM_Long || tag == ITEM_Double) {
|
||||
index++;
|
||||
} else if (tag == ITEM_Object) {
|
||||
const u2 class_index = u2_array[i2++] = cfs->get_u2(CHECK);
|
||||
guarantee_property(valid_klass_reference_at(class_index),
|
||||
"Bad class index %u in StackMap in class file %s",
|
||||
class_index, CHECK);
|
||||
} else if (tag == ITEM_Uninitialized) {
|
||||
const u2 offset = u2_array[i2++] = cfs->get_u2(CHECK);
|
||||
guarantee_property(
|
||||
offset < code_length,
|
||||
"Bad uninitialized type offset %u in StackMap in class file %s",
|
||||
offset, CHECK);
|
||||
} else {
|
||||
guarantee_property(
|
||||
tag <= (u1)ITEM_Uninitialized,
|
||||
"Unknown variable type %u in StackMap in class file %s",
|
||||
tag, CHECK);
|
||||
}
|
||||
}
|
||||
u2_array[*u2_index] = index;
|
||||
*u1_index = i1;
|
||||
*u2_index = i2;
|
||||
}
|
||||
|
||||
static const u1* parse_stackmap_table(const ClassFileStream* const cfs,
|
||||
u4 code_attribute_length,
|
||||
bool need_verify,
|
||||
|
@ -68,8 +68,7 @@ class ClassFileParser {
|
||||
//
|
||||
enum Publicity {
|
||||
INTERNAL,
|
||||
BROADCAST,
|
||||
NOF_PUBLICITY_LEVELS
|
||||
BROADCAST
|
||||
};
|
||||
|
||||
enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
|
||||
@ -270,14 +269,6 @@ class ClassFileParser {
|
||||
u4 method_attribute_length,
|
||||
TRAPS);
|
||||
|
||||
void parse_type_array(u2 array_length,
|
||||
u4 code_length,
|
||||
u4* const u1_index,
|
||||
u4* const u2_index,
|
||||
u1* const u1_array,
|
||||
u2* const u2_array,
|
||||
TRAPS);
|
||||
|
||||
// Classfile attribute parsing
|
||||
u2 parse_generic_signature_attribute(const ClassFileStream* const cfs, TRAPS);
|
||||
void parse_classfile_sourcefile_attribute(const ClassFileStream* const cfs, TRAPS);
|
||||
@ -524,7 +515,6 @@ class ClassFileParser {
|
||||
int itable_size() const { return _itable_size; }
|
||||
|
||||
u2 this_class_index() const { return _this_class_index; }
|
||||
u2 super_class_index() const { return _super_class_index; }
|
||||
|
||||
bool is_unsafe_anonymous() const { return _unsafe_anonymous_host != NULL; }
|
||||
bool is_interface() const { return _access_flags.is_interface(); }
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
||||
const bool ClassFileStream::verify = true;
|
||||
const bool ClassFileStream::no_verification = false;
|
||||
|
||||
void ClassFileStream::truncated_file_error(TRAPS) const {
|
||||
THROW_MSG(vmSymbols::java_lang_ClassFormatError(), "Truncated class file");
|
||||
@ -73,69 +72,6 @@ const ClassFileStream* ClassFileStream::clone() const {
|
||||
need_verify());
|
||||
}
|
||||
|
||||
u1 ClassFileStream::get_u1(TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(1, CHECK_0);
|
||||
} else {
|
||||
assert(1 <= _buffer_end - _current, "buffer overflow");
|
||||
}
|
||||
return *_current++;
|
||||
}
|
||||
|
||||
u2 ClassFileStream::get_u2(TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(2, CHECK_0);
|
||||
} else {
|
||||
assert(2 <= _buffer_end - _current, "buffer overflow");
|
||||
}
|
||||
const u1* tmp = _current;
|
||||
_current += 2;
|
||||
return Bytes::get_Java_u2((address)tmp);
|
||||
}
|
||||
|
||||
u4 ClassFileStream::get_u4(TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(4, CHECK_0);
|
||||
} else {
|
||||
assert(4 <= _buffer_end - _current, "buffer overflow");
|
||||
}
|
||||
const u1* tmp = _current;
|
||||
_current += 4;
|
||||
return Bytes::get_Java_u4((address)tmp);
|
||||
}
|
||||
|
||||
u8 ClassFileStream::get_u8(TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(8, CHECK_0);
|
||||
} else {
|
||||
assert(8 <= _buffer_end - _current, "buffer overflow");
|
||||
}
|
||||
const u1* tmp = _current;
|
||||
_current += 8;
|
||||
return Bytes::get_Java_u8((address)tmp);
|
||||
}
|
||||
|
||||
void ClassFileStream::skip_u1(int length, TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(length, CHECK);
|
||||
}
|
||||
_current += length;
|
||||
}
|
||||
|
||||
void ClassFileStream::skip_u2(int length, TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(length * 2, CHECK);
|
||||
}
|
||||
_current += length * 2;
|
||||
}
|
||||
|
||||
void ClassFileStream::skip_u4(int length, TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(length * 4, CHECK);
|
||||
}
|
||||
_current += length * 4;
|
||||
}
|
||||
|
||||
uint64_t ClassFileStream::compute_fingerprint() const {
|
||||
int classfile_size = length();
|
||||
int classfile_crc = ClassLoader::crc32(0, (const char*)buffer(), length());
|
||||
|
@ -52,7 +52,6 @@ class ClassFileStream: public ResourceObj {
|
||||
const char* const clone_source() const;
|
||||
|
||||
public:
|
||||
static const bool no_verification;
|
||||
static const bool verify;
|
||||
|
||||
ClassFileStream(const u1* buffer,
|
||||
@ -92,21 +91,34 @@ class ClassFileStream: public ResourceObj {
|
||||
}
|
||||
|
||||
// Read u1 from stream
|
||||
u1 get_u1(TRAPS) const;
|
||||
u1 get_u1_fast() const {
|
||||
return *_current++;
|
||||
}
|
||||
u1 get_u1(TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(1, CHECK_0);
|
||||
} else {
|
||||
assert(1 <= _buffer_end - _current, "buffer overflow");
|
||||
}
|
||||
return get_u1_fast();
|
||||
}
|
||||
|
||||
// Read u2 from stream
|
||||
u2 get_u2(TRAPS) const;
|
||||
u2 get_u2_fast() const {
|
||||
u2 res = Bytes::get_Java_u2((address)_current);
|
||||
_current += 2;
|
||||
return res;
|
||||
}
|
||||
u2 get_u2(TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(2, CHECK_0);
|
||||
} else {
|
||||
assert(2 <= _buffer_end - _current, "buffer overflow");
|
||||
}
|
||||
return get_u2_fast();
|
||||
}
|
||||
|
||||
// Read u4 from stream
|
||||
u4 get_u4(TRAPS) const;
|
||||
u4 get_u4_fast() const {
|
||||
u4 res = Bytes::get_Java_u4((address)_current);
|
||||
_current += 4;
|
||||
@ -114,25 +126,27 @@ class ClassFileStream: public ResourceObj {
|
||||
}
|
||||
|
||||
// Read u8 from stream
|
||||
u8 get_u8(TRAPS) const;
|
||||
u8 get_u8_fast() const {
|
||||
u8 res = Bytes::get_Java_u8((address)_current);
|
||||
_current += 8;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Skip length u1 or u2 elements from stream
|
||||
void skip_u1(int length, TRAPS) const;
|
||||
// Skip length elements from stream
|
||||
void skip_u1(int length, TRAPS) const {
|
||||
if (_need_verify) {
|
||||
guarantee_more(length, CHECK);
|
||||
}
|
||||
skip_u1_fast(length);
|
||||
}
|
||||
void skip_u1_fast(int length) const {
|
||||
_current += length;
|
||||
}
|
||||
|
||||
void skip_u2(int length, TRAPS) const;
|
||||
void skip_u2_fast(int length) const {
|
||||
_current += 2 * length;
|
||||
}
|
||||
|
||||
void skip_u4(int length, TRAPS) const;
|
||||
void skip_u4_fast(int length) const {
|
||||
_current += 4 * length;
|
||||
}
|
||||
|
@ -26,15 +26,6 @@
|
||||
#include "code/compressedStream.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
// 32-bit one-to-one sign encoding taken from Pack200
|
||||
// converts leading sign bits into leading zeroes with trailing sign bit
|
||||
inline juint CompressedStream::encode_sign(jint value) {
|
||||
return (value << 1) ^ (value >> 31);
|
||||
}
|
||||
inline jint CompressedStream::decode_sign(juint value) {
|
||||
return (value >> 1) ^ -(jint)(value & 1);
|
||||
}
|
||||
|
||||
// 32-bit self-inverse encoding of float bits
|
||||
// converts trailing zeroes (common in floats) to leading zeroes
|
||||
inline juint CompressedStream::reverse_int(juint i) {
|
||||
@ -46,7 +37,6 @@ inline juint CompressedStream::reverse_int(juint i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
jint CompressedReadStream::read_signed_int() {
|
||||
return decode_sign(read_int());
|
||||
}
|
||||
@ -90,11 +80,6 @@ void CompressedWriteStream::grow() {
|
||||
_size = _size * 2;
|
||||
}
|
||||
|
||||
void CompressedWriteStream::write_signed_int(jint value) {
|
||||
// this encoding, called SIGNED5, is taken from Pack200
|
||||
write_int(encode_sign(value));
|
||||
}
|
||||
|
||||
void CompressedWriteStream::write_float(jfloat value) {
|
||||
juint f = jint_cast(value);
|
||||
juint rf = reverse_int(f);
|
||||
@ -117,136 +102,3 @@ void CompressedWriteStream::write_long(jlong value) {
|
||||
write_signed_int(low(value));
|
||||
write_signed_int(high(value));
|
||||
}
|
||||
|
||||
|
||||
/// The remaining details
|
||||
|
||||
#ifndef PRODUCT
|
||||
// set this to trigger unit test
|
||||
void test_compressed_stream(int trace);
|
||||
bool test_compressed_stream_enabled = false;
|
||||
#endif
|
||||
|
||||
void CompressedWriteStream::write_int_mb(jint value) {
|
||||
debug_only(int pos1 = position());
|
||||
juint sum = value;
|
||||
for (int i = 0; ; ) {
|
||||
if (sum < L || i == MAX_i) {
|
||||
// remainder is either a "low code" or the 5th byte
|
||||
assert(sum == (u_char)sum, "valid byte");
|
||||
write((u_char)sum);
|
||||
break;
|
||||
}
|
||||
sum -= L;
|
||||
int b_i = L + (sum % H); // this is a "high code"
|
||||
sum >>= lg_H; // extracted 6 bits
|
||||
write(b_i); ++i;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (test_compressed_stream_enabled) { // hack to enable this stress test
|
||||
test_compressed_stream_enabled = false;
|
||||
test_compressed_stream(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
/// a unit test (can be run by hand from a debugger)
|
||||
|
||||
// Avoid a VS2005 compiler stack overflow w/ fastdebug build.
|
||||
// The following pragma optimize turns off optimization ONLY
|
||||
// for this block (a matching directive turns it back on later).
|
||||
// These directives can be removed once the MS VS.NET 2005
|
||||
// compiler stack overflow is fixed.
|
||||
#if defined(_MSC_VER) && _MSC_VER >=1400 && !defined(_WIN64)
|
||||
#pragma optimize("", off)
|
||||
#pragma warning(disable: 4748)
|
||||
#endif
|
||||
|
||||
// generator for an "interesting" set of critical values
|
||||
enum { stretch_limit = (1<<16) * (64-16+1) };
|
||||
static jlong stretch(jint x, int bits) {
|
||||
// put x[high 4] into place
|
||||
jlong h = (jlong)((x >> (16-4))) << (bits - 4);
|
||||
// put x[low 12] into place, sign extended
|
||||
jlong l = ((jlong)x << (64-12)) >> (64-12);
|
||||
// move l upwards, maybe
|
||||
l <<= (x >> 16);
|
||||
return h ^ l;
|
||||
}
|
||||
|
||||
PRAGMA_DIAG_PUSH
|
||||
PRAGMA_FORMAT_IGNORED // Someone needs to deal with this.
|
||||
void test_compressed_stream(int trace) {
|
||||
CompressedWriteStream bytes(stretch_limit * 100);
|
||||
jint n;
|
||||
int step = 0, fails = 0;
|
||||
#define CHECKXY(x, y, fmt) { \
|
||||
++step; \
|
||||
int xlen = (pos = decode.position()) - lastpos; lastpos = pos; \
|
||||
if (trace > 0 && (step % trace) == 0) { \
|
||||
tty->print_cr("step %d, n=%08x: value=" fmt " (len=%d)", \
|
||||
step, n, x, xlen); } \
|
||||
if (x != y) { \
|
||||
tty->print_cr("step %d, n=%d: " fmt " != " fmt, step, n, x, y); \
|
||||
fails++; \
|
||||
} }
|
||||
for (n = 0; n < (1<<8); n++) {
|
||||
jbyte x = (jbyte)n;
|
||||
bytes.write_byte(x); ++step;
|
||||
}
|
||||
for (n = 0; n < stretch_limit; n++) {
|
||||
jint x = (jint)stretch(n, 32);
|
||||
bytes.write_int(x); ++step;
|
||||
bytes.write_signed_int(x); ++step;
|
||||
bytes.write_float(jfloat_cast(x)); ++step;
|
||||
}
|
||||
for (n = 0; n < stretch_limit; n++) {
|
||||
jlong x = stretch(n, 64);
|
||||
bytes.write_long(x); ++step;
|
||||
bytes.write_double(jdouble_cast(x)); ++step;
|
||||
}
|
||||
int length = bytes.position();
|
||||
if (trace != 0)
|
||||
tty->print_cr("set up test of %d stream values, size %d", step, length);
|
||||
step = 0;
|
||||
// now decode it all
|
||||
CompressedReadStream decode(bytes.buffer());
|
||||
int pos, lastpos = decode.position();
|
||||
for (n = 0; n < (1<<8); n++) {
|
||||
jbyte x = (jbyte)n;
|
||||
jbyte y = decode.read_byte();
|
||||
CHECKXY(x, y, "%db");
|
||||
}
|
||||
for (n = 0; n < stretch_limit; n++) {
|
||||
jint x = (jint)stretch(n, 32);
|
||||
jint y1 = decode.read_int();
|
||||
CHECKXY(x, y1, "%du");
|
||||
jint y2 = decode.read_signed_int();
|
||||
CHECKXY(x, y2, "%di");
|
||||
jint y3 = jint_cast(decode.read_float());
|
||||
CHECKXY(x, y3, "%df");
|
||||
}
|
||||
for (n = 0; n < stretch_limit; n++) {
|
||||
jlong x = stretch(n, 64);
|
||||
jlong y1 = decode.read_long();
|
||||
CHECKXY(x, y1, INT64_FORMAT "l");
|
||||
jlong y2 = jlong_cast(decode.read_double());
|
||||
CHECKXY(x, y2, INT64_FORMAT "d");
|
||||
}
|
||||
int length2 = decode.position();
|
||||
if (trace != 0)
|
||||
tty->print_cr("finished test of %d stream values, size %d", step, length2);
|
||||
guarantee(length == length2, "bad length");
|
||||
guarantee(fails == 0, "test failures");
|
||||
}
|
||||
PRAGMA_DIAG_POP
|
||||
|
||||
#if defined(_MSC_VER) &&_MSC_VER >=1400 && !defined(_WIN64)
|
||||
#pragma warning(default: 4748)
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
#endif // PRODUCT
|
||||
|
@ -43,11 +43,11 @@ class CompressedStream : public ResourceObj {
|
||||
MAX_i = 4 // bytes are numbered in (0..4), max 5 bytes
|
||||
};
|
||||
|
||||
// these inlines are defined only in compressedStream.cpp
|
||||
static inline juint encode_sign(jint value); // for Pack200 SIGNED5
|
||||
static inline jint decode_sign(juint value); // for Pack200 SIGNED5
|
||||
static inline juint reverse_int(juint bits); // to trim trailing float 0's
|
||||
|
||||
// 32-bit one-to-one sign encoding taken from Pack200
|
||||
// converts leading sign bits into leading zeroes with trailing sign bit
|
||||
static juint encode_sign(jint value) { return (value << 1) ^ (value >> 31); }
|
||||
static jint decode_sign(juint value) { return (value >> 1) ^ -(jint)(value & 1); }
|
||||
static juint reverse_int(juint i); // to trim trailing float 0's
|
||||
public:
|
||||
CompressedStream(u_char* buffer, int position = 0) {
|
||||
_buffer = buffer;
|
||||
@ -134,7 +134,22 @@ class CompressedWriteStream : public CompressedStream {
|
||||
}
|
||||
void grow();
|
||||
|
||||
void write_int_mb(jint value); // UNSIGNED5 coding, 1-5 byte cases
|
||||
// UNSIGNED5 coding, 1-5 byte cases
|
||||
void write_int_mb(jint value) {
|
||||
juint sum = value;
|
||||
for (int i = 0; ; ) {
|
||||
if (sum < L || i == MAX_i) {
|
||||
// remainder is either a "low code" or the 5th byte
|
||||
assert(sum == (u_char)sum, "valid byte");
|
||||
write((u_char)sum);
|
||||
break;
|
||||
}
|
||||
sum -= L;
|
||||
int b_i = L + (sum % H); // this is a "high code"
|
||||
sum >>= lg_H; // extracted 6 bits
|
||||
write(b_i); ++i;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int _size;
|
||||
@ -151,7 +166,7 @@ class CompressedWriteStream : public CompressedStream {
|
||||
void write_int(jint value) { if ((juint)value < L && !full())
|
||||
store((u_char)value);
|
||||
else write_int_mb(value); }
|
||||
void write_signed_int(jint value); // write_int(encode_sign(value))
|
||||
void write_signed_int(jint value) { write_int(encode_sign(value)); }
|
||||
void write_float(jfloat value); // write_int(reverse_int(jint_cast(v)))
|
||||
void write_double(jdouble value); // write_int(reverse_int(<low,high>))
|
||||
void write_long(jlong value); // write_signed_int(<low,high>)
|
||||
|
@ -1684,35 +1684,11 @@ void Method::print_codes_on(int from, int to, outputStream* st) const {
|
||||
while (s.next() >= 0) BytecodeTracer::trace(mh, s.bcp(), st);
|
||||
}
|
||||
|
||||
|
||||
// Simple compression of line number tables. We use a regular compressed stream, except that we compress deltas
|
||||
// between (bci,line) pairs since they are smaller. If (bci delta, line delta) fits in (5-bit unsigned, 3-bit unsigned)
|
||||
// we save it as one byte, otherwise we write a 0xFF escape character and use regular compression. 0x0 is used
|
||||
// as end-of-stream terminator.
|
||||
|
||||
void CompressedLineNumberWriteStream::write_pair_regular(int bci_delta, int line_delta) {
|
||||
// bci and line number does not compress into single byte.
|
||||
// Write out escape character and use regular compression for bci and line number.
|
||||
write_byte((jubyte)0xFF);
|
||||
write_signed_int(bci_delta);
|
||||
write_signed_int(line_delta);
|
||||
}
|
||||
|
||||
// See comment in method.hpp which explains why this exists.
|
||||
#if defined(_M_AMD64) && _MSC_VER >= 1400
|
||||
#pragma optimize("", off)
|
||||
void CompressedLineNumberWriteStream::write_pair(int bci, int line) {
|
||||
write_pair_inline(bci, line);
|
||||
}
|
||||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
CompressedLineNumberReadStream::CompressedLineNumberReadStream(u_char* buffer) : CompressedReadStream(buffer) {
|
||||
_bci = 0;
|
||||
_line = 0;
|
||||
};
|
||||
|
||||
|
||||
bool CompressedLineNumberReadStream::read_pair() {
|
||||
jubyte next = read_byte();
|
||||
// Check for terminator
|
||||
|
@ -1022,36 +1022,12 @@ class CompressedLineNumberWriteStream: public CompressedWriteStream {
|
||||
// Write (bci, line number) pair to stream
|
||||
void write_pair_regular(int bci_delta, int line_delta);
|
||||
|
||||
inline void write_pair_inline(int bci, int line) {
|
||||
int bci_delta = bci - _bci;
|
||||
int line_delta = line - _line;
|
||||
_bci = bci;
|
||||
_line = line;
|
||||
// Skip (0,0) deltas - they do not add information and conflict with terminator.
|
||||
if (bci_delta == 0 && line_delta == 0) return;
|
||||
// Check if bci is 5-bit and line number 3-bit unsigned.
|
||||
if (((bci_delta & ~0x1F) == 0) && ((line_delta & ~0x7) == 0)) {
|
||||
// Compress into single byte.
|
||||
jubyte value = ((jubyte) bci_delta << 3) | (jubyte) line_delta;
|
||||
// Check that value doesn't match escape character.
|
||||
if (value != 0xFF) {
|
||||
write_byte(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
write_pair_regular(bci_delta, line_delta);
|
||||
}
|
||||
// If (bci delta, line delta) fits in (5-bit unsigned, 3-bit unsigned)
|
||||
// we save it as one byte, otherwise we write a 0xFF escape character
|
||||
// and use regular compression. 0x0 is used as end-of-stream terminator.
|
||||
void write_pair_inline(int bci, int line);
|
||||
|
||||
// Windows AMD64 + Apr 2005 PSDK with /O2 generates bad code for write_pair.
|
||||
// Disabling optimization doesn't work for methods in header files
|
||||
// so we force it to call through the non-optimized version in the .cpp.
|
||||
// It's gross, but it's the only way we can ensure that all callers are
|
||||
// fixed. _MSC_VER is defined by the windows compiler
|
||||
#if defined(_M_AMD64) && _MSC_VER >= 1400
|
||||
void write_pair(int bci, int line);
|
||||
#else
|
||||
void write_pair(int bci, int line) { write_pair_inline(bci, line); }
|
||||
#endif
|
||||
|
||||
// Write end-of-stream marker
|
||||
void write_terminator() { write_byte(0); }
|
||||
|
@ -48,6 +48,39 @@ inline CompiledMethod* volatile Method::code() const {
|
||||
return OrderAccess::load_acquire(&_code);
|
||||
}
|
||||
|
||||
// Write (bci, line number) pair to stream
|
||||
inline void CompressedLineNumberWriteStream::write_pair_regular(int bci_delta, int line_delta) {
|
||||
// bci and line number does not compress into single byte.
|
||||
// Write out escape character and use regular compression for bci and line number.
|
||||
write_byte((jubyte)0xFF);
|
||||
write_signed_int(bci_delta);
|
||||
write_signed_int(line_delta);
|
||||
}
|
||||
|
||||
inline void CompressedLineNumberWriteStream::write_pair_inline(int bci, int line) {
|
||||
int bci_delta = bci - _bci;
|
||||
int line_delta = line - _line;
|
||||
_bci = bci;
|
||||
_line = line;
|
||||
// Skip (0,0) deltas - they do not add information and conflict with terminator.
|
||||
if (bci_delta == 0 && line_delta == 0) return;
|
||||
// Check if bci is 5-bit and line number 3-bit unsigned.
|
||||
if (((bci_delta & ~0x1F) == 0) && ((line_delta & ~0x7) == 0)) {
|
||||
// Compress into single byte.
|
||||
jubyte value = ((jubyte) bci_delta << 3) | (jubyte) line_delta;
|
||||
// Check that value doesn't match escape character.
|
||||
if (value != 0xFF) {
|
||||
write_byte(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
write_pair_regular(bci_delta, line_delta);
|
||||
}
|
||||
|
||||
inline void CompressedLineNumberWriteStream::write_pair(int bci, int line) {
|
||||
write_pair_inline(bci, line);
|
||||
}
|
||||
|
||||
inline bool Method::has_compiled_code() const { return code() != NULL; }
|
||||
|
||||
#endif // SHARE_OOPS_METHOD_INLINE_HPP
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "memory/metadataFactory.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/method.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/relocator.hpp"
|
||||
|
Loading…
x
Reference in New Issue
Block a user