hotspot/src/share/vm/interpreter/bytecodes.cpp
// Format strings interpretation:
//
// b: bytecode
// c: signed constant, Java byte-ordering
// i: unsigned local index, Java byte-ordering (I = native byte ordering)
// j: unsigned CP cache index, Java byte-ordering (J = native byte ordering)
// k: unsigned CP index, Java byte-ordering
// o: branch offset, Java byte-ordering
// _: unused/ignored
// w: wide bytecode
//
// Note: The format strings are used for 2 purposes:
// 1. to specify the length of the bytecode
// (= number of characters in format string)
// 2. to derive bytecode format flags (_fmt_has_k, etc.)
//
// Note: For bytecodes with variable length, the format string is the empty string.
int Bytecodes::compute_flags(const char* format, int more_flags) {
{- -------------------------------------------
(1)
---------------------------------------- -}
if (format == NULL) return 0; // not even more_flags
int flags = more_flags;
const char* fp = format;
switch (*fp) {
case '\0':
flags |= _fmt_not_simple; // but variable
break;
case 'b':
flags |= _fmt_not_variable; // but simple
++fp; // skip 'b'
break;
case 'w':
flags |= _fmt_not_variable | _fmt_not_simple;
++fp; // skip 'w'
guarantee(*fp == 'b', "wide format must start with 'wb'");
++fp; // skip 'b'
break;
}
int has_nbo = 0, has_jbo = 0, has_size = 0;
for (;;) {
int this_flag = 0;
char fc = *fp++;
switch (fc) {
case '\0': // end of string
assert(flags == (jchar)flags, "change _format_flags");
return flags;
case '_': continue; // ignore these
case 'j': this_flag = _fmt_has_j; has_jbo = 1; break;
case 'k': this_flag = _fmt_has_k; has_jbo = 1; break;
case 'i': this_flag = _fmt_has_i; has_jbo = 1; break;
case 'c': this_flag = _fmt_has_c; has_jbo = 1; break;
case 'o': this_flag = _fmt_has_o; has_jbo = 1; break;
// uppercase versions mark native byte order (from Rewriter)
// actually, only the 'J' case happens currently
case 'J': this_flag = _fmt_has_j; has_nbo = 1; break;
case 'K': this_flag = _fmt_has_k; has_nbo = 1; break;
case 'I': this_flag = _fmt_has_i; has_nbo = 1; break;
case 'C': this_flag = _fmt_has_c; has_nbo = 1; break;
case 'O': this_flag = _fmt_has_o; has_nbo = 1; break;
default: guarantee(false, "bad char in format");
}
flags |= this_flag;
guarantee(!(has_jbo && has_nbo), "mixed byte orders in format");
if (has_nbo)
flags |= _fmt_has_nbo;
int this_size = 1;
if (*fp == fc) {
// advance beyond run of the same characters
this_size = 2;
while (*++fp == fc) this_size++;
switch (this_size) {
case 2: flags |= _fmt_has_u2; break;
case 4: flags |= _fmt_has_u4; break;
default: guarantee(false, "bad rep count in format");
}
}
guarantee(has_size == 0 || // no field yet
this_size == has_size || // same size
this_size < has_size && *fp == '\0', // last field can be short
"mixed field sizes in format");
has_size = this_size;
}
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.