Skip to content

Commit 04c83d3

Browse files
author
Daniel Kroening
committed
use bytecode_info instead of bytecode vector
The run-time generated bytecode table is replaced by bytecode_info. The linear search for the mnemonic is replaced by an array access.
1 parent 94cd0f1 commit 04c83d3

7 files changed

+48
-99
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -595,18 +595,6 @@ void java_bytecode_convert_methodt::convert(
595595
to_java_class_type(class_symbol.type).lambda_method_handles());
596596
}
597597

598-
const bytecode_infot &java_bytecode_convert_methodt::get_bytecode_info(
599-
const irep_idt &statement)
600-
{
601-
for(const bytecode_infot *p=bytecode_info; p->mnemonic!=nullptr; p++)
602-
if(statement==p->mnemonic)
603-
return *p;
604-
605-
error() << "failed to find bytecode mnemonic `"
606-
<< statement << '\'' << eom;
607-
throw 0;
608-
}
609-
610598
static irep_idt get_if_cmp_operator(const irep_idt &stmt)
611599
{
612600
if(stmt==patternt("if_?cmplt"))
@@ -1012,37 +1000,29 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10121000
// a new maximal key
10131001
assert(a_entry.first==--address_map.end());
10141002

1015-
if(i_it->statement!="goto" &&
1016-
i_it->statement!="return" &&
1017-
!(i_it->statement==patternt("?return")) &&
1018-
i_it->statement!="athrow" &&
1019-
i_it->statement!="jsr" &&
1020-
i_it->statement!="jsr_w" &&
1021-
i_it->statement!="ret")
1003+
const std::string statement = bytecode_info[i_it->bytecode].mnemonic;
1004+
1005+
if(
1006+
statement != "goto" && statement != "return" &&
1007+
!(statement == patternt("?return")) && statement != "athrow" &&
1008+
statement != "jsr" && statement != "jsr_w" && statement != "ret")
10221009
{
10231010
instructionst::const_iterator next=i_it;
10241011
if(++next!=instructions.end())
10251012
a_entry.first->second.successors.push_back(next->address);
10261013
}
10271014

1028-
if(i_it->statement=="athrow" ||
1029-
i_it->statement=="putfield" ||
1030-
i_it->statement=="getfield" ||
1031-
i_it->statement=="checkcast" ||
1032-
i_it->statement=="newarray" ||
1033-
i_it->statement=="anewarray" ||
1034-
i_it->statement=="idiv" ||
1035-
i_it->statement=="ldiv" ||
1036-
i_it->statement=="irem" ||
1037-
i_it->statement=="lrem" ||
1038-
i_it->statement==patternt("?astore") ||
1039-
i_it->statement==patternt("?aload") ||
1040-
i_it->statement=="invokestatic" ||
1041-
i_it->statement=="invokevirtual" ||
1042-
i_it->statement=="invokespecial" ||
1043-
i_it->statement=="invokeinterface" ||
1044-
(threading_support && (i_it->statement=="monitorenter" ||
1045-
i_it->statement=="monitorexit")))
1015+
if(
1016+
statement == "athrow" || statement == "putfield" ||
1017+
statement == "getfield" || statement == "checkcast" ||
1018+
statement == "newarray" || statement == "anewarray" ||
1019+
statement == "idiv" || statement == "ldiv" || statement == "irem" ||
1020+
statement == "lrem" || statement == patternt("?astore") ||
1021+
statement == patternt("?aload") || statement == "invokestatic" ||
1022+
statement == "invokevirtual" || statement == "invokespecial" ||
1023+
statement == "invokeinterface" ||
1024+
(threading_support &&
1025+
(statement == "monitorenter" || statement == "monitorexit")))
10461026
{
10471027
const std::vector<method_offsett> handler =
10481028
try_catch_handler(i_it->address, method.exception_table);
@@ -1051,13 +1031,10 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10511031
targets.insert(handler.begin(), handler.end());
10521032
}
10531033

1054-
if(i_it->statement=="goto" ||
1055-
i_it->statement==patternt("if_?cmp??") ||
1056-
i_it->statement==patternt("if??") ||
1057-
i_it->statement=="ifnonnull" ||
1058-
i_it->statement=="ifnull" ||
1059-
i_it->statement=="jsr" ||
1060-
i_it->statement=="jsr_w")
1034+
if(
1035+
statement == "goto" || statement == patternt("if_?cmp??") ||
1036+
statement == patternt("if??") || statement == "ifnonnull" ||
1037+
statement == "ifnull" || statement == "jsr" || statement == "jsr_w")
10611038
{
10621039
PRECONDITION(!i_it->args.empty());
10631040

@@ -1066,8 +1043,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10661043

10671044
a_entry.first->second.successors.push_back(target);
10681045

1069-
if(i_it->statement=="jsr" ||
1070-
i_it->statement=="jsr_w")
1046+
if(statement == "jsr" || statement == "jsr_w")
10711047
{
10721048
auto next = std::next(i_it);
10731049
DATA_INVARIANT(
@@ -1076,8 +1052,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10761052
jsr_ret_targets.push_back(next->address);
10771053
}
10781054
}
1079-
else if(i_it->statement=="tableswitch" ||
1080-
i_it->statement=="lookupswitch")
1055+
else if(statement == "tableswitch" || statement == "lookupswitch")
10811056
{
10821057
bool is_label=true;
10831058
for(const auto &arg : i_it->args)
@@ -1091,7 +1066,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
10911066
is_label=!is_label;
10921067
}
10931068
}
1094-
else if(i_it->statement=="ret")
1069+
else if(statement == "ret")
10951070
{
10961071
// Finish these later, once we've seen all jsr instructions.
10971072
ret_instructions.push_back(i_it);
@@ -1147,11 +1122,11 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
11471122
stack.empty() || instruction.predecessors.size() <= 1 ||
11481123
has_prefix(stack.front().get_string(ID_C_base_name), "$stack"));
11491124

1150-
irep_idt statement=i_it->statement;
11511125
exprt arg0=i_it->args.size()>=1?i_it->args[0]:nil_exprt();
11521126
exprt arg1=i_it->args.size()>=2?i_it->args[1]:nil_exprt();
11531127

1154-
const bytecode_infot &stmt_bytecode_info = get_bytecode_info(statement);
1128+
const bytecode_infot &stmt_bytecode_info = bytecode_info[i_it->bytecode];
1129+
std::string statement = stmt_bytecode_info.mnemonic;
11551130

11561131
// deal with _idx suffixes
11571132
if(statement.size()>=2 &&
@@ -1163,7 +1138,7 @@ code_blockt java_bytecode_convert_methodt::convert_instructions(
11631138
string2integer(
11641139
std::string(id2string(statement), statement.size()-1, 1)),
11651140
java_int_type());
1166-
statement=std::string(id2string(statement), 0, statement.size()-2);
1141+
statement = std::string(statement, 0, statement.size() - 2);
11671142
}
11681143

11691144
typet catch_type;

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: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,9 @@ static void infer_opaque_type_fields(
311311
for(const java_bytecode_parse_treet::instructiont &instruction :
312312
method.instructions)
313313
{
314-
if(instruction.statement == "getfield" ||
315-
instruction.statement == "putfield")
314+
const std::string statement =
315+
bytecode_info[instruction.bytecode].mnemonic;
316+
if(statement == "getfield" || statement == "putfield")
316317
{
317318
const fieldref_exprt &fieldref =
318319
expr_dynamic_cast<fieldref_exprt>(instruction.args[0]);
@@ -456,10 +457,11 @@ static void generate_constant_global_variables(
456457
{
457458
// ldc* instructions are Java bytecode "load constant" ops, which can
458459
// retrieve a numeric constant, String literal, or Class literal.
459-
if(instruction.statement == "ldc" ||
460-
instruction.statement == "ldc2" ||
461-
instruction.statement == "ldc_w" ||
462-
instruction.statement == "ldc2_w")
460+
const std::string statement =
461+
bytecode_info[instruction.bytecode].mnemonic;
462+
if(
463+
statement == "ldc" || statement == "ldc2" || statement == "ldc_w" ||
464+
statement == "ldc2_w")
463465
{
464466
INVARIANT(
465467
instruction.args.size() != 0,
@@ -584,8 +586,9 @@ static void create_stub_global_symbols(
584586
for(const java_bytecode_parse_treet::instructiont &instruction :
585587
method.instructions)
586588
{
587-
if(instruction.statement == "getstatic" ||
588-
instruction.statement == "putstatic")
589+
const std::string statement =
590+
bytecode_info[instruction.bytecode].mnemonic;
591+
if(statement == "getstatic" || statement == "putstatic")
589592
{
590593
INVARIANT(
591594
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

0 commit comments

Comments
 (0)