Example #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
}
Example #2
0
void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
  assert(x->number_of_arguments() == 3, "wrong type");
  LIRItem obj       (x->argument_at(0), this);  // AtomicLong object
  LIRItem cmp_value (x->argument_at(1), this);  // value to compare with field
  LIRItem new_value (x->argument_at(2), this);  // replace field with new_value if it matches cmp_value

  // compare value must be in rdx,eax (hi,lo); may be destroyed by cmpxchg8 instruction
  cmp_value.load_item_force(FrameMap::long0_opr);

  // new value must be in rcx,ebx (hi,lo)
  new_value.load_item_force(FrameMap::long1_opr);

  // object pointer register is overwritten with field address
  obj.load_item();

  // generate compare-and-swap; produces zero condition if swap occurs
  int value_offset = sun_misc_AtomicLongCSImpl::value_offset();
  LIR_Opr addr = new_pointer_register();
  __ leal(LIR_OprFact::address(new LIR_Address(obj.result(), value_offset, T_LONG)), addr);
  LIR_Opr t1 = LIR_OprFact::illegalOpr;  // no temp needed
  LIR_Opr t2 = LIR_OprFact::illegalOpr;  // no temp needed
  __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2);

  // generate conditional move of boolean result
  LIR_Opr result = rlock_result(x);
  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG);
}
Example #3
0
LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
                                              BasicType type, bool needs_card_mark) {
  int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type);

  LIR_Address* addr;
  if (index_opr->is_constant()) {
    int elem_size = type2aelembytes(type);
    addr = new LIR_Address(array_opr,
                           offset_in_bytes + index_opr->as_jint() * elem_size, type);
  } else {
#ifdef _LP64
    if (index_opr->type() == T_INT) {
      LIR_Opr tmp = new_register(T_LONG);
      __ convert(Bytecodes::_i2l, index_opr, tmp);
      index_opr = tmp;
    }
#endif // _LP64
    addr =  new LIR_Address(array_opr,
                            index_opr,
                            LIR_Address::scale(type),
                            offset_in_bytes, type);
  }
  if (needs_card_mark) {
    // This store will need a precise card mark, so go ahead and
    // compute the full adddres instead of computing once for the
    // store and again for the card mark.
    LIR_Opr tmp = new_pointer_register();
    __ leal(LIR_OprFact::address(addr), tmp);
    return new LIR_Address(tmp, type);
  } else {
    return addr;
  }
}
void InterpreterRuntime::SignatureHandlerGenerator::box(int from_offset, int to_offset) {
    __ leal(temp(), Address(from(), from_offset * wordSize));
    __ cmpl(Address(from(), from_offset * wordSize), 0); // do not use temp() to avoid AGI
    Label L;
    __ jcc(Assembler::notZero, L);
    __ movl(temp(), 0);
    __ bind(L);
    __ movl(Address(to(), to_offset * wordSize), temp());
}
void InterpreterStubs::generate_interpreter_rethrow_exception() {
  comment_section("Interpreter rethrow exception");
  comment("Register eax holds the exception; Interpreter state is not in registers");

  entry("interpreter_rethrow_exception");
  comment("Restore bytecode and locals pointers");
  movl(esi, Address(ebp, Constant(JavaFrame::bcp_store_offset())));
  movl(edi, Address(ebp, Constant(JavaFrame::locals_pointer_offset())));

  comment("Mark the bytecode pointer as being inside an exception");
  addl(esi, Constant(JavaFrame::exception_frame_flag));

  comment("Clear the expression stack");
  movl(esp, Address(ebp, Constant(JavaFrame::stack_bottom_pointer_offset())));
  
  comment("Push the exception on the expression stack");
  push_obj(eax);

  comment("Get exception handler bci for exception");
  interpreter_call_vm(Constant("exception_handler_bci_for_exception"), T_INT);
  
  comment("Check if we got a bci - otherwise unwind the activation");
  cmpl(eax, Constant(-1));
  jcc(equal, Constant("interpreter_unwind_activation"));
#if ENABLE_JAVA_DEBUGGER
  Label skip;
  cmpb(Address(Constant("_debugger_active")), Constant(0));
  jcc(equal, Constant(skip));
  movl(edx, eax);
  interpreter_call_vm(Constant("handle_caught_exception"), T_VOID);
  comment("Re-get exception handler bci for exception");
  interpreter_call_vm(Constant("exception_handler_bci_for_exception"), T_INT);
  bind(skip);
#endif
  comment("Convert the bytecode index into a bytecode pointer");
  movl(ecx, Address(ebp, Constant(JavaFrame::method_offset())));
  leal(esi, Address(ecx, eax, times_1, Constant(Method::base_offset())));

  // Dispatch to the exception handler.
  dispatch_next();

  entry_end(); // interpreter_rethrow_exception
}
Example #6
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
}
void LIR_Assembler::emit_op1(LIR_Op1* op) {
    switch (op->code()) {
    case lir_move:
        if (op->move_kind() == lir_move_volatile) {
            assert(op->patch_code() == lir_patch_none, "can't patch volatiles");
            volatile_move_op(op->in_opr(), op->result_opr(), op->type(), op->info());
        } else {
            move_op(op->in_opr(), op->result_opr(), op->type(),
                    op->patch_code(), op->info(), op->pop_fpu_stack(),
                    op->move_kind() == lir_move_unaligned,
                    op->move_kind() == lir_move_wide);
        }
        break;

    case lir_roundfp: {
        LIR_OpRoundFP* round_op = op->as_OpRoundFP();
        roundfp_op(round_op->in_opr(), round_op->tmp(), round_op->result_opr(), round_op->pop_fpu_stack());
        break;
    }

    case lir_return:
        return_op(op->in_opr());
        break;

    case lir_safepoint:
        if (compilation()->debug_info_recorder()->last_pc_offset() == code_offset()) {
            _masm->nop();
        }
        safepoint_poll(op->in_opr(), op->info());
        break;

    case lir_fxch:
        fxch(op->in_opr()->as_jint());
        break;

    case lir_fld:
        fld(op->in_opr()->as_jint());
        break;

    case lir_ffree:
        ffree(op->in_opr()->as_jint());
        break;

    case lir_branch:
        break;

    case lir_push:
        push(op->in_opr());
        break;

    case lir_pop:
        pop(op->in_opr());
        break;

    case lir_neg:
        negate(op->in_opr(), op->result_opr());
        break;

    case lir_leal:
        leal(op->in_opr(), op->result_opr());
        break;

    case lir_null_check:
        if (GenerateCompilerNullChecks) {
            ImplicitNullCheckStub* stub = add_debug_info_for_null_check_here(op->info());

            if (op->in_opr()->is_single_cpu()) {
                _masm->null_check(op->in_opr()->as_register(), stub->entry());
            } else {
                Unimplemented();
            }
        }
        break;

    case lir_monaddr:
        monitor_address(op->in_opr()->as_constant_ptr()->as_jint(), op->result_opr());
        break;

#ifdef SPARC
    case lir_pack64:
        pack64(op->in_opr(), op->result_opr());
        break;

    case lir_unpack64:
        unpack64(op->in_opr(), op->result_opr());
        break;
#endif

    case lir_unwind:
        unwind_op(op->in_opr());
        break;

    default:
        Unimplemented();
        break;
    }
}
Example #8
0
void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
  assert(x->number_of_arguments() == 4, "wrong type");
  LIRItem obj   (x->argument_at(0), this);  // object
  LIRItem offset(x->argument_at(1), this);  // offset of field
  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp

  assert(obj.type()->tag() == objectTag, "invalid type");

  // In 64bit the type can be long, sparc doesn't have this assert
  // assert(offset.type()->tag() == intTag, "invalid type");

  assert(cmp.type()->tag() == type->tag(), "invalid type");
  assert(val.type()->tag() == type->tag(), "invalid type");

  // get address of field
  obj.load_item();
  offset.load_nonconstant();

  if (type == objectType) {
    cmp.load_item_force(FrameMap::rax_oop_opr);
    val.load_item();
  } else if (type == intType) {
    cmp.load_item_force(FrameMap::rax_opr);
    val.load_item();
  } else if (type == longType) {
    cmp.load_item_force(FrameMap::long0_opr);
    val.load_item_force(FrameMap::long1_opr);
  } else {
    ShouldNotReachHere();
  }

  LIR_Opr addr = new_pointer_register();
  LIR_Address* a;
  if(offset.result()->is_constant()) {
    a = new LIR_Address(obj.result(),
                        NOT_LP64(offset.result()->as_constant_ptr()->as_jint()) LP64_ONLY((int)offset.result()->as_constant_ptr()->as_jlong()),
                        as_BasicType(type));
  } else {
    a = new LIR_Address(obj.result(),
                        offset.result(),
                        LIR_Address::times_1,
                        0,
                        as_BasicType(type));
  }
  __ leal(LIR_OprFact::address(a), addr);

  if (type == objectType) {  // Write-barrier needed for Object fields.
    // Do the pre-write barrier, if any.
    pre_barrier(addr, false, NULL);
  }

  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
  if (type == objectType)
    __ cas_obj(addr, cmp.result(), val.result(), ill, ill);
  else if (type == intType)
    __ cas_int(addr, cmp.result(), val.result(), ill, ill);
  else if (type == longType)
    __ cas_long(addr, cmp.result(), val.result(), ill, ill);
  else {
    ShouldNotReachHere();
  }

  // generate conditional move of boolean result
  LIR_Opr result = rlock_result(x);
  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
           result, as_BasicType(type));
  if (type == objectType) {   // Write-barrier needed for Object fields.
    // Seems to be precise
    post_barrier(addr, val.result());
  }
}
  address generate_call_stub(address& return_address) {
    StubCodeMark mark(this, "StubRoutines", "call_stub");
    address start = __ pc();

    // stub code parameters / addresses
    assert(frame::entry_frame_call_wrapper_offset == 2, "adjust this code");
    bool  sse_save = false;
    const Address esp_after_call(ebp, -4 * wordSize); // same as in generate_catch_exception()!
    const Address mxcsr_save    (ebp, -4 * wordSize);
    const Address result        (ebp,  3 * wordSize);
    const Address result_type   (ebp,  4 * wordSize);
    const Address method        (ebp,  5 * wordSize);
    const Address entry_point   (ebp,  6 * wordSize);
    const Address parameters    (ebp,  7 * wordSize);
    const Address parameter_size(ebp,  8 * wordSize);
    const Address thread        (ebp,  9 * wordSize); // same as in generate_catch_exception()!
#ifdef COMPILER2
    sse_save =  VM_Version::supports_sse();
#endif

    // stub code
    __ enter();    

    // save edi, esi, & ebx, according to C calling conventions
    __ pushl(edi);
    __ pushl(esi);
    __ pushl(ebx);
    __ subl(esp, wordSize);  // space for %mxcsr save
    // save and initialize %mxcsr
    if (sse_save) {
      __ stmxcsr(mxcsr_save);
      __ ldmxcsr(Address((int) StubRoutines::addr_mxcsr_std(), relocInfo::none));
    }

#ifdef ASSERT
    // make sure we have no pending exceptions
    { Label L;
      __ movl(ecx, thread);
      __ cmpl(Address(ecx, Thread::pending_exception_offset()), (int)NULL);
      __ jcc(Assembler::equal, L);
      __ stop("StubRoutines::call_stub: entered with pending exception");
      __ bind(L);
    }
#endif

    // pass parameters if any
    Label parameters_done;
    __ movl(ecx, parameter_size);  // parameter counter
    __ testl(ecx, ecx);
    __ jcc(Assembler::zero, parameters_done);

    // parameter passing loop

    Label loop;
    __ movl(edx, parameters);	       // parameter pointer
    __ movl(esi, ecx);                 // parameter counter is in esi now
    __ movl(ecx,  Address(edx));       // get first parameter in case it is a receiver

    __ bind(loop);
    __ movl(eax, Address(edx));	       // get parameter
    __ addl(edx, wordSize);            // advance to next parameter
    __ decl(esi);                      // decrement counter
    __ pushl(eax);                     // pass parameter
    __ jcc(Assembler::notZero, loop);

    // call Java function
    __ bind(parameters_done);
    __ movl(ebx, method);              // get methodOop
    __ movl(esi, entry_point);         // get entry_point
    __ call(esi, relocInfo::none);
    return_address = __ pc();

    // store result depending on type
    // (everything that is not T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT)
    __ movl(edi, result);
    Label is_long, is_float, is_double, exit;
    __ movl(esi, result_type);
    __ cmpl(esi, T_LONG);
    __ jcc(Assembler::equal, is_long);
    __ cmpl(esi, T_FLOAT);
    __ jcc(Assembler::equal, is_float);
    __ cmpl(esi, T_DOUBLE);
    __ jcc(Assembler::equal, is_double);

    // handle T_INT case
    __ movl(Address(edi), eax);
    __ bind(exit);

    // pop parameters
    __ movl(ecx, parameter_size);
    __ leal(esp, Address(esp, ecx, Address::times_4));

    // check if parameters have been popped correctly
#ifdef ASSERT
      Label esp_wrong;
      __ leal(edi, esp_after_call);
      __ cmpl(esp, edi);
      __ jcc(Assembler::notEqual, esp_wrong);
#endif

    // restore %mxcsr
    if (sse_save) {
      __ ldmxcsr(mxcsr_save);
    }
    // restore edi & esi
    __ addl(esp, wordSize);  // remove %mxcsr save area
    __ popl(ebx);
    __ popl(esi);
    __ popl(edi);    

    // return
    __ popl(ebp);
    __ ret(0);

    // handle return types different from T_INT
    __ bind(is_long);
    __ movl(Address(edi, 0 * wordSize), eax);
    __ movl(Address(edi, 1 * wordSize), edx);
    __ jmp(exit);

    __ bind(is_float);
    __ fstp_s(Address(edi));
    __ jmp(exit);

    __ bind(is_double);
    __ fstp_d(Address(edi));
    __ jmp(exit);

#ifdef ASSERT
      // stack pointer misadjusted
      __ bind(esp_wrong);
      __ stop("esp wrong after Java call");
#endif

    return start;
  }
Example #10
0
void NativeGenerator::generate_native_system_entries() {
  comment_section("Native entry points for system functions");

  rom_linkable_entry("native_jvm_unchecked_byte_arraycopy_entry");
  jmp(Constant("native_system_arraycopy_entry"));
  rom_linkable_entry_end();

  rom_linkable_entry("native_jvm_unchecked_char_arraycopy_entry");
  jmp(Constant("native_system_arraycopy_entry"));
  rom_linkable_entry_end();

  rom_linkable_entry("native_jvm_unchecked_int_arraycopy_entry");
  jmp(Constant("native_system_arraycopy_entry"));
  rom_linkable_entry_end();

  rom_linkable_entry("native_jvm_unchecked_long_arraycopy_entry");
  jmp(Constant("native_system_arraycopy_entry"));
  rom_linkable_entry_end();

  rom_linkable_entry("native_jvm_unchecked_obj_arraycopy_entry");
  jmp(Constant("native_system_arraycopy_entry"));
  rom_linkable_entry_end();

  rom_linkable_entry("native_system_arraycopy_entry");

  wtk_profile_quick_call(/* param_size*/ 5);

  Label bailout, cont, try_2_byte, try_4_byte, try_8_byte, do_4_byte;

  //  public static native void arraycopy(Object src, int src_position,
  //                                      Object dst, int dst_position,
  //                                      int length);
  comment("preserve method");
  pushl(ebx);

  // 8 is for the preserved method and the return address
  int  length_offset  =  JavaFrame::arg_offset_from_sp(0) + 8,
       dst_pos_offset =  JavaFrame::arg_offset_from_sp(1) + 8,
       dst_offset     =  JavaFrame::arg_offset_from_sp(2) + 8,
       src_pos_offset =  JavaFrame::arg_offset_from_sp(3) + 8,
       src_offset     =  JavaFrame::arg_offset_from_sp(4) + 8;

  comment("load arguments to registers");
  movl(ecx, Address(esp, Constant(length_offset)));
  movl(edi, Address(esp, Constant(dst_pos_offset)));
  movl(edx, Address(esp, Constant(dst_offset)));
  movl(esi, Address(esp, Constant(src_pos_offset)));
  movl(eax, Address(esp, Constant(src_offset)));

  // eax = src
  // ebx = tmp register
  // edx = dst
  // ecx = length
  // esi = src_pos
  // edi = dst_pos

  comment("if (src == NULL) goto bailout;");
  testl( eax, eax );
  jcc(zero, Constant(bailout));

  comment("if (dst == NULL) goto bailout;");
  testl( edx, edx );
  jcc(zero, Constant(bailout));

  comment("if (length < 0 || src_pos < 0 || dst_pos < 0) goto bailout;");
  movl(ebx, ecx);
  orl(ebx, esi);
  orl(ebx, edi);
  jcc(negative, Constant(bailout));

  comment("if ((unsigned int) dst.length < (unsigned int) dst_pos + (unsigned int) length) goto bailout;");
  movl(ebx, ecx);
  addl(ebx, edi);
  cmpl(Address(edx, Constant(Array::length_offset())), ebx);
  jcc(below, Constant(bailout));

  comment("if ((unsigned int) src.length < (unsigned int) src_pos + (unsigned int) length) goto bailout;");
  movl(ebx, ecx);
  addl(ebx, esi);
  cmpl(Address(eax, Constant(Array::length_offset())), ebx);
  jcc(below, Constant(bailout));

  comment("Same near test");
  comment("if (src.near != dst.near) goto bailout;");
  movl(ebx, Address(eax, Constant(Oop::klass_offset())));
  cmpl(ebx, Address(edx, Constant(Oop::klass_offset())));
  jcc(not_equal, Constant(bailout));

  comment("load the instance_size");
  movl(ebx, Address(ebx, Constant(JavaNear::klass_offset())));
  movsxw(ebx, Address(ebx, Constant(FarClass::instance_size_offset())));

  comment("if (instance_size != size_type_array_1()) goto try_2_byte");
  cmpl(ebx, Constant(InstanceSize::size_type_array_1));
  jcc(not_equal, Constant(try_2_byte));
  leal(esi, Address(eax, esi, times_1, Constant(Array::base_offset())));
  leal(edi, Address(edx, edi, times_1, Constant(Array::base_offset())));
  jmp(Constant(cont));

  bind(try_2_byte);
  comment("if (instance_size != size_type_array_2()) goto try_4_byte");
  cmpl(ebx, Constant(InstanceSize::size_type_array_2));
  jcc(not_equal, Constant(try_4_byte));
  leal(esi, Address(eax, esi, times_2, Constant(Array::base_offset())));
  leal(edi, Address(edx, edi, times_2, Constant(Array::base_offset())));
  shll(ecx, Constant(1));
  jmp(Constant(cont));

  bind(try_4_byte);
  comment("if (instance_size == size_type_array_4()) goto do_4_byte");
  cmpl(ebx, Constant(InstanceSize::size_type_array_4));
  jcc(equal, Constant(do_4_byte) );

  comment("if (instance_size != size_obj_array()) goto bailout");
  cmpl(ebx, Constant(InstanceSize::size_obj_array));
  jcc(not_equal, Constant(bailout));

  comment("if (dst < old_generation_end) goto bailout");
  cmpl( edx, Address( Constant( "_old_generation_end" ) ) );
  jcc( below, Constant(bailout));

  bind(do_4_byte);
  leal(esi, Address(eax, esi, times_4, Constant(Array::base_offset())));
  leal(edi, Address(edx, edi, times_4, Constant(Array::base_offset())));
  shll(ecx, Constant(2));

  bind(cont);
  comment("memmove(edi, esi, ecx);");
  pushl(ecx);
  pushl(esi);
  pushl(edi);
  call(Constant("memmove"));
  addl(esp, Constant(16));

  ret(Constant(5 * BytesPerStackElement));

  comment("Bail out to the general arraycopy 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_system_arraycopy_entry
}
Example #11
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 InterpreterStubs::generate_interpreter_fill_in_tags() {
  comment_section("Interpreter fill in tags");
  entry("interpreter_fill_in_tags");
  comment("eax: return address of method");
  comment("ebx: method");
  comment("ecx: size of parameters.  Guaranteed to be >= 1");
  comment("edx: call info from call site");
  comment("Must preserve eax, ebx, ecx");

  // stack layout:
  //   sp return address of caller
  //      --> argument n
  //      -->    ...
  //      --> argument 0

  Label extended_call_info;

  comment("Compact call info or normal call info?");
  testl(edx, edx); 
  jcc(positive, Constant(extended_call_info));

  Label loop_entry, loop_condition;
  comment("We have a compact call info");
  movl(edi, ecx);

bind(loop_entry);
  decl(edi);
  comment("Store int tag");
  movl(Address(esp, edi, times_8, Constant(BytesPerWord)), Constant(int_tag));
  comment("Test the bit in the call info");
  GUARANTEE(CallInfo::format1_tag_start == 0, "Tag must start at bit position 0 for this code to work");
  btl(edx, edi);
  jcc(carry_clear, Constant(loop_condition));
  comment("Store obj tag");
  movl(Address(esp, edi, times_8, Constant(BytesPerWord)), Constant(obj_tag));
  bind(loop_condition);
  testl(edi, edi);
  jcc(not_zero, Constant(loop_entry));
  ret();

bind(extended_call_info);
  comment("Normal call info");
  // The following code is slightly complicated.  "Bit offset" below
  // pretends like the callinfo's are in a bit array, as follows:
  //     Callinfo describing bci and offset
  //     Size [16 bits] and stack info 0-3
  //     Stack info 4-11
  // We ignore the fact that each of these words is preceded by a byte
  // that makes it look like an instruction.
  pushl(ecx); 
  pushl(ebx);
  Label loopx_entry, loopx_done;
 
  comment("Bit offset of first argument in CallInfo array");
  movzxw(edx, Address(eax, Constant(5 + 1)));  // total number of locals/expr
  subl(edx, ecx);               // number of locals/expr belonging to callee
  shll(edx, Constant(2));       // number of bits per nybble
  addl(edx, Constant(32 + 16)); // 48 bits is the 32 bit callinfo and 16bit size info

  comment("Decrement argument count; move to more convenient register");
  leal(esi, Address(ecx, Constant(-1)));

  comment("Location of tag of esi-th local");
  leal(ebx, Address(esp, Constant(3 * BytesPerWord)));

bind(loopx_entry);
  comment("eax holds the return address");
  comment("ebx holds address of the esi-th tag");
  comment("esi is the local whose tag we are setting");
  comment("edx contains the bit offset of Local 0 in the CallInfo array");
  comment("Get bit offset of esi-th local");
  leal(ecx, Address(edx, esi, times_4));

  comment("From bit offset, get word offset, then multiply by 5");
  movl(edi, ecx);
  shrl(edi, Constant(5));
  leal(edi, Address(edi, edi, times_4));

  comment("Get the appropriate CallInfo word; extract the nybble");
  movl(edi, Address(eax, edi, times_1, Constant(1)));
  shrl(edi);
  andl(edi, Constant(0xF));

  comment("Tag is (1 << value) >> 1.  This is 0 when value == 0");
  movl(ecx, edi);
  movl(edi, Constant(1));
  shll(edi);
  shrl(edi, Constant(1));

  comment("Store the tag");
  movl(Address(ebx), edi);

  comment("Are we done?");
  decl(esi); 
  addl(ebx, Constant(8));
  testl(esi, esi);
  jcc(greater_equal, Constant(loopx_entry));
bind(loopx_done);
  popl(ebx); 
  popl(ecx);
  ret();

  entry_end(); // interpreter_fill_in_tags
}
void LIR_Assembler::emit_op1(LIR_Op1* op) {
  switch (op->code()) {
    case lir_move:   
      if (op->move_kind() == lir_move_volatile) {
        assert(op->patch_code() == lir_patch_none, "can't patch volatiles");
        volatile_move_op(op->in_opr(), op->result_opr(), op->type(), op->info());
      } else {
move_op(op->in_opr(),op->result_opr(),op->tmp1_opr(),op->tmp2_opr(),op->tmp3_opr(),op->type(),
                op->patch_code(), op->info(), op->move_kind() == lir_move_unaligned);
      }
      break;

    case lir_prefetchr:
      prefetchr(op->in_opr());
      break;

    case lir_prefetchw:
      prefetchw(op->in_opr());
      break;

    case lir_return:
      return_op(op->in_opr()); 
      break;
    
    case lir_branch:
      break;

    case lir_push:
      push(op->in_opr());
      break;

    case lir_pop:
      pop(op->in_opr());
      break;

    case lir_neg:
      negate(op->in_opr(), op->result_opr());
      break;
    
    case lir_bit_test:
bit_test(op->in_opr(),op->result_opr());
      break;
    
    case lir_leal:
      leal(op->in_opr(), op->result_opr());
      break;
    
    case lir_null_check:
      if (GenerateCompilerNullChecks) {
null_check(op->in_opr(),op->info());
      }
      break;

    case lir_klassTable_oop_load:
      klassTable_oop_load(op->in_opr(), op->result_opr(), op->tmp1_opr());
      break;

    case lir_monaddr:
      monitor_address(op->in_opr()->as_constant_ptr()->as_jint(), op->result_opr());
      break;

    default:
      Unimplemented();
      break;
  }
}
Example #14
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
}