hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
author johnc
Thu, 07 Apr 2011 09:53:20 -0700
changeset 9176 42d9d1010f38
parent 8729 cdb7525d39cb
child 9181 d32bbcce6b1f
permissions -rw-r--r--
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer. Reviewed-by: kvn, iveresov, never, tonyp, dholmes
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
8067
f5f4eac4c48f 7008809: should report the class in ArrayStoreExceptions from compiled code
never
parents: 7427
diff changeset
     2
 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5046
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5046
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 5046
diff changeset
    21
 * questions.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
7397
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    25
#include "precompiled.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    26
#include "c1/c1_CodeStubs.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    27
#include "c1/c1_FrameMap.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    28
#include "c1/c1_LIRAssembler.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    29
#include "c1/c1_MacroAssembler.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    30
#include "c1/c1_Runtime1.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    31
#include "nativeInst_x86.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    32
#include "runtime/sharedRuntime.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    33
#include "vmreg_x86.inline.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    34
#ifndef SERIALGC
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    35
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
5b173b4ca846 6989984: Use standard include model for Hospot
stefank
parents: 6970
diff changeset
    36
#endif
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
#define __ ce->masm()->
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
float ConversionStub::float_zero = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
double ConversionStub::double_zero = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
void ConversionStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  assert(bytecode() == Bytecodes::_f2i || bytecode() == Bytecodes::_d2i, "other conversions do not require stub");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
  if (input()->is_single_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
    __ comiss(input()->as_xmm_float_reg(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
              ExternalAddress((address)&float_zero));
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  } else if (input()->is_double_xmm()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
    __ comisd(input()->as_xmm_double_reg(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
              ExternalAddress((address)&double_zero));
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  } else {
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
    56
    LP64_ONLY(ShouldNotReachHere());
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
    57
    __ push(rax);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
    __ ftst();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
    __ fnstsw_ax();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
    __ sahf();
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
    61
    __ pop(rax);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  Label NaN, do_return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
  __ jccb(Assembler::parity, NaN);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
  __ jccb(Assembler::below, do_return);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  // input is > 0 -> return maxInt
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
  // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  __ decrement(result()->as_register());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  __ jmpb(do_return);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
  // input is NaN -> return 0
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  __ bind(NaN);
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
    75
  __ xorptr(result()->as_register(), result()->as_register());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  __ bind(do_return);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
void CounterOverflowStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  __ bind(_entry);
6453
970dc585ab63 6953144: Tiered compilation
iveresov
parents: 5547
diff changeset
    83
  ce->store_parameter(_method->as_register(), 1);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  ce->store_parameter(_bci, 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::counter_overflow_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
  ce->verify_oop_map(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
                               bool throw_index_out_of_bounds_exception)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
  : _throw_index_out_of_bounds_exception(throw_index_out_of_bounds_exception)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  , _index(index)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
{
6745
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6453
diff changeset
    96
  assert(info != NULL, "must have info");
a34ef8968a84 6986046: C1 valuestack cleanup
roland
parents: 6453
diff changeset
    97
  _info = new CodeEmitInfo(info);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
void RangeCheckStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
  // pass the array index on stack because all registers must be preserved
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  if (_index->is_cpu_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    ce->store_parameter(_index->as_register(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
    ce->store_parameter(_index->as_jint(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  Runtime1::StubID stub_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
  if (_throw_index_out_of_bounds_exception) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
    stub_id = Runtime1::throw_index_exception_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
    stub_id = Runtime1::throw_range_check_failed_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  __ call(RuntimeAddress(Runtime1::entry_for(stub_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
  debug_only(__ should_not_reach_here());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  if (_offset != -1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_div0_exception_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
  debug_only(__ should_not_reach_here());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
// Implementation of NewInstanceStub
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
  _result = result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  _klass = klass;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  _klass_reg = klass_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
  _info = new CodeEmitInfo(info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  assert(stub_id == Runtime1::new_instance_id                 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
         stub_id == Runtime1::fast_new_instance_id            ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
         stub_id == Runtime1::fast_new_instance_init_check_id,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
         "need new_instance id");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
  _stub_id   = stub_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
void NewInstanceStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
  assert(__ rsp_offset() == 0, "frame size should be fixed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  __ bind(_entry);
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   150
  __ movptr(rdx, _klass_reg->as_register());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  __ call(RuntimeAddress(Runtime1::entry_for(_stub_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
  ce->verify_oop_map(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  assert(_result->as_register() == rax, "result must in rax,");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
// Implementation of NewTypeArrayStub
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
NewTypeArrayStub::NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  _klass_reg = klass_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  _length = length;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
  _result = result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  _info = new CodeEmitInfo(info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
void NewTypeArrayStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  assert(__ rsp_offset() == 0, "frame size should be fixed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
  assert(_length->as_register() == rbx, "length must in rbx,");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
  assert(_klass_reg->as_register() == rdx, "klass_reg must in rdx");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_type_array_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
  ce->verify_oop_map(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
  assert(_result->as_register() == rax, "result must in rax,");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
// Implementation of NewObjectArrayStub
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
NewObjectArrayStub::NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  _klass_reg = klass_reg;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  _result = result;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  _length = length;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
  _info = new CodeEmitInfo(info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
void NewObjectArrayStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
  assert(__ rsp_offset() == 0, "frame size should be fixed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
  assert(_length->as_register() == rbx, "length must in rbx,");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
  assert(_klass_reg->as_register() == rdx, "klass_reg must in rdx");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_object_array_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  ce->verify_oop_map(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
  assert(_result->as_register() == rax, "result must in rax,");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
// Implementation of MonitorAccessStubs
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
MonitorEnterStub::MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
: MonitorAccessStub(obj_reg, lock_reg)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
  _info = new CodeEmitInfo(info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
void MonitorEnterStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
  assert(__ rsp_offset() == 0, "frame size should be fixed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
  ce->store_parameter(_obj_reg->as_register(),  1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
  ce->store_parameter(_lock_reg->as_register(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
  Runtime1::StubID enter_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
  if (ce->compilation()->has_fpu_code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    enter_id = Runtime1::monitorenter_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
    enter_id = Runtime1::monitorenter_nofpu_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  __ call(RuntimeAddress(Runtime1::entry_for(enter_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  ce->verify_oop_map(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
void MonitorExitStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
  if (_compute_lock) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    // lock_reg was destroyed by fast unlocking attempt => recompute it
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
    ce->monitor_address(_monitor_ix, _lock_reg);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
  ce->store_parameter(_lock_reg->as_register(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
  // note: non-blocking leaf routine => no call info needed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
  Runtime1::StubID exit_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
  if (ce->compilation()->has_fpu_code()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
    exit_id = Runtime1::monitorexit_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
    exit_id = Runtime1::monitorexit_nofpu_id;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
  __ call(RuntimeAddress(Runtime1::entry_for(exit_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
// Implementation of patching:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
// - Copy the code at given offset to an inlined buffer (first the bytes, then the number of bytes)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
// - Replace original code with a call to the stub
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
// At Runtime:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
// - call to stub, jump to runtime
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
// - in runtime: preserve all registers (rspecially objects, i.e., source and destination object)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
// - in runtime: after initializing class, restore original code, reexecute instruction
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
int PatchingStub::_patch_info_offset = -NativeGeneralJump::instruction_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
void PatchingStub::align_patch_site(MacroAssembler* masm) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  // We're patching a 5-7 byte instruction on intel and we need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
  // make sure that we don't see a piece of the instruction.  It
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
  // appears mostly impossible on Intel to simply invalidate other
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
  // processors caches and since they may do aggressive prefetch it's
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
  // very hard to make a guess about what code might be in the icache.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
  // Force the instruction to be double word aligned so that it
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
  // doesn't span a cache line.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
  masm->align(round_to(NativeGeneralJump::instruction_size, wordSize));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
void PatchingStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
  assert(NativeCall::instruction_size <= _bytes_to_copy && _bytes_to_copy <= 0xFF, "not enough room for call");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
  Label call_patch;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
  // static field accesses have special semantics while the class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
  // initializer is being run so we emit a test which can be used to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
  // check that this code is being executed by the initializing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
  // thread.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
  address being_initialized_entry = __ pc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  if (CommentedAssembly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
    __ block_comment(" patch template");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
  if (_id == load_klass_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
    // produce a copy of the load klass instruction for use by the being initialized case
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
    address start = __ pc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
    jobject o = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
    __ movoop(_obj, o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
#ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
    for (int i = 0; i < _bytes_to_copy; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
      address ptr = (address)(_pc_start + i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
      int a_byte = (*ptr) & 0xFF;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
      assert(a_byte == *start++, "should be the same code");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
    // make a copy the code which is going to be patched.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
    for ( int i = 0; i < _bytes_to_copy; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
      address ptr = (address)(_pc_start + i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
      int a_byte = (*ptr) & 0xFF;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
      __ a_byte (a_byte);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
      *ptr = 0x90; // make the site look like a nop
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
  address end_of_patch = __ pc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
  int bytes_to_skip = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  if (_id == load_klass_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
    int offset = __ offset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
    if (CommentedAssembly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
      __ block_comment(" being_initialized check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
    assert(_obj != noreg, "must be a valid register");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
    Register tmp = rax;
8725
8c1e3dd5fe1b 7017732: move static fields into Class to prepare for perm gen removal
never
parents: 8067
diff changeset
   316
    Register tmp2 = rbx;
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   317
    __ push(tmp);
8725
8c1e3dd5fe1b 7017732: move static fields into Class to prepare for perm gen removal
never
parents: 8067
diff changeset
   318
    __ push(tmp2);
8729
cdb7525d39cb 7030300: more nightly failures after statics in Class changes
never
parents: 8725
diff changeset
   319
    __ load_heap_oop(tmp2, Address(_obj, java_lang_Class::klass_offset_in_bytes()));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
    __ get_thread(tmp);
8725
8c1e3dd5fe1b 7017732: move static fields into Class to prepare for perm gen removal
never
parents: 8067
diff changeset
   321
    __ cmpptr(tmp, Address(tmp2, instanceKlass::init_thread_offset_in_bytes() + sizeof(klassOopDesc)));
8c1e3dd5fe1b 7017732: move static fields into Class to prepare for perm gen removal
never
parents: 8067
diff changeset
   322
    __ pop(tmp2);
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   323
    __ pop(tmp);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
    __ jcc(Assembler::notEqual, call_patch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
    // access_field patches may execute the patched code before it's
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
    // copied back into place so we need to jump back into the main
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
    // code of the nmethod to continue execution.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
    __ jmp(_patch_site_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
    // make sure this extra code gets skipped
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
    bytes_to_skip += __ offset() - offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
  if (CommentedAssembly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
    __ block_comment("patch data encoded as movl");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
  // Now emit the patch record telling the runtime how to find the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  // pieces of the patch.  We only need 3 bytes but for readability of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
  // the disassembly we make the data look like a movl reg, imm32,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
  // which requires 5 bytes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
  int sizeof_patch_record = 5;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
  bytes_to_skip += sizeof_patch_record;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
  // emit the offsets needed to find the code to patch
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
  int being_initialized_entry_offset = __ pc() - being_initialized_entry + sizeof_patch_record;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  __ a_byte(0xB8);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  __ a_byte(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  __ a_byte(being_initialized_entry_offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  __ a_byte(bytes_to_skip);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
  __ a_byte(_bytes_to_copy);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
  address patch_info_pc = __ pc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
  assert(patch_info_pc - end_of_patch == bytes_to_skip, "incorrect patch info");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  address entry = __ pc();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
  NativeGeneralJump::insert_unconditional((address)_pc_start, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
  address target = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
  switch (_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
    case access_field_id:  target = Runtime1::entry_for(Runtime1::access_field_patching_id); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
    case load_klass_id:    target = Runtime1::entry_for(Runtime1::load_klass_patching_id); break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
    default: ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
  __ bind(call_patch);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
  if (CommentedAssembly) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
    __ block_comment("patch entry point");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  __ call(RuntimeAddress(target));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
  assert(_patch_info_offset == (patch_info_pc - __ pc()), "must not change");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  int jmp_off = __ offset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
  __ jmp(_patch_site_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  // Add enough nops so deoptimization can overwrite the jmp above with a call
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  // and not destroy the world.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
  for (int j = __ offset() ; j < jmp_off + 5 ; j++ ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
    __ nop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
  if (_id == load_klass_id) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
    CodeSection* cs = __ code_section();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
    RelocIterator iter(cs, (address)_pc_start, (address)(_pc_start + 1));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
    relocInfo::change_reloc_info_for_address(&iter, (address) _pc_start, relocInfo::oop_type, relocInfo::none);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
5046
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   386
void DeoptimizeStub::emit_code(LIR_Assembler* ce) {
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   387
  __ bind(_entry);
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   388
  __ call(RuntimeAddress(SharedRuntime::deopt_blob()->unpack_with_reexecution()));
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   389
  ce->add_call_info_here(_info);
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   390
  debug_only(__ should_not_reach_here());
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   391
}
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   392
27e801a857cb 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1412
diff changeset
   393
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  ce->compilation()->implicit_exception_table()->append(_offset, __ offset());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
  debug_only(__ should_not_reach_here());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
489c9b5090e2 Initial load
duke
parents:
diff changeset
   403
void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   404
  assert(__ rsp_offset() == 0, "frame size should be fixed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   405
489c9b5090e2 Initial load
duke
parents:
diff changeset
   406
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   407
  // pass the object on stack because all registers must be preserved
489c9b5090e2 Initial load
duke
parents:
diff changeset
   408
  if (_obj->is_cpu_register()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
    ce->store_parameter(_obj->as_register(), 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   410
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   411
  __ call(RuntimeAddress(Runtime1::entry_for(_stub)));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   412
  ce->add_call_info_here(_info);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   413
  debug_only(__ should_not_reach_here());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   414
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   415
489c9b5090e2 Initial load
duke
parents:
diff changeset
   416
489c9b5090e2 Initial load
duke
parents:
diff changeset
   417
void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   418
  //---------------slow case: call to native-----------------
489c9b5090e2 Initial load
duke
parents:
diff changeset
   419
  __ bind(_entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   420
  // Figure out where the args should go
489c9b5090e2 Initial load
duke
parents:
diff changeset
   421
  // This should really convert the IntrinsicID to the methodOop and signature
489c9b5090e2 Initial load
duke
parents:
diff changeset
   422
  // but I don't know how to do that.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   423
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
   424
  VMRegPair args[5];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
  BasicType signature[5] = { T_OBJECT, T_INT, T_OBJECT, T_INT, T_INT};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
  SharedRuntime::java_calling_convention(signature, args, 5, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
  // push parameters
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
  // (src, src_pos, dest, destPos, length)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
  Register r[5];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
  r[0] = src()->as_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  r[1] = src_pos()->as_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
  r[2] = dst()->as_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
  r[3] = dst_pos()->as_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
  r[4] = length()->as_register();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
  // next registers will get stored on the stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
  for (int i = 0; i < 5 ; i++ ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
    VMReg r_1 = args[i].first();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
    if (r_1->is_stack()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
      int st_off = r_1->reg2stack() * wordSize;
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   442
      __ movptr (Address(rsp, st_off), r[i]);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
      assert(r[i] == args[i].first()->as_Register(), "Wrong register for arg ");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  ce->align_call(lir_static_call);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
  ce->emit_static_call_stub();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
  AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
                         relocInfo::static_call_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
  __ call(resolve);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
  ce->add_call_info_here(info());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
#ifndef PRODUCT
1066
717c3345024f 5108146: Merge i486 and amd64 cpu directories
never
parents: 1
diff changeset
   457
  __ incrementl(ExternalAddress((address)&Runtime1::_arraycopy_slowcase_cnt));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
  __ jmp(_continuation);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   463
/////////////////////////////////////////////////////////////////////////////
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   464
#ifndef SERIALGC
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   465
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   466
void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
9176
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   467
  // At this point we know that marking is in progress.
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   468
  // If do_load() is true then we have to emit the
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   469
  // load of the previous value; otherwise it has already
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   470
  // been loaded into _pre_val.
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   471
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   472
  __ bind(_entry);
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   473
  assert(pre_val()->is_register(), "Precondition.");
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   474
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   475
  Register pre_val_reg = pre_val()->as_register();
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   476
9176
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   477
  if (do_load()) {
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   478
    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   479
  }
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   480
1394
apetrusenko
parents: 1066 1374
diff changeset
   481
  __ cmpptr(pre_val_reg, (int32_t) NULL_WORD);
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   482
  __ jcc(Assembler::equal, _continuation);
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   483
  ce->store_parameter(pre_val()->as_register(), 0);
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   484
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id)));
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   485
  __ jmp(_continuation);
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   486
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   487
}
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   488
9176
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   489
void G1UnsafeGetObjSATBBarrierStub::emit_code(LIR_Assembler* ce) {
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   490
  // At this point we know that offset == referent_offset.
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   491
  //
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   492
  // So we might have to emit:
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   493
  //   if (src == null) goto continuation.
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   494
  //
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   495
  // and we definitely have to emit:
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   496
  //   if (klass(src).reference_type == REF_NONE) goto continuation
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   497
  //   if (!marking_active) goto continuation
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   498
  //   if (pre_val == null) goto continuation
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   499
  //   call pre_barrier(pre_val)
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   500
  //   goto continuation
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   501
  //
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   502
  __ bind(_entry);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   503
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   504
  assert(src()->is_register(), "sanity");
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   505
  Register src_reg = src()->as_register();
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   506
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   507
  if (gen_src_check()) {
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   508
    // The original src operand was not a constant.
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   509
    // Generate src == null?
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   510
    __ cmpptr(src_reg, (int32_t) NULL_WORD);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   511
    __ jcc(Assembler::equal, _continuation);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   512
  }
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   513
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   514
  // Generate src->_klass->_reference_type == REF_NONE)?
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   515
  assert(tmp()->is_register(), "sanity");
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   516
  Register tmp_reg = tmp()->as_register();
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   517
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   518
  __ load_klass(tmp_reg, src_reg);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   519
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   520
  Address ref_type_adr(tmp_reg, instanceKlass::reference_type_offset_in_bytes() + sizeof(oopDesc));
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   521
  __ cmpl(ref_type_adr, REF_NONE);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   522
  __ jcc(Assembler::equal, _continuation);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   523
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   524
  // Is marking active?
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   525
  assert(thread()->is_register(), "precondition");
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   526
  Register thread_reg = thread()->as_register();
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   527
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   528
  Address in_progress(thread_reg, in_bytes(JavaThread::satb_mark_queue_offset() +
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   529
                                       PtrQueue::byte_offset_of_active()));
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   530
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   531
  if (in_bytes(PtrQueue::byte_width_of_active()) == 4) {
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   532
    __ cmpl(in_progress, 0);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   533
  } else {
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   534
    assert(in_bytes(PtrQueue::byte_width_of_active()) == 1, "Assumption");
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   535
    __ cmpb(in_progress, 0);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   536
  }
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   537
  __ jcc(Assembler::equal, _continuation);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   538
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   539
  // val == null?
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   540
  assert(val()->is_register(), "Precondition.");
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   541
  Register val_reg = val()->as_register();
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   542
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   543
  __ cmpptr(val_reg, (int32_t) NULL_WORD);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   544
  __ jcc(Assembler::equal, _continuation);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   545
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   546
  ce->store_parameter(val()->as_register(), 0);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   547
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id)));
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   548
  __ jmp(_continuation);
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   549
}
42d9d1010f38 7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents: 8729
diff changeset
   550
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   551
jbyte* G1PostBarrierStub::_byte_map_base = NULL;
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   552
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   553
jbyte* G1PostBarrierStub::byte_map_base_slow() {
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   554
  BarrierSet* bs = Universe::heap()->barrier_set();
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   555
  assert(bs->is_a(BarrierSet::G1SATBCTLogging),
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   556
         "Must be if we're using this.");
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   557
  return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   558
}
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   559
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   560
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   561
  __ bind(_entry);
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   562
  assert(addr()->is_register(), "Precondition.");
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   563
  assert(new_val()->is_register(), "Precondition.");
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   564
  Register new_val_reg = new_val()->as_register();
1394
apetrusenko
parents: 1066 1374
diff changeset
   565
  __ cmpptr(new_val_reg, (int32_t) NULL_WORD);
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   566
  __ jcc(Assembler::equal, _continuation);
6970
3ac175042286 6992477: fix for 6991512 broke sparc barriers
never
parents: 6745
diff changeset
   567
  ce->store_parameter(addr()->as_pointer_register(), 0);
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   568
  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id)));
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   569
  __ jmp(_continuation);
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   570
}
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   571
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   572
#endif // SERIALGC
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 1
diff changeset
   573
/////////////////////////////////////////////////////////////////////////////
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
#undef __