Ejemplo n.º 1
0
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;
  }
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 6
0
    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;
    };
Ejemplo n.º 7
0
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
}