< prev index next >

src/cpu/sparc/vm/macroAssembler_sparc.cpp

Print this page




2185                                              Label& L_no_such_interface) {
2186   assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
2187   assert(itable_index.is_constant() || itable_index.as_register() == method_result,
2188          "caller must use same register for non-constant itable index as for method");
2189 
2190   Label L_no_such_interface_restore;
2191   bool did_save = false;
2192   if (scan_temp == noreg || sethi_temp == noreg) {
2193     Register recv_2 = recv_klass->is_global() ? recv_klass : L0;
2194     Register intf_2 = intf_klass->is_global() ? intf_klass : L1;
2195     assert(method_result->is_global(), "must be able to return value");
2196     scan_temp  = L2;
2197     sethi_temp = L3;
2198     save_frame_and_mov(0, recv_klass, recv_2, intf_klass, intf_2);
2199     recv_klass = recv_2;
2200     intf_klass = intf_2;
2201     did_save = true;
2202   }
2203 
2204   // Compute start of first itableOffsetEntry (which is at the end of the vtable)
2205   int vtable_base = InstanceKlass::vtable_start_offset() * wordSize;
2206   int scan_step   = itableOffsetEntry::size() * wordSize;
2207   int vte_size    = vtableEntry::size() * wordSize;
2208 
2209   lduw(recv_klass, InstanceKlass::vtable_length_offset() * wordSize, scan_temp);
2210   // %%% We should store the aligned, prescaled offset in the klassoop.
2211   // Then the next several instructions would fold away.
2212 
2213   int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0);
2214   int itb_offset = vtable_base;
2215   if (round_to_unit != 0) {
2216     // hoist first instruction of round_to(scan_temp, BytesPerLong):
2217     itb_offset += round_to_unit - wordSize;
2218   }
2219   int itb_scale = exact_log2(vtableEntry::size() * wordSize);
2220   sll(scan_temp, itb_scale,  scan_temp);
2221   add(scan_temp, itb_offset, scan_temp);
2222   if (round_to_unit != 0) {
2223     // Round up to align_object_offset boundary
2224     // see code for InstanceKlass::start_of_itable!
2225     // Was: round_to(scan_temp, BytesPerLong);
2226     // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp);
2227     and3(scan_temp, -round_to_unit, scan_temp);
2228   }
2229   add(recv_klass, scan_temp, scan_temp);
2230 
2231   // Adjust recv_klass by scaled itable_index, so we can free itable_index.
2232   RegisterOrConstant itable_offset = itable_index;
2233   itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset);
2234   itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset);
2235   add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass);
2236 
2237   // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
2238   //   if (scan->interface() == intf) {
2239   //     result = (klass + scan->offset() + itable_index);


2277   if (did_save) {
2278     Label L_done;
2279     ba(L_done);
2280     delayed()->restore();
2281 
2282     bind(L_no_such_interface_restore);
2283     ba(L_no_such_interface);
2284     delayed()->restore();
2285 
2286     bind(L_done);
2287   }
2288 }
2289 
2290 
2291 // virtual method calling
2292 void MacroAssembler::lookup_virtual_method(Register recv_klass,
2293                                            RegisterOrConstant vtable_index,
2294                                            Register method_result) {
2295   assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg());
2296   Register sethi_temp = method_result;
2297   const int base = (InstanceKlass::vtable_start_offset() * wordSize +
2298                     // method pointer offset within the vtable entry:
2299                     vtableEntry::method_offset_in_bytes());
2300   RegisterOrConstant vtable_offset = vtable_index;
2301   // Each of the following three lines potentially generates an instruction.
2302   // But the total number of address formation instructions will always be
2303   // at most two, and will often be zero.  In any case, it will be optimal.
2304   // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x).
2305   // If vtable_index is a constant, we will have at most (set B+X<<N,t; ld_ptr k,t).
2306   vtable_offset = regcon_sll_ptr(vtable_index, exact_log2(vtableEntry::size() * wordSize), vtable_offset);
2307   vtable_offset = regcon_inc_ptr(vtable_offset, base, vtable_offset, sethi_temp);
2308   Address vtable_entry_addr(recv_klass, ensure_simm13_or_reg(vtable_offset, sethi_temp));
2309   ld_ptr(vtable_entry_addr, method_result);
2310 }
2311 
2312 
2313 void MacroAssembler::check_klass_subtype(Register sub_klass,
2314                                          Register super_klass,
2315                                          Register temp_reg,
2316                                          Register temp2_reg,
2317                                          Label& L_success) {
2318   Register sub_2 = sub_klass;
2319   Register sup_2 = super_klass;
2320   if (!sub_2->is_global())  sub_2 = L0;
2321   if (!sup_2->is_global())  sup_2 = L1;
2322   bool did_save = false;
2323   if (temp_reg == noreg || temp2_reg == noreg) {
2324     temp_reg = L2;
2325     temp2_reg = L3;
2326     save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2);




2185                                              Label& L_no_such_interface) {
2186   assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
2187   assert(itable_index.is_constant() || itable_index.as_register() == method_result,
2188          "caller must use same register for non-constant itable index as for method");
2189 
2190   Label L_no_such_interface_restore;
2191   bool did_save = false;
2192   if (scan_temp == noreg || sethi_temp == noreg) {
2193     Register recv_2 = recv_klass->is_global() ? recv_klass : L0;
2194     Register intf_2 = intf_klass->is_global() ? intf_klass : L1;
2195     assert(method_result->is_global(), "must be able to return value");
2196     scan_temp  = L2;
2197     sethi_temp = L3;
2198     save_frame_and_mov(0, recv_klass, recv_2, intf_klass, intf_2);
2199     recv_klass = recv_2;
2200     intf_klass = intf_2;
2201     did_save = true;
2202   }
2203 
2204   // Compute start of first itableOffsetEntry (which is at the end of the vtable)
2205   int vtable_base = in_bytes(InstanceKlass::vtable_start_offset());
2206   int scan_step   = itableOffsetEntry::size() * wordSize;
2207   int vte_size    = vtableEntry::size_in_bytes();
2208 
2209   lduw(recv_klass, in_bytes(InstanceKlass::vtable_length_offset()), scan_temp);
2210   // %%% We should store the aligned, prescaled offset in the klassoop.
2211   // Then the next several instructions would fold away.
2212 
2213   int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0);
2214   int itb_offset = vtable_base;
2215   if (round_to_unit != 0) {
2216     // hoist first instruction of round_to(scan_temp, BytesPerLong):
2217     itb_offset += round_to_unit - wordSize;
2218   }
2219   int itb_scale = exact_log2(vtableEntry::size_in_bytes());
2220   sll(scan_temp, itb_scale,  scan_temp);
2221   add(scan_temp, itb_offset, scan_temp);
2222   if (round_to_unit != 0) {
2223     // Round up to align_object_offset boundary
2224     // see code for InstanceKlass::start_of_itable!
2225     // Was: round_to(scan_temp, BytesPerLong);
2226     // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp);
2227     and3(scan_temp, -round_to_unit, scan_temp);
2228   }
2229   add(recv_klass, scan_temp, scan_temp);
2230 
2231   // Adjust recv_klass by scaled itable_index, so we can free itable_index.
2232   RegisterOrConstant itable_offset = itable_index;
2233   itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset);
2234   itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset);
2235   add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass);
2236 
2237   // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
2238   //   if (scan->interface() == intf) {
2239   //     result = (klass + scan->offset() + itable_index);


2277   if (did_save) {
2278     Label L_done;
2279     ba(L_done);
2280     delayed()->restore();
2281 
2282     bind(L_no_such_interface_restore);
2283     ba(L_no_such_interface);
2284     delayed()->restore();
2285 
2286     bind(L_done);
2287   }
2288 }
2289 
2290 
2291 // virtual method calling
2292 void MacroAssembler::lookup_virtual_method(Register recv_klass,
2293                                            RegisterOrConstant vtable_index,
2294                                            Register method_result) {
2295   assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg());
2296   Register sethi_temp = method_result;
2297   const int base = in_bytes(InstanceKlass::vtable_start_offset()) +
2298                    // method pointer offset within the vtable entry:
2299                    vtableEntry::method_offset_in_bytes();
2300   RegisterOrConstant vtable_offset = vtable_index;
2301   // Each of the following three lines potentially generates an instruction.
2302   // But the total number of address formation instructions will always be
2303   // at most two, and will often be zero.  In any case, it will be optimal.
2304   // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x).
2305   // If vtable_index is a constant, we will have at most (set B+X<<N,t; ld_ptr k,t).
2306   vtable_offset = regcon_sll_ptr(vtable_index, exact_log2(vtableEntry::size_in_bytes()), vtable_offset);
2307   vtable_offset = regcon_inc_ptr(vtable_offset, base, vtable_offset, sethi_temp);
2308   Address vtable_entry_addr(recv_klass, ensure_simm13_or_reg(vtable_offset, sethi_temp));
2309   ld_ptr(vtable_entry_addr, method_result);
2310 }
2311 
2312 
2313 void MacroAssembler::check_klass_subtype(Register sub_klass,
2314                                          Register super_klass,
2315                                          Register temp_reg,
2316                                          Register temp2_reg,
2317                                          Label& L_success) {
2318   Register sub_2 = sub_klass;
2319   Register sup_2 = super_klass;
2320   if (!sub_2->is_global())  sub_2 = L0;
2321   if (!sup_2->is_global())  sup_2 = L1;
2322   bool did_save = false;
2323   if (temp_reg == noreg || temp2_reg == noreg) {
2324     temp_reg = L2;
2325     temp2_reg = L3;
2326     save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2);


< prev index next >