Skip to content

Commit f117f25

Browse files
author
Daniel Kroening
authored
Merge pull request #4670 from diffblue/sort_bytecode_info
sort bytecode_info table by bytecode
2 parents 4e29f7e + b149012 commit f117f25

9 files changed

+278
-254
lines changed

jbmc/src/java_bytecode/bytecode_info.cpp

Lines changed: 208 additions & 154 deletions
Large diffs are not rendered by default.

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -590,18 +590,6 @@ void java_bytecode_convert_methodt::convert(
590590
to_java_class_type(class_symbol.type).lambda_method_handles());
591591
}
592592

593-
const bytecode_infot &java_bytecode_convert_methodt::get_bytecode_info(
594-
const irep_idt &statement)
595-
{
596-
for(const bytecode_infot *p=bytecode_info; p->mnemonic!=nullptr; p++)
597-
if(statement==p->mnemonic)
598-
return *p;
599-
600-
error() << "failed to find bytecode mnemonic `"
601-
<< statement << '\'' << eom;
602-
throw 0;
603-
}
604-
605593
static irep_idt get_if_cmp_operator(const irep_idt &stmt)
606594
{
607595
if(stmt==patternt("if_?cmplt"))
@@ -1007,64 +995,69 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
1007995
// a new maximal key
1008996
assert(a_entry.first==--address_map.end());
1009997

998+
const std::string statement = bytecode_info[i_it->bytecode].mnemonic;
999+
10101000
// clang-format off
1011-
if(i_it->statement != "goto" &&
1012-
i_it->statement != "return" &&
1013-
i_it->statement != patternt("?return") &&
1014-
i_it->statement != "athrow" &&
1015-
i_it->statement != "jsr" &&
1016-
i_it->statement != "jsr_w" &&
1017-
i_it->statement != "ret")
1001+
if(statement != "goto" &&
1002+
statement != "return" &&
1003+
statement != patternt("?return") &&
1004+
statement != "athrow" &&
1005+
statement != "jsr" &&
1006+
statement != "jsr_w" &&
1007+
statement != "ret")
10181008
{
10191009
// clang-format on
10201010
instructionst::const_iterator next=i_it;
10211011
if(++next!=instructions.end())
10221012
a_entry.first->second.successors.push_back(next->address);
10231013
}
10241014

1025-
if(i_it->statement=="athrow" ||
1026-
i_it->statement=="putfield" ||
1027-
i_it->statement=="getfield" ||
1028-
i_it->statement=="checkcast" ||
1029-
i_it->statement=="newarray" ||
1030-
i_it->statement=="anewarray" ||
1031-
i_it->statement=="idiv" ||
1032-
i_it->statement=="ldiv" ||
1033-
i_it->statement=="irem" ||
1034-
i_it->statement=="lrem" ||
1035-
i_it->statement==patternt("?astore") ||
1036-
i_it->statement==patternt("?aload") ||
1037-
i_it->statement=="invokestatic" ||
1038-
i_it->statement=="invokevirtual" ||
1039-
i_it->statement=="invokespecial" ||
1040-
i_it->statement=="invokeinterface" ||
1041-
(threading_support && (i_it->statement=="monitorenter" ||
1042-
i_it->statement=="monitorexit")))
1015+
// clang-format off
1016+
if(statement == "athrow" ||
1017+
statement == "putfield" ||
1018+
statement == "getfield" ||
1019+
statement == "checkcast" ||
1020+
statement == "newarray" ||
1021+
statement == "anewarray" ||
1022+
statement == "idiv" ||
1023+
statement == "ldiv" ||
1024+
statement == "irem" ||
1025+
statement == "lrem" ||
1026+
statement == patternt("?astore") ||
1027+
statement == patternt("?aload") ||
1028+
statement == "invokestatic" ||
1029+
statement == "invokevirtual" ||
1030+
statement == "invokespecial" ||
1031+
statement == "invokeinterface" ||
1032+
(threading_support &&
1033+
(statement == "monitorenter" || statement == "monitorexit")))
10431034
{
1035+
// clang-format on
10441036
const std::vector<method_offsett> handler =
10451037
try_catch_handler(i_it->address, method.exception_table);
10461038
std::list<method_offsett> &successors = a_entry.first->second.successors;
10471039
successors.insert(successors.end(), handler.begin(), handler.end());
10481040
targets.insert(handler.begin(), handler.end());
10491041
}
10501042

1051-
if(i_it->statement=="goto" ||
1052-
i_it->statement==patternt("if_?cmp??") ||
1053-
i_it->statement==patternt("if??") ||
1054-
i_it->statement=="ifnonnull" ||
1055-
i_it->statement=="ifnull" ||
1056-
i_it->statement=="jsr" ||
1057-
i_it->statement=="jsr_w")
1043+
// clang-format off
1044+
if(statement == "goto" ||
1045+
statement == patternt("if_?cmp??") ||
1046+
statement == patternt("if??") ||
1047+
statement == "ifnonnull" ||
1048+
statement == "ifnull" ||
1049+
statement == "jsr" ||
1050+
statement == "jsr_w")
10581051
{
1052+
// clang-format on
10591053
PRECONDITION(!i_it->args.empty());
10601054

10611055
auto target = numeric_cast_v<unsigned>(to_constant_expr(i_it->args[0]));
10621056
targets.insert(target);
10631057

10641058
a_entry.first->second.successors.push_back(target);
10651059

1066-
if(i_it->statement=="jsr" ||
1067-
i_it->statement=="jsr_w")
1060+
if(statement == "jsr" || statement == "jsr_w")
10681061
{
10691062
auto next = std::next(i_it);
10701063
DATA_INVARIANT(
@@ -1073,8 +1066,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10731066
jsr_ret_targets.push_back(next->address);
10741067
}
10751068
}
1076-
else if(i_it->statement=="tableswitch" ||
1077-
i_it->statement=="lookupswitch")
1069+
else if(statement == "tableswitch" || statement == "lookupswitch")
10781070
{
10791071
bool is_label=true;
10801072
for(const auto &arg : i_it->args)
@@ -1088,7 +1080,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10881080
is_label=!is_label;
10891081
}
10901082
}
1091-
else if(i_it->statement=="ret")
1083+
else if(statement == "ret")
10921084
{
10931085
// Finish these later, once we've seen all jsr instructions.
10941086
ret_instructions.push_back(i_it);
@@ -1144,11 +1136,11 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
11441136
stack.empty() || instruction.predecessors.size() <= 1 ||
11451137
has_prefix(stack.front().get_string(ID_C_base_name), "$stack"));
11461138

1147-
irep_idt statement=i_it->statement;
11481139
exprt arg0=i_it->args.size()>=1?i_it->args[0]:nil_exprt();
11491140
exprt arg1=i_it->args.size()>=2?i_it->args[1]:nil_exprt();
11501141

1151-
const bytecode_infot &stmt_bytecode_info = get_bytecode_info(statement);
1142+
const bytecode_infot &stmt_bytecode_info = bytecode_info[i_it->bytecode];
1143+
std::string statement = stmt_bytecode_info.mnemonic;
11521144

11531145
// deal with _idx suffixes
11541146
if(statement.size()>=2 &&

jbmc/src/java_bytecode/java_bytecode_convert_method_class.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,6 @@ class java_bytecode_convert_methodt:public messaget
304304
const methodt &,
305305
const java_class_typet::java_lambda_method_handlest &);
306306

307-
const bytecode_infot &get_bytecode_info(const irep_idt &statement);
308-
309307
codet get_clinit_call(const irep_idt &classname);
310308

311309
bool is_method_inherited(

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,9 @@ static void infer_opaque_type_fields(
316316
for(const java_bytecode_parse_treet::instructiont &instruction :
317317
method.instructions)
318318
{
319-
if(instruction.statement == "getfield" ||
320-
instruction.statement == "putfield")
319+
const std::string statement =
320+
bytecode_info[instruction.bytecode].mnemonic;
321+
if(statement == "getfield" || statement == "putfield")
321322
{
322323
const fieldref_exprt &fieldref =
323324
expr_dynamic_cast<fieldref_exprt>(instruction.args[0]);
@@ -461,11 +462,15 @@ static void generate_constant_global_variables(
461462
{
462463
// ldc* instructions are Java bytecode "load constant" ops, which can
463464
// retrieve a numeric constant, String literal, or Class literal.
464-
if(instruction.statement == "ldc" ||
465-
instruction.statement == "ldc2" ||
466-
instruction.statement == "ldc_w" ||
467-
instruction.statement == "ldc2_w")
465+
const std::string statement =
466+
bytecode_info[instruction.bytecode].mnemonic;
467+
// clang-format off
468+
if(statement == "ldc" ||
469+
statement == "ldc2" ||
470+
statement == "ldc_w" ||
471+
statement == "ldc2_w")
468472
{
473+
// clang-format on
469474
INVARIANT(
470475
instruction.args.size() != 0,
471476
"ldc instructions should have an argument");
@@ -589,8 +594,9 @@ static void create_stub_global_symbols(
589594
for(const java_bytecode_parse_treet::instructiont &instruction :
590595
method.instructions)
591596
{
592-
if(instruction.statement == "getstatic" ||
593-
instruction.statement == "putstatic")
597+
const std::string statement =
598+
bytecode_info[instruction.bytecode].mnemonic;
599+
if(statement == "getstatic" || statement == "putstatic")
594600
{
595601
INVARIANT(
596602
instruction.args.size() > 0,

jbmc/src/java_bytecode/java_bytecode_parse_tree.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ void java_bytecode_parse_treet::methodt::output(std::ostream &out) const
161161
out << " // " << i.source_location << '\n';
162162

163163
out << " " << i.address << ": ";
164-
out << i.statement;
164+
out << bytecode_info[i.bytecode].mnemonic;
165165

166166
bool first = true;
167167
for(const auto &arg : i.args)

jbmc/src/java_bytecode/java_bytecode_parse_tree.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ struct java_bytecode_parse_treet
5656
{
5757
source_locationt source_location;
5858
unsigned address;
59-
irep_idt statement;
59+
u8 bytecode;
6060
typedef std::vector<exprt> argst;
6161
argst args;
6262
};

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class java_bytecode_parsert:public parsert
3636
explicit java_bytecode_parsert(bool skip_instructions)
3737
: skip_instructions(skip_instructions)
3838
{
39-
populate_bytecode_mnemonics_table();
4039
}
4140

4241
virtual bool parse();
@@ -72,14 +71,6 @@ class java_bytecode_parsert:public parsert
7271
constant_poolt constant_pool;
7372

7473
protected:
75-
class bytecodet
76-
{
77-
public:
78-
irep_idt mnemonic;
79-
char format;
80-
};
81-
82-
std::vector<bytecodet> bytecodes;
8374
const bool skip_instructions = false;
8475

8576
pool_entryt &pool_entry(u2 index)
@@ -104,23 +95,6 @@ class java_bytecode_parsert:public parsert
10495
return *java_type_from_string(id2string(pool_entry(index).s));
10596
}
10697

107-
void populate_bytecode_mnemonics_table()
108-
{
109-
// This is only useful for rbytecodes, which in turn is only useful to
110-
// parse method instructions.
111-
if(skip_instructions)
112-
return;
113-
114-
// pre-hash the mnemonics, so we do this only once
115-
bytecodes.resize(256);
116-
for(const bytecode_infot *p=bytecode_info; p->mnemonic!=nullptr; p++)
117-
{
118-
assert(p->opcode<bytecodes.size());
119-
bytecodes[p->opcode].mnemonic=p->mnemonic;
120-
bytecodes[p->opcode].format=p->format;
121-
}
122-
}
123-
12498
void rClassFile();
12599
void rconstant_pool();
126100
void rinterfaces(classt &parsed_class);
@@ -954,9 +928,6 @@ void java_bytecode_parsert::rfields(classt &parsed_class)
954928
void java_bytecode_parsert::rbytecode(
955929
methodt::instructionst &instructions)
956930
{
957-
INVARIANT(
958-
bytecodes.size() == 256, "bytecode mnemonics should have been populated");
959-
960931
u4 code_length=read_u4();
961932

962933
u4 address;
@@ -978,19 +949,20 @@ void java_bytecode_parsert::rbytecode(
978949
// [ifald]load, [ifald]store, ret and iinc
979950
// All of these have either format of v, or V
980951
INVARIANT(
981-
bytecodes[bytecode].format == 'v' || bytecodes[bytecode].format == 'V',
982-
"Unexpected wide instruction: " +
983-
id2string(bytecodes[bytecode].mnemonic));
952+
bytecode_info[bytecode].format == 'v' ||
953+
bytecode_info[bytecode].format == 'V',
954+
std::string("Unexpected wide instruction: ") +
955+
bytecode_info[bytecode].mnemonic);
984956
}
985957

986958
instructions.push_back(instructiont());
987959
instructiont &instruction=instructions.back();
988-
instruction.statement=bytecodes[bytecode].mnemonic;
960+
instruction.bytecode = bytecode;
989961
instruction.address=start_of_instruction;
990962
instruction.source_location
991963
.set_java_bytecode_index(std::to_string(bytecode_index));
992964

993-
switch(bytecodes[bytecode].format)
965+
switch(bytecode_info[bytecode].format)
994966
{
995967
case ' ': // no further bytes
996968
break;

jbmc/src/java_bytecode/java_local_variable_table.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ static bool is_store_to_slot(
184184
const java_bytecode_convert_methodt::instructiont &inst,
185185
unsigned slotidx)
186186
{
187-
const std::string prevstatement=id2string(inst.statement);
187+
const std::string prevstatement = bytecode_info[inst.bytecode].mnemonic;
188+
188189
if(!(prevstatement.size()>=1 && prevstatement.substr(1, 5)=="store"))
189190
return false;
190191

jbmc/unit/java-testing-utils/require_parse_tree.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ void require_parse_tree::require_instructions_match_expectation(
9595
void require_parse_tree::expected_instructiont::require_instructions_equal(
9696
java_bytecode_parse_treet::instructiont actual_instruction) const
9797
{
98-
REQUIRE(actual_instruction.statement == instruction_mnemoic);
99-
REQUIRE(actual_instruction.args.size() == instruction_arguments.size());
98+
REQUIRE(
99+
instruction_mnemoic == bytecode_info[actual_instruction.bytecode].mnemonic);
100+
REQUIRE(instruction_arguments.size() == actual_instruction.args.size());
100101
auto actual_arg_it = actual_instruction.args.begin();
101102
for(const exprt &expected_arg : actual_instruction.args)
102103
{

0 commit comments

Comments
 (0)