1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
383
384 void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) {
385 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds");
386 if (c->is_bb_header(bci))
387 return;
388
389 if (TraceNewOopMapGeneration) {
390 tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci);
391 }
392 c->set_bbmark_bit(bci);
393 c->_bb_count++;
394 }
395
396
397 void GenerateOopMap::mark_bbheaders_and_count_gc_points() {
398 initialize_bb();
399
400 bool fellThrough = false; // False to get first BB marked.
401
402 // First mark all exception handlers as start of a basic-block
403 typeArrayOop excps = method()->exception_table();
404 for(int i = 0; i < excps->length(); i += 4) {
405 int handler_pc_idx = i+2;
406 bb_mark_fct(this, excps->int_at(handler_pc_idx), NULL);
407 }
408
409 // Then iterate through the code
410 BytecodeStream bcs(_method);
411 Bytecodes::Code bytecode;
412
413 while( (bytecode = bcs.next()) >= 0) {
414 int bci = bcs.bci();
415
416 if (!fellThrough)
417 bb_mark_fct(this, bci, NULL);
418
419 fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL);
420
421 /* We will also mark successors of jsr's as basic block headers. */
422 switch (bytecode) {
423 case Bytecodes::_jsr:
424 assert(!fellThrough, "should not happen");
425 bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL);
426 break;
433 if (possible_gc_point(&bcs))
434 _gc_points++;
435 }
436 }
437
438 void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) {
439 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds");
440 BasicBlock* bb = c->get_basic_block_at(bci);
441 if (bb->is_dead()) {
442 bb->mark_as_alive();
443 *data = 1; // Mark basicblock as changed
444 }
445 }
446
447
448 void GenerateOopMap::mark_reachable_code() {
449 int change = 1; // int to get function pointers to work
450
451 // Mark entry basic block as alive and all exception handlers
452 _basic_blocks[0].mark_as_alive();
453 typeArrayOop excps = method()->exception_table();
454 for(int i = 0; i < excps->length(); i += 4) {
455 int handler_pc_idx = i+2;
456 BasicBlock *bb = get_basic_block_at(excps->int_at(handler_pc_idx));
457 // If block is not already alive (due to multiple exception handlers to same bb), then
458 // make it alive
459 if (bb->is_dead()) bb->mark_as_alive();
460 }
461
462 BytecodeStream bcs(_method);
463
464 // Iterate through all basic blocks until we reach a fixpoint
465 while (change) {
466 change = 0;
467
468 for (int i = 0; i < _bb_count; i++) {
469 BasicBlock *bb = &_basic_blocks[i];
470 if (bb->is_alive()) {
471 // Position bytecodestream at last bytecode in basicblock
472 bcs.set_start(bb->_end_bci);
473 bcs.next();
474 Bytecodes::Code bytecode = bcs.code();
475 int bci = bcs.bci();
476 assert(bci == bb->_end_bci, "wrong bci");
1164 // assume an exception could be taken here.
1165 if (_monitor_top == 0) {
1166 return;
1167 }
1168 break;
1169
1170 case Bytecodes::_monitorexit:
1171 // If the monitor stack height is bad_monitors, then we have detected a
1172 // monitor matching problem earlier in the analysis. If the
1173 // monitor stack height is 0, we are about to pop a monitor
1174 // off of an empty stack. In either case, the bytecode
1175 // could throw an exception.
1176 if (_monitor_top != bad_monitors && _monitor_top != 0) {
1177 return;
1178 }
1179 break;
1180 }
1181
1182 if (_has_exceptions) {
1183 int bci = itr->bci();
1184 typeArrayOop exct = method()->exception_table();
1185 for(int i = 0; i< exct->length(); i+=4) {
1186 int start_pc = exct->int_at(i);
1187 int end_pc = exct->int_at(i+1);
1188 int handler_pc = exct->int_at(i+2);
1189 int catch_type = exct->int_at(i+3);
1190
1191 if (start_pc <= bci && bci < end_pc) {
1192 BasicBlock *excBB = get_basic_block_at(handler_pc);
1193 CellTypeState *excStk = excBB->stack();
1194 CellTypeState *cOpStck = stack();
1195 CellTypeState cOpStck_0 = cOpStck[0];
1196 int cOpStackTop = _stack_top;
1197
1198 // Exception stacks are always the same.
1199 assert(method()->max_stack() > 0, "sanity check");
1200
1201 // We remembered the size and first element of "cOpStck"
1202 // above; now we temporarily set them to the appropriate
1203 // values for an exception handler. */
1204 cOpStck[0] = CellTypeState::make_slot_ref(_max_locals);
1205 _stack_top = 1;
1206
1207 merge_state_into_bb(excBB);
1208
1209 // Now undo the temporary change.
2038 }
2039
2040 void GenerateOopMap::compute_map(TRAPS) {
2041 #ifndef PRODUCT
2042 if (TimeOopMap2) {
2043 method()->print_short_name(tty);
2044 tty->print(" ");
2045 }
2046 if (TimeOopMap) {
2047 _total_byte_count += method()->code_size();
2048 }
2049 #endif
2050 TraceTime t_single("oopmap time", TimeOopMap2);
2051 TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap);
2052
2053 // Initialize values
2054 _got_error = false;
2055 _conflict = false;
2056 _max_locals = method()->max_locals();
2057 _max_stack = method()->max_stack();
2058 _has_exceptions = (method()->exception_table()->length() > 0);
2059 _nof_refval_conflicts = 0;
2060 _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars
2061 _report_result = false;
2062 _report_result_for_send = false;
2063 _new_var_map = NULL;
2064 _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number;
2065 _did_rewriting = false;
2066 _did_relocation = false;
2067
2068 if (TraceNewOopMapGeneration) {
2069 tty->print("Method name: %s\n", method()->name()->as_C_string());
2070 if (Verbose) {
2071 _method->print_codes();
2072 tty->print_cr("Exception table:");
2073 typeArrayOop excps = method()->exception_table();
2074 for(int i = 0; i < excps->length(); i += 4) {
2075 tty->print_cr("[%d - %d] -> %d", excps->int_at(i + 0), excps->int_at(i + 1), excps->int_at(i + 2));
2076 }
2077 }
2078 }
2079
2080 // if no code - do nothing
2081 // compiler needs info
2082 if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) {
2083 fill_stackmap_prolog(0);
2084 fill_stackmap_epilog();
2085 return;
2086 }
2087 // Step 1: Compute all jump targets and their return value
2088 if (!_got_error)
2089 _rt.compute_ret_table(_method);
2090
2091 // Step 2: Find all basic blocks and count GC points
2092 if (!_got_error)
2093 mark_bbheaders_and_count_gc_points();
2094
2095 // Step 3: Calculate stack maps
|
1 /*
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
383
384 void GenerateOopMap::bb_mark_fct(GenerateOopMap *c, int bci, int *data) {
385 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds");
386 if (c->is_bb_header(bci))
387 return;
388
389 if (TraceNewOopMapGeneration) {
390 tty->print_cr("Basicblock#%d begins at: %d", c->_bb_count, bci);
391 }
392 c->set_bbmark_bit(bci);
393 c->_bb_count++;
394 }
395
396
397 void GenerateOopMap::mark_bbheaders_and_count_gc_points() {
398 initialize_bb();
399
400 bool fellThrough = false; // False to get first BB marked.
401
402 // First mark all exception handlers as start of a basic-block
403 ExceptionTable excps(method());
404 for(int i = 0; i < excps.length(); i ++) {
405 bb_mark_fct(this, excps.handler_pc(i), NULL);
406 }
407
408 // Then iterate through the code
409 BytecodeStream bcs(_method);
410 Bytecodes::Code bytecode;
411
412 while( (bytecode = bcs.next()) >= 0) {
413 int bci = bcs.bci();
414
415 if (!fellThrough)
416 bb_mark_fct(this, bci, NULL);
417
418 fellThrough = jump_targets_do(&bcs, &GenerateOopMap::bb_mark_fct, NULL);
419
420 /* We will also mark successors of jsr's as basic block headers. */
421 switch (bytecode) {
422 case Bytecodes::_jsr:
423 assert(!fellThrough, "should not happen");
424 bb_mark_fct(this, bci + Bytecodes::length_for(bytecode), NULL);
425 break;
432 if (possible_gc_point(&bcs))
433 _gc_points++;
434 }
435 }
436
437 void GenerateOopMap::reachable_basicblock(GenerateOopMap *c, int bci, int *data) {
438 assert(bci>= 0 && bci < c->method()->code_size(), "index out of bounds");
439 BasicBlock* bb = c->get_basic_block_at(bci);
440 if (bb->is_dead()) {
441 bb->mark_as_alive();
442 *data = 1; // Mark basicblock as changed
443 }
444 }
445
446
447 void GenerateOopMap::mark_reachable_code() {
448 int change = 1; // int to get function pointers to work
449
450 // Mark entry basic block as alive and all exception handlers
451 _basic_blocks[0].mark_as_alive();
452 ExceptionTable excps(method());
453 for(int i = 0; i < excps.length(); i++) {
454 BasicBlock *bb = get_basic_block_at(excps.handler_pc(i));
455 // If block is not already alive (due to multiple exception handlers to same bb), then
456 // make it alive
457 if (bb->is_dead()) bb->mark_as_alive();
458 }
459
460 BytecodeStream bcs(_method);
461
462 // Iterate through all basic blocks until we reach a fixpoint
463 while (change) {
464 change = 0;
465
466 for (int i = 0; i < _bb_count; i++) {
467 BasicBlock *bb = &_basic_blocks[i];
468 if (bb->is_alive()) {
469 // Position bytecodestream at last bytecode in basicblock
470 bcs.set_start(bb->_end_bci);
471 bcs.next();
472 Bytecodes::Code bytecode = bcs.code();
473 int bci = bcs.bci();
474 assert(bci == bb->_end_bci, "wrong bci");
1162 // assume an exception could be taken here.
1163 if (_monitor_top == 0) {
1164 return;
1165 }
1166 break;
1167
1168 case Bytecodes::_monitorexit:
1169 // If the monitor stack height is bad_monitors, then we have detected a
1170 // monitor matching problem earlier in the analysis. If the
1171 // monitor stack height is 0, we are about to pop a monitor
1172 // off of an empty stack. In either case, the bytecode
1173 // could throw an exception.
1174 if (_monitor_top != bad_monitors && _monitor_top != 0) {
1175 return;
1176 }
1177 break;
1178 }
1179
1180 if (_has_exceptions) {
1181 int bci = itr->bci();
1182 ExceptionTable exct(method());
1183 for(int i = 0; i< exct.length(); i++) {
1184 int start_pc = exct.start_pc(i);
1185 int end_pc = exct.end_pc(i);
1186 int handler_pc = exct.handler_pc(i);
1187 int catch_type = exct.catch_type_index(i);
1188
1189 if (start_pc <= bci && bci < end_pc) {
1190 BasicBlock *excBB = get_basic_block_at(handler_pc);
1191 CellTypeState *excStk = excBB->stack();
1192 CellTypeState *cOpStck = stack();
1193 CellTypeState cOpStck_0 = cOpStck[0];
1194 int cOpStackTop = _stack_top;
1195
1196 // Exception stacks are always the same.
1197 assert(method()->max_stack() > 0, "sanity check");
1198
1199 // We remembered the size and first element of "cOpStck"
1200 // above; now we temporarily set them to the appropriate
1201 // values for an exception handler. */
1202 cOpStck[0] = CellTypeState::make_slot_ref(_max_locals);
1203 _stack_top = 1;
1204
1205 merge_state_into_bb(excBB);
1206
1207 // Now undo the temporary change.
2036 }
2037
2038 void GenerateOopMap::compute_map(TRAPS) {
2039 #ifndef PRODUCT
2040 if (TimeOopMap2) {
2041 method()->print_short_name(tty);
2042 tty->print(" ");
2043 }
2044 if (TimeOopMap) {
2045 _total_byte_count += method()->code_size();
2046 }
2047 #endif
2048 TraceTime t_single("oopmap time", TimeOopMap2);
2049 TraceTime t_all(NULL, &_total_oopmap_time, TimeOopMap);
2050
2051 // Initialize values
2052 _got_error = false;
2053 _conflict = false;
2054 _max_locals = method()->max_locals();
2055 _max_stack = method()->max_stack();
2056 _has_exceptions = (method()->has_exception_handler());
2057 _nof_refval_conflicts = 0;
2058 _init_vars = new GrowableArray<intptr_t>(5); // There are seldom more than 5 init_vars
2059 _report_result = false;
2060 _report_result_for_send = false;
2061 _new_var_map = NULL;
2062 _ret_adr_tos = new GrowableArray<intptr_t>(5); // 5 seems like a good number;
2063 _did_rewriting = false;
2064 _did_relocation = false;
2065
2066 if (TraceNewOopMapGeneration) {
2067 tty->print("Method name: %s\n", method()->name()->as_C_string());
2068 if (Verbose) {
2069 _method->print_codes();
2070 tty->print_cr("Exception table:");
2071 ExceptionTable excps(method());
2072 for(int i = 0; i < excps.length(); i ++) {
2073 tty->print_cr("[%d - %d] -> %d",
2074 excps.start_pc(i), excps.end_pc(i), excps.handler_pc(i));
2075 }
2076 }
2077 }
2078
2079 // if no code - do nothing
2080 // compiler needs info
2081 if (method()->code_size() == 0 || _max_locals + method()->max_stack() == 0) {
2082 fill_stackmap_prolog(0);
2083 fill_stackmap_epilog();
2084 return;
2085 }
2086 // Step 1: Compute all jump targets and their return value
2087 if (!_got_error)
2088 _rt.compute_ret_table(_method);
2089
2090 // Step 2: Find all basic blocks and count GC points
2091 if (!_got_error)
2092 mark_bbheaders_and_count_gc_points();
2093
2094 // Step 3: Calculate stack maps
|