Mercurial > hg > graal-jvmci-8
comparison src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @ 1791:3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
Summary: Added profiling of instanceof and aastore.
Reviewed-by: kvn, jrose, never
author | iveresov |
---|---|
date | Mon, 13 Sep 2010 12:10:49 -0700 |
parents | d5d065957597 |
children | a3f7f95b0165 |
comparison
equal
deleted
inserted
replaced
1790:7f9553bedfd5 | 1791:3a294e483abc |
---|---|
2469 __ delayed()->nop(); | 2469 __ delayed()->nop(); |
2470 __ bind(next_test); | 2470 __ bind(next_test); |
2471 } | 2471 } |
2472 } | 2472 } |
2473 | 2473 |
2474 void LIR_Assembler::emit_checkcast(LIR_OpTypeCheck *op) { | 2474 |
2475 assert(op->code() == lir_checkcast, "Invalid operation"); | 2475 void LIR_Assembler::setup_md_access(ciMethod* method, int bci, |
2476 ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) { | |
2477 md = method->method_data(); | |
2478 if (md == NULL) { | |
2479 bailout("out of memory building methodDataOop"); | |
2480 return; | |
2481 } | |
2482 data = md->bci_to_data(bci); | |
2483 assert(data != NULL, "need data for checkcast"); | |
2484 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); | |
2485 if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) { | |
2486 // The offset is large so bias the mdo by the base of the slot so | |
2487 // that the ld can use simm13s to reference the slots of the data | |
2488 mdo_offset_bias = md->byte_offset_of_slot(data, DataLayout::header_offset()); | |
2489 } | |
2490 } | |
2491 | |
2492 void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { | |
2476 // we always need a stub for the failure case. | 2493 // we always need a stub for the failure case. |
2477 CodeStub* stub = op->stub(); | 2494 CodeStub* stub = op->stub(); |
2478 Register obj = op->object()->as_register(); | 2495 Register obj = op->object()->as_register(); |
2479 Register k_RInfo = op->tmp1()->as_register(); | 2496 Register k_RInfo = op->tmp1()->as_register(); |
2480 Register klass_RInfo = op->tmp2()->as_register(); | 2497 Register klass_RInfo = op->tmp2()->as_register(); |
2492 ciProfileData* data; | 2509 ciProfileData* data; |
2493 int mdo_offset_bias = 0; | 2510 int mdo_offset_bias = 0; |
2494 if (op->should_profile()) { | 2511 if (op->should_profile()) { |
2495 ciMethod* method = op->profiled_method(); | 2512 ciMethod* method = op->profiled_method(); |
2496 assert(method != NULL, "Should have method"); | 2513 assert(method != NULL, "Should have method"); |
2497 int bci = op->profiled_bci(); | 2514 setup_md_access(method, op->profiled_bci(), md, data, mdo_offset_bias); |
2498 md = method->method_data(); | 2515 |
2499 if (md == NULL) { | 2516 Label not_null; |
2500 bailout("out of memory building methodDataOop"); | 2517 __ br_notnull(obj, false, Assembler::pn, not_null); |
2501 return; | |
2502 } | |
2503 data = md->bci_to_data(bci); | |
2504 assert(data != NULL, "need data for checkcast"); | |
2505 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for checkcast"); | |
2506 if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) { | |
2507 // The offset is large so bias the mdo by the base of the slot so | |
2508 // that the ld can use simm13s to reference the slots of the data | |
2509 mdo_offset_bias = md->byte_offset_of_slot(data, DataLayout::header_offset()); | |
2510 } | |
2511 | |
2512 // We need two temporaries to perform this operation on SPARC, | |
2513 // so to keep things simple we perform a redundant test here | |
2514 Label profile_done; | |
2515 __ br_notnull(obj, false, Assembler::pn, profile_done); | |
2516 __ delayed()->nop(); | 2518 __ delayed()->nop(); |
2517 Register mdo = k_RInfo; | 2519 Register mdo = k_RInfo; |
2518 Register data_val = Rtmp1; | 2520 Register data_val = Rtmp1; |
2519 jobject2reg(md->constant_encoding(), mdo); | 2521 jobject2reg(md->constant_encoding(), mdo); |
2520 if (mdo_offset_bias > 0) { | 2522 if (mdo_offset_bias > 0) { |
2523 } | 2525 } |
2524 Address flags_addr(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias); | 2526 Address flags_addr(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias); |
2525 __ ldub(flags_addr, data_val); | 2527 __ ldub(flags_addr, data_val); |
2526 __ or3(data_val, BitData::null_seen_byte_constant(), data_val); | 2528 __ or3(data_val, BitData::null_seen_byte_constant(), data_val); |
2527 __ stb(data_val, flags_addr); | 2529 __ stb(data_val, flags_addr); |
2528 __ bind(profile_done); | 2530 __ ba(false, *obj_is_null); |
2529 } | 2531 __ delayed()->nop(); |
2530 Label profile_cast_failure; | 2532 __ bind(not_null); |
2531 | 2533 } else { |
2532 Label done, done_null; | 2534 __ br_null(obj, false, Assembler::pn, *obj_is_null); |
2533 // Where to go in case of cast failure | 2535 __ delayed()->nop(); |
2534 Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); | 2536 } |
2537 | |
2538 Label profile_cast_failure, profile_cast_success; | |
2539 Label *failure_target = op->should_profile() ? &profile_cast_failure : failure; | |
2540 Label *success_target = op->should_profile() ? &profile_cast_success : success; | |
2535 | 2541 |
2536 // patching may screw with our temporaries on sparc, | 2542 // patching may screw with our temporaries on sparc, |
2537 // so let's do it before loading the class | 2543 // so let's do it before loading the class |
2538 if (k->is_loaded()) { | 2544 if (k->is_loaded()) { |
2539 jobject2reg(k->constant_encoding(), k_RInfo); | 2545 jobject2reg(k->constant_encoding(), k_RInfo); |
2540 } else { | 2546 } else { |
2541 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); | 2547 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); |
2542 } | 2548 } |
2543 assert(obj != k_RInfo, "must be different"); | 2549 assert(obj != k_RInfo, "must be different"); |
2544 __ br_null(obj, false, Assembler::pn, done_null); | |
2545 __ delayed()->nop(); | |
2546 | 2550 |
2547 // get object class | 2551 // get object class |
2548 // not a safepoint as obj null check happens earlier | 2552 // not a safepoint as obj null check happens earlier |
2549 load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); | 2553 load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); |
2550 if (op->fast_check()) { | 2554 if (op->fast_check()) { |
2557 if (k->is_loaded()) { | 2561 if (k->is_loaded()) { |
2558 if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()) | 2562 if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()) |
2559 need_slow_path = false; | 2563 need_slow_path = false; |
2560 // perform the fast part of the checking logic | 2564 // perform the fast part of the checking logic |
2561 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg, | 2565 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, noreg, |
2562 (need_slow_path ? &done : NULL), | 2566 (need_slow_path ? success_target : NULL), |
2563 failure_target, NULL, | 2567 failure_target, NULL, |
2564 RegisterOrConstant(k->super_check_offset())); | 2568 RegisterOrConstant(k->super_check_offset())); |
2565 } else { | 2569 } else { |
2566 // perform the fast part of the checking logic | 2570 // perform the fast part of the checking logic |
2567 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, &done, | 2571 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, |
2568 failure_target, NULL); | 2572 failure_target, NULL); |
2569 } | 2573 } |
2570 if (need_slow_path) { | 2574 if (need_slow_path) { |
2571 // call out-of-line instance of __ check_klass_subtype_slow_path(...): | 2575 // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
2572 assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); | 2576 assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); |
2573 __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); | 2577 __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); |
2574 __ delayed()->nop(); | 2578 __ delayed()->nop(); |
2575 __ cmp(G3, 0); | 2579 __ cmp(G3, 0); |
2576 __ br(Assembler::equal, false, Assembler::pn, *failure_target); | 2580 __ br(Assembler::equal, false, Assembler::pn, *failure_target); |
2577 __ delayed()->nop(); | 2581 __ delayed()->nop(); |
2578 } | 2582 // Fall through to success case |
2579 } | 2583 } |
2580 __ bind(done); | 2584 } |
2581 | 2585 |
2582 if (op->should_profile()) { | 2586 if (op->should_profile()) { |
2583 Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtmp1; | 2587 Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtmp1; |
2584 assert_different_registers(obj, mdo, recv, tmp1); | 2588 assert_different_registers(obj, mdo, recv, tmp1); |
2585 | 2589 __ bind(profile_cast_success); |
2586 jobject2reg(md->constant_encoding(), mdo); | 2590 jobject2reg(md->constant_encoding(), mdo); |
2587 if (mdo_offset_bias > 0) { | 2591 if (mdo_offset_bias > 0) { |
2588 __ set(mdo_offset_bias, tmp1); | 2592 __ set(mdo_offset_bias, tmp1); |
2589 __ add(mdo, tmp1, mdo); | 2593 __ add(mdo, tmp1, mdo); |
2590 } | 2594 } |
2591 Label update_done; | |
2592 load(Address(obj, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); | 2595 load(Address(obj, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); |
2593 type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &update_done); | 2596 type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, success); |
2594 // Jump over the failure case | 2597 // Jump over the failure case |
2595 __ ba(false, update_done); | 2598 __ ba(false, *success); |
2596 __ delayed()->nop(); | 2599 __ delayed()->nop(); |
2597 | |
2598 | |
2599 // Cast failure case | 2600 // Cast failure case |
2600 __ bind(profile_cast_failure); | 2601 __ bind(profile_cast_failure); |
2601 jobject2reg(md->constant_encoding(), mdo); | 2602 jobject2reg(md->constant_encoding(), mdo); |
2602 if (mdo_offset_bias > 0) { | 2603 if (mdo_offset_bias > 0) { |
2603 __ set(mdo_offset_bias, tmp1); | 2604 __ set(mdo_offset_bias, tmp1); |
2605 } | 2606 } |
2606 Address data_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias); | 2607 Address data_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias); |
2607 __ ld_ptr(data_addr, tmp1); | 2608 __ ld_ptr(data_addr, tmp1); |
2608 __ sub(tmp1, DataLayout::counter_increment, tmp1); | 2609 __ sub(tmp1, DataLayout::counter_increment, tmp1); |
2609 __ st_ptr(tmp1, data_addr); | 2610 __ st_ptr(tmp1, data_addr); |
2610 __ ba(false, *stub->entry()); | 2611 __ ba(false, *failure); |
2611 __ delayed()->nop(); | 2612 __ delayed()->nop(); |
2612 | 2613 } |
2613 __ bind(update_done); | 2614 __ ba(false, *success); |
2614 } | 2615 __ delayed()->nop(); |
2615 | 2616 } |
2616 __ bind(done_null); | |
2617 __ mov(obj, dst); | |
2618 } | |
2619 | |
2620 | 2617 |
2621 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { | 2618 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { |
2622 LIR_Code code = op->code(); | 2619 LIR_Code code = op->code(); |
2623 if (code == lir_store_check) { | 2620 if (code == lir_store_check) { |
2624 Register value = op->object()->as_register(); | 2621 Register value = op->object()->as_register(); |
2626 Register k_RInfo = op->tmp1()->as_register(); | 2623 Register k_RInfo = op->tmp1()->as_register(); |
2627 Register klass_RInfo = op->tmp2()->as_register(); | 2624 Register klass_RInfo = op->tmp2()->as_register(); |
2628 Register Rtmp1 = op->tmp3()->as_register(); | 2625 Register Rtmp1 = op->tmp3()->as_register(); |
2629 | 2626 |
2630 __ verify_oop(value); | 2627 __ verify_oop(value); |
2631 | |
2632 CodeStub* stub = op->stub(); | 2628 CodeStub* stub = op->stub(); |
2633 Label done; | 2629 // check if it needs to be profiled |
2634 __ br_null(value, false, Assembler::pn, done); | 2630 ciMethodData* md; |
2635 __ delayed()->nop(); | 2631 ciProfileData* data; |
2632 int mdo_offset_bias = 0; | |
2633 if (op->should_profile()) { | |
2634 ciMethod* method = op->profiled_method(); | |
2635 assert(method != NULL, "Should have method"); | |
2636 setup_md_access(method, op->profiled_bci(), md, data, mdo_offset_bias); | |
2637 } | |
2638 Label profile_cast_success, profile_cast_failure, done; | |
2639 Label *success_target = op->should_profile() ? &profile_cast_success : &done; | |
2640 Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); | |
2641 | |
2642 if (op->should_profile()) { | |
2643 Label not_null; | |
2644 __ br_notnull(value, false, Assembler::pn, not_null); | |
2645 __ delayed()->nop(); | |
2646 Register mdo = k_RInfo; | |
2647 Register data_val = Rtmp1; | |
2648 jobject2reg(md->constant_encoding(), mdo); | |
2649 if (mdo_offset_bias > 0) { | |
2650 __ set(mdo_offset_bias, data_val); | |
2651 __ add(mdo, data_val, mdo); | |
2652 } | |
2653 Address flags_addr(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias); | |
2654 __ ldub(flags_addr, data_val); | |
2655 __ or3(data_val, BitData::null_seen_byte_constant(), data_val); | |
2656 __ stb(data_val, flags_addr); | |
2657 __ ba(false, done); | |
2658 __ delayed()->nop(); | |
2659 __ bind(not_null); | |
2660 } else { | |
2661 __ br_null(value, false, Assembler::pn, done); | |
2662 __ delayed()->nop(); | |
2663 } | |
2636 load(array, oopDesc::klass_offset_in_bytes(), k_RInfo, T_OBJECT, op->info_for_exception()); | 2664 load(array, oopDesc::klass_offset_in_bytes(), k_RInfo, T_OBJECT, op->info_for_exception()); |
2637 load(value, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); | 2665 load(value, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); |
2638 | 2666 |
2639 // get instance klass | 2667 // get instance klass |
2640 load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL); | 2668 load(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc), k_RInfo, T_OBJECT, NULL); |
2641 // perform the fast part of the checking logic | 2669 // perform the fast part of the checking logic |
2642 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, &done, stub->entry(), NULL); | 2670 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, O7, success_target, failure_target, NULL); |
2643 | 2671 |
2644 // call out-of-line instance of __ check_klass_subtype_slow_path(...): | 2672 // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
2645 assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); | 2673 assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); |
2646 __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); | 2674 __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); |
2647 __ delayed()->nop(); | 2675 __ delayed()->nop(); |
2648 __ cmp(G3, 0); | 2676 __ cmp(G3, 0); |
2649 __ br(Assembler::equal, false, Assembler::pn, *stub->entry()); | 2677 __ br(Assembler::equal, false, Assembler::pn, *failure_target); |
2650 __ delayed()->nop(); | 2678 __ delayed()->nop(); |
2679 // fall through to the success case | |
2680 | |
2681 if (op->should_profile()) { | |
2682 Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtmp1; | |
2683 assert_different_registers(value, mdo, recv, tmp1); | |
2684 __ bind(profile_cast_success); | |
2685 jobject2reg(md->constant_encoding(), mdo); | |
2686 if (mdo_offset_bias > 0) { | |
2687 __ set(mdo_offset_bias, tmp1); | |
2688 __ add(mdo, tmp1, mdo); | |
2689 } | |
2690 load(Address(value, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT); | |
2691 type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &done); | |
2692 __ ba(false, done); | |
2693 __ delayed()->nop(); | |
2694 // Cast failure case | |
2695 __ bind(profile_cast_failure); | |
2696 jobject2reg(md->constant_encoding(), mdo); | |
2697 if (mdo_offset_bias > 0) { | |
2698 __ set(mdo_offset_bias, tmp1); | |
2699 __ add(mdo, tmp1, mdo); | |
2700 } | |
2701 Address data_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias); | |
2702 __ ld_ptr(data_addr, tmp1); | |
2703 __ sub(tmp1, DataLayout::counter_increment, tmp1); | |
2704 __ st_ptr(tmp1, data_addr); | |
2705 __ ba(false, *stub->entry()); | |
2706 __ delayed()->nop(); | |
2707 } | |
2651 __ bind(done); | 2708 __ bind(done); |
2709 } else if (code == lir_checkcast) { | |
2710 Register obj = op->object()->as_register(); | |
2711 Register dst = op->result_opr()->as_register(); | |
2712 Label success; | |
2713 emit_typecheck_helper(op, &success, op->stub()->entry(), &success); | |
2714 __ bind(success); | |
2715 __ mov(obj, dst); | |
2652 } else if (code == lir_instanceof) { | 2716 } else if (code == lir_instanceof) { |
2653 Register obj = op->object()->as_register(); | 2717 Register obj = op->object()->as_register(); |
2654 Register k_RInfo = op->tmp1()->as_register(); | |
2655 Register klass_RInfo = op->tmp2()->as_register(); | |
2656 Register dst = op->result_opr()->as_register(); | 2718 Register dst = op->result_opr()->as_register(); |
2657 Register Rtmp1 = op->tmp3()->as_register(); | 2719 Label success, failure, done; |
2658 ciKlass* k = op->klass(); | 2720 emit_typecheck_helper(op, &success, &failure, &failure); |
2659 | 2721 __ bind(failure); |
2660 Label done; | 2722 __ set(0, dst); |
2661 if (obj == k_RInfo) { | 2723 __ ba(false, done); |
2662 k_RInfo = klass_RInfo; | 2724 __ delayed()->nop(); |
2663 klass_RInfo = obj; | 2725 __ bind(success); |
2664 } | 2726 __ set(1, dst); |
2665 // patching may screw with our temporaries on sparc, | 2727 __ bind(done); |
2666 // so let's do it before loading the class | |
2667 if (k->is_loaded()) { | |
2668 jobject2reg(k->constant_encoding(), k_RInfo); | |
2669 } else { | |
2670 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); | |
2671 } | |
2672 assert(obj != k_RInfo, "must be different"); | |
2673 __ br_null(obj, true, Assembler::pn, done); | |
2674 __ delayed()->set(0, dst); | |
2675 | |
2676 // get object class | |
2677 // not a safepoint as obj null check happens earlier | |
2678 load(obj, oopDesc::klass_offset_in_bytes(), klass_RInfo, T_OBJECT, NULL); | |
2679 if (op->fast_check()) { | |
2680 __ cmp(k_RInfo, klass_RInfo); | |
2681 __ brx(Assembler::equal, true, Assembler::pt, done); | |
2682 __ delayed()->set(1, dst); | |
2683 __ set(0, dst); | |
2684 __ bind(done); | |
2685 } else { | |
2686 bool need_slow_path = true; | |
2687 if (k->is_loaded()) { | |
2688 if (k->super_check_offset() != sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()) | |
2689 need_slow_path = false; | |
2690 // perform the fast part of the checking logic | |
2691 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, noreg, | |
2692 (need_slow_path ? &done : NULL), | |
2693 (need_slow_path ? &done : NULL), NULL, | |
2694 RegisterOrConstant(k->super_check_offset()), | |
2695 dst); | |
2696 } else { | |
2697 assert(dst != klass_RInfo && dst != k_RInfo, "need 3 registers"); | |
2698 // perform the fast part of the checking logic | |
2699 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, O7, dst, | |
2700 &done, &done, NULL, | |
2701 RegisterOrConstant(-1), | |
2702 dst); | |
2703 } | |
2704 if (need_slow_path) { | |
2705 // call out-of-line instance of __ check_klass_subtype_slow_path(...): | |
2706 assert(klass_RInfo == G3 && k_RInfo == G1, "incorrect call setup"); | |
2707 __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); | |
2708 __ delayed()->nop(); | |
2709 __ mov(G3, dst); | |
2710 } | |
2711 __ bind(done); | |
2712 } | |
2713 } else { | 2728 } else { |
2714 ShouldNotReachHere(); | 2729 ShouldNotReachHere(); |
2715 } | 2730 } |
2716 | 2731 |
2717 } | 2732 } |