Mercurial > hg > truffle
comparison src/cpu/x86/vm/assembler_x86.cpp @ 647:bd441136a5ce
Merge
author | kvn |
---|---|
date | Thu, 19 Mar 2009 09:13:24 -0700 |
parents | 7bb995fbd3c0 c517646eef23 |
children | c89f86385056 |
comparison
equal
deleted
inserted
replaced
640:ba50942c8138 | 647:bd441136a5ce |
---|---|
725 if (which == end_pc_operand) { | 725 if (which == end_pc_operand) { |
726 return ip + tail_size; | 726 return ip + tail_size; |
727 } | 727 } |
728 | 728 |
729 #ifdef _LP64 | 729 #ifdef _LP64 |
730 assert(false, "fix locate_operand"); | 730 assert(which == narrow_oop_operand && !is_64bit, "instruction is not a movl adr, imm32"); |
731 #else | 731 #else |
732 assert(which == imm_operand, "instruction has only an imm field"); | 732 assert(which == imm_operand, "instruction has only an imm field"); |
733 #endif // LP64 | 733 #endif // LP64 |
734 return ip; | 734 return ip; |
735 } | 735 } |
2191 void Assembler::pop(Register dst) { | 2191 void Assembler::pop(Register dst) { |
2192 int encode = prefix_and_encode(dst->encoding()); | 2192 int encode = prefix_and_encode(dst->encoding()); |
2193 emit_byte(0x58 | encode); | 2193 emit_byte(0x58 | encode); |
2194 } | 2194 } |
2195 | 2195 |
2196 void Assembler::popcntl(Register dst, Address src) { | |
2197 assert(VM_Version::supports_popcnt(), "must support"); | |
2198 InstructionMark im(this); | |
2199 emit_byte(0xF3); | |
2200 prefix(src, dst); | |
2201 emit_byte(0x0F); | |
2202 emit_byte(0xB8); | |
2203 emit_operand(dst, src); | |
2204 } | |
2205 | |
2206 void Assembler::popcntl(Register dst, Register src) { | |
2207 assert(VM_Version::supports_popcnt(), "must support"); | |
2208 emit_byte(0xF3); | |
2209 int encode = prefix_and_encode(dst->encoding(), src->encoding()); | |
2210 emit_byte(0x0F); | |
2211 emit_byte(0xB8); | |
2212 emit_byte(0xC0 | encode); | |
2213 } | |
2214 | |
2196 void Assembler::popf() { | 2215 void Assembler::popf() { |
2197 emit_byte(0x9D); | 2216 emit_byte(0x9D); |
2198 } | 2217 } |
2199 | 2218 |
2200 void Assembler::popl(Address dst) { | 2219 void Assembler::popl(Address dst) { |
3222 void Assembler::fyl2x() { | 3241 void Assembler::fyl2x() { |
3223 emit_byte(0xD9); | 3242 emit_byte(0xD9); |
3224 emit_byte(0xF1); | 3243 emit_byte(0xF1); |
3225 } | 3244 } |
3226 | 3245 |
3227 void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec, int format) { | |
3228 InstructionMark im(this); | |
3229 int encode = prefix_and_encode(dst->encoding()); | |
3230 emit_byte(0xB8 | encode); | |
3231 emit_data((int)imm32, rspec, format); | |
3232 } | |
3233 | 3246 |
3234 #ifndef _LP64 | 3247 #ifndef _LP64 |
3235 | 3248 |
3236 void Assembler::incl(Register dst) { | 3249 void Assembler::incl(Register dst) { |
3237 // Don't use it directly. Use MacroAssembler::incrementl() instead. | 3250 // Don't use it directly. Use MacroAssembler::incrementl() instead. |
3247 emit_byte(0xC7); | 3260 emit_byte(0xC7); |
3248 emit_operand(rax, dst); | 3261 emit_operand(rax, dst); |
3249 emit_data((int)imm32, rspec, 0); | 3262 emit_data((int)imm32, rspec, 0); |
3250 } | 3263 } |
3251 | 3264 |
3265 void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec) { | |
3266 InstructionMark im(this); | |
3267 int encode = prefix_and_encode(dst->encoding()); | |
3268 emit_byte(0xB8 | encode); | |
3269 emit_data((int)imm32, rspec, 0); | |
3270 } | |
3252 | 3271 |
3253 void Assembler::popa() { // 32bit | 3272 void Assembler::popa() { // 32bit |
3254 emit_byte(0x61); | 3273 emit_byte(0x61); |
3255 } | 3274 } |
3256 | 3275 |
3853 void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec) { | 3872 void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec) { |
3854 InstructionMark im(this); | 3873 InstructionMark im(this); |
3855 int encode = prefixq_and_encode(dst->encoding()); | 3874 int encode = prefixq_and_encode(dst->encoding()); |
3856 emit_byte(0xB8 | encode); | 3875 emit_byte(0xB8 | encode); |
3857 emit_data64(imm64, rspec); | 3876 emit_data64(imm64, rspec); |
3877 } | |
3878 | |
3879 void Assembler::mov_narrow_oop(Register dst, int32_t imm32, RelocationHolder const& rspec) { | |
3880 InstructionMark im(this); | |
3881 int encode = prefix_and_encode(dst->encoding()); | |
3882 emit_byte(0xB8 | encode); | |
3883 emit_data((int)imm32, rspec, narrow_oop_operand); | |
3884 } | |
3885 | |
3886 void Assembler::mov_narrow_oop(Address dst, int32_t imm32, RelocationHolder const& rspec) { | |
3887 InstructionMark im(this); | |
3888 prefix(dst); | |
3889 emit_byte(0xC7); | |
3890 emit_operand(rax, dst, 4); | |
3891 emit_data((int)imm32, rspec, narrow_oop_operand); | |
3892 } | |
3893 | |
3894 void Assembler::cmp_narrow_oop(Register src1, int32_t imm32, RelocationHolder const& rspec) { | |
3895 InstructionMark im(this); | |
3896 int encode = prefix_and_encode(src1->encoding()); | |
3897 emit_byte(0x81); | |
3898 emit_byte(0xF8 | encode); | |
3899 emit_data((int)imm32, rspec, narrow_oop_operand); | |
3900 } | |
3901 | |
3902 void Assembler::cmp_narrow_oop(Address src1, int32_t imm32, RelocationHolder const& rspec) { | |
3903 InstructionMark im(this); | |
3904 prefix(src1); | |
3905 emit_byte(0x81); | |
3906 emit_operand(rax, src1, 4); | |
3907 emit_data((int)imm32, rspec, narrow_oop_operand); | |
3858 } | 3908 } |
3859 | 3909 |
3860 void Assembler::movdq(XMMRegister dst, Register src) { | 3910 void Assembler::movdq(XMMRegister dst, Register src) { |
3861 // table D-1 says MMX/SSE2 | 3911 // table D-1 says MMX/SSE2 |
3862 NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); | 3912 NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), "")); |
4045 movq(rdx, Address(rsp, 13 * wordSize)); | 4095 movq(rdx, Address(rsp, 13 * wordSize)); |
4046 movq(rcx, Address(rsp, 14 * wordSize)); | 4096 movq(rcx, Address(rsp, 14 * wordSize)); |
4047 movq(rax, Address(rsp, 15 * wordSize)); | 4097 movq(rax, Address(rsp, 15 * wordSize)); |
4048 | 4098 |
4049 addq(rsp, 16 * wordSize); | 4099 addq(rsp, 16 * wordSize); |
4100 } | |
4101 | |
4102 void Assembler::popcntq(Register dst, Address src) { | |
4103 assert(VM_Version::supports_popcnt(), "must support"); | |
4104 InstructionMark im(this); | |
4105 emit_byte(0xF3); | |
4106 prefixq(src, dst); | |
4107 emit_byte(0x0F); | |
4108 emit_byte(0xB8); | |
4109 emit_operand(dst, src); | |
4110 } | |
4111 | |
4112 void Assembler::popcntq(Register dst, Register src) { | |
4113 assert(VM_Version::supports_popcnt(), "must support"); | |
4114 emit_byte(0xF3); | |
4115 int encode = prefixq_and_encode(dst->encoding(), src->encoding()); | |
4116 emit_byte(0x0F); | |
4117 emit_byte(0xB8); | |
4118 emit_byte(0xC0 | encode); | |
4050 } | 4119 } |
4051 | 4120 |
4052 void Assembler::popq(Address dst) { | 4121 void Assembler::popq(Address dst) { |
4053 InstructionMark im(this); | 4122 InstructionMark im(this); |
4054 prefixq(dst); | 4123 prefixq(dst); |
7215 movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); | 7284 movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); |
7216 movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); | 7285 movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); |
7217 } | 7286 } |
7218 | 7287 |
7219 | 7288 |
7289 void MacroAssembler::check_klass_subtype(Register sub_klass, | |
7290 Register super_klass, | |
7291 Register temp_reg, | |
7292 Label& L_success) { | |
7293 Label L_failure; | |
7294 check_klass_subtype_fast_path(sub_klass, super_klass, temp_reg, &L_success, &L_failure, NULL); | |
7295 check_klass_subtype_slow_path(sub_klass, super_klass, temp_reg, noreg, &L_success, NULL); | |
7296 bind(L_failure); | |
7297 } | |
7298 | |
7299 | |
7300 void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, | |
7301 Register super_klass, | |
7302 Register temp_reg, | |
7303 Label* L_success, | |
7304 Label* L_failure, | |
7305 Label* L_slow_path, | |
7306 RegisterConstant super_check_offset) { | |
7307 assert_different_registers(sub_klass, super_klass, temp_reg); | |
7308 bool must_load_sco = (super_check_offset.constant_or_zero() == -1); | |
7309 if (super_check_offset.is_register()) { | |
7310 assert_different_registers(sub_klass, super_klass, | |
7311 super_check_offset.as_register()); | |
7312 } else if (must_load_sco) { | |
7313 assert(temp_reg != noreg, "supply either a temp or a register offset"); | |
7314 } | |
7315 | |
7316 Label L_fallthrough; | |
7317 int label_nulls = 0; | |
7318 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } | |
7319 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } | |
7320 if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } | |
7321 assert(label_nulls <= 1, "at most one NULL in the batch"); | |
7322 | |
7323 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + | |
7324 Klass::secondary_super_cache_offset_in_bytes()); | |
7325 int sco_offset = (klassOopDesc::header_size() * HeapWordSize + | |
7326 Klass::super_check_offset_offset_in_bytes()); | |
7327 Address super_check_offset_addr(super_klass, sco_offset); | |
7328 | |
7329 // Hacked jcc, which "knows" that L_fallthrough, at least, is in | |
7330 // range of a jccb. If this routine grows larger, reconsider at | |
7331 // least some of these. | |
7332 #define local_jcc(assembler_cond, label) \ | |
7333 if (&(label) == &L_fallthrough) jccb(assembler_cond, label); \ | |
7334 else jcc( assembler_cond, label) /*omit semi*/ | |
7335 | |
7336 // Hacked jmp, which may only be used just before L_fallthrough. | |
7337 #define final_jmp(label) \ | |
7338 if (&(label) == &L_fallthrough) { /*do nothing*/ } \ | |
7339 else jmp(label) /*omit semi*/ | |
7340 | |
7341 // If the pointers are equal, we are done (e.g., String[] elements). | |
7342 // This self-check enables sharing of secondary supertype arrays among | |
7343 // non-primary types such as array-of-interface. Otherwise, each such | |
7344 // type would need its own customized SSA. | |
7345 // We move this check to the front of the fast path because many | |
7346 // type checks are in fact trivially successful in this manner, | |
7347 // so we get a nicely predicted branch right at the start of the check. | |
7348 cmpptr(sub_klass, super_klass); | |
7349 local_jcc(Assembler::equal, *L_success); | |
7350 | |
7351 // Check the supertype display: | |
7352 if (must_load_sco) { | |
7353 // Positive movl does right thing on LP64. | |
7354 movl(temp_reg, super_check_offset_addr); | |
7355 super_check_offset = RegisterConstant(temp_reg); | |
7356 } | |
7357 Address super_check_addr(sub_klass, super_check_offset, Address::times_1, 0); | |
7358 cmpptr(super_klass, super_check_addr); // load displayed supertype | |
7359 | |
7360 // This check has worked decisively for primary supers. | |
7361 // Secondary supers are sought in the super_cache ('super_cache_addr'). | |
7362 // (Secondary supers are interfaces and very deeply nested subtypes.) | |
7363 // This works in the same check above because of a tricky aliasing | |
7364 // between the super_cache and the primary super display elements. | |
7365 // (The 'super_check_addr' can address either, as the case requires.) | |
7366 // Note that the cache is updated below if it does not help us find | |
7367 // what we need immediately. | |
7368 // So if it was a primary super, we can just fail immediately. | |
7369 // Otherwise, it's the slow path for us (no success at this point). | |
7370 | |
7371 if (super_check_offset.is_register()) { | |
7372 local_jcc(Assembler::equal, *L_success); | |
7373 cmpl(super_check_offset.as_register(), sc_offset); | |
7374 if (L_failure == &L_fallthrough) { | |
7375 local_jcc(Assembler::equal, *L_slow_path); | |
7376 } else { | |
7377 local_jcc(Assembler::notEqual, *L_failure); | |
7378 final_jmp(*L_slow_path); | |
7379 } | |
7380 } else if (super_check_offset.as_constant() == sc_offset) { | |
7381 // Need a slow path; fast failure is impossible. | |
7382 if (L_slow_path == &L_fallthrough) { | |
7383 local_jcc(Assembler::equal, *L_success); | |
7384 } else { | |
7385 local_jcc(Assembler::notEqual, *L_slow_path); | |
7386 final_jmp(*L_success); | |
7387 } | |
7388 } else { | |
7389 // No slow path; it's a fast decision. | |
7390 if (L_failure == &L_fallthrough) { | |
7391 local_jcc(Assembler::equal, *L_success); | |
7392 } else { | |
7393 local_jcc(Assembler::notEqual, *L_failure); | |
7394 final_jmp(*L_success); | |
7395 } | |
7396 } | |
7397 | |
7398 bind(L_fallthrough); | |
7399 | |
7400 #undef local_jcc | |
7401 #undef final_jmp | |
7402 } | |
7403 | |
7404 | |
7405 void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, | |
7406 Register super_klass, | |
7407 Register temp_reg, | |
7408 Register temp2_reg, | |
7409 Label* L_success, | |
7410 Label* L_failure, | |
7411 bool set_cond_codes) { | |
7412 assert_different_registers(sub_klass, super_klass, temp_reg); | |
7413 if (temp2_reg != noreg) | |
7414 assert_different_registers(sub_klass, super_klass, temp_reg, temp2_reg); | |
7415 #define IS_A_TEMP(reg) ((reg) == temp_reg || (reg) == temp2_reg) | |
7416 | |
7417 Label L_fallthrough; | |
7418 int label_nulls = 0; | |
7419 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } | |
7420 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } | |
7421 assert(label_nulls <= 1, "at most one NULL in the batch"); | |
7422 | |
7423 // a couple of useful fields in sub_klass: | |
7424 int ss_offset = (klassOopDesc::header_size() * HeapWordSize + | |
7425 Klass::secondary_supers_offset_in_bytes()); | |
7426 int sc_offset = (klassOopDesc::header_size() * HeapWordSize + | |
7427 Klass::secondary_super_cache_offset_in_bytes()); | |
7428 Address secondary_supers_addr(sub_klass, ss_offset); | |
7429 Address super_cache_addr( sub_klass, sc_offset); | |
7430 | |
7431 // Do a linear scan of the secondary super-klass chain. | |
7432 // This code is rarely used, so simplicity is a virtue here. | |
7433 // The repne_scan instruction uses fixed registers, which we must spill. | |
7434 // Don't worry too much about pre-existing connections with the input regs. | |
7435 | |
7436 assert(sub_klass != rax, "killed reg"); // killed by mov(rax, super) | |
7437 assert(sub_klass != rcx, "killed reg"); // killed by lea(rcx, &pst_counter) | |
7438 | |
7439 // Get super_klass value into rax (even if it was in rdi or rcx). | |
7440 bool pushed_rax = false, pushed_rcx = false, pushed_rdi = false; | |
7441 if (super_klass != rax || UseCompressedOops) { | |
7442 if (!IS_A_TEMP(rax)) { push(rax); pushed_rax = true; } | |
7443 mov(rax, super_klass); | |
7444 } | |
7445 if (!IS_A_TEMP(rcx)) { push(rcx); pushed_rcx = true; } | |
7446 if (!IS_A_TEMP(rdi)) { push(rdi); pushed_rdi = true; } | |
7447 | |
7448 #ifndef PRODUCT | |
7449 int* pst_counter = &SharedRuntime::_partial_subtype_ctr; | |
7450 ExternalAddress pst_counter_addr((address) pst_counter); | |
7451 NOT_LP64( incrementl(pst_counter_addr) ); | |
7452 LP64_ONLY( lea(rcx, pst_counter_addr) ); | |
7453 LP64_ONLY( incrementl(Address(rcx, 0)) ); | |
7454 #endif //PRODUCT | |
7455 | |
7456 // We will consult the secondary-super array. | |
7457 movptr(rdi, secondary_supers_addr); | |
7458 // Load the array length. (Positive movl does right thing on LP64.) | |
7459 movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); | |
7460 // Skip to start of data. | |
7461 addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); | |
7462 | |
7463 // Scan RCX words at [RDI] for an occurrence of RAX. | |
7464 // Set NZ/Z based on last compare. | |
7465 #ifdef _LP64 | |
7466 // This part is tricky, as values in supers array could be 32 or 64 bit wide | |
7467 // and we store values in objArrays always encoded, thus we need to encode | |
7468 // the value of rax before repne. Note that rax is dead after the repne. | |
7469 if (UseCompressedOops) { | |
7470 encode_heap_oop_not_null(rax); | |
7471 // The superclass is never null; it would be a basic system error if a null | |
7472 // pointer were to sneak in here. Note that we have already loaded the | |
7473 // Klass::super_check_offset from the super_klass in the fast path, | |
7474 // so if there is a null in that register, we are already in the afterlife. | |
7475 repne_scanl(); | |
7476 } else | |
7477 #endif // _LP64 | |
7478 repne_scan(); | |
7479 | |
7480 // Unspill the temp. registers: | |
7481 if (pushed_rdi) pop(rdi); | |
7482 if (pushed_rcx) pop(rcx); | |
7483 if (pushed_rax) pop(rax); | |
7484 | |
7485 if (set_cond_codes) { | |
7486 // Special hack for the AD files: rdi is guaranteed non-zero. | |
7487 assert(!pushed_rdi, "rdi must be left non-NULL"); | |
7488 // Also, the condition codes are properly set Z/NZ on succeed/failure. | |
7489 } | |
7490 | |
7491 if (L_failure == &L_fallthrough) | |
7492 jccb(Assembler::notEqual, *L_failure); | |
7493 else jcc(Assembler::notEqual, *L_failure); | |
7494 | |
7495 // Success. Cache the super we found and proceed in triumph. | |
7496 movptr(super_cache_addr, super_klass); | |
7497 | |
7498 if (L_success != &L_fallthrough) { | |
7499 jmp(*L_success); | |
7500 } | |
7501 | |
7502 #undef IS_A_TEMP | |
7503 | |
7504 bind(L_fallthrough); | |
7505 } | |
7506 | |
7507 | |
7220 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { | 7508 void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { |
7221 ucomisd(dst, as_Address(src)); | 7509 ucomisd(dst, as_Address(src)); |
7222 } | 7510 } |
7223 | 7511 |
7224 void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { | 7512 void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { |
7708 } | 7996 } |
7709 | 7997 |
7710 void MacroAssembler::load_prototype_header(Register dst, Register src) { | 7998 void MacroAssembler::load_prototype_header(Register dst, Register src) { |
7711 #ifdef _LP64 | 7999 #ifdef _LP64 |
7712 if (UseCompressedOops) { | 8000 if (UseCompressedOops) { |
8001 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
7713 movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); | 8002 movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); |
7714 movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | 8003 if (Universe::narrow_oop_shift() != 0) { |
8004 assert(Address::times_8 == LogMinObjAlignmentInBytes && | |
8005 Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8006 movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | |
8007 } else { | |
8008 movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | |
8009 } | |
7715 } else | 8010 } else |
7716 #endif | 8011 #endif |
7717 { | 8012 { |
7718 movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); | 8013 movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); |
7719 movptr(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); | 8014 movptr(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); |
7720 } | 8015 } |
7721 } | 8016 } |
7722 | 8017 |
7723 void MacroAssembler::store_klass(Register dst, Register src) { | 8018 void MacroAssembler::store_klass(Register dst, Register src) { |
7724 #ifdef _LP64 | 8019 #ifdef _LP64 |
7725 if (UseCompressedOops) { | 8020 if (UseCompressedOops) { |
7758 } | 8053 } |
7759 | 8054 |
7760 // Algorithm must match oop.inline.hpp encode_heap_oop. | 8055 // Algorithm must match oop.inline.hpp encode_heap_oop. |
7761 void MacroAssembler::encode_heap_oop(Register r) { | 8056 void MacroAssembler::encode_heap_oop(Register r) { |
7762 assert (UseCompressedOops, "should be compressed"); | 8057 assert (UseCompressedOops, "should be compressed"); |
8058 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8059 if (Universe::narrow_oop_base() == NULL) { | |
8060 verify_oop(r, "broken oop in encode_heap_oop"); | |
8061 if (Universe::narrow_oop_shift() != 0) { | |
8062 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8063 shrq(r, LogMinObjAlignmentInBytes); | |
8064 } | |
8065 return; | |
8066 } | |
7763 #ifdef ASSERT | 8067 #ifdef ASSERT |
7764 if (CheckCompressedOops) { | 8068 if (CheckCompressedOops) { |
7765 Label ok; | 8069 Label ok; |
7766 push(rscratch1); // cmpptr trashes rscratch1 | 8070 push(rscratch1); // cmpptr trashes rscratch1 |
7767 cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); | 8071 cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
7768 jcc(Assembler::equal, ok); | 8072 jcc(Assembler::equal, ok); |
7769 stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); | 8073 stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); |
7770 bind(ok); | 8074 bind(ok); |
7771 pop(rscratch1); | 8075 pop(rscratch1); |
7772 } | 8076 } |
7778 shrq(r, LogMinObjAlignmentInBytes); | 8082 shrq(r, LogMinObjAlignmentInBytes); |
7779 } | 8083 } |
7780 | 8084 |
7781 void MacroAssembler::encode_heap_oop_not_null(Register r) { | 8085 void MacroAssembler::encode_heap_oop_not_null(Register r) { |
7782 assert (UseCompressedOops, "should be compressed"); | 8086 assert (UseCompressedOops, "should be compressed"); |
8087 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
7783 #ifdef ASSERT | 8088 #ifdef ASSERT |
7784 if (CheckCompressedOops) { | 8089 if (CheckCompressedOops) { |
7785 Label ok; | 8090 Label ok; |
7786 testq(r, r); | 8091 testq(r, r); |
7787 jcc(Assembler::notEqual, ok); | 8092 jcc(Assembler::notEqual, ok); |
7788 stop("null oop passed to encode_heap_oop_not_null"); | 8093 stop("null oop passed to encode_heap_oop_not_null"); |
7789 bind(ok); | 8094 bind(ok); |
7790 } | 8095 } |
7791 #endif | 8096 #endif |
7792 verify_oop(r, "broken oop in encode_heap_oop_not_null"); | 8097 verify_oop(r, "broken oop in encode_heap_oop_not_null"); |
7793 subq(r, r12_heapbase); | 8098 if (Universe::narrow_oop_base() != NULL) { |
7794 shrq(r, LogMinObjAlignmentInBytes); | 8099 subq(r, r12_heapbase); |
8100 } | |
8101 if (Universe::narrow_oop_shift() != 0) { | |
8102 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8103 shrq(r, LogMinObjAlignmentInBytes); | |
8104 } | |
7795 } | 8105 } |
7796 | 8106 |
7797 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { | 8107 void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { |
7798 assert (UseCompressedOops, "should be compressed"); | 8108 assert (UseCompressedOops, "should be compressed"); |
8109 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
7799 #ifdef ASSERT | 8110 #ifdef ASSERT |
7800 if (CheckCompressedOops) { | 8111 if (CheckCompressedOops) { |
7801 Label ok; | 8112 Label ok; |
7802 testq(src, src); | 8113 testq(src, src); |
7803 jcc(Assembler::notEqual, ok); | 8114 jcc(Assembler::notEqual, ok); |
7807 #endif | 8118 #endif |
7808 verify_oop(src, "broken oop in encode_heap_oop_not_null2"); | 8119 verify_oop(src, "broken oop in encode_heap_oop_not_null2"); |
7809 if (dst != src) { | 8120 if (dst != src) { |
7810 movq(dst, src); | 8121 movq(dst, src); |
7811 } | 8122 } |
7812 subq(dst, r12_heapbase); | 8123 if (Universe::narrow_oop_base() != NULL) { |
7813 shrq(dst, LogMinObjAlignmentInBytes); | 8124 subq(dst, r12_heapbase); |
8125 } | |
8126 if (Universe::narrow_oop_shift() != 0) { | |
8127 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8128 shrq(dst, LogMinObjAlignmentInBytes); | |
8129 } | |
7814 } | 8130 } |
7815 | 8131 |
7816 void MacroAssembler::decode_heap_oop(Register r) { | 8132 void MacroAssembler::decode_heap_oop(Register r) { |
7817 assert (UseCompressedOops, "should be compressed"); | 8133 assert (UseCompressedOops, "should be compressed"); |
8134 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8135 if (Universe::narrow_oop_base() == NULL) { | |
8136 if (Universe::narrow_oop_shift() != 0) { | |
8137 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8138 shlq(r, LogMinObjAlignmentInBytes); | |
8139 } | |
8140 verify_oop(r, "broken oop in decode_heap_oop"); | |
8141 return; | |
8142 } | |
7818 #ifdef ASSERT | 8143 #ifdef ASSERT |
7819 if (CheckCompressedOops) { | 8144 if (CheckCompressedOops) { |
7820 Label ok; | 8145 Label ok; |
7821 push(rscratch1); | 8146 push(rscratch1); |
7822 cmpptr(r12_heapbase, | 8147 cmpptr(r12_heapbase, |
7823 ExternalAddress((address)Universe::heap_base_addr())); | 8148 ExternalAddress((address)Universe::narrow_oop_base_addr())); |
7824 jcc(Assembler::equal, ok); | 8149 jcc(Assembler::equal, ok); |
7825 stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); | 8150 stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); |
7826 bind(ok); | 8151 bind(ok); |
7827 pop(rscratch1); | 8152 pop(rscratch1); |
7828 } | 8153 } |
7842 verify_oop(r, "broken oop in decode_heap_oop"); | 8167 verify_oop(r, "broken oop in decode_heap_oop"); |
7843 } | 8168 } |
7844 | 8169 |
7845 void MacroAssembler::decode_heap_oop_not_null(Register r) { | 8170 void MacroAssembler::decode_heap_oop_not_null(Register r) { |
7846 assert (UseCompressedOops, "should only be used for compressed headers"); | 8171 assert (UseCompressedOops, "should only be used for compressed headers"); |
8172 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
7847 // Cannot assert, unverified entry point counts instructions (see .ad file) | 8173 // Cannot assert, unverified entry point counts instructions (see .ad file) |
7848 // vtableStubs also counts instructions in pd_code_size_limit. | 8174 // vtableStubs also counts instructions in pd_code_size_limit. |
7849 // Also do not verify_oop as this is called by verify_oop. | 8175 // Also do not verify_oop as this is called by verify_oop. |
7850 assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); | 8176 if (Universe::narrow_oop_base() == NULL) { |
7851 leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); | 8177 if (Universe::narrow_oop_shift() != 0) { |
8178 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8179 shlq(r, LogMinObjAlignmentInBytes); | |
8180 } | |
8181 } else { | |
8182 assert (Address::times_8 == LogMinObjAlignmentInBytes && | |
8183 Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8184 leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); | |
8185 } | |
7852 } | 8186 } |
7853 | 8187 |
7854 void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { | 8188 void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { |
7855 assert (UseCompressedOops, "should only be used for compressed headers"); | 8189 assert (UseCompressedOops, "should only be used for compressed headers"); |
8190 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
7856 // Cannot assert, unverified entry point counts instructions (see .ad file) | 8191 // Cannot assert, unverified entry point counts instructions (see .ad file) |
7857 // vtableStubs also counts instructions in pd_code_size_limit. | 8192 // vtableStubs also counts instructions in pd_code_size_limit. |
7858 // Also do not verify_oop as this is called by verify_oop. | 8193 // Also do not verify_oop as this is called by verify_oop. |
7859 assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); | 8194 if (Universe::narrow_oop_shift() != 0) { |
7860 leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); | 8195 assert (Address::times_8 == LogMinObjAlignmentInBytes && |
8196 Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong"); | |
8197 leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); | |
8198 } else if (dst != src) { | |
8199 movq(dst, src); | |
8200 } | |
7861 } | 8201 } |
7862 | 8202 |
7863 void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { | 8203 void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { |
7864 assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); | 8204 assert (UseCompressedOops, "should only be used for compressed headers"); |
8205 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8206 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); | |
7865 int oop_index = oop_recorder()->find_index(obj); | 8207 int oop_index = oop_recorder()->find_index(obj); |
7866 RelocationHolder rspec = oop_Relocation::spec(oop_index); | 8208 RelocationHolder rspec = oop_Relocation::spec(oop_index); |
7867 mov_literal32(dst, oop_index, rspec, narrow_oop_operand); | 8209 mov_narrow_oop(dst, oop_index, rspec); |
8210 } | |
8211 | |
8212 void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { | |
8213 assert (UseCompressedOops, "should only be used for compressed headers"); | |
8214 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8215 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); | |
8216 int oop_index = oop_recorder()->find_index(obj); | |
8217 RelocationHolder rspec = oop_Relocation::spec(oop_index); | |
8218 mov_narrow_oop(dst, oop_index, rspec); | |
8219 } | |
8220 | |
8221 void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) { | |
8222 assert (UseCompressedOops, "should only be used for compressed headers"); | |
8223 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8224 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); | |
8225 int oop_index = oop_recorder()->find_index(obj); | |
8226 RelocationHolder rspec = oop_Relocation::spec(oop_index); | |
8227 Assembler::cmp_narrow_oop(dst, oop_index, rspec); | |
8228 } | |
8229 | |
8230 void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { | |
8231 assert (UseCompressedOops, "should only be used for compressed headers"); | |
8232 assert (Universe::heap() != NULL, "java heap should be initialized"); | |
8233 assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); | |
8234 int oop_index = oop_recorder()->find_index(obj); | |
8235 RelocationHolder rspec = oop_Relocation::spec(oop_index); | |
8236 Assembler::cmp_narrow_oop(dst, oop_index, rspec); | |
7868 } | 8237 } |
7869 | 8238 |
7870 void MacroAssembler::reinit_heapbase() { | 8239 void MacroAssembler::reinit_heapbase() { |
7871 if (UseCompressedOops) { | 8240 if (UseCompressedOops) { |
7872 movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); | 8241 movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); |
7873 } | 8242 } |
7874 } | 8243 } |
7875 #endif // _LP64 | 8244 #endif // _LP64 |
7876 | 8245 |
7877 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { | 8246 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { |