void Value::assign_register() { if (in_register()) { return; } #if ENABLE_ARM_VFP if (stack_type() == T_FLOAT) { set_register(RegisterAllocator::allocate_float_register()); } else if (stack_type() == T_DOUBLE) { set_vfp_double_register(RegisterAllocator::allocate_double_register()); } else #endif { if (!is_two_word()) { set_register(RegisterAllocator::allocate()); } else { // NOTE: avoid doing this: set_registers(allocate(), allocate()); // The order of parameter list evaluation is undefined in C, and // on linux/i386 and solaris/sparc the orders are opposite. The following // code forces the same order, so AOT generator will generate exact // same code on both Linux and Solaris hosts. Assembler::Register hi = RegisterAllocator::allocate(); Assembler::Register low = RegisterAllocator::allocate(); set_registers(low, hi); } } }
void HeapAddress::write_barrier_prolog() { GUARANTEE(stack_type() == T_OBJECT, "write barrier should not be updated for non-object stores"); // allocate an address register for the write barrier implementation set_address_register(RegisterAllocator::allocate()); // compute the effective address and store it in the address register BinaryAssembler::Address address = compute_address_for(lo_offset()); code_generator()->leal(address_register(), address); }
void HeapAddress::write_barrier_epilog() { GUARANTEE(stack_type() == T_OBJECT, "write barrier should not be updated for non-object stores"); GUARANTEE(has_address_register(), "cannot update write barrier without proper register"); // update the bit vector code_generator()->shrl(address_register(), LogBytesPerWord); code_generator()->bts(BinaryAssembler::Address((int) _bitvector_base), address_register()); // dereference the allocated register and clear the cache RegisterAllocator::dereference(address_register()); clear_address_register(); }
RawLocation::Actions RawLocation::do_conform_to(int my_index, RawLocation* other, int other_index, RawLocation::Actions allowed_actions) { // make sure object registers and locations have object values if (other->stack_type() == T_OBJECT && stack_type() != T_OBJECT) { // Conformance code makes it so that this is no longer necessary. SHOULD_NOT_REACH_HERE(); #if NOT_CURRENTLY_USED // if we clear an cached object location there's no need to clear // any registers, since the register cache (due to type conflicts) is // guaranteed never to be used again if (other.is_flushed() || other.is_cached()) { code_generator()->clear_object_location(index()); } else { GUARANTEE(other.is_changed(), "only case left"); Value other_value(other.type()); other.read_value(other_value); Oop::Raw null_obj; code_generator()->move(other_value, &null_obj); } return; #endif } // compute the merge action const Actions required_actions = merge_actions(other); const Actions actions = required_actions & allowed_actions; // handle loads/stores from/to locations if (actions & LOC_LOAD) { other->update_cache(other_index); } if (actions & LOC_STORE) { write_changes(my_index); } // handle register stores if (actions & REG_STORE && other->in_register()) { // declare & read values for both source and destination const Value this_value (this, my_index ); const Value other_value(other, other_index); // do the register store if (!other->is_register_identical_to(my_index, this, other_index)) { code_generator()->move(other_value, this_value); } } return required_actions & ~allowed_actions; }
bool RawLocation::is_register_identical_to(int my_index, RawLocation* other, int other_index) { GUARANTEE(in_register(), "must be in register"); // if the the other location isn't in a register we're not identical if (!other->in_register()) { return false; } // make sure the types match GUARANTEE(stack_type() == other->stack_type(), "types must match"); const Value this_value (this, my_index); const Value other_value(other, other_index); return this_value.lo_register() == other_value.lo_register() && (!this_value.use_two_registers() || this_value.hi_register() == other_value.hi_register() ); }
void Value::assign_register() { if (in_register()) return; switch(stack_type()) { case T_OBJECT : // fall through case T_ARRAY : // fall through case T_INT : set_register(RegisterAllocator::allocate()); break; case T_LONG : set_registers(RegisterAllocator::allocate(), RegisterAllocator::allocate()); break; #if ENABLE_ARM_VFP case T_FLOAT : set_register(RegisterAllocator::allocate_float_register()); break; case T_DOUBLE : set_vfp_double_register(RegisterAllocator::allocate_double_register()); break; #else // !ENABLE_ARM_VFP case T_FLOAT : // fall through case T_DOUBLE : set_register(RegisterAllocator::allocate_float_register()); break; #endif // ENABLE_ARM_VFP default : SHOULD_NOT_REACH_HERE(); break; } }