void CompilerStubs::generate_compiler_new_object() { comment_section("Compiler new object (any size)"); comment("Register edx holds the instance size, register ebx holds the prototypical near of the instance class"); Label slow_case; entry("compiler_new_object"); comment("Get _inline_allocation_top"); movl(eax, Address(Constant("_inline_allocation_top"))); comment("Compute new top"); leal(ecx, Address(eax, edx, times_1)); if (GenerateDebugAssembly) { comment("Check ExcessiveGC"); testl(Address(Constant("ExcessiveGC")), Constant(0)); jcc(not_zero, Constant(slow_case)); } comment("Compare against _inline_allocation_end"); cmpl(ecx, Address(Constant("_inline_allocation_end"))); jcc(above, Constant(slow_case)); comment("Allocation succeeded, set _inline_allocation_top"); movl(Address(Constant("_inline_allocation_top")), ecx); comment("Set prototypical near in object; no need for write barrier"); movl(Address(eax), ebx); comment("Compute remaining size"); decrement(edx, oopSize); comment("One-word object?"); Label init_done; jcc(zero, Constant(init_done)); comment("Zero object fields"); xorl(ecx, ecx); Label init_loop; bind(init_loop); movl(Address(eax, edx, times_1), ecx); decrement(edx, oopSize); jcc(not_zero, Constant(init_loop)); bind(init_done); comment("The newly allocated object is in register eax"); ret(); comment("Slow case - call the VM runtime system"); bind(slow_case); leal(eax, Address(Constant("newobject"))); goto_shared_call_vm(T_OBJECT); entry_end(); // compiler_new_object }
// void getPsrInfo(VM_Version::CpuidInfo* cpuid_info); address generate_getPsrInfo() { StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub"); # define __ _masm-> address start = __ pc(); // rbx is callee-save on both unix and windows // rcx and rdx are first and second argument registers on windows __ pushq(rbx); __ movq(r8, rarg0); __ xorl(rax, rax); __ cpuid(); __ leaq(r9, Address(r8, in_bytes(VM_Version::std_cpuid0_offset()))); __ movl(Address(r9, 0), rax); __ movl(Address(r9, 4), rbx); __ movl(Address(r9, 8), rcx); __ movl(Address(r9, 12), rdx); __ movl(rax, 1); __ cpuid(); __ leaq(r9, Address(r8, in_bytes(VM_Version::std_cpuid1_offset()))); __ movl(Address(r9, 0), rax); __ movl(Address(r9, 4), rbx); __ movl(Address(r9, 8), rcx); __ movl(Address(r9, 12), rdx); __ movl(rax, 0x80000001); __ cpuid(); __ leaq(r9, Address(r8, in_bytes(VM_Version::ext_cpuid1_offset()))); __ movl(Address(r9, 0), rax); __ movl(Address(r9, 4), rbx); __ movl(Address(r9, 8), rcx); __ movl(Address(r9, 12), rdx); __ popq(rbx); __ ret(0); return start; }
void CompilerStubs::generate_compiler_idiv_irem() { comment_section("Compiler integer divide and remainder"); comment("Register eax holds the dividend, register ebx holds the divisor"); entry("compiler_idiv_irem"); const int min_int = 0x80000000; Label normal_case, special_case; Label throw_exception; testl(ebx,ebx); jcc(equal, Constant(throw_exception)); // Check for special case cmpl(eax, Constant(min_int)); jcc(not_equal, Constant(normal_case)); xorl(edx, edx); // Prepare edx for possible special case (where remainder = 0) cmpl(ebx, Constant(-1)); jcc(equal, Constant(special_case)); // Handle normal case bind(normal_case); cdql(); idivl(ebx); // Normal and special case exit bind(special_case); ret(); bind(throw_exception); comment("Throw a DivisionByZeroException"); leal(eax, Address(Constant("division_by_zero_exception"))); goto_shared_call_vm(T_VOID); entry_end(); // compiler_idiv_irem }
void NativeGenerator::generate_native_string_entries() { comment_section("Native entry points for string functions"); { //--------------------java.lang.String.indexof0--------------------------- rom_linkable_entry("native_string_indexof0_entry"); wtk_profile_quick_call(/* param_size*/ 2); comment("Pop the return address"); popl(edi); comment("Push zero for fromIndex"); pushl(Constant(0)); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_indexof_entry")); rom_linkable_entry_end(); // native_string_indexof0_entry //--------------------java.lang.String.indexof--------------------------- rom_linkable_entry("native_string_indexof_entry"); Label cont, loop, test, failure, success; wtk_profile_quick_call(/* param_size*/ 3); comment("Pop the return address"); popl(edi); comment("Pop the argument: fromIndex"); pop_int(eax, eax); comment("Pop the argument: ch"); pop_int(ebx, ebx); comment("Pop the receiver"); pop_obj(ecx, ecx); cmpl(ebx, Constant(0xFFFF)); jcc(greater, Constant(failure)); cmpl(eax, Constant(0)); jcc(greater_equal, Constant(cont)); movl(eax, Constant(0)); bind(cont); movl(esi, Address(ecx, Constant(String::count_offset()))); comment("if (fromIndex >= count) { return -1; }"); cmpl(eax, esi); jcc(greater_equal, Constant(failure)); movl(edx, Address(ecx, Constant(String::offset_offset()))); addl(eax, edx); // i = offset + fromIndex addl(edx, esi); // int max = offset + count; movl(esi, Address(ecx, Constant(String::value_offset()))); // v = value. jmp(Constant(test)); bind(loop); cmpw(Address(esi, eax, times_2, Constant(Array::base_offset())), ebx); jcc(equal, Constant(success)); incl(eax); bind(test); cmpl(eax, edx); jcc(less, Constant(loop)); comment("Return -1 by pushing the value and jumping to the return address"); bind(failure); push_int(-1); jmp(edi); comment("Return i - offset by pushing the value and jumping to the return address"); bind(success); movl(esi, Address(ecx, Constant(String::offset_offset()))); // i = offset + fromIndex subl(eax, esi); push_int(eax); jmp(edi); rom_linkable_entry_end(); // native_string_indexof_entry } //----------------------java.lang.String.charAt--------------------------- { rom_linkable_entry("native_string_charAt_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String(java.lang.StringBuffer)------------- { rom_linkable_entry("native_string_init_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.equals(java.lang.Object)------------ { rom_linkable_entry("native_string_equals_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.indexOf(java.lang.String)----------- { rom_linkable_entry("native_string_indexof0_string_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.indexOf(java.lang.String)----------- { rom_linkable_entry("native_string_indexof_string_entry"); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); } //----------------------java.lang.String.compareTo--------------------------- { // java.lang.String.compareTo // Method int compareTo(java.lang.String) rom_linkable_entry("native_string_compareTo_entry"); wtk_profile_quick_call(/* param_size*/ 2); comment("preserve method"); pushl(ebx); // 8 is return address plus pushed method int str1_offset = JavaFrame::arg_offset_from_sp(0) + 8, str0_offset = JavaFrame::arg_offset_from_sp(1) + 8; comment("load arguments to registers"); movl(ecx, Address(esp, Constant(str1_offset))); movl(eax, Address(esp, Constant(str0_offset))); // eax: str0: this String // ebx: str1: String to compare against Label bailout; comment("Null check"); testl(ecx, ecx); jcc(zero, Constant(bailout)); comment("get str0.value[]"); movl(esi, Address(eax, Constant(String::value_offset()))); comment("get str0.offset"); movl(ebx, Address(eax, Constant(String::offset_offset()))); comment("compute start of character data"); leal(esi, Address(esi, ebx, times_2, Constant(Array::base_offset()))); comment("get str0.count"); movl(eax, Address(eax, Constant(String::count_offset()))); comment("get str1.value[]"); movl(edi, Address(ecx, Constant(String::value_offset()))); comment("get str1.offset"); movl(ebx, Address(ecx, Constant(String::offset_offset()))); comment("compute start of character data"); leal(edi, Address(edi, ebx, times_2, Constant(Array::base_offset()))); comment("get str1.count"); movl(ebx, Address(ecx, Constant(String::count_offset()))); // esi = str0 start of character data // edi = str1 start of character data // eax = str0 length // ebx = str1 length Label str1_longest; subl(eax, ebx); jcc(greater_equal, Constant(str1_longest)); // str1 is longer than str0 addl(ebx, eax); bind(str1_longest); // esi = str0 start of character data // edi = str1 start of character data // eax = str0.count - str1.count // ebx = min(str0.count, str1.count) // save str0.count - str1.count, we might need it later pushl(eax); xorl(ecx, ecx); Label loop, check_lengths, done; bind(loop); cmpl(ecx, ebx); jcc(above_equal, Constant(check_lengths)); movzxw(eax, Address(esi, ecx, times_2)); movzxw(edx, Address(edi, ecx, times_2)); subl(eax, edx); jcc(not_equal, Constant(done)); incl(ecx); jmp(Constant(loop)); bind(check_lengths); movl(eax, Address(esp)); bind(done); popl(ebx); // remove saved length difference // Push result on stack and return to caller popl(ebx); // remove method popl(edi); // pop return address addl(esp, Constant(2 * BytesPerStackElement)); // remove arguments push_int(eax); // push result jmp(edi); // return comment("Bail out to the general compareTo implementation"); bind(bailout); comment("pop method"); popl(ebx); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_compareTo_entry } //----------------------java.lang.String.endsWith---------------- { // java.lang.String.endsWith // Method boolean endsWith(java.lang.String) rom_linkable_entry("native_string_endsWith_entry"); wtk_profile_quick_call(/* param_size*/ 2); Label bailout; // 4 is return address int suffix_offset = JavaFrame::arg_offset_from_sp(0) + 4, this_offset = JavaFrame::arg_offset_from_sp(1) + 4; comment("load arguments to registers"); movl(eax, Address(esp, Constant(suffix_offset))); cmpl(eax, Constant(0)); jcc(equal, Constant(bailout)); movl(ecx, Address(esp, Constant(this_offset))); comment("Pop the return address"); popl(edi); movl(edx, Address(ecx, Constant(String::count_offset()))); subl(edx, Address(eax, Constant(String::count_offset()))); comment("Push (this.count - suffix.count) for toffset"); pushl(edx); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_startsWith_entry")); comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_endsWith_entry } //----------------------java.lang.String.startsWith---------------- { // java.lang.String.startsWith // Method boolean startsWith(java.lang.String) rom_linkable_entry("native_string_startsWith0_entry"); wtk_profile_quick_call(/* param_size*/ 2); Label bailout; // 4 is return address int prefix_offset = JavaFrame::arg_offset_from_sp(0) + 4; comment("Check if prefix is null"); cmpl(Address(esp, Constant(prefix_offset)), Constant(0)); jcc(equal, Constant(bailout)); comment("Pop the return address"); popl(edi); comment("Push zero for toffset"); pushl(Constant(0)); comment("Push back the return address"); pushl(edi); jmp(Constant("native_string_startsWith_entry")); comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_startsWith0_entry } { // ----------- java.lang.String.startsWith ------------------------------ // Method boolean startsWith(java.lang.String,int) rom_linkable_entry("native_string_startsWith_entry"); wtk_profile_quick_call(/* param_size*/ 3); Label bailout, return_false; // 4 is return address int prefix_offset = JavaFrame::arg_offset_from_sp(1) + 4; comment("Check if prefix is null"); cmpl(Address(esp, Constant(prefix_offset)), Constant(0)); jcc(equal, Constant(bailout)); comment("Pop the return address"); popl(edi); comment("Pop the argument: toffset"); pop_int(edx, edx); comment("Pop the argument: prefix"); pop_obj(eax, eax); comment("Pop the receiver"); pop_obj(ecx, ecx); comment("Preserve the return address"); pushl(edi); // ecx: this String // eax: prefix cmpl(edx, Constant(0)); jcc(less, Constant(return_false)); comment("if (toffset > this.count - prefix.count) return false;"); movl(ebx, Address(ecx, Constant(String::count_offset()))); subl(ebx, Address(eax, Constant(String::count_offset()))); cmpl(edx, ebx); jcc(greater, Constant(return_false)); comment("get this.value[]"); movl(esi, Address(ecx, Constant(String::value_offset()))); comment("get this.offset"); movl(ebx, Address(ecx, Constant(String::offset_offset()))); comment("add toffset"); addl(ebx, edx); comment("compute start of character data"); leal(esi, Address(esi, ebx, times_2, Constant(Array::base_offset()))); comment("get prefix.value[]"); movl(edi, Address(eax, Constant(String::value_offset()))); comment("get prefix.offset"); movl(ebx, Address(eax, Constant(String::offset_offset()))); comment("compute start of character data"); leal(edi, Address(edi, ebx, times_2, Constant(Array::base_offset()))); comment("get prefix.count"); movl(ecx, Address(eax, Constant(String::count_offset()))); comment("get the number of bytes to compare"); shll(ecx, Constant(1)); comment("memcmp(edi, esi, ecx);"); pushl(ecx); pushl(esi); pushl(edi); if (GenerateInlineAsm) { // VC++ treats memcmp() as an intrinsic function and would cause // reference to memcmp in Interpreter_i386.c to fail to compile. call(Constant("memcmp_from_interpreter")); } else { call(Constant("memcmp")); } addl(esp, Constant(12)); cmpl(eax, Constant(0)); jcc(not_equal, Constant(return_false)); // Push 1 on stack and return to caller popl(edi); // pop return address push_int(1); // push result jmp(edi); // return bind(return_false); // Push 0 on stack and return to caller popl(edi); // pop return address push_int(0); // push result jmp(edi); // return comment("Bail out to the general startsWith implementation"); bind(bailout); if (AddExternCUnderscore) { emit_instruction("jmp _interpreter_method_entry"); } else { emit_instruction("jmp interpreter_method_entry"); } rom_linkable_entry_end(); // native_string_startsWith_entry } }
void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { const Address src(from(), -offset() * wordSize); #ifdef _WIN64 switch (_num_args) { case 0: assert(offset() == 0, "argument register 1 can only be (non-null) receiver"); __ leaq(rarg1, src); _num_args++; break; case 1: __ leaq(rax, src); __ xorl(rarg2, rarg2); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, rarg2, rax); _num_args++; break; case 2: __ leaq(rax, src); __ xorl(rarg3, rarg3); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, rarg3, rax); _num_args++; break; default: __ leaq(rax, src); __ xorl(temp(), temp()); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, temp(), rax); __ movq(Address(to(), _stack_offset), temp()); _stack_offset += wordSize; break; } #else switch (_num_int_args) { case 0: assert(offset() == 0, "argument register 1 can only be (non-null) receiver"); __ leaq(rarg1, src); _num_int_args++; break; case 1: __ leaq(rax, src); __ xorl(rarg2, rarg2); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, rarg2, rax); _num_int_args++; break; case 2: __ leaq(rax, src); __ xorl(rarg3, rarg3); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, rarg3, rax); _num_int_args++; break; case 3: __ leaq(rax, src); __ xorl(rarg4, rarg4); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, rarg4, rax); _num_int_args++; break; case 4: __ leaq(rax, src); __ xorl(rarg5, rarg5); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, rarg5, rax); _num_int_args++; break; default: __ leaq(rax, src); __ xorl(temp(), temp()); __ cmpq(src, 0); __ cmovq(Assembler::notEqual, temp(), rax); __ movq(Address(to(), _stack_offset), temp()); _stack_offset += wordSize; break; } #endif }
address generate_getPsrInfo() { // Flags to test CPU type. const uint32_t HS_EFL_AC = 0x40000; const uint32_t HS_EFL_ID = 0x200000; // Values for when we don't have a CPUID instruction. const int CPU_FAMILY_SHIFT = 8; const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT); const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done; StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub"); # define __ _masm-> address start = __ pc(); // // void getPsrInfo(VM_Version::CpuidInfo* cpuid_info); // // LP64: rcx and rdx are first and second argument registers on windows __ push(rbp); #ifdef _LP64 __ mov(rbp, c_rarg0); // cpuid_info address #else __ movptr(rbp, Address(rsp, 8)); // cpuid_info address #endif __ push(rbx); __ push(rsi); __ pushf(); // preserve rbx, and flags __ pop(rax); __ push(rax); __ mov(rcx, rax); // // if we are unable to change the AC flag, we have a 386 // __ xorl(rax, HS_EFL_AC); __ push(rax); __ popf(); __ pushf(); __ pop(rax); __ cmpptr(rax, rcx); __ jccb(Assembler::notEqual, detect_486); __ movl(rax, CPU_FAMILY_386); __ movl(Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())), rax); __ jmp(done); // // If we are unable to change the ID flag, we have a 486 which does // not support the "cpuid" instruction. // __ bind(detect_486); __ mov(rax, rcx); __ xorl(rax, HS_EFL_ID); __ push(rax); __ popf(); __ pushf(); __ pop(rax); __ cmpptr(rcx, rax); __ jccb(Assembler::notEqual, detect_586); __ bind(cpu486); __ movl(rax, CPU_FAMILY_486); __ movl(Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())), rax); __ jmp(done); // // At this point, we have a chip which supports the "cpuid" instruction // __ bind(detect_586); __ xorl(rax, rax); __ cpuid(); __ orl(rax, rax); __ jcc(Assembler::equal, cpu486); // if cpuid doesn't support an input // value of at least 1, we give up and // assume a 486 __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); __ cmpl(rax, 0xa); // Is cpuid(0xB) supported? __ jccb(Assembler::belowEqual, std_cpuid4); // // cpuid(0xB) Processor Topology // __ movl(rax, 0xb); __ xorl(rcx, rcx); // Threads level __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB0_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); __ movl(rax, 0xb); __ movl(rcx, 1); // Cores level __ cpuid(); __ push(rax); __ andl(rax, 0x1f); // Determine if valid topology level __ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level __ andl(rax, 0xffff); __ pop(rax); __ jccb(Assembler::equal, std_cpuid4); __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB1_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); __ movl(rax, 0xb); __ movl(rcx, 2); // Packages level __ cpuid(); __ push(rax); __ andl(rax, 0x1f); // Determine if valid topology level __ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level __ andl(rax, 0xffff); __ pop(rax); __ jccb(Assembler::equal, std_cpuid4); __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB2_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // cpuid(0x4) Deterministic cache params // __ bind(std_cpuid4); __ movl(rax, 4); __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x4) supported? __ jccb(Assembler::greater, std_cpuid1); __ xorl(rcx, rcx); // L1 cache __ cpuid(); __ push(rax); __ andl(rax, 0x1f); // Determine if valid cache parameters used __ orl(rax, rax); // eax[4:0] == 0 indicates invalid cache __ pop(rax); __ jccb(Assembler::equal, std_cpuid1); __ lea(rsi, Address(rbp, in_bytes(VM_Version::dcp_cpuid4_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // Standard cpuid(0x1) // __ bind(std_cpuid1); __ movl(rax, 1); __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // Check if OS has enabled XGETBV instruction to access XCR0 // (OSXSAVE feature flag) and CPU supports AVX // __ andl(rcx, 0x18000000); __ cmpl(rcx, 0x18000000); __ jccb(Assembler::notEqual, sef_cpuid); // // XCR0, XFEATURE_ENABLED_MASK register // __ xorl(rcx, rcx); // zero for XCR0 register __ xgetbv(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rdx); // // cpuid(0x7) Structured Extended Features // __ bind(sef_cpuid); __ movl(rax, 7); __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x7) supported? __ jccb(Assembler::greater, ext_cpuid); __ xorl(rcx, rcx); __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); // // Extended cpuid(0x80000000) // __ bind(ext_cpuid); __ movl(rax, 0x80000000); __ cpuid(); __ cmpl(rax, 0x80000000); // Is cpuid(0x80000001) supported? __ jcc(Assembler::belowEqual, done); __ cmpl(rax, 0x80000004); // Is cpuid(0x80000005) supported? __ jccb(Assembler::belowEqual, ext_cpuid1); __ cmpl(rax, 0x80000006); // Is cpuid(0x80000007) supported? __ jccb(Assembler::belowEqual, ext_cpuid5); __ cmpl(rax, 0x80000007); // Is cpuid(0x80000008) supported? __ jccb(Assembler::belowEqual, ext_cpuid7); // // Extended cpuid(0x80000008) // __ movl(rax, 0x80000008); __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid8_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // Extended cpuid(0x80000007) // __ bind(ext_cpuid7); __ movl(rax, 0x80000007); __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid7_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // Extended cpuid(0x80000005) // __ bind(ext_cpuid5); __ movl(rax, 0x80000005); __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid5_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // Extended cpuid(0x80000001) // __ bind(ext_cpuid1); __ movl(rax, 0x80000001); __ cpuid(); __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid1_offset()))); __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rbx); __ movl(Address(rsi, 8), rcx); __ movl(Address(rsi,12), rdx); // // return // __ bind(done); __ popf(); __ pop(rsi); __ pop(rbx); __ pop(rbp); __ ret(0); # undef __ return start; };
void CompilerStubs::generate_compiler_new_obj_array() { comment_section("Compiler stub: new object array"); comment("- ebx holds the prototypical near of the array class"); entry("compiler_new_obj_array"); comment("Get array length"); // add BytesPerWord for return address movl(edx, Address(esp, Constant(BytesPerWord + JavaFrame::arg_offset_from_sp(0)))); Label slow_case; comment("Check if the array length is too large or negative"); cmpl(edx, Constant(maximum_safe_array_length)); jcc(above, Constant(slow_case)); comment("Get _inline_allocation_top"); movl(eax, Address(Constant("_inline_allocation_top"))); if (GenerateDebugAssembly) { comment("Check ExcessiveGC"); testl(Address(Constant("ExcessiveGC")), Constant(0)); jcc(not_zero, Constant(slow_case)); } comment("Compute new top"); leal(ecx, Address(eax, edx, times_4, Constant(Array::base_offset()))); comment("Check for overflow"); cmpl(ecx, eax); jcc(below, Constant(slow_case)); comment("Compare against _inline_allocation_end"); cmpl(ecx, Address(Constant("_inline_allocation_end"))); jcc(above, Constant(slow_case)); comment("Allocation succeeded, set _inline_allocation_top"); movl(Address(Constant("_inline_allocation_top")), ecx); comment("Set prototypical near in object; no need for write barrier"); movl(Address(eax), ebx); comment("Set the length"); movl(Address(eax, Constant(Array::length_offset())), edx); comment("Compute remaining size"); testl(edx, edx); comment("Empty array?"); Label init_done; jcc(equal, Constant(init_done)); comment("Zero array elements"); xorl(ecx, ecx); Label init_loop; bind(init_loop); movl(Address(eax, edx, times_4, Constant(Array::base_offset() - oopSize)), ecx); decrement(edx, 1); jcc(not_zero, Constant(init_loop)); bind(init_done); comment("The newly allocated array is in register eax"); ret(); comment("Slow case - call the VM runtime system"); bind(slow_case); leal(eax, Address(Constant("anewarray"))); goto_shared_call_vm(T_ARRAY); entry_end(); // compiler_new_obj_array }