src/cpu/mips/vm/templateTable_mips_64.cpp

Tue, 12 Jun 2018 13:58:17 +0800

author
zhaixiang
date
Tue, 12 Jun 2018 13:58:17 +0800
changeset 9144
cecfc245b19a
parent 9135
69fd39209afe
child 9205
cce12244eb8c
permissions
-rw-r--r--

#7157 Fix all forgot saying delayed() when filling delay slot issues
Summary: enable check_delay and guarantee delay_state is at_delay_slot when filling delay slot
Reviewed-by: aoqi

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@8863 3 * Copyright (c) 2015, 2018, Loongson Technology. All rights reserved.
aoqi@1 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@1 5 *
aoqi@1 6 * This code is free software; you can redistribute it and/or modify it
aoqi@1 7 * under the terms of the GNU General Public License version 2 only, as
aoqi@1 8 * published by the Free Software Foundation.
aoqi@1 9 *
aoqi@1 10 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@1 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@1 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@1 13 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@1 14 * accompanied this code).
aoqi@1 15 *
aoqi@1 16 * You should have received a copy of the GNU General Public License version
aoqi@1 17 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@1 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@1 19 *
aoqi@1 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@1 21 * or visit www.oracle.com if you need additional information or have any
aoqi@1 22 * questions.
aoqi@1 23 *
aoqi@1 24 */
aoqi@1 25
aoqi@1 26 #include "precompiled.hpp"
aoqi@1 27 #include "asm/macroAssembler.hpp"
aoqi@1 28 #include "interpreter/interpreter.hpp"
aoqi@1 29 #include "interpreter/interpreterRuntime.hpp"
aoqi@1 30 #include "interpreter/templateTable.hpp"
aoqi@1 31 #include "memory/universe.inline.hpp"
aoqi@1 32 #include "oops/methodData.hpp"
aoqi@1 33 #include "oops/objArrayKlass.hpp"
aoqi@1 34 #include "oops/oop.inline.hpp"
aoqi@1 35 #include "prims/methodHandles.hpp"
aoqi@1 36 #include "runtime/sharedRuntime.hpp"
aoqi@1 37 #include "runtime/stubRoutines.hpp"
aoqi@1 38 #include "runtime/synchronizer.hpp"
aoqi@9043 39 #include "utilities/macros.hpp"
aoqi@1 40
aoqi@1 41
aoqi@1 42 #ifndef CC_INTERP
aoqi@1 43
aoqi@1 44 #define __ _masm->
aoqi@1 45
aoqi@1 46 // Platform-dependent initialization
aoqi@1 47
aoqi@1 48 void TemplateTable::pd_initialize() {
aoqi@1 49 // No mips specific initialization
aoqi@1 50 }
aoqi@1 51
aoqi@1 52 // Address computation: local variables
aoqi@6880 53
aoqi@1 54 static inline Address iaddress(int n) {
aoqi@1 55 return Address(LVP, Interpreter::local_offset_in_bytes(n));
aoqi@1 56 }
aoqi@1 57
aoqi@1 58 static inline Address laddress(int n) {
aoqi@1 59 return iaddress(n + 1);
aoqi@1 60 }
aoqi@1 61
aoqi@1 62 static inline Address faddress(int n) {
aoqi@1 63 return iaddress(n);
aoqi@1 64 }
aoqi@1 65
aoqi@1 66 static inline Address daddress(int n) {
aoqi@1 67 return laddress(n);
aoqi@1 68 }
aoqi@1 69
aoqi@1 70 static inline Address aaddress(int n) {
aoqi@1 71 return iaddress(n);
aoqi@1 72 }
aoqi@1 73 static inline Address haddress(int n) { return iaddress(n + 0); }
aoqi@1 74
aoqi@6880 75
aoqi@6880 76 static inline Address at_sp() { return Address(SP, 0); }
aoqi@1 77 static inline Address at_sp_p1() { return Address(SP, 1 * wordSize); }
aoqi@1 78 static inline Address at_sp_p2() { return Address(SP, 2 * wordSize); }
aoqi@1 79
aoqi@1 80 // At top of Java expression stack which may be different than esp(). It
aoqi@1 81 // isn't for category 1 objects.
aoqi@1 82 static inline Address at_tos () {
aoqi@1 83 Address tos = Address(SP, Interpreter::expr_offset_in_bytes(0));
aoqi@1 84 return tos;
aoqi@1 85 }
aoqi@1 86
aoqi@1 87 static inline Address at_tos_p1() {
aoqi@1 88 return Address(SP, Interpreter::expr_offset_in_bytes(1));
aoqi@1 89 }
aoqi@1 90
aoqi@1 91 static inline Address at_tos_p2() {
aoqi@1 92 return Address(SP, Interpreter::expr_offset_in_bytes(2));
aoqi@1 93 }
aoqi@1 94
aoqi@1 95 static inline Address at_tos_p3() {
aoqi@1 96 return Address(SP, Interpreter::expr_offset_in_bytes(3));
aoqi@1 97 }
aoqi@1 98
aoqi@6880 99 // we use S0 as bcp, be sure you have bcp in S0 before you call any of the Template generator
aoqi@1 100 Address TemplateTable::at_bcp(int offset) {
aoqi@1 101 assert(_desc->uses_bcp(), "inconsistent uses_bcp information");
aoqi@1 102 return Address(BCP, offset);
aoqi@1 103 }
aoqi@1 104
fujie@8001 105 // Miscelaneous helper routines
fujie@8001 106 // Store an oop (or NULL) at the address described by obj.
fujie@8001 107 // If val == noreg this means store a NULL
fujie@8001 108
fujie@8004 109 // rdx --> T3
fujie@8004 110 // rbx --> T1
fujie@8004 111 // r8 --> T9
fujie@8004 112 // r15 --> TREG
fujie@8001 113 static void do_oop_store(InterpreterMacroAssembler* _masm,
fujie@8001 114 Address obj,
fujie@8001 115 Register val,
fujie@8001 116 BarrierSet::Name barrier,
fujie@8001 117 bool precise) {
fujie@8001 118 assert(val == noreg || val == V0, "parameter is just for looks");
fujie@8001 119 switch (barrier) {
fujie@8001 120 #if INCLUDE_ALL_GCS
fujie@8003 121 case BarrierSet::G1SATBCT:
fujie@8003 122 case BarrierSet::G1SATBCTLogging:
fujie@8003 123 {
fujie@8004 124 // flatten object address if needed
fujie@8004 125 if (obj.index() == noreg && obj.disp() == 0) {
fujie@8004 126 if (obj.base() != T3) {
fujie@8004 127 __ move(T3, obj.base());
fujie@8004 128 }
fujie@8004 129 } else {
fujie@8004 130 __ lea(T3, obj);
fujie@8004 131 }
fujie@8004 132 __ g1_write_barrier_pre(T3 /* obj */,
fujie@8004 133 T1 /* pre_val */,
fujie@8004 134 TREG /* thread */,
fujie@8004 135 T9 /* tmp */,
fujie@8004 136 val != noreg /* tosca_live */,
fujie@8004 137 false /* expand_call */);
fujie@8004 138 if (val == noreg) {
fujie@8004 139 __ store_heap_oop_null(Address(T3, 0));
fujie@8004 140 } else {
fujie@8004 141 // G1 barrier needs uncompressed oop for region cross check.
fujie@8004 142 Register new_val = val;
fujie@8004 143 if (UseCompressedOops) {
fujie@8004 144 new_val = T1;
fujie@8004 145 __ move(new_val, val);
fujie@8004 146 }
fujie@8004 147 __ store_heap_oop(Address(T3, 0), val);
fujie@8004 148 __ g1_write_barrier_post(T3 /* store_adr */,
fujie@8004 149 new_val /* new_val */,
fujie@8004 150 TREG /* thread */,
fujie@8004 151 T9 /* tmp */,
fujie@8004 152 T1 /* tmp2 */);
fujie@8004 153 }
fujie@8003 154 }
fujie@8001 155 break;
fujie@8001 156 #endif // INCLUDE_ALL_GCS
fujie@8001 157 case BarrierSet::CardTableModRef:
fujie@8001 158 case BarrierSet::CardTableExtension:
fujie@8001 159 {
fujie@8001 160 if (val == noreg) {
fujie@8001 161 __ store_heap_oop_null(obj);
fujie@8001 162 } else {
fujie@8001 163 __ store_heap_oop(obj, val);
fujie@8001 164 // flatten object address if needed
fujie@8001 165 if (!precise || (obj.index() == noreg && obj.disp() == 0)) {
fujie@8001 166 __ store_check(obj.base());
fujie@8001 167 } else {
fujie@8003 168 __ lea(T9, obj);
fujie@8003 169 __ store_check(T9);
fujie@8001 170 }
fujie@8001 171 }
fujie@8001 172 }
fujie@8001 173 break;
fujie@8001 174 case BarrierSet::ModRef:
fujie@8001 175 case BarrierSet::Other:
fujie@8001 176 if (val == noreg) {
fujie@8001 177 __ store_heap_oop_null(obj);
fujie@8001 178 } else {
fujie@8001 179 __ store_heap_oop(obj, val);
fujie@8001 180 }
fujie@8001 181 break;
fujie@8001 182 default :
fujie@8001 183 ShouldNotReachHere();
fujie@8001 184
fujie@8001 185 }
fujie@8001 186 }
fujie@8001 187
aoqi@1 188 // bytecode folding
aoqi@1 189 void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
aoqi@6880 190 Register tmp_reg, bool load_bc_into_bc_reg/*=true*/,
aoqi@1 191 int byte_no) {
aoqi@6880 192 if (!RewriteBytecodes) return;
aoqi@1 193 Label L_patch_done;
aoqi@6880 194
aoqi@1 195 switch (bc) {
aoqi@1 196 case Bytecodes::_fast_aputfield:
aoqi@1 197 case Bytecodes::_fast_bputfield:
fujie@8858 198 case Bytecodes::_fast_zputfield:
aoqi@1 199 case Bytecodes::_fast_cputfield:
aoqi@1 200 case Bytecodes::_fast_dputfield:
aoqi@1 201 case Bytecodes::_fast_fputfield:
aoqi@1 202 case Bytecodes::_fast_iputfield:
aoqi@1 203 case Bytecodes::_fast_lputfield:
aoqi@1 204 case Bytecodes::_fast_sputfield:
aoqi@1 205 {
aoqi@6880 206 // We skip bytecode quickening for putfield instructions when
aoqi@6880 207 // the put_code written to the constant pool cache is zero.
aoqi@6880 208 // This is required so that every execution of this instruction
aoqi@6880 209 // calls out to InterpreterRuntime::resolve_get_put to do
aoqi@6880 210 // additional, required work.
aoqi@6880 211 assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
aoqi@6880 212 assert(load_bc_into_bc_reg, "we use bc_reg as temp");
aoqi@6880 213 __ get_cache_and_index_and_bytecode_at_bcp(tmp_reg, bc_reg, tmp_reg, byte_no, 1);
aoqi@6880 214 __ daddi(bc_reg, R0, bc);
aoqi@6880 215 __ beq(tmp_reg, R0, L_patch_done);
aoqi@6880 216 __ delayed()->nop();
aoqi@1 217 }
aoqi@1 218 break;
aoqi@1 219 default:
aoqi@1 220 assert(byte_no == -1, "sanity");
aoqi@6880 221 // the pair bytecodes have already done the load.
aoqi@6880 222 if (load_bc_into_bc_reg) {
aoqi@6880 223 __ move(bc_reg, bc);
aoqi@6880 224 }
aoqi@1 225 }
aoqi@1 226
aoqi@1 227 if (JvmtiExport::can_post_breakpoint()) {
aoqi@1 228 Label L_fast_patch;
aoqi@1 229 // if a breakpoint is present we can't rewrite the stream directly
aoqi@1 230 __ lbu(tmp_reg, at_bcp(0));
aoqi@1 231 __ move(AT, Bytecodes::_breakpoint);
aoqi@1 232 __ bne(tmp_reg, AT, L_fast_patch);
aoqi@1 233 __ delayed()->nop();
aoqi@1 234
aoqi@1 235 __ get_method(tmp_reg);
aoqi@6880 236 // Let breakpoint table handling rewrite to quicker bytecode
aoqi@6880 237 __ call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6880 238 InterpreterRuntime::set_original_bytecode_at), tmp_reg, BCP, bc_reg);
aoqi@1 239
aoqi@1 240 __ b(L_patch_done);
aoqi@1 241 __ delayed()->nop();
aoqi@1 242 __ bind(L_fast_patch);
aoqi@1 243 }
aoqi@1 244
aoqi@1 245 #ifdef ASSERT
aoqi@1 246 Label L_okay;
aoqi@1 247 __ lbu(tmp_reg, at_bcp(0));
aoqi@1 248 __ move(AT, (int)Bytecodes::java_code(bc));
aoqi@1 249 __ beq(tmp_reg, AT, L_okay);
aoqi@1 250 __ delayed()->nop();
aoqi@1 251 __ beq(tmp_reg, bc_reg, L_patch_done);
aoqi@1 252 __ delayed()->nop();
aoqi@1 253 __ stop("patching the wrong bytecode");
aoqi@1 254 __ bind(L_okay);
aoqi@1 255 #endif
aoqi@1 256
aoqi@1 257 // patch bytecode
aoqi@1 258 __ sb(bc_reg, at_bcp(0));
aoqi@1 259 __ bind(L_patch_done);
aoqi@1 260 }
aoqi@1 261
aoqi@1 262
aoqi@1 263 // Individual instructions
aoqi@1 264
aoqi@1 265 void TemplateTable::nop() {
aoqi@1 266 transition(vtos, vtos);
aoqi@1 267 // nothing to do
aoqi@1 268 }
aoqi@1 269
aoqi@1 270 void TemplateTable::shouldnotreachhere() {
aoqi@1 271 transition(vtos, vtos);
aoqi@1 272 __ stop("shouldnotreachhere bytecode");
aoqi@1 273 }
aoqi@1 274
aoqi@1 275 void TemplateTable::aconst_null() {
aoqi@1 276 transition(vtos, atos);
aoqi@1 277 __ move(FSR, R0);
aoqi@1 278 }
aoqi@1 279
aoqi@1 280 void TemplateTable::iconst(int value) {
aoqi@1 281 transition(vtos, itos);
aoqi@1 282 if (value == 0) {
aoqi@1 283 __ move(FSR, R0);
aoqi@1 284 } else {
aoqi@1 285 __ move(FSR, value);
aoqi@1 286 }
aoqi@1 287 }
aoqi@1 288
aoqi@1 289 void TemplateTable::lconst(int value) {
aoqi@1 290 transition(vtos, ltos);
aoqi@1 291 if (value == 0) {
aoqi@1 292 __ move(FSR, R0);
aoqi@1 293 } else {
aoqi@1 294 __ move(FSR, value);
aoqi@1 295 }
aoqi@1 296 }
aoqi@1 297
aoqi@1 298 void TemplateTable::fconst(int value) {
aoqi@1 299 transition(vtos, ftos);
aoqi@1 300 switch( value ) {
fujie@6888 301 case 0: __ mtc1(R0, FSF); return;
fujie@6888 302 case 1: __ addiu(AT, R0, 1); break;
fujie@6888 303 case 2: __ addiu(AT, R0, 2); break;
aoqi@1 304 default: ShouldNotReachHere();
aoqi@1 305 }
fujie@6888 306 __ mtc1(AT, FSF);
fujie@6888 307 __ cvt_s_w(FSF, FSF);
aoqi@1 308 }
aoqi@1 309
aoqi@1 310 void TemplateTable::dconst(int value) {
aoqi@1 311 transition(vtos, dtos);
aoqi@1 312 switch( value ) {
aoqi@7997 313 case 0: __ dmtc1(R0, FSF);
fujie@6888 314 return;
fujie@6888 315 case 1: __ daddiu(AT, R0, 1);
fujie@6888 316 __ dmtc1(AT, FSF);
fujie@6888 317 __ cvt_d_w(FSF, FSF);
fujie@6888 318 break;
aoqi@1 319 default: ShouldNotReachHere();
aoqi@1 320 }
aoqi@1 321 }
aoqi@1 322
aoqi@1 323 void TemplateTable::bipush() {
aoqi@1 324 transition(vtos, itos);
aoqi@1 325 __ lb(FSR, at_bcp(1));
aoqi@1 326 }
aoqi@1 327
aoqi@1 328 void TemplateTable::sipush() {
aoqi@6880 329 transition(vtos, itos);
fujie@6888 330 __ lb(FSR, BCP, 1);
fujie@6888 331 __ lbu(AT, BCP, 2);
aoqi@7997 332 __ dsll(FSR, FSR, 8);
fujie@6888 333 __ orr(FSR, FSR, AT);
aoqi@1 334 }
aoqi@1 335
aoqi@1 336 // T1 : tags
aoqi@1 337 // T2 : index
aoqi@1 338 // T3 : cpool
aoqi@1 339 // T8 : tag
aoqi@1 340 void TemplateTable::ldc(bool wide) {
aoqi@1 341 transition(vtos, vtos);
aoqi@1 342 Label call_ldc, notFloat, notClass, Done;
aoqi@1 343 // get index in cpool
aoqi@1 344 if (wide) {
fujie@6885 345 __ get_unsigned_2_byte_index_at_bcp(T2, 1);
aoqi@1 346 } else {
aoqi@1 347 __ lbu(T2, at_bcp(1));
aoqi@1 348 }
aoqi@1 349
aoqi@1 350 __ get_cpool_and_tags(T3, T1);
aoqi@1 351
aoqi@1 352 const int base_offset = ConstantPool::header_size() * wordSize;
aoqi@1 353 const int tags_offset = Array<u1>::base_offset_in_bytes();
aoqi@1 354
aoqi@1 355 // get type
fujie@6885 356 if (UseLoongsonISA && Assembler::is_simm(sizeof(tags_offset), 8)) {
fujie@6885 357 __ gslbx(T1, T1, T2, tags_offset);
fujie@6885 358 } else {
fujie@6885 359 __ dadd(AT, T1, T2);
fujie@6885 360 __ lb(T1, AT, tags_offset);
fujie@6885 361 }
aoqi@1 362 //now T1 is the tag
aoqi@1 363
aoqi@1 364 // unresolved class - get the resolved class
aoqi@1 365 __ daddiu(AT, T1, - JVM_CONSTANT_UnresolvedClass);
aoqi@1 366 __ beq(AT, R0, call_ldc);
aoqi@1 367 __ delayed()->nop();
aoqi@1 368
aoqi@1 369 // unresolved class in error (resolution failed) - call into runtime
aoqi@1 370 // so that the same error from first resolution attempt is thrown.
aoqi@6880 371 __ daddiu(AT, T1, -JVM_CONSTANT_UnresolvedClassInError);
aoqi@1 372 __ beq(AT, R0, call_ldc);
aoqi@1 373 __ delayed()->nop();
aoqi@1 374
aoqi@1 375 // resolved class - need to call vm to get java mirror of the class
aoqi@1 376 __ daddiu(AT, T1, - JVM_CONSTANT_Class);
aoqi@1 377 __ bne(AT, R0, notClass);
aoqi@1 378 __ delayed()->dsll(T2, T2, Address::times_8);
aoqi@1 379
aoqi@1 380 __ bind(call_ldc);
aoqi@1 381 __ move(A1, wide);
aoqi@1 382 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), A1);
fujie@6885 383 //__ push(atos);
fujie@6885 384 __ sd(FSR, SP, - Interpreter::stackElementSize);
aoqi@1 385 __ b(Done);
fujie@6885 386 __ delayed()->daddiu(SP, SP, - Interpreter::stackElementSize);
fujie@6885 387 __ nop(); // added for performance issue
fujie@6885 388
aoqi@1 389 __ bind(notClass);
aoqi@1 390 __ daddiu(AT, T1, -JVM_CONSTANT_Float);
aoqi@1 391 __ bne(AT, R0, notFloat);
aoqi@1 392 __ delayed()->nop();
aoqi@1 393 // ftos
fujie@6885 394 if (UseLoongsonISA && Assembler::is_simm(sizeof(base_offset), 8)) {
fujie@6885 395 __ gslwxc1(FSF, T3, T2, base_offset);
fujie@6885 396 } else {
fujie@6885 397 __ dadd(AT, T3, T2);
fujie@6885 398 __ lwc1(FSF, AT, base_offset);
fujie@6885 399 }
fujie@6885 400 //__ push_f();
fujie@6885 401 __ swc1(FSF, SP, - Interpreter::stackElementSize);
aoqi@1 402 __ b(Done);
fujie@6885 403 __ delayed()->daddiu(SP, SP, - Interpreter::stackElementSize);
aoqi@1 404
aoqi@1 405 __ bind(notFloat);
aoqi@1 406 #ifdef ASSERT
aoqi@6880 407 {
aoqi@1 408 Label L;
aoqi@1 409 __ daddiu(AT, T1, -JVM_CONSTANT_Integer);
aoqi@1 410 __ beq(AT, R0, L);
aoqi@1 411 __ delayed()->nop();
aoqi@1 412 __ stop("unexpected tag type in ldc");
aoqi@1 413 __ bind(L);
aoqi@1 414 }
aoqi@1 415 #endif
fujie@6885 416 // itos JVM_CONSTANT_Integer only
fujie@6885 417 if (UseLoongsonISA && Assembler::is_simm(sizeof(base_offset), 8)) {
fujie@6885 418 __ gslwx(FSR, T3, T2, base_offset);
fujie@6885 419 } else {
fujie@6885 420 __ dadd(T0, T3, T2);
fujie@6885 421 __ lw(FSR, T0, base_offset);
fujie@6885 422 }
aoqi@1 423 __ push(itos);
aoqi@1 424 __ bind(Done);
aoqi@1 425 }
aoqi@1 426
aoqi@1 427 // Fast path for caching oop constants.
aoqi@1 428 void TemplateTable::fast_aldc(bool wide) {
aoqi@1 429 transition(vtos, atos);
aoqi@1 430
aoqi@1 431 Register result = FSR;
aoqi@1 432 Register tmp = SSR;
aoqi@1 433 int index_size = wide ? sizeof(u2) : sizeof(u1);
aoqi@1 434
aoqi@1 435 Label resolved;
aoqi@6880 436
aoqi@6880 437 // We are resolved if the resolved reference cache entry contains a
aoqi@6880 438 // non-null object (String, MethodType, etc.)
aoqi@1 439 assert_different_registers(result, tmp);
aoqi@1 440 __ get_cache_index_at_bcp(tmp, 1, index_size);
aoqi@1 441 __ load_resolved_reference_at_index(result, tmp);
aoqi@1 442 __ bne(result, R0, resolved);
aoqi@1 443 __ delayed()->nop();
aoqi@1 444
aoqi@1 445 address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
aoqi@1 446 // first time invocation - must resolve first
aoqi@1 447 int i = (int)bytecode();
aoqi@1 448 __ move(tmp, i);
aoqi@1 449 __ call_VM(result, entry, tmp);
aoqi@1 450
aoqi@1 451 __ bind(resolved);
aoqi@1 452
aoqi@1 453 if (VerifyOops) {
aoqi@1 454 __ verify_oop(result);
aoqi@1 455 }
aoqi@1 456 }
aoqi@1 457
aoqi@1 458
aoqi@1 459 // used register: T2, T3, T1
aoqi@1 460 // T2 : index
aoqi@1 461 // T3 : cpool
aoqi@1 462 // T1 : tag
aoqi@1 463 void TemplateTable::ldc2_w() {
aoqi@1 464 transition(vtos, vtos);
aoqi@1 465 Label Long, Done;
aoqi@1 466
aoqi@1 467 // get index in cpool
fujie@6889 468 __ get_unsigned_2_byte_index_at_bcp(T2, 1);
aoqi@1 469
aoqi@1 470 __ get_cpool_and_tags(T3, T1);
aoqi@1 471
aoqi@1 472 const int base_offset = ConstantPool::header_size() * wordSize;
aoqi@1 473 const int tags_offset = Array<u1>::base_offset_in_bytes();
aoqi@1 474
aoqi@1 475 // get type in T1
fujie@6889 476 if (UseLoongsonISA && Assembler::is_simm(tags_offset, 8)) {
fujie@6889 477 __ gslbx(T1, T1, T2, tags_offset);
fujie@6889 478 } else {
fujie@6889 479 __ dadd(AT, T1, T2);
fujie@6889 480 __ lb(T1, AT, tags_offset);
fujie@6889 481 }
aoqi@1 482
aoqi@1 483 __ daddiu(AT, T1, - JVM_CONSTANT_Double);
aoqi@1 484 __ bne(AT, R0, Long);
aoqi@1 485 __ delayed()->dsll(T2, T2, Address::times_8);
fujie@6889 486
aoqi@6880 487 // dtos
fujie@6889 488 if (UseLoongsonISA && Assembler::is_simm(base_offset, 8)) {
fujie@6889 489 __ gsldxc1(FSF, T3, T2, base_offset);
fujie@6889 490 } else {
fujie@6889 491 __ daddu(AT, T3, T2);
fujie@6889 492 __ ldc1(FSF, AT, base_offset);
fujie@6889 493 }
aoqi@1 494 __ sdc1(FSF, SP, - 2 * wordSize);
aoqi@1 495 __ b(Done);
aoqi@1 496 __ delayed()->daddi(SP, SP, - 2 * wordSize);
aoqi@1 497
aoqi@1 498 // ltos
aoqi@1 499 __ bind(Long);
fujie@6889 500 if (UseLoongsonISA && Assembler::is_simm(base_offset, 8)) {
fujie@6889 501 __ gsldx(FSR, T3, T2, base_offset);
fujie@6889 502 } else {
fujie@6889 503 __ dadd(AT, T3, T2);
fujie@6889 504 __ ld(FSR, AT, base_offset);
fujie@6889 505 }
aoqi@1 506 __ push(ltos);
aoqi@1 507
aoqi@1 508 __ bind(Done);
aoqi@1 509 }
aoqi@1 510
aoqi@1 511 // we compute the actual local variable address here
aoqi@1 512 // the x86 dont do so for it has scaled index memory access model, we dont have, so do here
aoqi@1 513 void TemplateTable::locals_index(Register reg, int offset) {
aoqi@1 514 __ lbu(reg, at_bcp(offset));
aoqi@1 515 __ dsll(reg, reg, Address::times_8);
aoqi@1 516 __ dsub(reg, LVP, reg);
aoqi@1 517 }
aoqi@1 518
aoqi@1 519 // this method will do bytecode folding of the two form:
aoqi@6880 520 // iload iload iload caload
aoqi@1 521 // used register : T2, T3
aoqi@1 522 // T2 : bytecode
aoqi@1 523 // T3 : folded code
aoqi@1 524 void TemplateTable::iload() {
aoqi@1 525 transition(vtos, itos);
aoqi@6880 526 if (RewriteFrequentPairs) {
aoqi@1 527 Label rewrite, done;
aoqi@1 528 // get the next bytecode in T2
aoqi@1 529 __ lbu(T2, at_bcp(Bytecodes::length_for(Bytecodes::_iload)));
aoqi@1 530 // if _iload, wait to rewrite to iload2. We only want to rewrite the
aoqi@1 531 // last two iloads in a pair. Comparing against fast_iload means that
aoqi@1 532 // the next bytecode is neither an iload or a caload, and therefore
aoqi@1 533 // an iload pair.
aoqi@1 534 __ move(AT, Bytecodes::_iload);
aoqi@1 535 __ beq(AT, T2, done);
aoqi@1 536 __ delayed()->nop();
aoqi@1 537
aoqi@1 538 __ move(T3, Bytecodes::_fast_iload2);
aoqi@1 539 __ move(AT, Bytecodes::_fast_iload);
aoqi@1 540 __ beq(AT, T2, rewrite);
aoqi@1 541 __ delayed()->nop();
aoqi@1 542
aoqi@1 543 // if _caload, rewrite to fast_icaload
aoqi@1 544 __ move(T3, Bytecodes::_fast_icaload);
aoqi@1 545 __ move(AT, Bytecodes::_caload);
aoqi@1 546 __ beq(AT, T2, rewrite);
aoqi@1 547 __ delayed()->nop();
aoqi@1 548
aoqi@1 549 // rewrite so iload doesn't check again.
aoqi@1 550 __ move(T3, Bytecodes::_fast_iload);
aoqi@1 551
aoqi@1 552 // rewrite
aoqi@1 553 // T3 : fast bytecode
aoqi@1 554 __ bind(rewrite);
aoqi@1 555 patch_bytecode(Bytecodes::_iload, T3, T2, false);
aoqi@1 556 __ bind(done);
aoqi@1 557 }
aoqi@1 558
aoqi@1 559 // Get the local value into tos
aoqi@1 560 locals_index(T2);
aoqi@1 561 __ lw(FSR, T2, 0);
aoqi@1 562 }
aoqi@1 563
aoqi@1 564 // used register T2
aoqi@1 565 // T2 : index
aoqi@1 566 void TemplateTable::fast_iload2() {
aoqi@6880 567 transition(vtos, itos);
aoqi@6880 568 locals_index(T2);
aoqi@6880 569 __ lw(FSR, T2, 0);
aoqi@6880 570 __ push(itos);
aoqi@6880 571 locals_index(T2, 3);
aoqi@6880 572 __ lw(FSR, T2, 0);
aoqi@1 573 }
aoqi@6880 574
aoqi@1 575 // used register T2
aoqi@1 576 // T2 : index
aoqi@1 577 void TemplateTable::fast_iload() {
aoqi@1 578 transition(vtos, itos);
aoqi@1 579 locals_index(T2);
aoqi@1 580 __ lw(FSR, T2, 0);
aoqi@1 581 }
aoqi@1 582
aoqi@1 583 // used register T2
aoqi@1 584 // T2 : index
aoqi@1 585 void TemplateTable::lload() {
aoqi@1 586 transition(vtos, ltos);
aoqi@1 587 locals_index(T2);
aoqi@1 588 __ ld(FSR, T2, -wordSize);
aoqi@1 589 }
aoqi@1 590
aoqi@1 591 // used register T2
aoqi@1 592 // T2 : index
aoqi@1 593 void TemplateTable::fload() {
aoqi@1 594 transition(vtos, ftos);
aoqi@1 595 locals_index(T2);
aoqi@1 596 __ lwc1(FSF, T2, 0);
aoqi@1 597 }
aoqi@1 598
aoqi@1 599 // used register T2
aoqi@1 600 // T2 : index
aoqi@1 601 void TemplateTable::dload() {
aoqi@1 602 transition(vtos, dtos);
aoqi@1 603 locals_index(T2);
aoqi@6880 604 __ ldc1(FSF, T2, -wordSize);
aoqi@1 605 }
aoqi@1 606
aoqi@1 607 // used register T2
aoqi@1 608 // T2 : index
aoqi@6880 609 void TemplateTable::aload() {
aoqi@1 610 transition(vtos, atos);
aoqi@1 611 locals_index(T2);
aoqi@1 612 __ ld(FSR, T2, 0);
aoqi@1 613 }
aoqi@1 614
aoqi@1 615 void TemplateTable::locals_index_wide(Register reg) {
fujie@6890 616 __ get_unsigned_2_byte_index_at_bcp(reg, 2);
aoqi@1 617 __ dsll(reg, reg, Address::times_8);
aoqi@1 618 __ dsub(reg, LVP, reg);
aoqi@1 619 }
aoqi@1 620
aoqi@1 621 // used register T2
aoqi@1 622 // T2 : index
aoqi@1 623 void TemplateTable::wide_iload() {
aoqi@6880 624 transition(vtos, itos);
aoqi@6880 625 locals_index_wide(T2);
aoqi@6880 626 __ ld(FSR, T2, 0);
aoqi@1 627 }
aoqi@1 628
aoqi@1 629 // used register T2
aoqi@1 630 // T2 : index
aoqi@1 631 void TemplateTable::wide_lload() {
aoqi@6880 632 transition(vtos, ltos);
aoqi@6880 633 locals_index_wide(T2);
wangxue@6881 634 __ ld(FSR, T2, -wordSize);
aoqi@1 635 }
aoqi@1 636
aoqi@1 637 // used register T2
aoqi@1 638 // T2 : index
aoqi@1 639 void TemplateTable::wide_fload() {
aoqi@6880 640 transition(vtos, ftos);
aoqi@6880 641 locals_index_wide(T2);
aoqi@6880 642 __ lwc1(FSF, T2, 0);
aoqi@1 643 }
aoqi@1 644
aoqi@1 645 // used register T2
aoqi@1 646 // T2 : index
aoqi@1 647 void TemplateTable::wide_dload() {
aoqi@6880 648 transition(vtos, dtos);
aoqi@6880 649 locals_index_wide(T2);
wangxue@6881 650 __ ldc1(FSF, T2, -wordSize);
aoqi@1 651 }
aoqi@1 652
aoqi@1 653 // used register T2
aoqi@1 654 // T2 : index
aoqi@1 655 void TemplateTable::wide_aload() {
aoqi@6880 656 transition(vtos, atos);
aoqi@6880 657 locals_index_wide(T2);
aoqi@6880 658 __ ld(FSR, T2, 0);
aoqi@1 659 }
aoqi@1 660
aoqi@1 661 // we use A2 as the regiser for index, BE CAREFUL!
aoqi@1 662 // we dont use our tge 29 now, for later optimization
aoqi@1 663 void TemplateTable::index_check(Register array, Register index) {
aoqi@1 664 // Pop ptr into array
aoqi@1 665 __ pop_ptr(array);
aoqi@1 666 index_check_without_pop(array, index);
aoqi@1 667 }
aoqi@1 668
aoqi@1 669 void TemplateTable::index_check_without_pop(Register array, Register index) {
aoqi@1 670 // destroys ebx
aoqi@1 671 // check array
aoqi@1 672 __ null_check(array, arrayOopDesc::length_offset_in_bytes());
aoqi@1 673
fujie@108 674 #ifdef _LP64
fujie@108 675 // sign extend since tos (index) might contain garbage in upper bits
fujie@108 676 __ sll(index, index, 0);
fujie@108 677 #endif // _LP64
fujie@108 678
aoqi@1 679 // check index
aoqi@1 680 Label ok;
aoqi@1 681 __ lw(AT, array, arrayOopDesc::length_offset_in_bytes());
aoqi@1 682 #ifndef OPT_RANGECHECK
aoqi@1 683 __ sltu(AT, index, AT);
aoqi@1 684 __ bne(AT, R0, ok);
aoqi@6880 685 __ delayed()->nop();
aoqi@1 686
aoqi@1 687 //throw_ArrayIndexOutOfBoundsException assume abberrant index in A2
aoqi@6880 688 if (A2 != index) __ move(A2, index);
aoqi@1 689 __ jmp(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry);
aoqi@1 690 __ delayed()->nop();
aoqi@1 691 __ bind(ok);
aoqi@1 692 #else
aoqi@1 693 __ lw(AT, array, arrayOopDesc::length_offset_in_bytes());
aoqi@1 694 __ move(A2, index);
aoqi@1 695 __ tgeu(A2, AT, 29);
aoqi@1 696 #endif
aoqi@1 697 }
aoqi@1 698
aoqi@1 699 void TemplateTable::iaload() {
aoqi@1 700 transition(itos, itos);
aoqi@6880 701 if(UseBoundCheckInstruction) {
jiangshaofeng@362 702 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 703 __ dsll(FSR, FSR, 2);
jiangshaofeng@362 704 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 705 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_INT));
aoqi@6880 706
jiangshaofeng@362 707 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 708 __ dsll(AT, AT, 2);
jiangshaofeng@362 709 __ dadd(AT, SSR, AT);
jiangshaofeng@362 710 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_INT));
aoqi@6880 711
jiangshaofeng@362 712 __ gslwle(FSR, FSR, AT);
jiangshaofeng@362 713 } else {
jiangshaofeng@362 714 index_check(SSR, FSR);
jiangshaofeng@362 715 __ dsll(FSR, FSR, 2);
fujie@6890 716 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_INT), 8)) {
fujie@6890 717 __ gslwx(FSR, FSR, SSR, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6890 718 } else {
fujie@6890 719 __ dadd(FSR, SSR, FSR);
fujie@6890 720 __ lw(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6890 721 }
jiangshaofeng@362 722 }
aoqi@1 723 }
aoqi@1 724
aoqi@1 725 void TemplateTable::laload() {
aoqi@1 726 transition(itos, ltos);
jiangshaofeng@362 727 if(UseBoundCheckInstruction) {
jiangshaofeng@362 728 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 729 __ dsll(FSR, FSR, Address::times_8);
jiangshaofeng@362 730 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 731 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize);
aoqi@6880 732
jiangshaofeng@362 733 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 734 __ dsll(AT, AT, Address::times_8);
jiangshaofeng@362 735 __ dadd(AT, SSR, AT);
jiangshaofeng@362 736 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize);
aoqi@6880 737
aoqi@6880 738 __ gsldle(FSR, FSR, AT);
jiangshaofeng@362 739 } else {
jiangshaofeng@362 740 index_check(SSR, FSR);
jiangshaofeng@362 741 __ dsll(AT, FSR, Address::times_8);
fujie@6890 742 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_LONG), 8)) {
fujie@6890 743 __ gsldx(FSR, SSR, AT, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6890 744 } else {
fujie@6890 745 __ dadd(AT, SSR, AT);
fujie@6890 746 __ ld(FSR, AT, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6890 747 }
jiangshaofeng@362 748 }
aoqi@1 749 }
aoqi@1 750
aoqi@1 751 void TemplateTable::faload() {
jiangshaofeng@362 752 transition(itos, ftos);
jiangshaofeng@362 753 if(UseBoundCheckInstruction) {
jiangshaofeng@362 754 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 755 __ shl(FSR, 2);
jiangshaofeng@362 756 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 757 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
aoqi@6880 758
jiangshaofeng@362 759 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 760 __ shl(AT, 2);
jiangshaofeng@362 761 __ dadd(AT, SSR, AT);
jiangshaofeng@362 762 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
aoqi@6880 763
jiangshaofeng@362 764 __ gslwlec1(FSF, FSR, AT);
jiangshaofeng@362 765 } else {
aoqi@6880 766 index_check(SSR, FSR);
jiangshaofeng@362 767 __ shl(FSR, 2);
fujie@6890 768 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 8)) {
fujie@6890 769 __ gslwxc1(FSF, SSR, FSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6890 770 } else {
fujie@6890 771 __ dadd(FSR, SSR, FSR);
fujie@6890 772 __ lwc1(FSF, FSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6890 773 }
jiangshaofeng@362 774 }
aoqi@1 775 }
aoqi@1 776
aoqi@1 777 void TemplateTable::daload() {
jiangshaofeng@362 778 transition(itos, dtos);
jiangshaofeng@362 779 if(UseBoundCheckInstruction) {
jiangshaofeng@362 780 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 781 __ dsll(FSR, FSR, 3);
jiangshaofeng@362 782 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 783 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize);
aoqi@6880 784
jiangshaofeng@362 785 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 786 __ dsll(AT, AT, 3);
jiangshaofeng@362 787 __ dadd(AT, SSR, AT);
jiangshaofeng@362 788 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize);
aoqi@6880 789
jiangshaofeng@362 790 __ gsldlec1(FSF, FSR, AT);
jiangshaofeng@362 791 } else {
aoqi@6880 792 index_check(SSR, FSR);
jiangshaofeng@362 793 __ dsll(AT, FSR, 3);
fujie@6890 794 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 8)) {
fujie@6890 795 __ gsldxc1(FSF, SSR, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6890 796 } else {
fujie@6890 797 __ dadd(AT, SSR, AT);
fujie@6890 798 __ ldc1(FSF, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6890 799 }
jiangshaofeng@362 800 }
aoqi@1 801 }
aoqi@1 802
aoqi@1 803 void TemplateTable::aaload() {
aoqi@1 804 transition(itos, atos);
aoqi@1 805 index_check(SSR, FSR);
aoqi@1 806 __ dsll(FSR, FSR, UseCompressedOops ? Address::times_4 : Address::times_8);
aoqi@1 807 __ dadd(FSR, SSR, FSR);
aoqi@1 808 //add for compressedoops
aoqi@1 809 __ load_heap_oop(FSR, Address(FSR, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
aoqi@1 810 }
aoqi@1 811
aoqi@1 812 void TemplateTable::baload() {
aoqi@1 813 transition(itos, itos);
jiangshaofeng@362 814 if(UseBoundCheckInstruction) {
jiangshaofeng@362 815 __ pop(SSR); //SSR:array FSR:index
jiangshaofeng@362 816 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 817 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_BYTE)); //base
jiangshaofeng@362 818
aoqi@6880 819 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 820 __ dadd(AT, SSR, AT);
jiangshaofeng@362 821 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_BYTE)); //bound
jiangshaofeng@362 822
jiangshaofeng@362 823 __ gslble(FSR, FSR, AT);
jiangshaofeng@362 824 } else {
aoqi@6880 825 index_check(SSR, FSR);
fujie@6890 826 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_BYTE), 8)) {
fujie@6890 827 __ gslbx(FSR, SSR, FSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6890 828 } else {
fujie@6890 829 __ dadd(FSR, SSR, FSR);
fujie@6890 830 __ lb(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6890 831 }
jiangshaofeng@362 832 }
aoqi@1 833 }
aoqi@1 834
aoqi@1 835 void TemplateTable::caload() {
aoqi@1 836 transition(itos, itos);
aoqi@1 837 index_check(SSR, FSR);
aoqi@1 838 __ dsll(FSR, FSR, Address::times_2);
aoqi@1 839 __ dadd(FSR, SSR, FSR);
aoqi@1 840 __ lhu(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
aoqi@1 841 }
aoqi@1 842
aoqi@1 843 // iload followed by caload frequent pair
aoqi@1 844 // used register : T2
aoqi@1 845 // T2 : index
aoqi@1 846 void TemplateTable::fast_icaload() {
aoqi@1 847 transition(vtos, itos);
aoqi@1 848 // load index out of locals
aoqi@1 849 locals_index(T2);
aoqi@1 850 __ lw(FSR, T2, 0);
aoqi@1 851 index_check(SSR, FSR);
aoqi@1 852 __ dsll(FSR, FSR, 1);
aoqi@1 853 __ dadd(FSR, SSR, FSR);
aoqi@1 854 __ lhu(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
aoqi@1 855 }
aoqi@1 856
aoqi@1 857 void TemplateTable::saload() {
aoqi@1 858 transition(itos, itos);
jiangshaofeng@362 859 if(UseBoundCheckInstruction) {
jiangshaofeng@362 860 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 861 __ dsll(FSR, FSR, Address::times_2);
jiangshaofeng@362 862 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 863 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_SHORT));
aoqi@6880 864
jiangshaofeng@362 865 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 866 __ dsll(AT, AT, Address::times_2);
jiangshaofeng@362 867 __ dadd(AT, SSR, AT);
jiangshaofeng@362 868 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_SHORT));
aoqi@6880 869
aoqi@6880 870 __ gslhle(FSR, FSR, AT);
jiangshaofeng@362 871 } else {
aoqi@6880 872 index_check(SSR, FSR);
jiangshaofeng@362 873 __ dsll(FSR, FSR, Address::times_2);
fujie@6890 874 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_SHORT), 8)) {
fujie@6890 875 __ gslhx(FSR, SSR, FSR, arrayOopDesc::base_offset_in_bytes(T_SHORT));
fujie@6890 876 } else {
fujie@6890 877 __ dadd(FSR, SSR, FSR);
fujie@6890 878 __ lh(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_SHORT));
fujie@6890 879 }
jiangshaofeng@362 880 }
aoqi@1 881 }
aoqi@1 882
aoqi@1 883 void TemplateTable::iload(int n) {
aoqi@6880 884 transition(vtos, itos);
aoqi@6880 885 __ lw(FSR, iaddress(n));
aoqi@1 886 }
aoqi@1 887
aoqi@1 888 void TemplateTable::lload(int n) {
aoqi@6880 889 transition(vtos, ltos);
aoqi@6880 890 __ ld(FSR, laddress(n));
aoqi@1 891 }
aoqi@1 892
aoqi@1 893 void TemplateTable::fload(int n) {
aoqi@1 894 transition(vtos, ftos);
aoqi@1 895 __ lwc1(FSF, faddress(n));
aoqi@1 896 }
aoqi@6880 897
aoqi@1 898 void TemplateTable::dload(int n) {
aoqi@6880 899 transition(vtos, dtos);
aoqi@6880 900 __ ldc1(FSF, laddress(n));
aoqi@1 901 }
aoqi@1 902
aoqi@1 903 void TemplateTable::aload(int n) {
aoqi@1 904 transition(vtos, atos);
aoqi@1 905 __ ld(FSR, aaddress(n));
aoqi@1 906 }
aoqi@1 907
aoqi@1 908 // used register : T2, T3
aoqi@1 909 // T2 : bytecode
aoqi@1 910 // T3 : folded code
aoqi@1 911 void TemplateTable::aload_0() {
aoqi@6880 912 transition(vtos, atos);
aoqi@6880 913 // According to bytecode histograms, the pairs:
aoqi@6880 914 //
aoqi@6880 915 // _aload_0, _fast_igetfield
aoqi@6880 916 // _aload_0, _fast_agetfield
aoqi@6880 917 // _aload_0, _fast_fgetfield
aoqi@6880 918 //
aoqi@6880 919 // occur frequently. If RewriteFrequentPairs is set, the (slow)
aoqi@6880 920 // _aload_0 bytecode checks if the next bytecode is either
aoqi@6880 921 // _fast_igetfield, _fast_agetfield or _fast_fgetfield and then
aoqi@6880 922 // rewrites the current bytecode into a pair bytecode; otherwise it
aoqi@6880 923 // rewrites the current bytecode into _fast_aload_0 that doesn't do
aoqi@6880 924 // the pair check anymore.
aoqi@6880 925 //
aoqi@6880 926 // Note: If the next bytecode is _getfield, the rewrite must be
aoqi@6880 927 // delayed, otherwise we may miss an opportunity for a pair.
aoqi@6880 928 //
aoqi@6880 929 // Also rewrite frequent pairs
aoqi@6880 930 // aload_0, aload_1
aoqi@6880 931 // aload_0, iload_1
aoqi@6880 932 // These bytecodes with a small amount of code are most profitable
aoqi@6880 933 // to rewrite
aoqi@6880 934 if (RewriteFrequentPairs) {
aoqi@6880 935 Label rewrite, done;
aoqi@6880 936 // get the next bytecode in T2
aoqi@6880 937 __ lbu(T2, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0)));
aoqi@6880 938
aoqi@6880 939 // do actual aload_0
aoqi@6880 940 aload(0);
aoqi@6880 941
aoqi@6880 942 // if _getfield then wait with rewrite
aoqi@6880 943 __ move(AT, Bytecodes::_getfield);
aoqi@6880 944 __ beq(AT, T2, done);
aoqi@6880 945 __ delayed()->nop();
aoqi@6880 946
aoqi@6880 947 // if _igetfield then reqrite to _fast_iaccess_0
aoqi@6880 948 assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) ==
aoqi@6880 949 Bytecodes::_aload_0,
aoqi@6880 950 "fix bytecode definition");
aoqi@6880 951 __ move(T3, Bytecodes::_fast_iaccess_0);
aoqi@6880 952 __ move(AT, Bytecodes::_fast_igetfield);
aoqi@6880 953 __ beq(AT, T2, rewrite);
aoqi@6880 954 __ delayed()->nop();
aoqi@6880 955
aoqi@6880 956 // if _agetfield then reqrite to _fast_aaccess_0
aoqi@6880 957 assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) ==
aoqi@6880 958 Bytecodes::_aload_0,
aoqi@6880 959 "fix bytecode definition");
aoqi@6880 960 __ move(T3, Bytecodes::_fast_aaccess_0);
aoqi@6880 961 __ move(AT, Bytecodes::_fast_agetfield);
aoqi@6880 962 __ beq(AT, T2, rewrite);
aoqi@6880 963 __ delayed()->nop();
aoqi@6880 964
aoqi@6880 965 // if _fgetfield then reqrite to _fast_faccess_0
aoqi@6880 966 assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) ==
aoqi@6880 967 Bytecodes::_aload_0,
aoqi@6880 968 "fix bytecode definition");
aoqi@6880 969 __ move(T3, Bytecodes::_fast_faccess_0);
aoqi@6880 970 __ move(AT, Bytecodes::_fast_fgetfield);
aoqi@6880 971 __ beq(AT, T2, rewrite);
aoqi@6880 972 __ delayed()->nop();
aoqi@6880 973
aoqi@6880 974 // else rewrite to _fast_aload0
aoqi@6880 975 assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) ==
aoqi@6880 976 Bytecodes::_aload_0,
aoqi@6880 977 "fix bytecode definition");
aoqi@6880 978 __ move(T3, Bytecodes::_fast_aload_0);
aoqi@6880 979
aoqi@6880 980 // rewrite
aoqi@6880 981 __ bind(rewrite);
aoqi@6880 982 patch_bytecode(Bytecodes::_aload_0, T3, T2, false);
aoqi@6880 983
aoqi@6880 984 __ bind(done);
aoqi@6880 985 } else {
aoqi@6880 986 aload(0);
aoqi@6880 987 }
aoqi@1 988 }
aoqi@1 989
aoqi@1 990 void TemplateTable::istore() {
aoqi@6880 991 transition(itos, vtos);
aoqi@6880 992 locals_index(T2);
aoqi@6880 993 __ sw(FSR, T2, 0);
aoqi@1 994 }
aoqi@1 995
aoqi@1 996 void TemplateTable::lstore() {
aoqi@1 997 transition(ltos, vtos);
aoqi@1 998 locals_index(T2);
aoqi@1 999 __ sd(FSR, T2, -wordSize);
aoqi@1 1000 }
aoqi@1 1001
aoqi@1 1002 void TemplateTable::fstore() {
aoqi@6880 1003 transition(ftos, vtos);
aoqi@6880 1004 locals_index(T2);
aoqi@6880 1005 __ swc1(FSF, T2, 0);
aoqi@1 1006 }
aoqi@1 1007
aoqi@1 1008 void TemplateTable::dstore() {
aoqi@1 1009 transition(dtos, vtos);
aoqi@1 1010 locals_index(T2);
aoqi@1 1011 __ sdc1(FSF, T2, -wordSize);
aoqi@1 1012 }
aoqi@1 1013
aoqi@1 1014 void TemplateTable::astore() {
aoqi@1 1015 transition(vtos, vtos);
aoqi@1 1016 __ pop_ptr(FSR);
aoqi@1 1017 locals_index(T2);
aoqi@1 1018 __ sd(FSR, T2, 0);
aoqi@1 1019 }
aoqi@1 1020
aoqi@1 1021 void TemplateTable::wide_istore() {
aoqi@6880 1022 transition(vtos, vtos);
aoqi@6880 1023 __ pop_i(FSR);
aoqi@6880 1024 locals_index_wide(T2);
aoqi@6880 1025 __ sd(FSR, T2, 0);
aoqi@1 1026 }
aoqi@1 1027
aoqi@1 1028 void TemplateTable::wide_lstore() {
aoqi@6880 1029 transition(vtos, vtos);
aoqi@6880 1030 __ pop_l(FSR);
aoqi@6880 1031 locals_index_wide(T2);
wangxue@6881 1032 __ sd(FSR, T2, -wordSize);
aoqi@1 1033 }
aoqi@1 1034
aoqi@1 1035 void TemplateTable::wide_fstore() {
aoqi@6880 1036 wide_istore();
aoqi@1 1037 }
aoqi@1 1038
aoqi@1 1039 void TemplateTable::wide_dstore() {
aoqi@6880 1040 wide_lstore();
aoqi@1 1041 }
aoqi@1 1042
aoqi@1 1043 void TemplateTable::wide_astore() {
aoqi@6880 1044 transition(vtos, vtos);
aoqi@6880 1045 __ pop_ptr(FSR);
aoqi@6880 1046 locals_index_wide(T2);
aoqi@6880 1047 __ sd(FSR, T2, 0);
aoqi@1 1048 }
aoqi@1 1049
aoqi@1 1050 // used register : T2
aoqi@1 1051 void TemplateTable::iastore() {
aoqi@1 1052 transition(itos, vtos);
jiangshaofeng@362 1053 __ pop_i(SSR); // T2: array SSR: index
jiangshaofeng@362 1054 if(UseBoundCheckInstruction) {
aoqi@6880 1055 __ pop_ptr(T2);
jiangshaofeng@362 1056 __ dsll(SSR, SSR, Address::times_4);
jiangshaofeng@362 1057 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1058 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_INT)); // base
aoqi@6880 1059
aoqi@6880 1060 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1061 __ dsll(AT, AT, Address::times_4);
jiangshaofeng@362 1062 __ dadd(AT, T2, AT);
jiangshaofeng@362 1063 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_INT)); //bound
aoqi@6880 1064
jiangshaofeng@362 1065 __ gsswle(FSR, SSR, AT);
jiangshaofeng@362 1066 } else {
jiangshaofeng@362 1067 index_check(T2, SSR); // prefer index in ebx
jiangshaofeng@362 1068 __ dsll(SSR, SSR, Address::times_4);
fujie@6891 1069 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_INT), 8)) {
fujie@6891 1070 __ gsswx(FSR, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6891 1071 } else {
fujie@6891 1072 __ dadd(T2, T2, SSR);
fujie@6891 1073 __ sw(FSR, T2, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6891 1074 }
jiangshaofeng@362 1075 }
aoqi@1 1076 }
aoqi@1 1077
aoqi@1 1078
aoqi@1 1079
aoqi@1 1080 // used register T2, T3
aoqi@1 1081 void TemplateTable::lastore() {
aoqi@1 1082 transition(ltos, vtos);
aoqi@1 1083 __ pop_i (T2);
jiangshaofeng@362 1084 if(UseBoundCheckInstruction) {
aoqi@6880 1085 __ pop_ptr(T3);
jiangshaofeng@362 1086 __ dsll(T2, T2, Address::times_8);
jiangshaofeng@362 1087 __ dadd(T2, T3, T2);
jiangshaofeng@362 1088 __ addi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize); // base
aoqi@6880 1089
aoqi@6880 1090 __ lw(AT, T3, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1091 __ dsll(AT, AT, Address::times_8);
jiangshaofeng@362 1092 __ dadd(AT, T3, AT);
jiangshaofeng@362 1093 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize); //bound
aoqi@6880 1094
jiangshaofeng@362 1095 __ gssdle(FSR, T2, AT);
jiangshaofeng@362 1096 } else {
jiangshaofeng@362 1097 index_check(T3, T2);
jiangshaofeng@362 1098 __ dsll(T2, T2, Address::times_8);
fujie@6891 1099 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_LONG), 8)) {
fujie@6891 1100 __ gssdx(FSR, T3, T2, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6891 1101 } else {
fujie@6891 1102 __ dadd(T3, T3, T2);
fujie@6891 1103 __ sd(FSR, T3, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6891 1104 }
jiangshaofeng@362 1105 }
aoqi@1 1106 }
aoqi@1 1107
aoqi@1 1108 // used register T2
aoqi@1 1109 void TemplateTable::fastore() {
aoqi@1 1110 transition(ftos, vtos);
aoqi@6880 1111 __ pop_i(SSR);
jiangshaofeng@362 1112 if(UseBoundCheckInstruction) {
aoqi@6880 1113 __ pop_ptr(T2);
jiangshaofeng@362 1114 __ dsll(SSR, SSR, Address::times_4);
jiangshaofeng@362 1115 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1116 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT)); // base
aoqi@6880 1117
aoqi@6880 1118 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1119 __ dsll(AT, AT, Address::times_4);
jiangshaofeng@362 1120 __ dadd(AT, T2, AT);
jiangshaofeng@362 1121 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_FLOAT)); //bound
aoqi@6880 1122
jiangshaofeng@362 1123 __ gsswlec1(FSF, SSR, AT);
jiangshaofeng@362 1124 } else {
aoqi@6880 1125 index_check(T2, SSR);
jiangshaofeng@362 1126 __ dsll(SSR, SSR, Address::times_4);
fujie@6891 1127 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 8)) {
fujie@6891 1128 __ gsswxc1(FSF, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6891 1129 } else {
fujie@6891 1130 __ dadd(T2, T2, SSR);
fujie@6891 1131 __ swc1(FSF, T2, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6891 1132 }
jiangshaofeng@362 1133 }
aoqi@1 1134 }
aoqi@1 1135
aoqi@1 1136 // used register T2, T3
aoqi@1 1137 void TemplateTable::dastore() {
aoqi@1 1138 transition(dtos, vtos);
aoqi@6880 1139 __ pop_i (T2);
jiangshaofeng@362 1140 if(UseBoundCheckInstruction) {
aoqi@6880 1141 __ pop_ptr(T3);
jiangshaofeng@362 1142 __ dsll(T2, T2, Address::times_8);
jiangshaofeng@362 1143 __ dadd(T2, T3, T2);
jiangshaofeng@362 1144 __ addi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize); // base
aoqi@6880 1145
aoqi@6880 1146 __ lw(AT, T3, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1147 __ dsll(AT, AT, Address::times_8);
jiangshaofeng@362 1148 __ dadd(AT, T3, AT);
jiangshaofeng@362 1149 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize); //bound
aoqi@6880 1150
jiangshaofeng@362 1151 __ gssdlec1(FSF, T2, AT);
jiangshaofeng@362 1152 } else {
aoqi@6880 1153 index_check(T3, T2);
jiangshaofeng@362 1154 __ dsll(T2, T2, Address::times_8);
fujie@6891 1155 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 8)) {
fujie@6891 1156 __ gssdxc1(FSF, T3, T2, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6891 1157 } else {
fujie@6891 1158 __ daddu(T3, T3, T2);
fujie@6891 1159 __ sdc1(FSF, T3, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6891 1160 }
jiangshaofeng@362 1161 }
aoqi@1 1162 }
aoqi@1 1163
aoqi@1 1164 // used register : T2, T3, T8
aoqi@1 1165 // T2 : array
aoqi@1 1166 // T3 : subklass
aoqi@1 1167 // T8 : supklass
aoqi@1 1168 void TemplateTable::aastore() {
aoqi@1 1169 Label is_null, ok_is_subtype, done;
aoqi@1 1170 transition(vtos, vtos);
aoqi@1 1171 // stack: ..., array, index, value
aoqi@1 1172 __ ld(FSR, at_tos()); // Value
aoqi@1 1173 __ lw(SSR, at_tos_p1()); // Index
aoqi@1 1174 __ ld(T2, at_tos_p2()); // Array
aoqi@1 1175
aoqi@1 1176 // index_check(T2, SSR);
aoqi@1 1177 index_check_without_pop(T2, SSR);
aoqi@1 1178 // do array store check - check for NULL value first
aoqi@1 1179 __ beq(FSR, R0, is_null);
aoqi@1 1180 __ delayed()->nop();
aoqi@1 1181
aoqi@1 1182 // Move subklass into T3
aoqi@1 1183 //add for compressedoops
aoqi@1 1184 __ load_klass(T3, FSR);
aoqi@1 1185 // Move superklass into T8
aoqi@1 1186 //add for compressedoops
aoqi@1 1187 __ load_klass(T8, T2);
aoqi@1 1188 __ ld(T8, Address(T8, ObjArrayKlass::element_klass_offset()));
aoqi@1 1189 // Compress array+index*4+12 into a single register. T2
aoqi@1 1190 __ dsll(AT, SSR, UseCompressedOops? Address::times_4 : Address::times_8);
aoqi@1 1191 __ dadd(T2, T2, AT);
aoqi@1 1192 __ daddi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
aoqi@1 1193
aoqi@1 1194 // Generate subtype check.
aoqi@1 1195 // Superklass in T8. Subklass in T3.
fujie@8003 1196 __ gen_subtype_check(T8, T3, ok_is_subtype);
aoqi@1 1197 // Come here on failure
aoqi@1 1198 // object is at FSR
fujie@8003 1199 __ jmp(Interpreter::_throw_ArrayStoreException_entry);
aoqi@1 1200 __ delayed()->nop();
aoqi@1 1201 // Come here on success
aoqi@1 1202 __ bind(ok_is_subtype);
fujie@8003 1203 do_oop_store(_masm, Address(T2, 0), FSR, _bs->kind(), true);
aoqi@1 1204 __ b(done);
aoqi@1 1205 __ delayed()->nop();
aoqi@1 1206
aoqi@1 1207 // Have a NULL in FSR, EDX=T2, SSR=index. Store NULL at ary[idx]
aoqi@1 1208 __ bind(is_null);
aoqi@1 1209 __ profile_null_seen(T9);
aoqi@1 1210 __ dsll(AT, SSR, UseCompressedOops? Address::times_4 : Address::times_8);
aoqi@1 1211 __ dadd(T2, T2, AT);
fujie@8003 1212 do_oop_store(_masm, Address(T2, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), noreg, _bs->kind(), true);
aoqi@1 1213
aoqi@1 1214 __ bind(done);
aoqi@1 1215 __ daddi(SP, SP, 3 * Interpreter::stackElementSize);
aoqi@1 1216 }
aoqi@1 1217
aoqi@1 1218 void TemplateTable::bastore() {
aoqi@1 1219 transition(itos, vtos);
aoqi@6880 1220 __ pop_i(SSR);
jiangshaofeng@362 1221 if(UseBoundCheckInstruction) {
fujie@8858 1222 guarantee(false, "unimplemented yet!");
aoqi@6880 1223 __ pop_ptr(T2);
jiangshaofeng@362 1224 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1225 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // base
aoqi@6880 1226
aoqi@6880 1227 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1228 __ dadd(AT, T2, AT);
jiangshaofeng@362 1229 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_BYTE)); //bound
aoqi@6880 1230
jiangshaofeng@362 1231 __ gssble(FSR, SSR, AT);
jiangshaofeng@362 1232 } else {
jiangshaofeng@362 1233 index_check(T2, SSR);
fujie@8858 1234
fujie@8858 1235 // Need to check whether array is boolean or byte
fujie@8858 1236 // since both types share the bastore bytecode.
fujie@8858 1237 __ load_klass(T9, T2);
fujie@8858 1238 __ lw(T9, T9, in_bytes(Klass::layout_helper_offset()));
fujie@8858 1239
fujie@8858 1240 int diffbit = Klass::layout_helper_boolean_diffbit();
fujie@8858 1241 __ move(AT, diffbit);
fujie@8858 1242
fujie@8858 1243 Label L_skip;
fujie@8858 1244 __ andr(AT, T9, AT);
fujie@8858 1245 __ beq(AT, R0, L_skip);
zhaixiang@9144 1246 __ delayed()->nop();
fujie@8858 1247 __ andi(FSR, FSR, 0x1);
fujie@8858 1248 __ bind(L_skip);
fujie@8858 1249
fujie@6891 1250 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_BYTE), 8)) {
fujie@6891 1251 __ gssbx(FSR, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6891 1252 } else {
fujie@6891 1253 __ dadd(SSR, T2, SSR);
fujie@6891 1254 __ sb(FSR, SSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6891 1255 }
jiangshaofeng@362 1256 }
aoqi@1 1257 }
aoqi@1 1258
aoqi@1 1259 void TemplateTable::castore() {
aoqi@1 1260 transition(itos, vtos);
aoqi@6880 1261 __ pop_i(SSR);
jiangshaofeng@362 1262 if(UseBoundCheckInstruction) {
aoqi@6880 1263 __ pop_ptr(T2);
jiangshaofeng@362 1264 __ dsll(SSR, SSR, Address::times_2);
jiangshaofeng@362 1265 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1266 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_CHAR)); // base
aoqi@6880 1267
aoqi@6880 1268 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1269 __ dsll(AT, AT, Address::times_2);
jiangshaofeng@362 1270 __ dadd(AT, T2, AT);
jiangshaofeng@362 1271 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_CHAR)); //bound
aoqi@6880 1272
jiangshaofeng@362 1273 __ gsshle(FSR, SSR, AT);
jiangshaofeng@362 1274 } else {
aoqi@6880 1275 index_check(T2, SSR);
jiangshaofeng@362 1276 __ dsll(SSR, SSR, Address::times_2);
fujie@6891 1277 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_CHAR), 8)) {
fujie@6891 1278 __ gsshx(FSR, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
fujie@6891 1279 } else {
fujie@6891 1280 __ dadd(SSR, T2, SSR);
fujie@6891 1281 __ sh(FSR, SSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
fujie@6891 1282 }
jiangshaofeng@362 1283 }
aoqi@1 1284 }
aoqi@1 1285
aoqi@1 1286 void TemplateTable::sastore() {
aoqi@1 1287 castore();
aoqi@1 1288 }
aoqi@1 1289
aoqi@1 1290 void TemplateTable::istore(int n) {
aoqi@1 1291 transition(itos, vtos);
aoqi@1 1292 __ sw(FSR, iaddress(n));
aoqi@1 1293 }
aoqi@1 1294
aoqi@1 1295 void TemplateTable::lstore(int n) {
aoqi@1 1296 transition(ltos, vtos);
aoqi@1 1297 __ sd(FSR, laddress(n));
aoqi@1 1298 }
aoqi@1 1299
aoqi@1 1300 void TemplateTable::fstore(int n) {
aoqi@1 1301 transition(ftos, vtos);
aoqi@1 1302 __ swc1(FSF, faddress(n));
aoqi@1 1303 }
aoqi@1 1304
aoqi@1 1305 void TemplateTable::dstore(int n) {
aoqi@1 1306 transition(dtos, vtos);
aoqi@1 1307 __ sdc1(FSF, laddress(n));
aoqi@1 1308 }
aoqi@1 1309
aoqi@1 1310 void TemplateTable::astore(int n) {
aoqi@1 1311 transition(vtos, vtos);
aoqi@1 1312 __ pop_ptr(FSR);
aoqi@1 1313 __ sd(FSR, aaddress(n));
aoqi@1 1314 }
aoqi@1 1315
aoqi@1 1316 void TemplateTable::pop() {
aoqi@1 1317 transition(vtos, vtos);
aoqi@1 1318 __ daddi(SP, SP, Interpreter::stackElementSize);
aoqi@1 1319 }
aoqi@1 1320
aoqi@1 1321 void TemplateTable::pop2() {
aoqi@1 1322 transition(vtos, vtos);
aoqi@1 1323 __ daddi(SP, SP, 2 * Interpreter::stackElementSize);
aoqi@1 1324 }
aoqi@1 1325
aoqi@1 1326 void TemplateTable::dup() {
aoqi@1 1327 transition(vtos, vtos);
aoqi@1 1328 // stack: ..., a
aoqi@1 1329 __ load_ptr(0, FSR);
aoqi@1 1330 __ push_ptr(FSR);
aoqi@1 1331 // stack: ..., a, a
aoqi@1 1332 }
aoqi@1 1333
aoqi@1 1334 // blows FSR
aoqi@1 1335 void TemplateTable::dup_x1() {
aoqi@6880 1336 transition(vtos, vtos);
aoqi@6880 1337 // stack: ..., a, b
aoqi@6880 1338 __ load_ptr(0, FSR); // load b
aoqi@6880 1339 __ load_ptr(1, A5); // load a
aoqi@6880 1340 __ store_ptr(1, FSR); // store b
aoqi@6880 1341 __ store_ptr(0, A5); // store a
aoqi@6880 1342 __ push_ptr(FSR); // push b
aoqi@6880 1343 // stack: ..., b, a, b
aoqi@1 1344 }
aoqi@1 1345
aoqi@1 1346 // blows FSR
aoqi@1 1347 void TemplateTable::dup_x2() {
aoqi@6880 1348 transition(vtos, vtos);
aoqi@6880 1349 // stack: ..., a, b, c
aoqi@6880 1350 __ load_ptr(0, FSR); // load c
aoqi@6880 1351 __ load_ptr(2, A5); // load a
aoqi@6880 1352 __ store_ptr(2, FSR); // store c in a
aoqi@6880 1353 __ push_ptr(FSR); // push c
aoqi@6880 1354 // stack: ..., c, b, c, c
aoqi@6880 1355 __ load_ptr(2, FSR); // load b
aoqi@6880 1356 __ store_ptr(2, A5); // store a in b
aoqi@6880 1357 // stack: ..., c, a, c, c
aoqi@6880 1358 __ store_ptr(1, FSR); // store b in c
aoqi@6880 1359 // stack: ..., c, a, b, c
aoqi@1 1360 }
aoqi@1 1361
aoqi@1 1362 // blows FSR
aoqi@1 1363 void TemplateTable::dup2() {
aoqi@6880 1364 transition(vtos, vtos);
aoqi@6880 1365 // stack: ..., a, b
aoqi@6880 1366 __ load_ptr(1, FSR); // load a
aoqi@6880 1367 __ push_ptr(FSR); // push a
aoqi@6880 1368 __ load_ptr(1, FSR); // load b
aoqi@6880 1369 __ push_ptr(FSR); // push b
aoqi@6880 1370 // stack: ..., a, b, a, b
aoqi@1 1371 }
aoqi@1 1372
aoqi@1 1373 // blows FSR
aoqi@1 1374 void TemplateTable::dup2_x1() {
aoqi@6880 1375 transition(vtos, vtos);
aoqi@6880 1376 // stack: ..., a, b, c
aoqi@6880 1377 __ load_ptr(0, T2); // load c
aoqi@6880 1378 __ load_ptr(1, FSR); // load b
aoqi@6880 1379 __ push_ptr(FSR); // push b
aoqi@6880 1380 __ push_ptr(T2); // push c
aoqi@6880 1381 // stack: ..., a, b, c, b, c
aoqi@6880 1382 __ store_ptr(3, T2); // store c in b
aoqi@6880 1383 // stack: ..., a, c, c, b, c
aoqi@6880 1384 __ load_ptr(4, T2); // load a
aoqi@6880 1385 __ store_ptr(2, T2); // store a in 2nd c
aoqi@6880 1386 // stack: ..., a, c, a, b, c
aoqi@6880 1387 __ store_ptr(4, FSR); // store b in a
aoqi@6880 1388 // stack: ..., b, c, a, b, c
aoqi@6880 1389
aoqi@6880 1390 // stack: ..., b, c, a, b, c
aoqi@1 1391 }
aoqi@1 1392
aoqi@1 1393 // blows FSR, SSR
aoqi@1 1394 void TemplateTable::dup2_x2() {
aoqi@6880 1395 transition(vtos, vtos);
aoqi@6880 1396 // stack: ..., a, b, c, d
aoqi@6880 1397 // stack: ..., a, b, c, d
aoqi@6880 1398 __ load_ptr(0, T2); // load d
aoqi@6880 1399 __ load_ptr(1, FSR); // load c
aoqi@6880 1400 __ push_ptr(FSR); // push c
aoqi@6880 1401 __ push_ptr(T2); // push d
aoqi@6880 1402 // stack: ..., a, b, c, d, c, d
aoqi@6880 1403 __ load_ptr(4, FSR); // load b
aoqi@6880 1404 __ store_ptr(2, FSR); // store b in d
aoqi@6880 1405 __ store_ptr(4, T2); // store d in b
aoqi@6880 1406 // stack: ..., a, d, c, b, c, d
aoqi@6880 1407 __ load_ptr(5, T2); // load a
aoqi@6880 1408 __ load_ptr(3, FSR); // load c
aoqi@6880 1409 __ store_ptr(3, T2); // store a in c
aoqi@6880 1410 __ store_ptr(5, FSR); // store c in a
aoqi@6880 1411 // stack: ..., c, d, a, b, c, d
aoqi@6880 1412
aoqi@6880 1413 // stack: ..., c, d, a, b, c, d
aoqi@1 1414 }
aoqi@1 1415
aoqi@1 1416 // blows FSR
aoqi@1 1417 void TemplateTable::swap() {
aoqi@6880 1418 transition(vtos, vtos);
aoqi@6880 1419 // stack: ..., a, b
aoqi@6880 1420
aoqi@6880 1421 __ load_ptr(1, A5); // load a
aoqi@6880 1422 __ load_ptr(0, FSR); // load b
aoqi@6880 1423 __ store_ptr(0, A5); // store a in b
aoqi@6880 1424 __ store_ptr(1, FSR); // store b in a
aoqi@6880 1425
aoqi@6880 1426 // stack: ..., b, a
aoqi@1 1427 }
aoqi@1 1428
aoqi@1 1429 void TemplateTable::iop2(Operation op) {
aoqi@6880 1430 transition(itos, itos);
fujie@6887 1431
fujie@6887 1432 __ pop_i(SSR);
aoqi@6880 1433 switch (op) {
fujie@6887 1434 case add : __ addu32(FSR, SSR, FSR); break;
fujie@6887 1435 case sub : __ subu32(FSR, SSR, FSR); break;
fujie@6887 1436 case mul : __ mul(FSR, SSR, FSR); break;
fujie@6887 1437 case _and : __ andr(FSR, SSR, FSR); break;
fujie@6887 1438 case _or : __ orr(FSR, SSR, FSR); break;
fujie@6887 1439 case _xor : __ xorr(FSR, SSR, FSR); break;
fujie@6887 1440 case shl : __ sllv(FSR, SSR, FSR); break; // implicit masking of lower 5 bits by Intel shift instr. mips also
fujie@6887 1441 case shr : __ srav(FSR, SSR, FSR); break; // implicit masking of lower 5 bits by Intel shift instr. mips also
fujie@6887 1442 case ushr : __ srlv(FSR, SSR, FSR); break; // implicit masking of lower 5 bits by Intel shift instr. mips also
aoqi@6880 1443 default : ShouldNotReachHere();
aoqi@6880 1444 }
aoqi@1 1445 }
aoqi@1 1446
aoqi@1 1447 // the result stored in FSR, SSR,
aoqi@1 1448 // used registers : T2, T3
aoqi@1 1449 void TemplateTable::lop2(Operation op) {
aoqi@1 1450 transition(ltos, ltos);
fujie@6893 1451 __ pop_l(T2);
fujie@6893 1452
aoqi@1 1453 switch (op) {
fujie@6887 1454 case add : __ daddu(FSR, T2, FSR); break;
fujie@6887 1455 case sub : __ dsubu(FSR, T2, FSR); break;
fujie@6887 1456 case _and: __ andr(FSR, T2, FSR); break;
fujie@6887 1457 case _or : __ orr(FSR, T2, FSR); break;
fujie@6887 1458 case _xor: __ xorr(FSR, T2, FSR); break;
aoqi@1 1459 default : ShouldNotReachHere();
aoqi@1 1460 }
aoqi@1 1461 }
aoqi@1 1462
aoqi@6880 1463 // java require this bytecode could handle 0x80000000/-1, dont cause a overflow exception,
aoqi@1 1464 // the result is 0x80000000
aoqi@1 1465 // the godson2 cpu do the same, so we need not handle this specially like x86
aoqi@1 1466 void TemplateTable::idiv() {
aoqi@6880 1467 transition(itos, itos);
aoqi@6880 1468 Label not_zero;
aoqi@6880 1469
aoqi@6880 1470 __ bne(FSR, R0, not_zero);
aoqi@6880 1471 __ delayed()->nop();
aoqi@6880 1472 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@6880 1473 __ delayed()->nop();
aoqi@6880 1474 __ bind(not_zero);
aoqi@6880 1475
aoqi@6880 1476 __ pop_i(SSR);
aoqi@6880 1477 if (UseLoongsonISA) {
aoqi@6880 1478 __ gsdiv(FSR, SSR, FSR);
aoqi@6880 1479 } else {
aoqi@6880 1480 __ div(SSR, FSR);
aoqi@6880 1481 __ mflo(FSR);
aoqi@6880 1482 }
aoqi@1 1483 }
aoqi@1 1484
aoqi@1 1485 void TemplateTable::irem() {
aoqi@6880 1486 transition(itos, itos);
aoqi@6880 1487 Label not_zero;
aoqi@6880 1488 __ pop_i(SSR);
aoqi@6880 1489 __ div(SSR, FSR);
aoqi@6880 1490
aoqi@6880 1491 __ bne(FSR, R0, not_zero);
aoqi@6880 1492 __ delayed()->nop();
aoqi@6880 1493 //__ brk(7);
aoqi@6880 1494 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@6880 1495 __ delayed()->nop();
aoqi@6880 1496
aoqi@6880 1497 __ bind(not_zero);
aoqi@6880 1498 __ mfhi(FSR);
aoqi@1 1499 }
aoqi@1 1500
aoqi@1 1501 void TemplateTable::lmul() {
aoqi@1 1502 transition(ltos, ltos);
jiangshaofeng@89 1503 __ pop_l(T2);
jiangshaofeng@89 1504 if(UseLoongsonISA){
jiangshaofeng@89 1505 __ gsdmult(FSR, T2, FSR);
jiangshaofeng@89 1506 } else {
aoqi@6880 1507 __ dmult(T2, FSR);
aoqi@6880 1508 __ mflo(FSR);
aoqi@6880 1509 }
aoqi@6880 1510 }
aoqi@1 1511
aoqi@1 1512 // NOTE: i DONT use the Interpreter::_throw_ArithmeticException_entry
aoqi@1 1513 void TemplateTable::ldiv() {
aoqi@1 1514 transition(ltos, ltos);
aoqi@1 1515 Label normal;
aoqi@1 1516
aoqi@1 1517 __ bne(FSR, R0, normal);
aoqi@1 1518 __ delayed()->nop();
aoqi@1 1519
aoqi@6880 1520 //__ brk(7); //generate FPE
aoqi@1 1521 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@1 1522 __ delayed()->nop();
aoqi@1 1523
aoqi@1 1524 __ bind(normal);
fujie@6893 1525 __ pop_l(A2);
chenhaoxuan@87 1526 if (UseLoongsonISA) {
aoqi@6880 1527 __ gsddiv(FSR, A2, FSR);
chenhaoxuan@87 1528 } else {
chenhaoxuan@87 1529 __ ddiv(A2, FSR);
chenhaoxuan@87 1530 __ mflo(FSR);
chenhaoxuan@87 1531 }
aoqi@1 1532 }
aoqi@1 1533
aoqi@1 1534 // NOTE: i DONT use the Interpreter::_throw_ArithmeticException_entry
aoqi@1 1535 void TemplateTable::lrem() {
aoqi@1 1536 transition(ltos, ltos);
aoqi@1 1537 Label normal;
aoqi@1 1538
aoqi@1 1539 __ bne(FSR, R0, normal);
aoqi@1 1540 __ delayed()->nop();
aoqi@1 1541
aoqi@1 1542 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@1 1543 __ delayed()->nop();
aoqi@1 1544
aoqi@1 1545 __ bind(normal);
fujie@6893 1546 __ pop_l (A2);
lifangyuan@88 1547
lifangyuan@88 1548 if(UseLoongsonISA){
lifangyuan@88 1549 __ gsdmod(FSR, A2, FSR);
aoqi@6880 1550 } else {
lifangyuan@88 1551 __ ddiv(A2, FSR);
lifangyuan@88 1552 __ mfhi(FSR);
lifangyuan@88 1553 }
aoqi@1 1554 }
aoqi@1 1555
aoqi@1 1556 // result in FSR
aoqi@1 1557 // used registers : T0
aoqi@1 1558 void TemplateTable::lshl() {
aoqi@1 1559 transition(itos, ltos);
fujie@6893 1560 __ pop_l(T0);
aoqi@1 1561 __ dsllv(FSR, T0, FSR);
aoqi@1 1562 }
aoqi@1 1563
aoqi@1 1564 // used registers : T0
aoqi@1 1565 void TemplateTable::lshr() {
aoqi@1 1566 transition(itos, ltos);
fujie@6893 1567 __ pop_l(T0);
aoqi@1 1568 __ dsrav(FSR, T0, FSR);
aoqi@1 1569 }
aoqi@1 1570
aoqi@1 1571 // used registers : T0
aoqi@1 1572 void TemplateTable::lushr() {
aoqi@1 1573 transition(itos, ltos);
fujie@6893 1574 __ pop_l(T0);
aoqi@1 1575 __ dsrlv(FSR, T0, FSR);
aoqi@1 1576 }
aoqi@1 1577
aoqi@1 1578 // result in FSF
aoqi@1 1579 void TemplateTable::fop2(Operation op) {
aoqi@6880 1580 transition(ftos, ftos);
aoqi@6880 1581 switch (op) {
aoqi@6880 1582 case add:
aoqi@6880 1583 __ lwc1(FTF, at_sp());
aoqi@6880 1584 __ add_s(FSF, FTF, FSF);
aoqi@6880 1585 break;
aoqi@6880 1586 case sub:
aoqi@6880 1587 __ lwc1(FTF, at_sp());
aoqi@6880 1588 __ sub_s(FSF, FTF, FSF);
aoqi@6880 1589 break;
aoqi@6880 1590 case mul:
aoqi@6880 1591 __ lwc1(FTF, at_sp());
aoqi@6880 1592 __ mul_s(FSF, FTF, FSF);
aoqi@6880 1593 break;
aoqi@6880 1594 case div:
aoqi@6880 1595 __ lwc1(FTF, at_sp());
aoqi@6880 1596 __ div_s(FSF, FTF, FSF);
aoqi@6880 1597 break;
aoqi@6880 1598 case rem:
aoqi@6880 1599 __ mov_s(F13, FSF);
aoqi@6880 1600 __ lwc1(F12, at_sp());
aoqi@6880 1601 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::frem), 2);
aoqi@6880 1602 break;
aoqi@6880 1603 default : ShouldNotReachHere();
aoqi@6880 1604 }
aoqi@6880 1605
aoqi@6880 1606 __ daddi(SP, SP, 1 * wordSize);
aoqi@1 1607 }
aoqi@1 1608
aoqi@1 1609 // result in SSF||FSF
aoqi@1 1610 // i dont handle the strict flags
aoqi@1 1611 void TemplateTable::dop2(Operation op) {
aoqi@6880 1612 transition(dtos, dtos);
aoqi@6880 1613 switch (op) {
aoqi@6880 1614 case add:
aoqi@6880 1615 __ ldc1(FTF, at_sp());
aoqi@6880 1616 __ add_d(FSF, FTF, FSF);
aoqi@6880 1617 break;
aoqi@6880 1618 case sub:
aoqi@6880 1619 __ ldc1(FTF, at_sp());
aoqi@6880 1620 __ sub_d(FSF, FTF, FSF);
aoqi@6880 1621 break;
aoqi@6880 1622 case mul:
aoqi@6880 1623 __ ldc1(FTF, at_sp());
aoqi@6880 1624 __ mul_d(FSF, FTF, FSF);
aoqi@6880 1625 break;
aoqi@6880 1626 case div:
aoqi@6880 1627 __ ldc1(FTF, at_sp());
aoqi@6880 1628 __ div_d(FSF, FTF, FSF);
aoqi@6880 1629 break;
aoqi@6880 1630 case rem:
aoqi@6880 1631 __ mov_d(F13, FSF);
aoqi@6880 1632 __ ldc1(F12, at_sp());
aoqi@6880 1633 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::drem), 2);
aoqi@6880 1634 break;
aoqi@6880 1635 default : ShouldNotReachHere();
aoqi@6880 1636 }
aoqi@6880 1637
aoqi@6880 1638 __ daddi(SP, SP, 2 * wordSize);
aoqi@1 1639 }
aoqi@1 1640
aoqi@1 1641 void TemplateTable::ineg() {
aoqi@6880 1642 transition(itos, itos);
wangxue@7998 1643 __ subu32(FSR, R0, FSR);
aoqi@1 1644 }
aoqi@1 1645
aoqi@1 1646 void TemplateTable::lneg() {
aoqi@6880 1647 transition(ltos, ltos);
aoqi@6880 1648 __ dsubu(FSR, R0, FSR);
aoqi@1 1649 }
aoqi@6880 1650
aoqi@6880 1651 void TemplateTable::fneg() {
aoqi@6880 1652 transition(ftos, ftos);
aoqi@6880 1653 __ neg_s(FSF, FSF);
aoqi@1 1654 }
aoqi@1 1655
aoqi@1 1656 void TemplateTable::dneg() {
aoqi@6880 1657 transition(dtos, dtos);
aoqi@6880 1658 __ neg_d(FSF, FSF);
aoqi@1 1659 }
aoqi@1 1660
aoqi@1 1661 // used registers : T2
aoqi@1 1662 void TemplateTable::iinc() {
aoqi@6880 1663 transition(vtos, vtos);
aoqi@6880 1664 locals_index(T2);
aoqi@6880 1665 __ lw(FSR, T2, 0);
aoqi@6880 1666 __ lb(AT, at_bcp(2)); // get constant
aoqi@6880 1667 __ daddu(FSR, FSR, AT);
aoqi@6880 1668 __ sw(FSR, T2, 0);
aoqi@1 1669 }
aoqi@1 1670
aoqi@1 1671 // used register : T2
aoqi@1 1672 void TemplateTable::wide_iinc() {
aoqi@6880 1673 transition(vtos, vtos);
aoqi@6880 1674 locals_index_wide(T2);
aoqi@6880 1675 __ get_2_byte_integer_at_bcp(FSR, AT, 4);
aoqi@6880 1676 __ hswap(FSR);
aoqi@6880 1677 __ lw(AT, T2, 0);
aoqi@6880 1678 __ daddu(FSR, AT, FSR);
aoqi@6880 1679 __ sw(FSR, T2, 0);
aoqi@1 1680 }
aoqi@1 1681
aoqi@1 1682 void TemplateTable::convert() {
aoqi@1 1683 // Checking
aoqi@1 1684 #ifdef ASSERT
aoqi@6880 1685 {
aoqi@6880 1686 TosState tos_in = ilgl;
aoqi@1 1687 TosState tos_out = ilgl;
aoqi@1 1688 switch (bytecode()) {
aoqi@1 1689 case Bytecodes::_i2l: // fall through
aoqi@1 1690 case Bytecodes::_i2f: // fall through
aoqi@1 1691 case Bytecodes::_i2d: // fall through
aoqi@1 1692 case Bytecodes::_i2b: // fall through
aoqi@1 1693 case Bytecodes::_i2c: // fall through
aoqi@1 1694 case Bytecodes::_i2s: tos_in = itos; break;
aoqi@1 1695 case Bytecodes::_l2i: // fall through
aoqi@1 1696 case Bytecodes::_l2f: // fall through
aoqi@1 1697 case Bytecodes::_l2d: tos_in = ltos; break;
aoqi@1 1698 case Bytecodes::_f2i: // fall through
aoqi@1 1699 case Bytecodes::_f2l: // fall through
aoqi@1 1700 case Bytecodes::_f2d: tos_in = ftos; break;
aoqi@1 1701 case Bytecodes::_d2i: // fall through
aoqi@1 1702 case Bytecodes::_d2l: // fall through
aoqi@1 1703 case Bytecodes::_d2f: tos_in = dtos; break;
aoqi@1 1704 default : ShouldNotReachHere();
aoqi@1 1705 }
aoqi@1 1706 switch (bytecode()) {
aoqi@1 1707 case Bytecodes::_l2i: // fall through
aoqi@1 1708 case Bytecodes::_f2i: // fall through
aoqi@1 1709 case Bytecodes::_d2i: // fall through
aoqi@1 1710 case Bytecodes::_i2b: // fall through
aoqi@1 1711 case Bytecodes::_i2c: // fall through
aoqi@1 1712 case Bytecodes::_i2s: tos_out = itos; break;
aoqi@1 1713 case Bytecodes::_i2l: // fall through
aoqi@1 1714 case Bytecodes::_f2l: // fall through
aoqi@1 1715 case Bytecodes::_d2l: tos_out = ltos; break;
aoqi@1 1716 case Bytecodes::_i2f: // fall through
aoqi@1 1717 case Bytecodes::_l2f: // fall through
aoqi@1 1718 case Bytecodes::_d2f: tos_out = ftos; break;
aoqi@1 1719 case Bytecodes::_i2d: // fall through
aoqi@1 1720 case Bytecodes::_l2d: // fall through
aoqi@1 1721 case Bytecodes::_f2d: tos_out = dtos; break;
aoqi@1 1722 default : ShouldNotReachHere();
aoqi@1 1723 }
aoqi@1 1724 transition(tos_in, tos_out);
aoqi@1 1725 }
aoqi@1 1726 #endif // ASSERT
aoqi@1 1727
aoqi@1 1728 // Conversion
aoqi@1 1729 // (Note: use pushl(ecx)/popl(ecx) for 1/2-word stack-ptr manipulation)
aoqi@1 1730 switch (bytecode()) {
aoqi@1 1731 case Bytecodes::_i2l:
aoqi@1 1732 __ sll(FSR, FSR, 0);
aoqi@1 1733 break;
aoqi@1 1734 case Bytecodes::_i2f:
aoqi@1 1735 __ mtc1(FSR, FSF);
aoqi@1 1736 __ cvt_s_w(FSF, FSF);
aoqi@1 1737 break;
aoqi@1 1738 case Bytecodes::_i2d:
aoqi@1 1739 __ mtc1(FSR, FSF);
aoqi@1 1740 __ cvt_d_w(FSF, FSF);
aoqi@1 1741 break;
aoqi@1 1742 case Bytecodes::_i2b:
fujie@256 1743 __ seb(FSR, FSR);
aoqi@1 1744 break;
aoqi@1 1745 case Bytecodes::_i2c:
aoqi@1 1746 __ andi(FSR, FSR, 0xFFFF); // truncate upper 56 bits
aoqi@1 1747 break;
aoqi@1 1748 case Bytecodes::_i2s:
fujie@256 1749 __ seh(FSR, FSR);
aoqi@1 1750 break;
aoqi@1 1751 case Bytecodes::_l2i:
fujie@257 1752 __ sll(FSR, FSR, 0);
aoqi@1 1753 break;
aoqi@1 1754 case Bytecodes::_l2f:
aoqi@1 1755 __ dmtc1(FSR, FSF);
aoqi@1 1756 __ cvt_s_l(FSF, FSF);
aoqi@1 1757 break;
aoqi@1 1758 case Bytecodes::_l2d:
aoqi@1 1759 __ dmtc1(FSR, FSF);
aoqi@1 1760 __ cvt_d_l(FSF, FSF);
aoqi@1 1761 break;
aoqi@1 1762 case Bytecodes::_f2i:
aoqi@6880 1763 {
aoqi@6880 1764 Label L;
aoqi@6880 1765
aoqi@6880 1766 __ trunc_w_s(F12, FSF);
aoqi@6880 1767 __ move(AT, 0x7fffffff);
aoqi@6880 1768 __ mfc1(FSR, F12);
aoqi@6880 1769 __ c_un_s(FSF, FSF); //NaN?
aoqi@6880 1770 __ movt(FSR, R0);
aoqi@6880 1771
aoqi@6880 1772 __ bne(AT, FSR, L);
aoqi@6880 1773 __ delayed()->lui(T9, 0x8000);
aoqi@6880 1774
aoqi@6880 1775 __ mfc1(AT, FSF);
aoqi@6880 1776 __ andr(AT, AT, T9);
aoqi@6880 1777
aoqi@6880 1778 __ movn(FSR, T9, AT);
aoqi@6880 1779
aoqi@6880 1780 __ bind(L);
aoqi@6880 1781 }
aoqi@1 1782 break;
aoqi@1 1783 case Bytecodes::_f2l:
aoqi@6880 1784 {
aoqi@6880 1785 Label L;
aoqi@6880 1786
aoqi@6880 1787 __ trunc_l_s(F12, FSF);
aoqi@6880 1788 __ daddiu(AT, R0, -1);
aoqi@6880 1789 __ dsrl(AT, AT, 1);
aoqi@6880 1790 __ dmfc1(FSR, F12);
aoqi@6880 1791 __ c_un_s(FSF, FSF); //NaN?
aoqi@6880 1792 __ movt(FSR, R0);
aoqi@6880 1793
aoqi@6880 1794 __ bne(AT, FSR, L);
aoqi@6880 1795 __ delayed()->lui(T9, 0x8000);
aoqi@6880 1796
aoqi@6880 1797 __ mfc1(AT, FSF);
aoqi@6880 1798 __ andr(AT, AT, T9);
aoqi@6880 1799
aoqi@6880 1800 __ dsll32(T9, T9, 0);
aoqi@6880 1801 __ movn(FSR, T9, AT);
aoqi@6880 1802
aoqi@6880 1803 __ bind(L);
aoqi@6880 1804 }
aoqi@1 1805 break;
aoqi@1 1806 case Bytecodes::_f2d:
aoqi@1 1807 __ cvt_d_s(FSF, FSF);
aoqi@1 1808 break;
aoqi@1 1809 case Bytecodes::_d2i:
aoqi@6880 1810 {
aoqi@6880 1811 Label L;
aoqi@6880 1812
aoqi@6880 1813 __ trunc_w_d(F12, FSF);
aoqi@6880 1814 __ move(AT, 0x7fffffff);
aoqi@6880 1815 __ mfc1(FSR, F12);
aoqi@6880 1816
aoqi@6880 1817 __ bne(FSR, AT, L);
aoqi@6880 1818 __ delayed()->mtc1(R0, F12);
aoqi@6880 1819
aoqi@6880 1820 __ cvt_d_w(F12, F12);
aoqi@6880 1821 __ c_ult_d(FSF, F12);
aoqi@6880 1822 __ bc1f(L);
aoqi@6880 1823 __ delayed()->addiu(T9, R0, -1);
aoqi@6880 1824
aoqi@6880 1825 __ c_un_d(FSF, FSF); //NaN?
aoqi@6880 1826 __ subu32(FSR, T9, AT);
aoqi@6880 1827 __ movt(FSR, R0);
aoqi@6880 1828
aoqi@6880 1829 __ bind(L);
aoqi@6880 1830 }
aoqi@1 1831 break;
aoqi@1 1832 case Bytecodes::_d2l:
aoqi@6880 1833 {
aoqi@6880 1834 Label L;
aoqi@6880 1835
aoqi@6880 1836 __ trunc_l_d(F12, FSF);
aoqi@6880 1837 __ daddiu(AT, R0, -1);
aoqi@6880 1838 __ dsrl(AT, AT, 1);
aoqi@6880 1839 __ dmfc1(FSR, F12);
aoqi@6880 1840
aoqi@6880 1841 __ bne(FSR, AT, L);
aoqi@6880 1842 __ delayed()->mtc1(R0, F12);
aoqi@6880 1843
aoqi@6880 1844 __ cvt_d_w(F12, F12);
aoqi@6880 1845 __ c_ult_d(FSF, F12);
aoqi@6880 1846 __ bc1f(L);
aoqi@6880 1847 __ delayed()->daddiu(T9, R0, -1);
aoqi@6880 1848
aoqi@6880 1849 __ c_un_d(FSF, FSF); //NaN?
aoqi@6880 1850 __ subu(FSR, T9, AT);
aoqi@6880 1851 __ movt(FSR, R0);
aoqi@6880 1852
aoqi@6880 1853 __ bind(L);
aoqi@6880 1854 }
aoqi@1 1855 break;
aoqi@1 1856 case Bytecodes::_d2f:
aoqi@1 1857 __ cvt_s_d(FSF, FSF);
aoqi@1 1858 break;
aoqi@1 1859 default :
aoqi@1 1860 ShouldNotReachHere();
aoqi@1 1861 }
aoqi@1 1862 }
aoqi@1 1863
aoqi@1 1864 void TemplateTable::lcmp() {
aoqi@1 1865 transition(ltos, itos);
aoqi@1 1866
aoqi@1 1867 Label low, high, done;
aoqi@1 1868 __ pop(T0);
aoqi@1 1869 __ pop(R0);
aoqi@1 1870 __ slt(AT, T0, FSR);
aoqi@1 1871 __ bne(AT, R0, low);
aoqi@1 1872 __ delayed()->nop();
aoqi@1 1873
aoqi@1 1874 __ bne(T0, FSR, high);
aoqi@1 1875 __ delayed()->nop();
aoqi@1 1876
aoqi@1 1877 __ li(FSR, (long)0);
aoqi@1 1878 __ b(done);
aoqi@1 1879 __ delayed()->nop();
aoqi@1 1880
aoqi@1 1881 __ bind(low);
aoqi@1 1882 __ li(FSR, (long)-1);
aoqi@1 1883 __ b(done);
aoqi@1 1884 __ delayed()->nop();
aoqi@1 1885
aoqi@1 1886 __ bind(high);
aoqi@1 1887 __ li(FSR, (long)1);
aoqi@1 1888 __ b(done);
aoqi@1 1889 __ delayed()->nop();
aoqi@1 1890
aoqi@1 1891 __ bind(done);
aoqi@1 1892 }
aoqi@1 1893
aoqi@1 1894 void TemplateTable::float_cmp(bool is_float, int unordered_result) {
aoqi@6880 1895 Label less, done;
aoqi@6880 1896
aoqi@6880 1897 __ move(FSR, R0);
aoqi@6880 1898
aoqi@6880 1899 if (is_float) {
aoqi@6880 1900 __ lwc1(FTF, at_sp());
aoqi@6880 1901 __ c_eq_s(FTF, FSF);
aoqi@6880 1902 __ bc1t(done);
aoqi@6880 1903 __ delayed()->daddi(SP, SP, 1 * wordSize);
aoqi@6880 1904
aoqi@6880 1905 if (unordered_result<0)
aoqi@6880 1906 __ c_ult_s(FTF, FSF);
aoqi@6880 1907 else
aoqi@6880 1908 __ c_olt_s(FTF, FSF);
aoqi@6880 1909 } else {
aoqi@6880 1910 __ ldc1(FTF, at_sp());
aoqi@6880 1911 __ c_eq_d(FTF, FSF);
aoqi@6880 1912 __ bc1t(done);
aoqi@6880 1913 __ delayed()->daddi(SP, SP, 2 * wordSize);
aoqi@6880 1914
aoqi@6880 1915 if (unordered_result<0)
aoqi@6880 1916 __ c_ult_d(FTF, FSF);
aoqi@6880 1917 else
aoqi@6880 1918 __ c_olt_d(FTF, FSF);
aoqi@6880 1919 }
aoqi@6880 1920 __ bc1t(less);
aoqi@6880 1921 __ delayed()->nop();
aoqi@6880 1922 __ move(FSR, 1);
aoqi@6880 1923 __ b(done);
aoqi@6880 1924 __ delayed()->nop();
aoqi@6880 1925 __ bind(less);
aoqi@6880 1926 __ move(FSR, -1);
aoqi@6880 1927 __ bind(done);
aoqi@1 1928 }
aoqi@1 1929
aoqi@1 1930
aoqi@1 1931 // used registers : T3, A7, Rnext
aoqi@1 1932 // FSR : return bci, this is defined by the vm specification
aoqi@1 1933 // T2 : MDO taken count
aoqi@1 1934 // T3 : method
aoqi@1 1935 // A7 : offset
aoqi@1 1936 // Rnext : next bytecode, this is required by dispatch_base
aoqi@1 1937 void TemplateTable::branch(bool is_jsr, bool is_wide) {
aoqi@1 1938 __ get_method(T3);
aoqi@6880 1939 __ profile_taken_branch(A7, T2); // only C2 meaningful
aoqi@1 1940
aoqi@1 1941 #ifndef CORE
aoqi@6880 1942 const ByteSize be_offset = MethodCounters::backedge_counter_offset() +
aoqi@6880 1943 InvocationCounter::counter_offset();
aoqi@6880 1944 const ByteSize inv_offset = MethodCounters::invocation_counter_offset() +
aoqi@6880 1945 InvocationCounter::counter_offset();
aoqi@1 1946 #endif // CORE
aoqi@1 1947
aoqi@1 1948 // Load up T4 with the branch displacement
aoqi@1 1949 if (!is_wide) {
fujie@6895 1950 __ lb(A7, BCP, 1);
fujie@6895 1951 __ lbu(AT, BCP, 2);
aoqi@7997 1952 __ dsll(A7, A7, 8);
fujie@6895 1953 __ orr(A7, A7, AT);
aoqi@1 1954 } else {
aoqi@15 1955 __ get_4_byte_integer_at_bcp(A7, AT, 1);
aoqi@1 1956 __ swap(A7);
aoqi@1 1957 }
aoqi@1 1958
aoqi@1 1959 // Handle all the JSR stuff here, then exit.
aoqi@6880 1960 // It's much shorter and cleaner than intermingling with the non-JSR
aoqi@6880 1961 // normal-branch stuff occuring below.
aoqi@1 1962 if (is_jsr) {
aoqi@1 1963 // Pre-load the next target bytecode into Rnext
aoqi@1 1964 __ dadd(AT, BCP, A7);
aoqi@1 1965 __ lbu(Rnext, AT, 0);
aoqi@1 1966
aoqi@1 1967 // compute return address as bci in FSR
aoqi@1 1968 __ daddi(FSR, BCP, (is_wide?5:3) - in_bytes(ConstMethod::codes_offset()));
aoqi@1 1969 __ ld(AT, T3, in_bytes(Method::const_offset()));
aoqi@1 1970 __ dsub(FSR, FSR, AT);
aoqi@1 1971 // Adjust the bcp in BCP by the displacement in A7
aoqi@1 1972 __ dadd(BCP, BCP, A7);
aoqi@1 1973 // jsr returns atos that is not an oop
aoqi@1 1974 // Push return address
aoqi@1 1975 __ push_i(FSR);
aoqi@1 1976 // jsr returns vtos
aoqi@1 1977 __ dispatch_only_noverify(vtos);
aoqi@1 1978
aoqi@1 1979 return;
aoqi@1 1980 }
aoqi@1 1981
aoqi@1 1982 // Normal (non-jsr) branch handling
aoqi@1 1983
aoqi@1 1984 // Adjust the bcp in S0 by the displacement in T4
aoqi@1 1985 __ dadd(BCP, BCP, A7);
aoqi@1 1986
aoqi@1 1987 #ifdef CORE
aoqi@1 1988 // Pre-load the next target bytecode into EBX
aoqi@1 1989 __ lbu(Rnext, BCP, 0);
aoqi@1 1990 // continue with the bytecode @ target
aoqi@1 1991 __ dispatch_only(vtos);
aoqi@1 1992 #else
aoqi@1 1993 assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters");
aoqi@1 1994 Label backedge_counter_overflow;
aoqi@1 1995 Label profile_method;
aoqi@1 1996 Label dispatch;
aoqi@1 1997 if (UseLoopCounter) {
aoqi@1 1998 // increment backedge counter for backward branches
aoqi@1 1999 // eax: MDO
aoqi@1 2000 // ebx: MDO bumped taken-count
aoqi@1 2001 // T3: method
aoqi@1 2002 // T4: target offset
aoqi@1 2003 // BCP: target bcp
aoqi@1 2004 // LVP: locals pointer
aoqi@6880 2005 __ bgtz(A7, dispatch); // check if forward or backward branch
aoqi@1 2006 __ delayed()->nop();
aoqi@1 2007
aoqi@1 2008 // check if MethodCounters exists
aoqi@1 2009 Label has_counters;
aoqi@6880 2010 __ ld(AT, T3, in_bytes(Method::method_counters_offset())); // use AT as MDO, TEMP
aoqi@1 2011 __ bne(AT, R0, has_counters);
zhaixiang@9144 2012 __ delayed()->nop();
aoqi@418 2013 __ push(T3);
aoqi@1 2014 //__ push(A7);
aoqi@1 2015 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters),
aoqi@1 2016 T3);
aoqi@1 2017 //__ pop(A7);
aoqi@418 2018 __ pop(T3);
aoqi@1 2019 __ ld(AT, T3, in_bytes(Method::method_counters_offset())); // use AT as MDO, TEMP
aoqi@1 2020 __ beq(AT, R0, dispatch);
zhaixiang@9144 2021 __ delayed()->nop();
aoqi@1 2022 __ bind(has_counters);
aoqi@1 2023
aoqi@6880 2024 // increment back edge counter
aoqi@1 2025 __ ld(T1, T3, in_bytes(Method::method_counters_offset()));
aoqi@1 2026 __ lw(T0, T1, in_bytes(be_offset));
aoqi@1 2027 __ increment(T0, InvocationCounter::count_increment);
aoqi@1 2028 __ sw(T0, T1, in_bytes(be_offset));
aoqi@1 2029
aoqi@1 2030 // load invocation counter
aoqi@1 2031 __ lw(T1, T1, in_bytes(inv_offset));
aoqi@1 2032 // buffer bit added, mask no needed
aoqi@1 2033
aoqi@1 2034 // dadd backedge counter & invocation counter
aoqi@1 2035 __ dadd(T1, T1, T0);
aoqi@1 2036
aoqi@1 2037 if (ProfileInterpreter) {
aoqi@1 2038 // Test to see if we should create a method data oop
aoqi@1 2039 // T1 : backedge counter & invocation counter
fujie@6895 2040 if (Assembler::is_simm16(InvocationCounter::InterpreterProfileLimit)) {
fujie@6895 2041 __ slti(AT, T1, InvocationCounter::InterpreterProfileLimit);
fujie@6895 2042 } else {
fujie@6895 2043 __ li(AT, (long)&InvocationCounter::InterpreterProfileLimit);
fujie@6895 2044 __ lw(AT, AT, 0);
fujie@6895 2045 __ slt(AT, T1, AT);
fujie@6895 2046 }
fujie@6895 2047
aoqi@1 2048 __ bne(AT, R0, dispatch);
aoqi@1 2049 __ delayed()->nop();
aoqi@1 2050
aoqi@1 2051 // if no method data exists, go to profile method
aoqi@1 2052 __ test_method_data_pointer(T1, profile_method);
aoqi@1 2053
aoqi@1 2054 if (UseOnStackReplacement) {
fujie@6895 2055 if (Assembler::is_simm16(InvocationCounter::InterpreterBackwardBranchLimit)) {
fujie@6895 2056 __ slti(AT, T2, InvocationCounter::InterpreterBackwardBranchLimit);
fujie@6895 2057 } else {
fujie@6895 2058 __ li(AT, (long)&InvocationCounter::InterpreterBackwardBranchLimit);
fujie@6895 2059 __ lw(AT, AT, 0);
fujie@6895 2060 __ slt(AT, T2, AT);
fujie@6895 2061 }
fujie@6895 2062
aoqi@6880 2063 __ bne(AT, R0, dispatch);
aoqi@6880 2064 __ delayed()->nop();
aoqi@6880 2065
aoqi@6880 2066 // When ProfileInterpreter is on, the backedge_count comes
aoqi@6880 2067 // from the methodDataOop, which value does not get reset on
aoqi@6880 2068 // the call to frequency_counter_overflow().
aoqi@6880 2069 // To avoid excessive calls to the overflow routine while
aoqi@6880 2070 // the method is being compiled, dadd a second test to make
aoqi@6880 2071 // sure the overflow function is called only once every
aoqi@6880 2072 // overflow_frequency.
aoqi@6880 2073 const int overflow_frequency = 1024;
aoqi@6880 2074 __ andi(AT, T2, overflow_frequency-1);
aoqi@6880 2075 __ beq(AT, R0, backedge_counter_overflow);
aoqi@6880 2076 __ delayed()->nop();
aoqi@1 2077 }
aoqi@1 2078 } else {
aoqi@1 2079 if (UseOnStackReplacement) {
aoqi@6880 2080 // check for overflow against eax, which is the sum of the counters
aoqi@6880 2081 __ li(AT, (long)&InvocationCounter::InterpreterBackwardBranchLimit);
aoqi@6880 2082 __ lw(AT, AT, 0);
aoqi@6880 2083 __ slt(AT, T1, AT);
aoqi@6880 2084 __ beq(AT, R0, backedge_counter_overflow);
aoqi@6880 2085 __ delayed()->nop();
aoqi@1 2086 }
aoqi@1 2087 }
aoqi@1 2088 __ bind(dispatch);
aoqi@1 2089 }
aoqi@1 2090
aoqi@1 2091 // Pre-load the next target bytecode into Rnext
aoqi@1 2092 __ lbu(Rnext, BCP, 0);
aoqi@1 2093
aoqi@1 2094 // continue with the bytecode @ target
aoqi@1 2095 // FSR: return bci for jsr's, unused otherwise
aoqi@1 2096 // Rnext: target bytecode
aoqi@1 2097 // BCP: target bcp
aoqi@1 2098 __ dispatch_only(vtos);
aoqi@1 2099
aoqi@1 2100 if (UseLoopCounter) {
aoqi@1 2101 if (ProfileInterpreter) {
aoqi@1 2102 // Out-of-line code to allocate method data oop.
aoqi@1 2103 __ bind(profile_method);
aoqi@1 2104 __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
aoqi@1 2105 __ lbu(Rnext, BCP, 0);
aoqi@1 2106 __ set_method_data_pointer_for_bcp();
aoqi@1 2107 __ b(dispatch);
aoqi@1 2108 __ delayed()->nop();
aoqi@1 2109 }
aoqi@1 2110
aoqi@1 2111 if (UseOnStackReplacement) {
aoqi@1 2112 // invocation counter overflow
aoqi@1 2113 __ bind(backedge_counter_overflow);
aoqi@6880 2114 __ sub(A7, BCP, A7); // branch bcp
aoqi@6880 2115 call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6880 2116 InterpreterRuntime::frequency_counter_overflow), A7);
aoqi@1 2117 __ lbu(Rnext, BCP, 0);
aoqi@1 2118
aoqi@1 2119 // V0: osr nmethod (osr ok) or NULL (osr not possible)
aoqi@1 2120 // V1: osr adapter frame return address
aoqi@1 2121 // Rnext: target bytecode
aoqi@1 2122 // LVP: locals pointer
aoqi@1 2123 // BCP: bcp
aoqi@1 2124 __ beq(V0, R0, dispatch);
aoqi@1 2125 __ delayed()->nop();
aoqi@1 2126 // nmethod may have been invalidated (VM may block upon call_VM return)
aoqi@1 2127 __ lw(T3, V0, nmethod::entry_bci_offset());
aoqi@1 2128 __ move(AT, InvalidOSREntryBci);
aoqi@1 2129 __ beq(AT, T3, dispatch);
aoqi@1 2130 __ delayed()->nop();
aoqi@1 2131 // We need to prepare to execute the OSR method. First we must
aoqi@1 2132 // migrate the locals and monitors off of the stack.
aoqi@1 2133 //eax V0: osr nmethod (osr ok) or NULL (osr not possible)
aoqi@1 2134 //ebx V1: osr adapter frame return address
aoqi@1 2135 //edx Rnext: target bytecode
aoqi@1 2136 //edi LVP: locals pointer
aoqi@1 2137 //esi BCP: bcp
aoqi@6880 2138 __ move(BCP, V0);
aoqi@1 2139 // const Register thread = ecx;
aoqi@1 2140 const Register thread = TREG;
aoqi@1 2141 #ifndef OPT_THREAD
aoqi@1 2142 __ get_thread(thread);
aoqi@1 2143 #endif
aoqi@6880 2144 call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@6880 2145 SharedRuntime::OSR_migration_begin));
aoqi@1 2146 // eax is OSR buffer, move it to expected parameter location
aoqi@6880 2147 //refer to osrBufferPointer in c1_LIRAssembler_mips.cpp
aoqi@1 2148 __ move(T0, V0);
aoqi@1 2149
aoqi@1 2150 // pop the interpreter frame
aoqi@6880 2151 __ ld(A7, Address(FP, frame::interpreter_frame_sender_sp_offset * wordSize));
aoqi@6880 2152 //FIXME, shall we keep the return address on the stack?
aoqi@1 2153 __ leave(); // remove frame anchor
aoqi@6880 2154 __ move(LVP, RA);
aoqi@1 2155 __ move(SP, A7);
aoqi@1 2156
aoqi@6880 2157 __ move(AT, -(StackAlignmentInBytes));
aoqi@6880 2158 __ andr(SP , SP , AT);
aoqi@6880 2159
aoqi@6880 2160 // push the (possibly adjusted) return address
aoqi@6880 2161 //refer to osr_entry in c1_LIRAssembler_mips.cpp
aoqi@6880 2162 __ ld(AT, BCP, nmethod::osr_entry_point_offset());
aoqi@6880 2163 __ jr(AT);
aoqi@1 2164 __ delayed()->nop();
aoqi@1 2165 }
aoqi@1 2166 }
aoqi@1 2167 #endif // not CORE
aoqi@1 2168 }
aoqi@1 2169
aoqi@6880 2170
aoqi@1 2171 void TemplateTable::if_0cmp(Condition cc) {
aoqi@1 2172 transition(itos, vtos);
aoqi@1 2173 // assume branch is more often taken than not (loops use backward branches)
aoqi@1 2174 Label not_taken;
aoqi@1 2175 switch(cc) {
aoqi@1 2176 case not_equal:
aoqi@1 2177 __ beq(FSR, R0, not_taken);
aoqi@1 2178 break;
aoqi@1 2179 case equal:
aoqi@1 2180 __ bne(FSR, R0, not_taken);
aoqi@1 2181 break;
aoqi@1 2182 case less:
aoqi@1 2183 __ bgez(FSR, not_taken);
aoqi@1 2184 break;
aoqi@1 2185 case less_equal:
aoqi@1 2186 __ bgtz(FSR, not_taken);
aoqi@1 2187 break;
aoqi@1 2188 case greater:
aoqi@1 2189 __ blez(FSR, not_taken);
aoqi@1 2190 break;
aoqi@1 2191 case greater_equal:
aoqi@1 2192 __ bltz(FSR, not_taken);
aoqi@1 2193 break;
aoqi@1 2194 }
aoqi@1 2195 __ delayed()->nop();
aoqi@1 2196
aoqi@1 2197 branch(false, false);
aoqi@1 2198
aoqi@1 2199 __ bind(not_taken);
aoqi@1 2200 __ profile_not_taken_branch(FSR);
aoqi@1 2201 }
aoqi@1 2202
aoqi@1 2203 void TemplateTable::if_icmp(Condition cc) {
aoqi@1 2204 transition(itos, vtos);
aoqi@1 2205 // assume branch is more often taken than not (loops use backward branches)
aoqi@1 2206 Label not_taken;
aoqi@1 2207
aoqi@6880 2208 __ pop_i(SSR);
aoqi@1 2209 switch(cc) {
aoqi@1 2210 case not_equal:
aoqi@1 2211 __ beq(SSR, FSR, not_taken);
aoqi@1 2212 break;
aoqi@1 2213 case equal:
aoqi@1 2214 __ bne(SSR, FSR, not_taken);
aoqi@1 2215 break;
aoqi@1 2216 case less:
aoqi@1 2217 __ slt(AT, SSR, FSR);
aoqi@1 2218 __ beq(AT, R0, not_taken);
aoqi@1 2219 break;
aoqi@1 2220 case less_equal:
aoqi@1 2221 __ slt(AT, FSR, SSR);
aoqi@1 2222 __ bne(AT, R0, not_taken);
aoqi@1 2223 break;
aoqi@1 2224 case greater:
aoqi@1 2225 __ slt(AT, FSR, SSR);
aoqi@1 2226 __ beq(AT, R0, not_taken);
aoqi@1 2227 break;
aoqi@1 2228 case greater_equal:
aoqi@1 2229 __ slt(AT, SSR, FSR);
aoqi@1 2230 __ bne(AT, R0, not_taken);
aoqi@1 2231 break;
aoqi@1 2232 }
aoqi@1 2233 __ delayed()->nop();
aoqi@1 2234
aoqi@1 2235 branch(false, false);
aoqi@1 2236 __ bind(not_taken);
aoqi@1 2237 __ profile_not_taken_branch(FSR);
aoqi@1 2238 }
aoqi@1 2239
aoqi@1 2240 void TemplateTable::if_nullcmp(Condition cc) {
aoqi@1 2241 transition(atos, vtos);
aoqi@1 2242 // assume branch is more often taken than not (loops use backward branches)
aoqi@1 2243 Label not_taken;
aoqi@1 2244 switch(cc) {
aoqi@1 2245 case not_equal:
aoqi@1 2246 __ beq(FSR, R0, not_taken);
aoqi@1 2247 break;
aoqi@1 2248 case equal:
aoqi@1 2249 __ bne(FSR, R0, not_taken);
aoqi@1 2250 break;
aoqi@1 2251 default:
aoqi@1 2252 ShouldNotReachHere();
aoqi@1 2253 }
aoqi@1 2254 __ delayed()->nop();
aoqi@1 2255
aoqi@1 2256 branch(false, false);
aoqi@1 2257 __ bind(not_taken);
aoqi@1 2258 __ profile_not_taken_branch(FSR);
aoqi@1 2259 }
aoqi@1 2260
aoqi@1 2261
aoqi@1 2262 void TemplateTable::if_acmp(Condition cc) {
aoqi@6880 2263 transition(atos, vtos);
aoqi@6880 2264 // assume branch is more often taken than not (loops use backward branches)
aoqi@6880 2265 Label not_taken;
aoqi@6880 2266 // __ lw(SSR, SP, 0);
aoqi@6880 2267 __ pop_ptr(SSR);
aoqi@6880 2268 switch(cc) {
aoqi@6880 2269 case not_equal:
aoqi@6880 2270 __ beq(SSR, FSR, not_taken);
aoqi@6880 2271 break;
aoqi@6880 2272 case equal:
aoqi@6880 2273 __ bne(SSR, FSR, not_taken);
aoqi@6880 2274 break;
aoqi@6880 2275 default:
aoqi@6880 2276 ShouldNotReachHere();
aoqi@6880 2277 }
aoqi@6880 2278 __ delayed()->nop();
aoqi@6880 2279
aoqi@6880 2280 branch(false, false);
aoqi@6880 2281
aoqi@6880 2282 __ bind(not_taken);
aoqi@6880 2283 __ profile_not_taken_branch(FSR);
aoqi@1 2284 }
aoqi@1 2285
aoqi@1 2286 // used registers : T1, T2, T3
aoqi@1 2287 // T1 : method
aoqi@1 2288 // T2 : returb bci
aoqi@1 2289 void TemplateTable::ret() {
aoqi@6880 2290 transition(vtos, vtos);
aoqi@6880 2291
aoqi@6880 2292 locals_index(T2);
aoqi@6880 2293 __ ld(T2, T2, 0);
aoqi@6880 2294 __ profile_ret(T2, T3);
aoqi@6880 2295
aoqi@6880 2296 __ get_method(T1);
aoqi@6880 2297 __ ld(BCP, T1, in_bytes(Method::const_offset()));
aoqi@6880 2298 __ dadd(BCP, BCP, T2);
aoqi@6880 2299 __ daddi(BCP, BCP, in_bytes(ConstMethod::codes_offset()));
aoqi@6880 2300
aoqi@6880 2301 __ dispatch_next(vtos);
aoqi@1 2302 }
aoqi@1 2303
aoqi@1 2304 // used registers : T1, T2, T3
aoqi@1 2305 // T1 : method
aoqi@1 2306 // T2 : returb bci
aoqi@1 2307 void TemplateTable::wide_ret() {
aoqi@6880 2308 transition(vtos, vtos);
aoqi@6880 2309
aoqi@6880 2310 locals_index_wide(T2);
aoqi@6880 2311 __ ld(T2, T2, 0); // get return bci, compute return bcp
aoqi@6880 2312 __ profile_ret(T2, T3);
aoqi@6880 2313
aoqi@6880 2314 __ get_method(T1);
aoqi@6880 2315 __ ld(BCP, T1, in_bytes(Method::const_offset()));
aoqi@6880 2316 __ dadd(BCP, BCP, T2);
aoqi@6880 2317 __ daddi(BCP, BCP, in_bytes(ConstMethod::codes_offset()));
aoqi@6880 2318
aoqi@6880 2319 __ dispatch_next(vtos);
aoqi@1 2320 }
aoqi@1 2321
aoqi@1 2322 // used register T2, T3, A7, Rnext
aoqi@1 2323 // T2 : bytecode pointer
aoqi@1 2324 // T3 : low
aoqi@1 2325 // A7 : high
aoqi@1 2326 // Rnext : dest bytecode, required by dispatch_base
aoqi@1 2327 void TemplateTable::tableswitch() {
aoqi@6880 2328 Label default_case, continue_execution;
aoqi@6880 2329 transition(itos, vtos);
aoqi@6880 2330
aoqi@6880 2331 // align BCP
aoqi@6880 2332 __ daddi(T2, BCP, BytesPerInt);
aoqi@6880 2333 __ li(AT, -BytesPerInt);
aoqi@6880 2334 __ andr(T2, T2, AT);
aoqi@6880 2335
aoqi@6880 2336 // load lo & hi
aoqi@6880 2337 __ lw(T3, T2, 1 * BytesPerInt);
aoqi@6880 2338 __ swap(T3);
aoqi@6880 2339 __ lw(A7, T2, 2 * BytesPerInt);
aoqi@6880 2340 __ swap(A7);
aoqi@6880 2341
aoqi@6880 2342 // check against lo & hi
aoqi@6880 2343 __ slt(AT, FSR, T3);
aoqi@6880 2344 __ bne(AT, R0, default_case);
aoqi@6880 2345 __ delayed()->nop();
aoqi@6880 2346
aoqi@6880 2347 __ slt(AT, A7, FSR);
aoqi@6880 2348 __ bne(AT, R0, default_case);
aoqi@6880 2349 __ delayed()->nop();
aoqi@6880 2350
aoqi@6880 2351 // lookup dispatch offset, in A7 big endian
aoqi@6880 2352 __ dsub(FSR, FSR, T3);
aoqi@6880 2353 __ dsll(AT, FSR, Address::times_4);
aoqi@6880 2354 __ dadd(AT, T2, AT);
aoqi@6880 2355 __ lw(A7, AT, 3 * BytesPerInt);
aoqi@6880 2356 __ profile_switch_case(FSR, T9, T3);
aoqi@6880 2357
aoqi@6880 2358 __ bind(continue_execution);
aoqi@6880 2359 __ swap(A7);
aoqi@6880 2360 __ dadd(BCP, BCP, A7);
aoqi@6880 2361 __ lbu(Rnext, BCP, 0);
aoqi@6880 2362 __ dispatch_only(vtos);
aoqi@6880 2363
aoqi@6880 2364 // handle default
aoqi@6880 2365 __ bind(default_case);
aoqi@6880 2366 __ profile_switch_default(FSR);
aoqi@6880 2367 __ lw(A7, T2, 0);
aoqi@6880 2368 __ b(continue_execution);
aoqi@6880 2369 __ delayed()->nop();
aoqi@1 2370 }
aoqi@1 2371
aoqi@1 2372 void TemplateTable::lookupswitch() {
aoqi@6880 2373 transition(itos, itos);
aoqi@6880 2374 __ stop("lookupswitch bytecode should have been rewritten");
aoqi@1 2375 }
aoqi@1 2376
aoqi@1 2377 // used registers : T2, T3, A7, Rnext
aoqi@1 2378 // T2 : bytecode pointer
aoqi@1 2379 // T3 : pair index
aoqi@1 2380 // A7 : offset
aoqi@1 2381 // Rnext : dest bytecode
aoqi@1 2382 // the data after the opcode is the same as lookupswitch
aoqi@1 2383 // see Rewriter::rewrite_method for more information
aoqi@1 2384 void TemplateTable::fast_linearswitch() {
aoqi@1 2385 transition(itos, vtos);
aoqi@6880 2386 Label loop_entry, loop, found, continue_execution;
aoqi@1 2387
aoqi@1 2388 // swap eax so we can avoid swapping the table entries
aoqi@1 2389 __ swap(FSR);
aoqi@1 2390
aoqi@1 2391 // align BCP
aoqi@1 2392 __ daddi(T2, BCP, BytesPerInt);
aoqi@1 2393 __ li(AT, -BytesPerInt);
aoqi@1 2394 __ andr(T2, T2, AT);
aoqi@1 2395
aoqi@1 2396 // set counter
aoqi@1 2397 __ lw(T3, T2, BytesPerInt);
aoqi@1 2398 __ swap(T3);
aoqi@1 2399 __ b(loop_entry);
aoqi@1 2400 __ delayed()->nop();
aoqi@1 2401
aoqi@1 2402 // table search
aoqi@1 2403 __ bind(loop);
aoqi@1 2404 // get the entry value
aoqi@1 2405 __ dsll(AT, T3, Address::times_8);
aoqi@1 2406 __ dadd(AT, T2, AT);
aoqi@1 2407 __ lw(AT, AT, 2 * BytesPerInt);
aoqi@1 2408
aoqi@1 2409 // found?
aoqi@1 2410 __ beq(FSR, AT, found);
aoqi@1 2411 __ delayed()->nop();
aoqi@1 2412
aoqi@1 2413 __ bind(loop_entry);
aoqi@1 2414 __ bgtz(T3, loop);
aoqi@1 2415 __ delayed()->daddiu(T3, T3, -1);
aoqi@1 2416
aoqi@1 2417 // default case
aoqi@1 2418 __ profile_switch_default(FSR);
aoqi@1 2419 __ lw(A7, T2, 0);
aoqi@1 2420 __ b(continue_execution);
aoqi@1 2421 __ delayed()->nop();
aoqi@1 2422
aoqi@1 2423 // entry found -> get offset
aoqi@1 2424 __ bind(found);
aoqi@1 2425 __ dsll(AT, T3, Address::times_8);
aoqi@1 2426 __ dadd(AT, T2, AT);
aoqi@1 2427 __ lw(A7, AT, 3 * BytesPerInt);
aoqi@1 2428 __ profile_switch_case(T3, FSR, T2);
aoqi@1 2429
aoqi@1 2430 // continue execution
aoqi@6880 2431 __ bind(continue_execution);
aoqi@1 2432 __ swap(A7);
aoqi@1 2433 __ dadd(BCP, BCP, A7);
aoqi@1 2434 __ lbu(Rnext, BCP, 0);
aoqi@1 2435 __ dispatch_only(vtos);
aoqi@1 2436 }
aoqi@1 2437
aoqi@1 2438 // used registers : T0, T1, T2, T3, A7, Rnext
aoqi@1 2439 // T2 : pairs address(array)
aoqi@1 2440 // Rnext : dest bytecode
aoqi@1 2441 // the data after the opcode is the same as lookupswitch
aoqi@1 2442 // see Rewriter::rewrite_method for more information
aoqi@1 2443 void TemplateTable::fast_binaryswitch() {
aoqi@1 2444 transition(itos, vtos);
aoqi@1 2445 // Implementation using the following core algorithm:
aoqi@1 2446 //
aoqi@1 2447 // int binary_search(int key, LookupswitchPair* array, int n) {
aoqi@1 2448 // // Binary search according to "Methodik des Programmierens" by
aoqi@1 2449 // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985.
aoqi@1 2450 // int i = 0;
aoqi@1 2451 // int j = n;
aoqi@1 2452 // while (i+1 < j) {
aoqi@1 2453 // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q)
aoqi@1 2454 // // with Q: for all i: 0 <= i < n: key < a[i]
aoqi@1 2455 // // where a stands for the array and assuming that the (inexisting)
aoqi@1 2456 // // element a[n] is infinitely big.
aoqi@1 2457 // int h = (i + j) >> 1;
aoqi@1 2458 // // i < h < j
aoqi@1 2459 // if (key < array[h].fast_match()) {
aoqi@1 2460 // j = h;
aoqi@1 2461 // } else {
aoqi@1 2462 // i = h;
aoqi@1 2463 // }
aoqi@1 2464 // }
aoqi@1 2465 // // R: a[i] <= key < a[i+1] or Q
aoqi@1 2466 // // (i.e., if key is within array, i is the correct index)
aoqi@1 2467 // return i;
aoqi@1 2468 // }
aoqi@1 2469
aoqi@1 2470 // register allocation
aoqi@1 2471 const Register array = T2;
aoqi@1 2472 const Register i = T3, j = A7;
aoqi@1 2473 const Register h = T1;
aoqi@1 2474 const Register temp = T0;
aoqi@1 2475 const Register key = FSR;
aoqi@1 2476
aoqi@1 2477 // setup array
aoqi@1 2478 __ daddi(array, BCP, 3*BytesPerInt);
aoqi@1 2479 __ li(AT, -BytesPerInt);
aoqi@1 2480 __ andr(array, array, AT);
aoqi@1 2481
aoqi@1 2482 // initialize i & j
aoqi@1 2483 __ move(i, R0);
aoqi@1 2484 __ lw(j, array, - 1 * BytesPerInt);
aoqi@6880 2485 // Convert j into native byteordering
aoqi@1 2486 __ swap(j);
aoqi@1 2487
aoqi@1 2488 // and start
aoqi@1 2489 Label entry;
aoqi@1 2490 __ b(entry);
aoqi@1 2491 __ delayed()->nop();
aoqi@1 2492
aoqi@1 2493 // binary search loop
aoqi@6880 2494 {
aoqi@1 2495 Label loop;
aoqi@1 2496 __ bind(loop);
aoqi@1 2497 // int h = (i + j) >> 1;
aoqi@1 2498 __ dadd(h, i, j);
aoqi@1 2499 __ dsrl(h, h, 1);
aoqi@1 2500 // if (key < array[h].fast_match()) {
aoqi@1 2501 // j = h;
aoqi@1 2502 // } else {
aoqi@1 2503 // i = h;
aoqi@1 2504 // }
aoqi@1 2505 // Convert array[h].match to native byte-ordering before compare
aoqi@1 2506 __ dsll(AT, h, Address::times_8);
aoqi@1 2507 __ dadd(AT, array, AT);
aoqi@1 2508 __ lw(temp, AT, 0 * BytesPerInt);
aoqi@1 2509 __ swap(temp);
aoqi@1 2510
aoqi@1 2511 {
aoqi@1 2512 Label set_i, end_of_if;
aoqi@1 2513 __ slt(AT, key, temp);
aoqi@1 2514 __ beq(AT, R0, set_i);
aoqi@6880 2515 __ delayed()->nop();
aoqi@1 2516
aoqi@1 2517 __ b(end_of_if);
aoqi@1 2518 __ delayed(); __ move(j, h);
aoqi@1 2519
aoqi@1 2520 __ bind(set_i);
aoqi@1 2521 __ move(i, h);
aoqi@1 2522
aoqi@1 2523 __ bind(end_of_if);
aoqi@1 2524 }
aoqi@1 2525 // while (i+1 < j)
aoqi@1 2526 __ bind(entry);
aoqi@1 2527 __ daddi(h, i, 1);
aoqi@1 2528 __ slt(AT, h, j);
aoqi@1 2529 __ bne(AT, R0, loop);
aoqi@1 2530 __ delayed()->nop();
aoqi@1 2531 }
aoqi@1 2532
aoqi@1 2533 // end of binary search, result index is i (must check again!)
aoqi@1 2534 Label default_case;
aoqi@1 2535 // Convert array[i].match to native byte-ordering before compare
aoqi@1 2536 __ dsll(AT, i, Address::times_8);
aoqi@1 2537 __ dadd(AT, array, AT);
aoqi@1 2538 __ lw(temp, AT, 0 * BytesPerInt);
aoqi@1 2539 __ swap(temp);
aoqi@1 2540 __ bne(key, temp, default_case);
aoqi@1 2541 __ delayed()->nop();
aoqi@1 2542
aoqi@1 2543 // entry found -> j = offset
aoqi@1 2544 __ dsll(AT, i, Address::times_8);
aoqi@1 2545 __ dadd(AT, array, AT);
aoqi@1 2546 __ lw(j, AT, 1 * BytesPerInt);
aoqi@1 2547 __ profile_switch_case(i, key, array);
aoqi@1 2548 __ swap(j);
aoqi@1 2549
aoqi@1 2550 __ dadd(BCP, BCP, j);
aoqi@1 2551 __ lbu(Rnext, BCP, 0);
aoqi@1 2552 __ dispatch_only(vtos);
aoqi@1 2553
aoqi@1 2554 // default case -> j = default offset
aoqi@1 2555 __ bind(default_case);
aoqi@1 2556 __ profile_switch_default(i);
aoqi@1 2557 __ lw(j, array, - 2 * BytesPerInt);
aoqi@1 2558 __ swap(j);
aoqi@1 2559 __ dadd(BCP, BCP, j);
aoqi@1 2560 __ lbu(Rnext, BCP, 0);
aoqi@1 2561 __ dispatch_only(vtos);
aoqi@1 2562 }
aoqi@1 2563
aoqi@1 2564 void TemplateTable::_return(TosState state) {
aoqi@1 2565 transition(state, state);
aoqi@6880 2566 assert(_desc->calls_vm(),
aoqi@6880 2567 "inconsistent calls_vm information"); // call in remove_activation
aoqi@6880 2568
aoqi@1 2569 if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
aoqi@1 2570 assert(state == vtos, "only valid state");
aoqi@1 2571 __ ld(T1, aaddress(0));
aoqi@1 2572 __ load_klass(LVP, T1);
aoqi@1 2573 __ lw(LVP, LVP, in_bytes(Klass::access_flags_offset()));
aoqi@6880 2574 __ move(AT, JVM_ACC_HAS_FINALIZER);
aoqi@1 2575 __ andr(AT, AT, LVP);//by_css
aoqi@1 2576 Label skip_register_finalizer;
aoqi@1 2577 __ beq(AT, R0, skip_register_finalizer);
aoqi@6880 2578 __ delayed()->nop();
aoqi@6880 2579 __ call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@6880 2580 InterpreterRuntime::register_finalizer), T1);
aoqi@1 2581 __ bind(skip_register_finalizer);
aoqi@1 2582 }
fujie@8858 2583
fujie@8858 2584 // Narrow result if state is itos but result type is smaller.
fujie@8858 2585 // Need to narrow in the return bytecode rather than in generate_return_entry
fujie@8858 2586 // since compiled code callers expect the result to already be narrowed.
fujie@8858 2587 if (state == itos) {
fujie@8858 2588 __ narrow(FSR);
fujie@8858 2589 }
fujie@8858 2590
aoqi@1 2591 __ remove_activation(state, T9);
fujie@32 2592 __ sync();
aoqi@1 2593
aoqi@1 2594 __ jr(T9);
aoqi@1 2595 __ delayed()->nop();
aoqi@1 2596 }
aoqi@1 2597
aoqi@1 2598 // ----------------------------------------------------------------------------
aoqi@1 2599 // Volatile variables demand their effects be made known to all CPU's
aoqi@1 2600 // in order. Store buffers on most chips allow reads & writes to
aoqi@1 2601 // reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode
aoqi@1 2602 // without some kind of memory barrier (i.e., it's not sufficient that
aoqi@1 2603 // the interpreter does not reorder volatile references, the hardware
aoqi@1 2604 // also must not reorder them).
aoqi@1 2605 //
aoqi@1 2606 // According to the new Java Memory Model (JMM):
aoqi@1 2607 // (1) All volatiles are serialized wrt to each other. ALSO reads &
aoqi@1 2608 // writes act as aquire & release, so:
aoqi@1 2609 // (2) A read cannot let unrelated NON-volatile memory refs that
aoqi@1 2610 // happen after the read float up to before the read. It's OK for
aoqi@1 2611 // non-volatile memory refs that happen before the volatile read to
aoqi@1 2612 // float down below it.
aoqi@1 2613 // (3) Similar a volatile write cannot let unrelated NON-volatile
aoqi@1 2614 // memory refs that happen BEFORE the write float down to after the
aoqi@1 2615 // write. It's OK for non-volatile memory refs that happen after the
aoqi@1 2616 // volatile write to float up before it.
aoqi@1 2617 //
aoqi@1 2618 // We only put in barriers around volatile refs (they are expensive),
aoqi@1 2619 // not _between_ memory refs (that would require us to track the
aoqi@1 2620 // flavor of the previous memory refs). Requirements (2) and (3)
aoqi@1 2621 // require some barriers before volatile stores and after volatile
aoqi@1 2622 // loads. These nearly cover requirement (1) but miss the
aoqi@1 2623 // volatile-store-volatile-load case. This final case is placed after
aoqi@1 2624 // volatile-stores although it could just as well go before
aoqi@1 2625 // volatile-loads.
fujie@8024 2626 void TemplateTable::volatile_barrier() {
fujie@8024 2627 if(os::is_MP()) __ sync();
aoqi@1 2628 }
aoqi@1 2629
aoqi@1 2630 // we dont shift left 2 bits in get_cache_and_index_at_bcp
aoqi@6880 2631 // for we always need shift the index we use it. the ConstantPoolCacheEntry
aoqi@6880 2632 // is 16-byte long, index is the index in
aoqi@6880 2633 // ConstantPoolCache, so cache + base_offset() + index * 16 is
aoqi@1 2634 // the corresponding ConstantPoolCacheEntry
aoqi@1 2635 // used registers : T2
aoqi@1 2636 // NOTE : the returned index need also shift left 4 to get the address!
aoqi@1 2637 void TemplateTable::resolve_cache_and_index(int byte_no,
aoqi@1 2638 Register Rcache,
aoqi@6880 2639 Register index,
aoqi@1 2640 size_t index_size) {
aoqi@1 2641 assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
aoqi@1 2642 const Register temp = A1;
aoqi@1 2643 assert_different_registers(Rcache, index);
aoqi@6880 2644
aoqi@1 2645 Label resolved;
aoqi@1 2646 __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
aoqi@1 2647 // is resolved?
aoqi@1 2648 int i = (int)bytecode();
aoqi@1 2649 __ addi(temp, temp, -i);
aoqi@1 2650 __ beq(temp, R0, resolved);
aoqi@1 2651 __ delayed()->nop();
aoqi@1 2652 // resolve first time through
aoqi@1 2653 address entry;
aoqi@1 2654 switch (bytecode()) {
aoqi@1 2655 case Bytecodes::_getstatic : // fall through
aoqi@1 2656 case Bytecodes::_putstatic : // fall through
aoqi@1 2657 case Bytecodes::_getfield : // fall through
aoqi@6880 2658 case Bytecodes::_putfield :
aoqi@6880 2659 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put);
aoqi@1 2660 break;
aoqi@1 2661 case Bytecodes::_invokevirtual : // fall through
aoqi@1 2662 case Bytecodes::_invokespecial : // fall through
aoqi@1 2663 case Bytecodes::_invokestatic : // fall through
aoqi@6880 2664 case Bytecodes::_invokeinterface:
aoqi@6880 2665 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
aoqi@1 2666 break;
aoqi@1 2667 case Bytecodes::_invokehandle:
aoqi@1 2668 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);
aoqi@1 2669 break;
aoqi@1 2670 case Bytecodes::_invokedynamic:
aoqi@1 2671 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
aoqi@1 2672 break;
aoqi@6880 2673 default :
aoqi@1 2674 fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
aoqi@6880 2675 break;
aoqi@1 2676 }
aoqi@1 2677
aoqi@1 2678 __ move(temp, i);
aoqi@1 2679 __ call_VM(NOREG, entry, temp);
aoqi@1 2680
aoqi@1 2681 // Update registers with resolved info
aoqi@1 2682 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
aoqi@1 2683 __ bind(resolved);
aoqi@1 2684 }
aoqi@1 2685
aoqi@1 2686 // The Rcache and index registers must be set before call
aoqi@1 2687 void TemplateTable::load_field_cp_cache_entry(Register obj,
aoqi@1 2688 Register cache,
aoqi@1 2689 Register index,
aoqi@1 2690 Register off,
aoqi@1 2691 Register flags,
aoqi@1 2692 bool is_static = false) {
aoqi@1 2693 assert_different_registers(cache, index, flags, off);
aoqi@6880 2694
aoqi@1 2695 ByteSize cp_base_offset = ConstantPoolCache::base_offset();
aoqi@1 2696 // Field offset
aoqi@1 2697 __ dsll(AT, index, Address::times_ptr);
aoqi@1 2698 __ dadd(AT, cache, AT);
aoqi@1 2699 __ ld(off, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()));
aoqi@6880 2700 // Flags
aoqi@1 2701 __ ld(flags, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()));
aoqi@1 2702
aoqi@6880 2703 // klass overwrite register
aoqi@1 2704 if (is_static) {
aoqi@6880 2705 __ ld(obj, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset()));
aoqi@1 2706 const int mirror_offset = in_bytes(Klass::java_mirror_offset());
aoqi@1 2707 __ ld(obj, Address(obj, mirror_offset));
aoqi@1 2708
aoqi@6880 2709 __ verify_oop(obj);
aoqi@1 2710 }
aoqi@1 2711 }
aoqi@1 2712
aoqi@1 2713 // get the method, itable_index and flags of the current invoke
aoqi@1 2714 void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
aoqi@1 2715 Register method,
aoqi@1 2716 Register itable_index,
aoqi@1 2717 Register flags,
aoqi@1 2718 bool is_invokevirtual,
aoqi@1 2719 bool is_invokevfinal, /*unused*/
aoqi@1 2720 bool is_invokedynamic) {
aoqi@1 2721 // setup registers
aoqi@1 2722 const Register cache = T3;
aoqi@1 2723 const Register index = T1;
aoqi@1 2724 assert_different_registers(method, flags);
aoqi@1 2725 assert_different_registers(method, cache, index);
aoqi@1 2726 assert_different_registers(itable_index, flags);
aoqi@1 2727 assert_different_registers(itable_index, cache, index);
aoqi@1 2728 assert(is_invokevirtual == (byte_no == f2_byte), "is invokevirtual flag redundant");
aoqi@1 2729 // determine constant pool cache field offsets
aoqi@1 2730 const int method_offset = in_bytes(
aoqi@6880 2731 ConstantPoolCache::base_offset() +
aoqi@1 2732 ((byte_no == f2_byte)
aoqi@1 2733 ? ConstantPoolCacheEntry::f2_offset()
aoqi@6880 2734 : ConstantPoolCacheEntry::f1_offset()));
aoqi@1 2735 const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +
aoqi@6880 2736 ConstantPoolCacheEntry::flags_offset());
aoqi@1 2737 // access constant pool cache fields
aoqi@1 2738 const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
aoqi@6880 2739 ConstantPoolCacheEntry::f2_offset());
aoqi@6880 2740
aoqi@1 2741 size_t index_size = (is_invokedynamic ? sizeof(u4): sizeof(u2));
aoqi@1 2742 resolve_cache_and_index(byte_no, cache, index, index_size);
aoqi@1 2743
aoqi@1 2744 //assert(wordSize == 8, "adjust code below");
aoqi@6880 2745 // note we shift 4 not 2, for we get is the true inde
aoqi@1 2746 // of ConstantPoolCacheEntry, not the shifted 2-bit index as x86 version
aoqi@1 2747 __ dsll(AT, index, Address::times_ptr);
aoqi@1 2748 __ dadd(AT, cache, AT);
aoqi@1 2749 __ ld(method, AT, method_offset);
aoqi@1 2750
aoqi@1 2751 if (itable_index != NOREG) {
aoqi@1 2752 __ ld(itable_index, AT, index_offset);
aoqi@1 2753 }
aoqi@1 2754 __ ld(flags, AT, flags_offset);
aoqi@1 2755 }
aoqi@1 2756
aoqi@1 2757 // The registers cache and index expected to be set before call.
aoqi@1 2758 // Correct values of the cache and index registers are preserved.
aoqi@1 2759 void TemplateTable::jvmti_post_field_access(Register cache, Register index,
aoqi@1 2760 bool is_static, bool has_tos) {
aoqi@1 2761 // do the JVMTI work here to avoid disturbing the register state below
aoqi@1 2762 // We use c_rarg registers here because we want to use the register used in
aoqi@1 2763 // the call to the VM
aoqi@6880 2764 if (JvmtiExport::can_post_field_access()) {
aoqi@6880 2765 // Check to see if a field access watch has been set before we
aoqi@6880 2766 // take the time to call into the VM.
aoqi@6880 2767 Label L1;
aoqi@6883 2768 // kill FSR
aoqi@6883 2769 Register tmp1 = T2;
aoqi@6883 2770 Register tmp2 = T1;
aoqi@6883 2771 Register tmp3 = T3;
aoqi@6883 2772 assert_different_registers(cache, index, AT);
aoqi@6880 2773 __ li(AT, (intptr_t)JvmtiExport::get_field_access_count_addr());
aoqi@6883 2774 __ lw(AT, AT, 0);
aoqi@6883 2775 __ beq(AT, R0, L1);
aoqi@6880 2776 __ delayed()->nop();
aoqi@6880 2777
aoqi@6883 2778 __ get_cache_and_index_at_bcp(tmp2, tmp3, 1);
aoqi@6883 2779
aoqi@6880 2780 // cache entry pointer
aoqi@6883 2781 __ daddi(tmp2, tmp2, in_bytes(ConstantPoolCache::base_offset()));
aoqi@6883 2782 __ shl(tmp3, LogBytesPerWord);
aoqi@6883 2783 __ dadd(tmp2, tmp2, tmp3);
aoqi@6880 2784 if (is_static) {
aoqi@6883 2785 __ move(tmp1, R0);
aoqi@6880 2786 } else {
aoqi@6883 2787 __ ld(tmp1, SP, 0);
aoqi@6883 2788 __ verify_oop(tmp1);
aoqi@6880 2789 }
aoqi@6883 2790 // tmp1: object pointer or NULL
aoqi@6883 2791 // tmp2: cache entry pointer
aoqi@6883 2792 // tmp3: jvalue object on the stack
aoqi@6880 2793 __ call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6883 2794 InterpreterRuntime::post_field_access),
aoqi@6883 2795 tmp1, tmp2, tmp3);
aoqi@6880 2796 __ get_cache_and_index_at_bcp(cache, index, 1);
aoqi@6880 2797 __ bind(L1);
aoqi@6880 2798 }
aoqi@1 2799 }
aoqi@1 2800
aoqi@1 2801 void TemplateTable::pop_and_check_object(Register r) {
aoqi@1 2802 __ pop_ptr(r);
aoqi@1 2803 __ null_check(r); // for field access must check obj.
aoqi@1 2804 __ verify_oop(r);
aoqi@1 2805 }
aoqi@1 2806
aoqi@1 2807 // used registers : T1, T2, T3, T1
aoqi@1 2808 // T1 : flags
aoqi@1 2809 // T2 : off
aoqi@1 2810 // T3 : obj
aoqi@1 2811 // T1 : field address
aoqi@1 2812 // The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the
aoqi@1 2813 // following mapping to the TosState states:
aoqi@1 2814 // btos: 0
aoqi@1 2815 // ctos: 1
aoqi@1 2816 // stos: 2
aoqi@1 2817 // itos: 3
aoqi@1 2818 // ltos: 4
aoqi@1 2819 // ftos: 5
aoqi@1 2820 // dtos: 6
aoqi@1 2821 // atos: 7
aoqi@1 2822 // vtos: 8
aoqi@1 2823 // see ConstantPoolCacheEntry::set_field for more info
aoqi@1 2824 void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
aoqi@1 2825 transition(vtos, vtos);
aoqi@1 2826
aoqi@1 2827 const Register cache = T3;
aoqi@1 2828 const Register index = T0;
aoqi@1 2829
aoqi@1 2830 const Register obj = T3;
aoqi@1 2831 const Register off = T2;
aoqi@1 2832 const Register flags = T1;
fujie@8025 2833
fujie@8026 2834 const Register scratch = T8;
fujie@8025 2835
aoqi@1 2836 resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
aoqi@6883 2837 jvmti_post_field_access(cache, index, is_static, false);
aoqi@1 2838 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
aoqi@1 2839
fujie@8026 2840 {
fujie@8026 2841 __ move(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift);
fujie@8026 2842 __ andr(scratch, scratch, flags);
fujie@8026 2843
fujie@8026 2844 Label notVolatile;
fujie@8026 2845 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 2846 __ delayed()->nop();
fujie@8026 2847 volatile_barrier();
fujie@8026 2848 __ bind(notVolatile);
fujie@8026 2849 }
fujie@8026 2850
aoqi@1 2851 if (!is_static) pop_and_check_object(obj);
aoqi@1 2852 __ dadd(index, obj, off);
aoqi@1 2853
aoqi@1 2854
fujie@8858 2855 Label Done, notByte, notBool, notInt, notShort, notChar,
aoqi@6880 2856 notLong, notFloat, notObj, notDouble;
aoqi@1 2857
aoqi@1 2858 assert(btos == 0, "change code, btos != 0");
aoqi@1 2859 __ dsrl(flags, flags, ConstantPoolCacheEntry::tos_state_shift);
fujie@8858 2860 __ andi(flags, flags, ConstantPoolCacheEntry::tos_state_mask);
aoqi@1 2861 __ bne(flags, R0, notByte);
aoqi@1 2862 __ delayed()->nop();
aoqi@1 2863
aoqi@1 2864 // btos
aoqi@6880 2865 __ lb(FSR, index, 0);
aoqi@1 2866 __ sd(FSR, SP, - wordSize);
aoqi@1 2867
aoqi@1 2868 // Rewrite bytecode to be faster
aoqi@1 2869 if (!is_static) {
aoqi@1 2870 patch_bytecode(Bytecodes::_fast_bgetfield, T3, T2);
aoqi@1 2871 }
aoqi@1 2872 __ b(Done);
aoqi@1 2873 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2874
fujie@8858 2875
aoqi@1 2876 __ bind(notByte);
fujie@8858 2877 __ move(AT, ztos);
fujie@8858 2878 __ bne(flags, AT, notBool);
fujie@8858 2879 __ delayed()->nop();
fujie@8858 2880
fujie@8858 2881 // ztos
fujie@8858 2882 __ lb(FSR, index, 0);
fujie@8858 2883 __ sd(FSR, SP, - wordSize);
fujie@8858 2884
fujie@8858 2885 // Rewrite bytecode to be faster
fujie@8858 2886 if (!is_static) {
fujie@8858 2887 // patch_bytecode(Bytecodes::_fast_igetfield, T3, T2);
fujie@8858 2888 patch_bytecode(Bytecodes::_fast_bgetfield, T3, T2);
fujie@8858 2889 }
fujie@8858 2890 __ b(Done);
fujie@8858 2891 __ delayed()->daddi(SP, SP, - wordSize);
fujie@8858 2892
fujie@8858 2893
fujie@8858 2894 __ bind(notBool);
aoqi@1 2895 __ move(AT, itos);
aoqi@1 2896 __ bne(flags, AT, notInt);
aoqi@1 2897 __ delayed()->nop();
aoqi@1 2898
aoqi@1 2899 // itos
aoqi@1 2900 __ lw(FSR, index, 0);
aoqi@1 2901 __ sd(FSR, SP, - wordSize);
aoqi@1 2902
aoqi@1 2903 // Rewrite bytecode to be faster
aoqi@1 2904 if (!is_static) {
aoqi@1 2905 // patch_bytecode(Bytecodes::_fast_igetfield, T3, T2);
aoqi@1 2906 patch_bytecode(Bytecodes::_fast_igetfield, T3, T2);
aoqi@1 2907 }
aoqi@1 2908 __ b(Done);
aoqi@1 2909 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2910
aoqi@1 2911 __ bind(notInt);
aoqi@1 2912 __ move(AT, atos);
aoqi@1 2913 __ bne(flags, AT, notObj);
aoqi@1 2914 __ delayed()->nop();
aoqi@1 2915
aoqi@1 2916 // atos
aoqi@1 2917 //add for compressedoops
aoqi@1 2918 __ load_heap_oop(FSR, Address(index, 0));
aoqi@1 2919 __ sd(FSR, SP, - wordSize);
aoqi@1 2920
aoqi@1 2921 if (!is_static) {
aoqi@1 2922 //patch_bytecode(Bytecodes::_fast_agetfield, T3, T2);
aoqi@1 2923 patch_bytecode(Bytecodes::_fast_agetfield, T3, T2);
aoqi@1 2924 }
aoqi@1 2925 __ b(Done);
aoqi@1 2926 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2927
aoqi@1 2928 __ bind(notObj);
aoqi@1 2929 __ move(AT, ctos);
aoqi@1 2930 __ bne(flags, AT, notChar);
aoqi@1 2931 __ delayed()->nop();
aoqi@1 2932
aoqi@1 2933 // ctos
aoqi@1 2934 __ lhu(FSR, index, 0);
aoqi@1 2935 __ sd(FSR, SP, - wordSize);
aoqi@1 2936
aoqi@1 2937 if (!is_static) {
aoqi@1 2938 patch_bytecode(Bytecodes::_fast_cgetfield, T3, T2);
aoqi@1 2939 }
aoqi@1 2940 __ b(Done);
aoqi@1 2941 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2942
aoqi@1 2943 __ bind(notChar);
aoqi@1 2944 __ move(AT, stos);
aoqi@1 2945 __ bne(flags, AT, notShort);
aoqi@1 2946 __ delayed()->nop();
aoqi@1 2947
aoqi@1 2948 // stos
aoqi@1 2949 __ lh(FSR, index, 0);
aoqi@1 2950 __ sd(FSR, SP, - wordSize);
aoqi@1 2951
aoqi@1 2952 if (!is_static) {
aoqi@1 2953 patch_bytecode(Bytecodes::_fast_sgetfield, T3, T2);
aoqi@1 2954 }
aoqi@1 2955 __ b(Done);
aoqi@1 2956 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2957
aoqi@1 2958 __ bind(notShort);
aoqi@1 2959 __ move(AT, ltos);
aoqi@1 2960 __ bne(flags, AT, notLong);
aoqi@1 2961 __ delayed()->nop();
aoqi@1 2962
aoqi@1 2963 // FIXME : the load/store should be atomic, we have no simple method to do this in mips32
aoqi@1 2964 // ltos
aoqi@1 2965 __ ld(FSR, index, 0 * wordSize);
aoqi@1 2966 __ sd(FSR, SP, -2 * wordSize);
aoqi@1 2967 __ sd(R0, SP, -1 * wordSize);
aoqi@1 2968
aoqi@1 2969 // Don't rewrite to _fast_lgetfield for potential volatile case.
aoqi@1 2970 __ b(Done);
aoqi@1 2971 __ delayed()->daddi(SP, SP, - 2 * wordSize);
aoqi@1 2972
aoqi@1 2973 __ bind(notLong);
aoqi@1 2974 __ move(AT, ftos);
aoqi@1 2975 __ bne(flags, AT, notFloat);
aoqi@1 2976 __ delayed()->nop();
aoqi@1 2977
aoqi@1 2978 // ftos
aoqi@1 2979 __ lwc1(FSF, index, 0);
aoqi@1 2980 __ sdc1(FSF, SP, - wordSize);
aoqi@1 2981
aoqi@1 2982 if (!is_static) {
aoqi@1 2983 patch_bytecode(Bytecodes::_fast_fgetfield, T3, T2);
aoqi@1 2984 }
aoqi@1 2985 __ b(Done);
aoqi@1 2986 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2987
aoqi@1 2988 __ bind(notFloat);
aoqi@1 2989 __ move(AT, dtos);
fujie@8024 2990 #ifdef ASSERT
aoqi@1 2991 __ bne(flags, AT, notDouble);
aoqi@1 2992 __ delayed()->nop();
fujie@8024 2993 #endif
aoqi@1 2994
aoqi@1 2995 // dtos
aoqi@1 2996 __ ldc1(FSF, index, 0 * wordSize);
aoqi@1 2997 __ sdc1(FSF, SP, - 2 * wordSize);
aoqi@1 2998 __ sd(R0, SP, - 1 * wordSize);
aoqi@1 2999
aoqi@1 3000 if (!is_static) {
aoqi@1 3001 patch_bytecode(Bytecodes::_fast_dgetfield, T3, T2);
aoqi@1 3002 }
fujie@8024 3003
fujie@8024 3004 __ daddi(SP, SP, - 2 * wordSize);
fujie@8024 3005
fujie@8024 3006 #ifdef ASSERT
aoqi@1 3007 __ b(Done);
aoqi@9124 3008 __ delayed()->nop();
aoqi@1 3009 __ bind(notDouble);
aoqi@1 3010 __ stop("Bad state");
fujie@8024 3011 #endif
aoqi@1 3012
aoqi@1 3013 __ bind(Done);
fujie@8025 3014
fujie@8026 3015 {
fujie@8026 3016 Label notVolatile;
fujie@8026 3017 __ beq(scratch, R0, notVolatile);
aoqi@9124 3018 __ delayed()->nop();
fujie@8026 3019 volatile_barrier();
fujie@8026 3020 __ bind(notVolatile);
fujie@8026 3021 }
aoqi@1 3022 }
aoqi@1 3023
aoqi@6880 3024
aoqi@1 3025 void TemplateTable::getfield(int byte_no) {
aoqi@1 3026 getfield_or_static(byte_no, false);
aoqi@1 3027 }
aoqi@1 3028
aoqi@1 3029 void TemplateTable::getstatic(int byte_no) {
aoqi@1 3030 getfield_or_static(byte_no, true);
aoqi@1 3031 }
aoqi@1 3032
aoqi@1 3033 // The registers cache and index expected to be set before call.
aoqi@1 3034 // The function may destroy various registers, just not the cache and index registers.
aoqi@1 3035 void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) {
aoqi@6883 3036 transition(vtos, vtos);
aoqi@6883 3037
aoqi@6880 3038 ByteSize cp_base_offset = ConstantPoolCache::base_offset();
aoqi@6880 3039
aoqi@6880 3040 if (JvmtiExport::can_post_field_modification()) {
aoqi@6883 3041 // Check to see if a field modification watch has been set before
aoqi@6883 3042 // we take the time to call into the VM.
aoqi@6880 3043 Label L1;
aoqi@6883 3044 //kill AT, T1, T2, T3, T9
aoqi@6883 3045 Register tmp1 = T2;
aoqi@6883 3046 Register tmp2 = T1;
aoqi@6883 3047 Register tmp3 = T3;
aoqi@6883 3048 Register tmp4 = T9;
aoqi@6883 3049 assert_different_registers(cache, index, tmp4);
aoqi@6880 3050
aoqi@6880 3051 __ li(AT, JvmtiExport::get_field_modification_count_addr());
aoqi@6883 3052 __ lw(AT, AT, 0);
aoqi@6883 3053 __ beq(AT, R0, L1);
aoqi@6880 3054 __ delayed()->nop();
aoqi@6880 3055
aoqi@6883 3056 __ get_cache_and_index_at_bcp(tmp2, tmp4, 1);
aoqi@6880 3057
aoqi@6880 3058 if (is_static) {
aoqi@6883 3059 __ move(tmp1, R0);
aoqi@6880 3060 } else {
aoqi@6883 3061 // Life is harder. The stack holds the value on top, followed by
aoqi@6883 3062 // the object. We don't know the size of the value, though; it
aoqi@6883 3063 // could be one or two words depending on its type. As a result,
aoqi@6883 3064 // we must find the type to determine where the object is.
aoqi@6880 3065 Label two_word, valsize_known;
aoqi@6883 3066 __ dsll(AT, tmp4, Address::times_8);
aoqi@6883 3067 __ dadd(AT, tmp2, AT);
aoqi@6883 3068 __ ld(tmp3, AT, in_bytes(cp_base_offset +
aoqi@6883 3069 ConstantPoolCacheEntry::flags_offset()));
aoqi@6883 3070 __ shr(tmp3, ConstantPoolCacheEntry::tos_state_shift);
aoqi@6880 3071
aoqi@6880 3072 // Make sure we don't need to mask ecx for tos_state_shift
aoqi@6880 3073 // after the above shift
aoqi@6880 3074 ConstantPoolCacheEntry::verify_tos_state_shift();
aoqi@6883 3075 __ move(tmp1, SP);
aoqi@6880 3076 __ move(AT, ltos);
aoqi@6883 3077 __ beq(tmp3, AT, two_word);
aoqi@6880 3078 __ delayed()->nop();
aoqi@6880 3079 __ move(AT, dtos);
aoqi@6883 3080 __ beq(tmp3, AT, two_word);
aoqi@6880 3081 __ delayed()->nop();
aoqi@6880 3082 __ b(valsize_known);
aoqi@6883 3083 __ delayed()->daddi(tmp1, tmp1, Interpreter::expr_offset_in_bytes(1) );
aoqi@6880 3084
aoqi@6880 3085 __ bind(two_word);
aoqi@6883 3086 __ daddi(tmp1, tmp1, Interpreter::expr_offset_in_bytes(2));
aoqi@6880 3087
aoqi@6880 3088 __ bind(valsize_known);
aoqi@6880 3089 // setup object pointer
aoqi@6883 3090 __ ld(tmp1, tmp1, 0*wordSize);
aoqi@6880 3091 }
aoqi@6880 3092 // cache entry pointer
aoqi@6883 3093 __ daddi(tmp2, tmp2, in_bytes(cp_base_offset));
aoqi@6883 3094 __ shl(tmp4, LogBytesPerWord);
aoqi@6883 3095 __ daddu(tmp2, tmp2, tmp4);
aoqi@6880 3096 // object (tos)
aoqi@6883 3097 __ move(tmp3, SP);
aoqi@6883 3098 // tmp1: object pointer set up above (NULL if static)
aoqi@6883 3099 // tmp2: cache entry pointer
aoqi@6883 3100 // tmp3: jvalue object on the stack
aoqi@6883 3101 __ call_VM(NOREG,
aoqi@6883 3102 CAST_FROM_FN_PTR(address,
aoqi@6883 3103 InterpreterRuntime::post_field_modification),
aoqi@6883 3104 tmp1, tmp2, tmp3);
aoqi@6880 3105 __ get_cache_and_index_at_bcp(cache, index, 1);
aoqi@6880 3106 __ bind(L1);
aoqi@6880 3107 }
aoqi@1 3108 }
aoqi@1 3109
aoqi@1 3110 // used registers : T0, T1, T2, T3, T8
aoqi@1 3111 // T1 : flags
aoqi@1 3112 // T2 : off
aoqi@1 3113 // T3 : obj
aoqi@1 3114 // T8 : volatile bit
aoqi@1 3115 // see ConstantPoolCacheEntry::set_field for more info
aoqi@1 3116 void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
aoqi@1 3117 transition(vtos, vtos);
aoqi@1 3118
aoqi@1 3119 const Register cache = T3;
aoqi@1 3120 const Register index = T0;
aoqi@1 3121 const Register obj = T3;
aoqi@1 3122 const Register off = T2;
aoqi@1 3123 const Register flags = T1;
aoqi@1 3124 const Register bc = T3;
aoqi@1 3125
fujie@8026 3126 const Register scratch = T8;
fujie@8025 3127
aoqi@1 3128 resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
aoqi@6883 3129 jvmti_post_field_mod(cache, index, is_static);
aoqi@1 3130 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
aoqi@1 3131
fujie@8026 3132 Label Done;
fujie@8026 3133 {
fujie@8026 3134 __ move(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift);
fujie@8026 3135 __ andr(scratch, scratch, flags);
fujie@8026 3136
fujie@8026 3137 Label notVolatile;
fujie@8026 3138 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3139 __ delayed()->nop();
fujie@8026 3140 volatile_barrier();
fujie@8026 3141 __ bind(notVolatile);
fujie@8026 3142 }
fujie@8026 3143
aoqi@1 3144
fujie@8858 3145 Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
aoqi@6880 3146
aoqi@1 3147 assert(btos == 0, "change code, btos != 0");
fujie@8003 3148
aoqi@1 3149 // btos
aoqi@1 3150 __ dsrl(flags, flags, ConstantPoolCacheEntry::tos_state_shift);
aoqi@1 3151 __ andi(flags, flags, ConstantPoolCacheEntry::tos_state_mask);
aoqi@1 3152 __ bne(flags, R0, notByte);
aoqi@1 3153 __ delayed()->nop();
aoqi@1 3154
aoqi@1 3155 __ pop(btos);
aoqi@1 3156 if (!is_static) {
aoqi@6880 3157 pop_and_check_object(obj);
aoqi@1 3158 }
aoqi@1 3159 __ dadd(AT, obj, off);
aoqi@1 3160 __ sb(FSR, AT, 0);
aoqi@1 3161
aoqi@1 3162 if (!is_static) {
aoqi@1 3163 patch_bytecode(Bytecodes::_fast_bputfield, bc, off, true, byte_no);
aoqi@1 3164 }
aoqi@1 3165 __ b(Done);
aoqi@1 3166 __ delayed()->nop();
aoqi@1 3167
fujie@8858 3168 // ztos
fujie@8858 3169 __ bind(notByte);
fujie@8858 3170 __ move(AT, ztos);
fujie@8858 3171 __ bne(flags, AT, notBool);
fujie@8858 3172 __ delayed()->nop();
fujie@8858 3173
fujie@8858 3174 __ pop(ztos);
fujie@8858 3175 if (!is_static) {
fujie@8858 3176 pop_and_check_object(obj);
fujie@8858 3177 }
fujie@8858 3178 __ dadd(AT, obj, off);
fujie@8858 3179 __ andi(FSR, FSR, 0x1);
fujie@8858 3180 __ sb(FSR, AT, 0);
fujie@8858 3181
fujie@8858 3182 if (!is_static) {
fujie@8858 3183 patch_bytecode(Bytecodes::_fast_zputfield, bc, off, true, byte_no);
fujie@8858 3184 }
fujie@8858 3185 __ b(Done);
fujie@8858 3186 __ delayed()->nop();
fujie@8858 3187
fujie@8003 3188 // itos
fujie@8858 3189 __ bind(notBool);
aoqi@1 3190 __ move(AT, itos);
aoqi@1 3191 __ bne(flags, AT, notInt);
aoqi@1 3192 __ delayed()->nop();
aoqi@1 3193
aoqi@1 3194 __ pop(itos);
aoqi@1 3195 if (!is_static) {
aoqi@6880 3196 pop_and_check_object(obj);
aoqi@1 3197 }
aoqi@1 3198 __ dadd(AT, obj, off);
aoqi@1 3199 __ sw(FSR, AT, 0);
aoqi@1 3200
aoqi@1 3201 if (!is_static) {
aoqi@1 3202 patch_bytecode(Bytecodes::_fast_iputfield, bc, off, true, byte_no);
aoqi@1 3203 }
aoqi@1 3204 __ b(Done);
aoqi@6880 3205 __ delayed()->nop();
fujie@8003 3206
fujie@8003 3207 // atos
aoqi@1 3208 __ bind(notInt);
aoqi@1 3209 __ move(AT, atos);
aoqi@1 3210 __ bne(flags, AT, notObj);
aoqi@1 3211 __ delayed()->nop();
aoqi@1 3212
aoqi@1 3213 __ pop(atos);
aoqi@1 3214 if (!is_static) {
aoqi@6880 3215 pop_and_check_object(obj);
aoqi@1 3216 }
aoqi@1 3217
fujie@8003 3218 do_oop_store(_masm, Address(obj, off, Address::times_1, 0), FSR, _bs->kind(), false);
aoqi@1 3219
aoqi@1 3220 if (!is_static) {
aoqi@1 3221 patch_bytecode(Bytecodes::_fast_aputfield, bc, off, true, byte_no);
aoqi@1 3222 }
aoqi@1 3223 __ b(Done);
aoqi@1 3224 __ delayed()->nop();
fujie@8003 3225
fujie@8003 3226 // ctos
aoqi@1 3227 __ bind(notObj);
aoqi@1 3228 __ move(AT, ctos);
aoqi@1 3229 __ bne(flags, AT, notChar);
aoqi@1 3230 __ delayed()->nop();
aoqi@1 3231
aoqi@1 3232 __ pop(ctos);
aoqi@1 3233 if (!is_static) {
aoqi@6880 3234 pop_and_check_object(obj);
aoqi@1 3235 }
aoqi@1 3236 __ dadd(AT, obj, off);
aoqi@1 3237 __ sh(FSR, AT, 0);
aoqi@1 3238 if (!is_static) {
aoqi@1 3239 patch_bytecode(Bytecodes::_fast_cputfield, bc, off, true, byte_no);
aoqi@1 3240 }
aoqi@1 3241 __ b(Done);
aoqi@1 3242 __ delayed()->nop();
fujie@8003 3243
fujie@8003 3244 // stos
aoqi@1 3245 __ bind(notChar);
aoqi@1 3246 __ move(AT, stos);
aoqi@1 3247 __ bne(flags, AT, notShort);
aoqi@1 3248 __ delayed()->nop();
aoqi@1 3249
aoqi@1 3250 __ pop(stos);
aoqi@1 3251 if (!is_static) {
aoqi@6880 3252 pop_and_check_object(obj);
aoqi@1 3253 }
aoqi@1 3254 __ dadd(AT, obj, off);
aoqi@1 3255 __ sh(FSR, AT, 0);
aoqi@1 3256 if (!is_static) {
aoqi@1 3257 patch_bytecode(Bytecodes::_fast_sputfield, bc, off, true, byte_no);
aoqi@1 3258 }
aoqi@1 3259 __ b(Done);
aoqi@1 3260 __ delayed()->nop();
fujie@8003 3261
fujie@8003 3262 // ltos
aoqi@1 3263 __ bind(notShort);
aoqi@1 3264 __ move(AT, ltos);
aoqi@1 3265 __ bne(flags, AT, notLong);
aoqi@1 3266 __ delayed()->nop();
aoqi@1 3267
aoqi@1 3268 __ pop(ltos);
aoqi@1 3269 if (!is_static) {
aoqi@6880 3270 pop_and_check_object(obj);
aoqi@1 3271 }
aoqi@1 3272 __ dadd(AT, obj, off);
aoqi@1 3273 __ sd(FSR, AT, 0);
aoqi@1 3274 if (!is_static) {
aoqi@1 3275 patch_bytecode(Bytecodes::_fast_lputfield, bc, off, true, byte_no);
aoqi@1 3276 }
fujie@8025 3277 __ b(Done);
aoqi@1 3278 __ delayed()->nop();
aoqi@1 3279
fujie@8003 3280 // ftos
aoqi@1 3281 __ bind(notLong);
aoqi@1 3282 __ move(AT, ftos);
aoqi@1 3283 __ bne(flags, AT, notFloat);
aoqi@1 3284 __ delayed()->nop();
aoqi@1 3285
aoqi@1 3286 __ pop(ftos);
aoqi@1 3287 if (!is_static) {
aoqi@6880 3288 pop_and_check_object(obj);
aoqi@1 3289 }
aoqi@1 3290 __ dadd(AT, obj, off);
aoqi@1 3291 __ swc1(FSF, AT, 0);
aoqi@1 3292 if (!is_static) {
aoqi@1 3293 patch_bytecode(Bytecodes::_fast_fputfield, bc, off, true, byte_no);
aoqi@1 3294 }
aoqi@1 3295 __ b(Done);
aoqi@1 3296 __ delayed()->nop();
fujie@8003 3297
fujie@8003 3298
fujie@8003 3299 // dtos
aoqi@1 3300 __ bind(notFloat);
aoqi@1 3301 __ move(AT, dtos);
fujie@8024 3302 #ifdef ASSERT
aoqi@1 3303 __ bne(flags, AT, notDouble);
aoqi@1 3304 __ delayed()->nop();
fujie@8024 3305 #endif
aoqi@1 3306
aoqi@1 3307 __ pop(dtos);
aoqi@1 3308 if (!is_static) {
aoqi@6880 3309 pop_and_check_object(obj);
aoqi@1 3310 }
aoqi@1 3311 __ dadd(AT, obj, off);
aoqi@1 3312 __ sdc1(FSF, AT, 0);
aoqi@1 3313 if (!is_static) {
aoqi@1 3314 patch_bytecode(Bytecodes::_fast_dputfield, bc, off, true, byte_no);
aoqi@1 3315 }
aoqi@6880 3316
aoqi@6880 3317 #ifdef ASSERT
aoqi@1 3318 __ b(Done);
aoqi@1 3319 __ delayed()->nop();
aoqi@6880 3320
aoqi@1 3321 __ bind(notDouble);
aoqi@1 3322 __ stop("Bad state");
aoqi@6880 3323 #endif
aoqi@1 3324
aoqi@1 3325 __ bind(Done);
aoqi@1 3326
fujie@8026 3327 {
fujie@8026 3328 Label notVolatile;
fujie@8026 3329 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3330 __ delayed()->nop();
fujie@8026 3331 volatile_barrier();
fujie@8026 3332 __ bind(notVolatile);
fujie@8026 3333 }
aoqi@1 3334 }
aoqi@1 3335
aoqi@1 3336 void TemplateTable::putfield(int byte_no) {
aoqi@1 3337 putfield_or_static(byte_no, false);
aoqi@1 3338 }
aoqi@1 3339
aoqi@1 3340 void TemplateTable::putstatic(int byte_no) {
aoqi@1 3341 putfield_or_static(byte_no, true);
aoqi@1 3342 }
aoqi@1 3343
aoqi@1 3344 // used registers : T1, T2, T3
aoqi@1 3345 // T1 : cp_entry
aoqi@1 3346 // T2 : obj
aoqi@1 3347 // T3 : value pointer
aoqi@1 3348 void TemplateTable::jvmti_post_fast_field_mod() {
aoqi@6880 3349 if (JvmtiExport::can_post_field_modification()) {
aoqi@6880 3350 // Check to see if a field modification watch has been set before
aoqi@6880 3351 // we take the time to call into the VM.
aoqi@6880 3352 Label L2;
aoqi@6883 3353 //kill AT, T1, T2, T3, T9
aoqi@6883 3354 Register tmp1 = T2;
aoqi@6883 3355 Register tmp2 = T1;
aoqi@6883 3356 Register tmp3 = T3;
aoqi@6883 3357 Register tmp4 = T9;
aoqi@6880 3358 __ li(AT, JvmtiExport::get_field_modification_count_addr());
aoqi@6883 3359 __ lw(tmp3, AT, 0);
aoqi@6883 3360 __ beq(tmp3, R0, L2);
aoqi@6880 3361 __ delayed()->nop();
aoqi@6883 3362 __ pop_ptr(tmp1);
aoqi@6883 3363 __ verify_oop(tmp1);
aoqi@6883 3364 __ push_ptr(tmp1);
aoqi@6880 3365 switch (bytecode()) { // load values into the jvalue object
aoqi@6883 3366 case Bytecodes::_fast_aputfield: __ push_ptr(FSR); break;
aoqi@6883 3367 case Bytecodes::_fast_bputfield: // fall through
fujie@8858 3368 case Bytecodes::_fast_zputfield: // fall through
aoqi@6883 3369 case Bytecodes::_fast_sputfield: // fall through
aoqi@6883 3370 case Bytecodes::_fast_cputfield: // fall through
aoqi@6883 3371 case Bytecodes::_fast_iputfield: __ push_i(FSR); break;
aoqi@6883 3372 case Bytecodes::_fast_dputfield: __ push_d(FSF); break;
aoqi@6883 3373 case Bytecodes::_fast_fputfield: __ push_f(); break;
aoqi@6883 3374 case Bytecodes::_fast_lputfield: __ push_l(FSR); break;
aoqi@6880 3375 default: ShouldNotReachHere();
aoqi@6880 3376 }
aoqi@6883 3377 __ move(tmp3, SP);
aoqi@6880 3378 // access constant pool cache entry
aoqi@6883 3379 __ get_cache_entry_pointer_at_bcp(tmp2, FSR, 1);
aoqi@6883 3380 __ verify_oop(tmp1);
aoqi@6883 3381 // tmp1: object pointer copied above
aoqi@6883 3382 // tmp2: cache entry pointer
aoqi@6883 3383 // tmp3: jvalue object on the stack
aoqi@6883 3384 __ call_VM(NOREG,
aoqi@6883 3385 CAST_FROM_FN_PTR(address,
aoqi@6883 3386 InterpreterRuntime::post_field_modification),
aoqi@6883 3387 tmp1, tmp2, tmp3);
aoqi@6883 3388
aoqi@6883 3389 switch (bytecode()) { // restore tos values
aoqi@6883 3390 case Bytecodes::_fast_aputfield: __ pop_ptr(FSR); break;
aoqi@6883 3391 case Bytecodes::_fast_bputfield: // fall through
fujie@8858 3392 case Bytecodes::_fast_zputfield: // fall through
aoqi@6883 3393 case Bytecodes::_fast_sputfield: // fall through
aoqi@6883 3394 case Bytecodes::_fast_cputfield: // fall through
aoqi@6883 3395 case Bytecodes::_fast_iputfield: __ pop_i(FSR); break;
aoqi@6883 3396 case Bytecodes::_fast_dputfield: __ pop_d(); break;
aoqi@6883 3397 case Bytecodes::_fast_fputfield: __ pop_f(); break;
aoqi@6883 3398 case Bytecodes::_fast_lputfield: __ pop_l(FSR); break;
aoqi@6883 3399 }
aoqi@6880 3400 __ bind(L2);
aoqi@6880 3401 }
aoqi@1 3402 }
aoqi@1 3403
aoqi@1 3404 // used registers : T2, T3, T1
aoqi@1 3405 // T2 : index & off & field address
aoqi@1 3406 // T3 : cache & obj
aoqi@1 3407 // T1 : flags
aoqi@1 3408 void TemplateTable::fast_storefield(TosState state) {
aoqi@1 3409 transition(state, vtos);
aoqi@1 3410
fujie@8026 3411 const Register scratch = T8;
fujie@8026 3412
aoqi@1 3413 ByteSize base = ConstantPoolCache::base_offset();
aoqi@1 3414
aoqi@1 3415 jvmti_post_fast_field_mod();
aoqi@1 3416
aoqi@1 3417 // access constant pool cache
aoqi@1 3418 __ get_cache_and_index_at_bcp(T3, T2, 1);
aoqi@1 3419
aoqi@1 3420 // test for volatile with edx but edx is tos register for lputfield.
aoqi@6880 3421 __ dsll(AT, T2, Address::times_8);
aoqi@1 3422 __ dadd(AT, T3, AT);
aoqi@1 3423 __ ld(T1, AT, in_bytes(base + ConstantPoolCacheEntry::flags_offset()));
aoqi@1 3424
aoqi@1 3425 // replace index with field offset from cache entry
aoqi@1 3426 __ ld(T2, AT, in_bytes(base + ConstantPoolCacheEntry::f2_offset()));
aoqi@1 3427
fujie@8026 3428 Label Done;
fujie@8026 3429 {
fujie@8026 3430 __ move(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift);
fujie@8026 3431 __ andr(scratch, scratch, T1);
fujie@8026 3432
fujie@8026 3433 Label notVolatile;
fujie@8026 3434 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3435 __ delayed()->nop();
fujie@8026 3436 volatile_barrier();
fujie@8026 3437 __ bind(notVolatile);
fujie@8026 3438 }
aoqi@1 3439
aoqi@1 3440 // Get object from stack
aoqi@1 3441 pop_and_check_object(T3);
aoqi@6880 3442
fujie@8003 3443 if (bytecode() != Bytecodes::_fast_aputfield) {
fujie@8003 3444 // field address
fujie@8003 3445 __ dadd(T2, T3, T2);
fujie@8003 3446 }
aoqi@1 3447
aoqi@1 3448 // access field
aoqi@1 3449 switch (bytecode()) {
fujie@8858 3450 case Bytecodes::_fast_zputfield:
fujie@8858 3451 __ andi(FSR, FSR, 0x1); // boolean is true if LSB is 1
fujie@8858 3452 // fall through to bputfield
aoqi@6880 3453 case Bytecodes::_fast_bputfield:
aoqi@1 3454 __ sb(FSR, T2, 0);
aoqi@1 3455 break;
aoqi@1 3456 case Bytecodes::_fast_sputfield: // fall through
aoqi@6880 3457 case Bytecodes::_fast_cputfield:
aoqi@1 3458 __ sh(FSR, T2, 0);
aoqi@1 3459 break;
aoqi@6880 3460 case Bytecodes::_fast_iputfield:
aoqi@1 3461 __ sw(FSR, T2, 0);
aoqi@1 3462 break;
aoqi@6880 3463 case Bytecodes::_fast_lputfield:
aoqi@1 3464 __ sd(FSR, T2, 0 * wordSize);
aoqi@1 3465 break;
aoqi@6880 3466 case Bytecodes::_fast_fputfield:
aoqi@1 3467 __ swc1(FSF, T2, 0);
aoqi@1 3468 break;
aoqi@6880 3469 case Bytecodes::_fast_dputfield:
aoqi@1 3470 __ sdc1(FSF, T2, 0 * wordSize);
aoqi@1 3471 break;
aoqi@6880 3472 case Bytecodes::_fast_aputfield:
fujie@8003 3473 do_oop_store(_masm, Address(T3, T2, Address::times_1, 0), FSR, _bs->kind(), false);
aoqi@1 3474 break;
aoqi@1 3475 default:
aoqi@1 3476 ShouldNotReachHere();
aoqi@1 3477 }
aoqi@1 3478
fujie@8026 3479 {
fujie@8026 3480 Label notVolatile;
fujie@8026 3481 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3482 __ delayed()->nop();
fujie@8026 3483 volatile_barrier();
fujie@8026 3484 __ bind(notVolatile);
fujie@8026 3485 }
aoqi@1 3486 }
aoqi@1 3487
aoqi@1 3488 // used registers : T2, T3, T1
aoqi@1 3489 // T3 : cp_entry & cache
aoqi@1 3490 // T2 : index & offset
aoqi@1 3491 void TemplateTable::fast_accessfield(TosState state) {
aoqi@1 3492 transition(atos, state);
aoqi@1 3493
fujie@8026 3494 const Register scratch = T8;
fujie@8026 3495
aoqi@1 3496 // do the JVMTI work here to avoid disturbing the register state below
aoqi@1 3497 if (JvmtiExport::can_post_field_access()) {
aoqi@1 3498 // Check to see if a field access watch has been set before we take
aoqi@1 3499 // the time to call into the VM.
aoqi@1 3500 Label L1;
aoqi@1 3501 __ li(AT, (intptr_t)JvmtiExport::get_field_access_count_addr());
aoqi@1 3502 __ lw(T3, AT, 0);
aoqi@1 3503 __ beq(T3, R0, L1);
aoqi@1 3504 __ delayed()->nop();
aoqi@1 3505 // access constant pool cache entry
aoqi@1 3506 __ get_cache_entry_pointer_at_bcp(T3, T1, 1);
aoqi@1 3507 __ move(TSR, FSR);
aoqi@1 3508 __ verify_oop(FSR);
aoqi@1 3509 // FSR: object pointer copied above
aoqi@1 3510 // T3: cache entry pointer
aoqi@6880 3511 __ call_VM(NOREG,
aoqi@6880 3512 CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access),
aoqi@6880 3513 FSR, T3);
aoqi@1 3514 __ move(FSR, TSR);
aoqi@1 3515 __ bind(L1);
aoqi@1 3516 }
aoqi@1 3517
aoqi@1 3518 // access constant pool cache
aoqi@1 3519 __ get_cache_and_index_at_bcp(T3, T2, 1);
aoqi@1 3520 // replace index with field offset from cache entry
aoqi@1 3521 __ dsll(AT, T2, Address::times_8);
aoqi@1 3522 __ dadd(AT, T3, AT);
fujie@8025 3523 __ ld(T2, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()));
fujie@8025 3524
fujie@8026 3525 {
fujie@8026 3526 __ ld(AT, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
fujie@8026 3527 __ move(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift);
fujie@8026 3528 __ andr(scratch, scratch, AT);
fujie@8026 3529
fujie@8026 3530 Label notVolatile;
fujie@8026 3531 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3532 __ delayed()->nop();
fujie@8026 3533 volatile_barrier();
fujie@8026 3534 __ bind(notVolatile);
fujie@8026 3535 }
aoqi@1 3536
aoqi@1 3537 // eax: object
aoqi@1 3538 __ verify_oop(FSR);
aoqi@1 3539 __ null_check(FSR);
aoqi@1 3540 // field addresses
aoqi@1 3541 __ dadd(FSR, FSR, T2);
aoqi@1 3542
aoqi@1 3543 // access field
aoqi@1 3544 switch (bytecode()) {
aoqi@6880 3545 case Bytecodes::_fast_bgetfield:
aoqi@1 3546 __ lb(FSR, FSR, 0);
aoqi@1 3547 break;
aoqi@6880 3548 case Bytecodes::_fast_sgetfield:
aoqi@1 3549 __ lh(FSR, FSR, 0);
aoqi@1 3550 break;
aoqi@6880 3551 case Bytecodes::_fast_cgetfield:
aoqi@1 3552 __ lhu(FSR, FSR, 0);
aoqi@1 3553 break;
aoqi@1 3554 case Bytecodes::_fast_igetfield:
aoqi@1 3555 __ lw(FSR, FSR, 0);
aoqi@1 3556 break;
aoqi@6880 3557 case Bytecodes::_fast_lgetfield:
aoqi@6880 3558 __ stop("should not be rewritten");
aoqi@1 3559 break;
aoqi@6880 3560 case Bytecodes::_fast_fgetfield:
aoqi@1 3561 __ lwc1(FSF, FSR, 0);
aoqi@1 3562 break;
aoqi@6880 3563 case Bytecodes::_fast_dgetfield:
aoqi@1 3564 __ ldc1(FSF, FSR, 0);
aoqi@1 3565 break;
aoqi@1 3566 case Bytecodes::_fast_agetfield:
aoqi@1 3567 //add for compressedoops
aoqi@1 3568 __ load_heap_oop(FSR, Address(FSR, 0));
aoqi@1 3569 __ verify_oop(FSR);
aoqi@1 3570 break;
aoqi@1 3571 default:
aoqi@1 3572 ShouldNotReachHere();
aoqi@1 3573 }
aoqi@1 3574
fujie@8026 3575 {
fujie@8026 3576 Label notVolatile;
fujie@8026 3577 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3578 __ delayed()->nop();
fujie@8026 3579 volatile_barrier();
fujie@8026 3580 __ bind(notVolatile);
fujie@8026 3581 }
aoqi@1 3582 }
aoqi@1 3583
aoqi@1 3584 // generator for _fast_iaccess_0, _fast_aaccess_0, _fast_faccess_0
aoqi@1 3585 // used registers : T1, T2, T3, T1
aoqi@1 3586 // T1 : obj & field address
aoqi@1 3587 // T2 : off
aoqi@1 3588 // T3 : cache
aoqi@1 3589 // T1 : index
aoqi@1 3590 void TemplateTable::fast_xaccess(TosState state) {
aoqi@1 3591 transition(vtos, state);
aoqi@8027 3592
fujie@8026 3593 const Register scratch = T8;
fujie@8025 3594
aoqi@1 3595 // get receiver
aoqi@1 3596 __ ld(T1, aaddress(0));
aoqi@1 3597 // access constant pool cache
aoqi@1 3598 __ get_cache_and_index_at_bcp(T3, T2, 2);
aoqi@1 3599 __ dsll(AT, T2, Address::times_8);
aoqi@1 3600 __ dadd(AT, T3, AT);
aoqi@6880 3601 __ ld(T2, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()));
aoqi@6880 3602
fujie@8026 3603 {
fujie@8026 3604 __ ld(AT, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()));
fujie@8026 3605 __ move(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift);
fujie@8026 3606 __ andr(scratch, scratch, AT);
fujie@8026 3607
fujie@8026 3608 Label notVolatile;
fujie@8026 3609 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3610 __ delayed()->nop();
fujie@8026 3611 volatile_barrier();
fujie@8026 3612 __ bind(notVolatile);
fujie@8026 3613 }
fujie@8026 3614
aoqi@6880 3615 // make sure exception is reported in correct bcp range (getfield is
aoqi@6880 3616 // next instruction)
aoqi@1 3617 __ daddi(BCP, BCP, 1);
aoqi@1 3618 __ null_check(T1);
aoqi@1 3619 __ dadd(T1, T1, T2);
aoqi@1 3620
aoqi@1 3621 if (state == itos) {
aoqi@1 3622 __ lw(FSR, T1, 0);
aoqi@1 3623 } else if (state == atos) {
aoqi@1 3624 __ load_heap_oop(FSR, Address(T1, 0));
aoqi@1 3625 __ verify_oop(FSR);
aoqi@1 3626 } else if (state == ftos) {
aoqi@1 3627 __ lwc1(FSF, T1, 0);
aoqi@1 3628 } else {
aoqi@1 3629 ShouldNotReachHere();
aoqi@1 3630 }
aoqi@1 3631 __ daddi(BCP, BCP, -1);
fujie@8025 3632
fujie@8026 3633 {
fujie@8026 3634 Label notVolatile;
fujie@8026 3635 __ beq(scratch, R0, notVolatile);
zhaixiang@9144 3636 __ delayed()->nop();
fujie@8026 3637 volatile_barrier();
fujie@8026 3638 __ bind(notVolatile);
fujie@8026 3639 }
aoqi@1 3640 }
aoqi@1 3641
aoqi@6880 3642
aoqi@6880 3643
aoqi@6880 3644 //-----------------------------------------------------------------------------
aoqi@1 3645 // Calls
aoqi@1 3646
aoqi@6880 3647 void TemplateTable::count_calls(Register method, Register temp) {
aoqi@6880 3648 // implemented elsewhere
aoqi@6880 3649 ShouldNotReachHere();
aoqi@1 3650 }
aoqi@1 3651
aoqi@1 3652 // method, index, recv, flags: T1, T2, T3, T1
aoqi@1 3653 // byte_no = 2 for _invokevirtual, 1 else
aoqi@1 3654 // T0 : return address
aoqi@6880 3655 // get the method & index of the invoke, and push the return address of
aoqi@1 3656 // the invoke(first word in the frame)
aoqi@1 3657 // this address is where the return code jmp to.
aoqi@1 3658 // NOTE : this method will set T3&T1 as recv&flags
aoqi@1 3659 void TemplateTable::prepare_invoke(int byte_no,
aoqi@6880 3660 Register method, // linked method (or i-klass)
aoqi@6880 3661 Register index, // itable index, MethodType, etc.
aoqi@6880 3662 Register recv, // if caller wants to see it
aoqi@6880 3663 Register flags // if caller wants to test it
aoqi@6880 3664 ) {
aoqi@1 3665 // determine flags
aoqi@1 3666 const Bytecodes::Code code = bytecode();
aoqi@1 3667 const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
aoqi@1 3668 const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
aoqi@1 3669 const bool is_invokehandle = code == Bytecodes::_invokehandle;
aoqi@1 3670 const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
aoqi@1 3671 const bool is_invokespecial = code == Bytecodes::_invokespecial;
aoqi@1 3672 const bool load_receiver = (recv != noreg);
aoqi@1 3673 const bool save_flags = (flags != noreg);
aoqi@1 3674 assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic),"");
aoqi@1 3675 assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");
aoqi@1 3676 assert(flags == noreg || flags == T1, "error flags reg.");
aoqi@1 3677 assert(recv == noreg || recv == T3, "error recv reg.");
aoqi@6880 3678
aoqi@1 3679 // setup registers & access constant pool cache
aoqi@1 3680 if(recv == noreg) recv = T3;
aoqi@1 3681 if(flags == noreg) flags = T1;
aoqi@1 3682 assert_different_registers(method, index, recv, flags);
aoqi@1 3683
aoqi@1 3684 // save 'interpreter return address'
aoqi@1 3685 __ save_bcp();
aoqi@1 3686
aoqi@1 3687 load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
aoqi@6880 3688
aoqi@1 3689 if (is_invokedynamic || is_invokehandle) {
aoqi@1 3690 Label L_no_push;
aoqi@1 3691 __ move(AT, (1 << ConstantPoolCacheEntry::has_appendix_shift));
aoqi@1 3692 __ andr(AT, AT, flags);
aoqi@1 3693 __ beq(AT, R0, L_no_push);
aoqi@1 3694 __ delayed()->nop();
aoqi@1 3695 // Push the appendix as a trailing parameter.
aoqi@1 3696 // This must be done before we get the receiver,
aoqi@1 3697 // since the parameter_size includes it.
aoqi@1 3698 Register tmp = SSR;
aoqi@1 3699 __ push(tmp);
aoqi@1 3700 __ move(tmp, index);
aoqi@1 3701 assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
aoqi@1 3702 __ load_resolved_reference_at_index(index, tmp);
aoqi@1 3703 __ pop(tmp);
aoqi@1 3704 __ push(index); // push appendix (MethodType, CallSite, etc.)
aoqi@1 3705 __ bind(L_no_push);
aoqi@1 3706 }
aoqi@1 3707
aoqi@6880 3708 // load receiver if needed (after appendix is pushed so parameter size is correct)
aoqi@6880 3709 // Note: no return address pushed yet
aoqi@1 3710 if (load_receiver) {
aoqi@6880 3711 __ move(AT, ConstantPoolCacheEntry::parameter_size_mask);
aoqi@6880 3712 __ andr(recv, flags, AT);
aoqi@6880 3713 // 2014/07/31 Fu: Since we won't push RA on stack, no_return_pc_pushed_yet should be 0.
aoqi@6880 3714 const int no_return_pc_pushed_yet = 0; // argument slot correction before we push return address
aoqi@6880 3715 const int receiver_is_at_end = -1; // back off one slot to get receiver
aoqi@6880 3716 Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);
aoqi@6880 3717 __ ld(recv, recv_addr);
aoqi@6880 3718 __ verify_oop(recv);
aoqi@1 3719 }
aoqi@1 3720 if(save_flags) {
aoqi@1 3721 __ move(BCP, flags);
aoqi@1 3722 }
aoqi@6880 3723
aoqi@1 3724 // compute return type
aoqi@1 3725 __ dsrl(flags, flags, ConstantPoolCacheEntry::tos_state_shift);
aoqi@1 3726 __ andi(flags, flags, 0xf);
aoqi@1 3727
aoqi@1 3728 // Make sure we don't need to mask flags for tos_state_shift after the above shift
aoqi@1 3729 ConstantPoolCacheEntry::verify_tos_state_shift();
aoqi@1 3730 // load return address
aoqi@6880 3731 {
aoqi@1 3732 const address table = (address) Interpreter::invoke_return_entry_table_for(code);
aoqi@1 3733 __ li(AT, (long)table);
aoqi@1 3734 __ dsll(flags, flags, LogBytesPerWord);
aoqi@1 3735 __ dadd(AT, AT, flags);
aoqi@1 3736 __ ld(RA, AT, 0);
aoqi@1 3737 }
aoqi@6880 3738
aoqi@1 3739 if (save_flags) {
aoqi@1 3740 __ move(flags, BCP);
aoqi@1 3741 __ restore_bcp();
aoqi@1 3742 }
aoqi@1 3743 }
aoqi@1 3744
aoqi@1 3745 // used registers : T0, T3, T1, T2
aoqi@1 3746 // T3 : recv, this two register using convention is by prepare_invoke
aoqi@1 3747 // T1 : flags, klass
aoqi@1 3748 // Rmethod : method, index must be Rmethod
aoqi@6880 3749 void TemplateTable::invokevirtual_helper(Register index,
aoqi@6880 3750 Register recv,
aoqi@6880 3751 Register flags) {
aoqi@1 3752
aoqi@1 3753 assert_different_registers(index, recv, flags, T2);
aoqi@1 3754
aoqi@1 3755 // Test for an invoke of a final method
aoqi@1 3756 Label notFinal;
aoqi@1 3757 __ move(AT, (1 << ConstantPoolCacheEntry::is_vfinal_shift));
aoqi@1 3758 __ andr(AT, flags, AT);
aoqi@1 3759 __ beq(AT, R0, notFinal);
aoqi@1 3760 __ delayed()->nop();
aoqi@1 3761
aoqi@1 3762 Register method = index; // method must be Rmethod
aoqi@1 3763 assert(method == Rmethod, "methodOop must be Rmethod for interpreter calling convention");
aoqi@1 3764
aoqi@1 3765 // do the call - the index is actually the method to call
aoqi@6880 3766 // the index is indeed methodOop, for this is vfinal,
aoqi@1 3767 // see ConstantPoolCacheEntry::set_method for more info
aoqi@1 3768
aoqi@1 3769 __ verify_oop(method);
aoqi@1 3770
aoqi@1 3771 // It's final, need a null check here!
aoqi@1 3772 __ null_check(recv);
aoqi@1 3773
aoqi@1 3774 // profile this call
aoqi@1 3775 __ profile_final_call(T2);
aoqi@1 3776
aoqi@6880 3777 // 2014/11/24 Fu
aoqi@1 3778 // T2: tmp, used for mdp
aoqi@1 3779 // method: callee
aoqi@1 3780 // T9: tmp
aoqi@6880 3781 // is_virtual: true
aoqi@1 3782 __ profile_arguments_type(T2, method, T9, true);
aoqi@1 3783
aoqi@1 3784 __ jump_from_interpreted(method, T2);
aoqi@1 3785
aoqi@1 3786 __ bind(notFinal);
aoqi@1 3787
aoqi@1 3788 // get receiver klass
aoqi@1 3789 __ null_check(recv, oopDesc::klass_offset_in_bytes());
aoqi@1 3790 __ load_klass(T2, recv);
aoqi@1 3791 __ verify_oop(T2);
aoqi@6880 3792
aoqi@1 3793 // profile this call
aoqi@1 3794 __ profile_virtual_call(T2, T0, T1);
aoqi@1 3795
aoqi@1 3796 // get target methodOop & entry point
aoqi@6880 3797 const int base = InstanceKlass::vtable_start_offset() * wordSize;
fujie@211 3798 assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
fujie@211 3799 __ dsll(AT, index, Address::times_ptr);
fujie@211 3800 // T2: receiver
aoqi@1 3801 __ dadd(AT, T2, AT);
aoqi@6880 3802 //this is a ualign read
aoqi@1 3803 __ ld(method, AT, base + vtableEntry::method_offset_in_bytes());
fujie@211 3804 __ profile_arguments_type(T2, method, T9, true);
aoqi@1 3805 __ jump_from_interpreted(method, T2);
aoqi@1 3806
aoqi@1 3807 }
aoqi@1 3808
aoqi@1 3809 void TemplateTable::invokevirtual(int byte_no) {
aoqi@1 3810 transition(vtos, vtos);
aoqi@1 3811 assert(byte_no == f2_byte, "use this argument");
aoqi@1 3812 prepare_invoke(byte_no, Rmethod, NOREG, T3, T1);
aoqi@1 3813 // now recv & flags in T3, T1
aoqi@1 3814 invokevirtual_helper(Rmethod, T3, T1);
aoqi@1 3815 }
aoqi@1 3816
aoqi@1 3817 // T9 : entry
aoqi@1 3818 // Rmethod : method
aoqi@1 3819 void TemplateTable::invokespecial(int byte_no) {
aoqi@1 3820 transition(vtos, vtos);
aoqi@1 3821 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3822 prepare_invoke(byte_no, Rmethod, NOREG, T3);
aoqi@1 3823 // now recv & flags in T3, T1
aoqi@1 3824 __ verify_oop(T3);
aoqi@1 3825 __ null_check(T3);
aoqi@1 3826 __ profile_call(T9);
aoqi@1 3827
aoqi@6880 3828 // 2014/11/24 Fu
aoqi@1 3829 // T8: tmp, used for mdp
aoqi@1 3830 // Rmethod: callee
aoqi@1 3831 // T9: tmp
aoqi@6880 3832 // is_virtual: false
aoqi@1 3833 __ profile_arguments_type(T8, Rmethod, T9, false);
aoqi@1 3834
aoqi@1 3835 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 3836 __ move(T0, T3);//aoqi ?
aoqi@1 3837 }
aoqi@1 3838
aoqi@1 3839 void TemplateTable::invokestatic(int byte_no) {
aoqi@1 3840 transition(vtos, vtos);
aoqi@1 3841 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3842 prepare_invoke(byte_no, Rmethod, NOREG);
aoqi@1 3843 __ verify_oop(Rmethod);
aoqi@1 3844
aoqi@1 3845 __ profile_call(T9);
aoqi@1 3846
aoqi@6880 3847 // 2014/11/24 Fu
aoqi@1 3848 // T8: tmp, used for mdp
aoqi@1 3849 // Rmethod: callee
aoqi@1 3850 // T9: tmp
aoqi@6880 3851 // is_virtual: false
aoqi@1 3852 __ profile_arguments_type(T8, Rmethod, T9, false);
aoqi@1 3853
aoqi@1 3854 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 3855 }
aoqi@1 3856
aoqi@6880 3857 // i have no idea what to do here, now. for future change. FIXME.
aoqi@1 3858 void TemplateTable::fast_invokevfinal(int byte_no) {
aoqi@6880 3859 transition(vtos, vtos);
aoqi@6880 3860 assert(byte_no == f2_byte, "use this argument");
aoqi@6880 3861 __ stop("fast_invokevfinal not used on mips64");
aoqi@1 3862 }
aoqi@1 3863
aoqi@1 3864 // used registers : T0, T1, T2, T3, T1, A7
aoqi@1 3865 // T0 : itable, vtable, entry
aoqi@1 3866 // T1 : interface
aoqi@1 3867 // T3 : receiver
aoqi@1 3868 // T1 : flags, klass
aoqi@1 3869 // Rmethod : index, method, this is required by interpreter_entry
aoqi@1 3870 void TemplateTable::invokeinterface(int byte_no) {
aoqi@1 3871 transition(vtos, vtos);
aoqi@1 3872 //this method will use T1-T4 and T0
aoqi@1 3873 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3874 prepare_invoke(byte_no, T2, Rmethod, T3, T1);
aoqi@9043 3875 // T2: reference klass
aoqi@9043 3876 // Rmethod: method
aoqi@6880 3877 // T3: receiver
aoqi@1 3878 // T1: flags
aoqi@6880 3879
aoqi@6880 3880 // Special case of invokeinterface called for virtual method of
aoqi@6880 3881 // java.lang.Object. See cpCacheOop.cpp for details.
aoqi@6880 3882 // This code isn't produced by javac, but could be produced by
aoqi@6880 3883 // another compliant java compiler.
aoqi@1 3884 Label notMethod;
aoqi@1 3885 __ move(AT, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift));
aoqi@1 3886 __ andr(AT, T1, AT);
aoqi@1 3887 __ beq(AT, R0, notMethod);
aoqi@1 3888 __ delayed()->nop();
aoqi@1 3889
aoqi@1 3890 invokevirtual_helper(Rmethod, T3, T1);
aoqi@1 3891 __ bind(notMethod);
aoqi@1 3892 // Get receiver klass into T1 - also a null check
aoqi@1 3893 //add for compressedoops
aoqi@1 3894 __ load_klass(T1, T3);
aoqi@1 3895 __ verify_oop(T1);
aoqi@1 3896
aoqi@9043 3897 Label no_such_interface, no_such_method;
aoqi@9043 3898
aoqi@9043 3899 // Receiver subtype check against REFC.
aoqi@9043 3900 // Superklass in rax. Subklass in rdx. Blows rcx, rdi.
aoqi@9043 3901 __ lookup_interface_method(// inputs: rec. class, interface, itable index
aoqi@9043 3902 T1, T2, noreg,
aoqi@9043 3903 // outputs: scan temp. reg, scan temp. reg
aoqi@9043 3904 T0, FSR,
aoqi@9043 3905 no_such_interface,
aoqi@9043 3906 /*return_method=*/false);
aoqi@9043 3907
aoqi@9043 3908
aoqi@1 3909 // profile this call
aoqi@1 3910 __ profile_virtual_call(T1, T0, FSR);
aoqi@1 3911
aoqi@9043 3912 // Get declaring interface class from method, and itable index
aoqi@9043 3913 __ ld_ptr(T2, Rmethod, in_bytes(Method::const_offset()));
aoqi@9043 3914 __ ld_ptr(T2, T2, in_bytes(ConstMethod::constants_offset()));
aoqi@9043 3915 __ ld_ptr(T2, T2, ConstantPool::pool_holder_offset_in_bytes());
aoqi@9043 3916 __ lw(Rmethod, Rmethod, in_bytes(Method::itable_index_offset()));
aoqi@9043 3917 __ addi(Rmethod, Rmethod, (-1) * Method::itable_index_max);
aoqi@9043 3918 __ subu32(Rmethod, R0, Rmethod);
aoqi@9043 3919
aoqi@9043 3920 __ lookup_interface_method(// inputs: rec. class, interface, itable index
aoqi@9043 3921 T1, T2, Rmethod,
aoqi@9043 3922 // outputs: method, scan temp. reg
aoqi@9043 3923 Rmethod, T0,
aoqi@9043 3924 no_such_interface);
aoqi@9043 3925
aoqi@9043 3926 // Rmethod: Method* to call
aoqi@1 3927 // T3: receiver
aoqi@1 3928 // Check for abstract method error
aoqi@1 3929 // Note: This should be done more efficiently via a throw_abstract_method_error
aoqi@1 3930 // interpreter entry point and a conditional jump to it in case of a null
aoqi@1 3931 // method.
aoqi@9043 3932 __ beq(Rmethod, R0, no_such_method);
aoqi@9043 3933 __ delayed()->nop();
aoqi@9043 3934
aoqi@9043 3935 __ profile_arguments_type(T1, Rmethod, T0, true);
aoqi@9043 3936
aoqi@9043 3937 // do the call
aoqi@9043 3938 // T3: receiver
aoqi@9043 3939 // Rmethod: Method*
aoqi@9043 3940 __ jump_from_interpreted(Rmethod, T1);
aoqi@9043 3941 __ should_not_reach_here();
aoqi@9043 3942
aoqi@9043 3943 // exception handling code follows...
aoqi@9043 3944 // note: must restore interpreter registers to canonical
aoqi@9043 3945 // state for exception handling to work correctly!
aoqi@9043 3946
aoqi@9043 3947 __ bind(no_such_method);
aoqi@9043 3948 // throw exception
aoqi@9043 3949 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
aoqi@9043 3950 // the call_VM checks for exception, so we should never return here.
aoqi@9043 3951 __ should_not_reach_here();
aoqi@9043 3952
aoqi@9043 3953 __ bind(no_such_interface);
aoqi@9043 3954 // throw exception
aoqi@9043 3955 __ call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@9043 3956 InterpreterRuntime::throw_IncompatibleClassChangeError));
aoqi@9043 3957 // the call_VM checks for exception, so we should never return here.
aoqi@9043 3958 __ should_not_reach_here();
aoqi@9043 3959
aoqi@1 3960 }
aoqi@1 3961
aoqi@6880 3962
aoqi@1 3963 void TemplateTable::invokehandle(int byte_no) {
aoqi@1 3964 transition(vtos, vtos);
aoqi@1 3965 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3966 const Register T2_method = Rmethod;
aoqi@1 3967 const Register FSR_mtype = FSR;
aoqi@1 3968 const Register T3_recv = T3;
aoqi@1 3969
aoqi@1 3970 if (!EnableInvokeDynamic) {
aoqi@1 3971 // rewriter does not generate this bytecode
aoqi@1 3972 __ should_not_reach_here();
aoqi@1 3973 return;
aoqi@1 3974 }
aoqi@6880 3975
aoqi@1 3976 prepare_invoke(byte_no, T2_method, FSR_mtype, T3_recv);
aoqi@1 3977 //??__ verify_method_ptr(T2_method);
aoqi@1 3978 __ verify_oop(T3_recv);
aoqi@1 3979 __ null_check(T3_recv);
aoqi@6880 3980
aoqi@1 3981 // rax: MethodType object (from cpool->resolved_references[f1], if necessary)
aoqi@1 3982 // rbx: MH.invokeExact_MT method (from f2)
aoqi@6880 3983
aoqi@1 3984 // Note: rax_mtype is already pushed (if necessary) by prepare_invoke
aoqi@6880 3985
aoqi@1 3986 // FIXME: profile the LambdaForm also
aoqi@1 3987 __ profile_final_call(T9);
aoqi@1 3988
aoqi@6880 3989 // 2014/11/24 Fu
aoqi@1 3990 // T8: tmp, used for mdp
aoqi@1 3991 // T2_method: callee
aoqi@1 3992 // T9: tmp
aoqi@1 3993 // is_virtual: true
aoqi@1 3994 __ profile_arguments_type(T8, T2_method, T9, true);
aoqi@6880 3995
aoqi@1 3996 __ jump_from_interpreted(T2_method, T9);
aoqi@1 3997 }
aoqi@1 3998
aoqi@1 3999 void TemplateTable::invokedynamic(int byte_no) {
aoqi@1 4000 transition(vtos, vtos);
aoqi@1 4001 assert(byte_no == f1_byte, "use this argument");
aoqi@6880 4002
aoqi@1 4003 if (!EnableInvokeDynamic) {
aoqi@1 4004 // We should not encounter this bytecode if !EnableInvokeDynamic.
aoqi@1 4005 // The verifier will stop it. However, if we get past the verifier,
aoqi@1 4006 // this will stop the thread in a reasonable way, without crashing the JVM.
aoqi@1 4007 __ call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@1 4008 InterpreterRuntime::throw_IncompatibleClassChangeError));
aoqi@1 4009 // the call_VM checks for exception, so we should never return here.
aoqi@1 4010 __ should_not_reach_here();
aoqi@1 4011 return;
aoqi@1 4012 }
aoqi@6880 4013
aoqi@1 4014 //const Register Rmethod = T2;
aoqi@1 4015 const Register T2_callsite = T2;
aoqi@6880 4016
aoqi@1 4017 prepare_invoke(byte_no, Rmethod, T2_callsite);
aoqi@6880 4018
aoqi@1 4019 // rax: CallSite object (from cpool->resolved_references[f1])
aoqi@1 4020 // rbx: MH.linkToCallSite method (from f2)
aoqi@6880 4021
aoqi@1 4022 // Note: rax_callsite is already pushed by prepare_invoke
aoqi@1 4023 // %%% should make a type profile for any invokedynamic that takes a ref argument
aoqi@1 4024 // profile this call
aoqi@1 4025 __ profile_call(T9);
aoqi@1 4026
aoqi@6880 4027 // 2014/11/24 Fu
aoqi@1 4028 // T8: tmp, used for mdp
aoqi@1 4029 // Rmethod: callee
aoqi@1 4030 // T9: tmp
aoqi@6880 4031 // is_virtual: false
aoqi@1 4032 __ profile_arguments_type(T8, Rmethod, T9, false);
aoqi@1 4033
aoqi@1 4034 __ verify_oop(T2_callsite);
aoqi@6880 4035
aoqi@1 4036 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 4037 }
aoqi@1 4038
aoqi@6880 4039 //-----------------------------------------------------------------------------
aoqi@1 4040 // Allocation
aoqi@1 4041 // T1 : tags & buffer end & thread
aoqi@1 4042 // T2 : object end
aoqi@1 4043 // T3 : klass
aoqi@1 4044 // T1 : object size
aoqi@1 4045 // A1 : cpool
aoqi@1 4046 // A2 : cp index
aoqi@1 4047 // return object in FSR
aoqi@1 4048 void TemplateTable::_new() {
aoqi@1 4049 transition(vtos, atos);
fujie@6884 4050 __ get_unsigned_2_byte_index_at_bcp(A2, 1);
aoqi@1 4051
aoqi@1 4052 Label slow_case;
aoqi@1 4053 Label done;
aoqi@1 4054 Label initialize_header;
aoqi@6880 4055 Label initialize_object; // including clearing the fields
aoqi@1 4056 Label allocate_shared;
aoqi@1 4057
aoqi@1 4058 // get InstanceKlass in T3
aoqi@1 4059 __ get_cpool_and_tags(A1, T1);
fujie@6884 4060
aoqi@1 4061 __ dsll(AT, A2, Address::times_8);
fujie@6884 4062 if (UseLoongsonISA && Assembler::is_simm(sizeof(ConstantPool), 8)) {
fujie@6884 4063 __ gsldx(T3, A1, AT, sizeof(ConstantPool));
fujie@6884 4064 } else {
fujie@6884 4065 __ dadd(AT, A1, AT);
fujie@6884 4066 __ ld(T3, AT, sizeof(ConstantPool));
fujie@6884 4067 }
aoqi@1 4068
aoqi@6880 4069 // make sure the class we're about to instantiate has been resolved.
aoqi@1 4070 // Note: slow_case does a pop of stack, which is why we loaded class/pushed above
aoqi@1 4071 const int tags_offset = Array<u1>::base_offset_in_bytes();
fujie@6884 4072 if (UseLoongsonISA && Assembler::is_simm(tags_offset, 8)) {
fujie@6884 4073 __ gslbx(AT, T1, A2, tags_offset);
fujie@6884 4074 } else {
fujie@6884 4075 __ dadd(T1, T1, A2);
fujie@6884 4076 __ lb(AT, T1, tags_offset);
fujie@6884 4077 }
aoqi@1 4078 __ daddiu(AT, AT, - (int)JVM_CONSTANT_Class);
aoqi@1 4079 __ bne(AT, R0, slow_case);
zhaixiang@9135 4080 __ delayed()->nop();
aoqi@1 4081
aoqi@6880 4082
aoqi@6880 4083 // make sure klass is initialized & doesn't have finalizer
aoqi@1 4084 // make sure klass is fully initialized
Jin@2 4085 __ lhu(T1, T3, in_bytes(InstanceKlass::init_state_offset()));
aoqi@1 4086 __ daddiu(AT, T1, - (int)InstanceKlass::fully_initialized);
aoqi@1 4087 __ bne(AT, R0, slow_case);
zhaixiang@9135 4088 __ delayed()->nop();
aoqi@1 4089
aoqi@1 4090 // has_finalizer
fujie@6884 4091 __ lw(T0, T3, in_bytes(Klass::layout_helper_offset()) );
fujie@6884 4092 __ andi(AT, T0, Klass::_lh_instance_slow_path_bit);
aoqi@1 4093 __ bne(AT, R0, slow_case);
zhaixiang@9135 4094 __ delayed()->nop();
aoqi@1 4095
aoqi@1 4096 // Allocate the instance
aoqi@1 4097 // 1) Try to allocate in the TLAB
aoqi@1 4098 // 2) if fail and the object is large allocate in the shared Eden
aoqi@1 4099 // 3) if the above fails (or is not applicable), go to a slow case
aoqi@1 4100 // (creates a new TLAB, etc.)
aoqi@1 4101
aoqi@1 4102 const bool allow_shared_alloc =
aoqi@1 4103 Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode;
aoqi@1 4104
aoqi@1 4105 if (UseTLAB) {
aoqi@1 4106 #ifndef OPT_THREAD
aoqi@1 4107 const Register thread = T8;
aoqi@1 4108 __ get_thread(thread);
aoqi@1 4109 #else
aoqi@1 4110 const Register thread = TREG;
aoqi@1 4111 #endif
aoqi@1 4112 // get tlab_top
aoqi@1 4113 __ ld(FSR, thread, in_bytes(JavaThread::tlab_top_offset()));
aoqi@1 4114 // get tlab_end
aoqi@1 4115 __ ld(AT, thread, in_bytes(JavaThread::tlab_end_offset()));
fujie@6884 4116 __ dadd(T2, FSR, T0);
aoqi@1 4117 __ slt(AT, AT, T2);
aoqi@1 4118 __ bne(AT, R0, allow_shared_alloc ? allocate_shared : slow_case);
aoqi@1 4119 __ delayed()->nop();
aoqi@1 4120 __ sd(T2, thread, in_bytes(JavaThread::tlab_top_offset()));
aoqi@1 4121
aoqi@1 4122 if (ZeroTLAB) {
aoqi@1 4123 // the fields have been already cleared
fujie@6884 4124 __ beq(R0, R0, initialize_header);
aoqi@1 4125 } else {
aoqi@1 4126 // initialize both the header and fields
fujie@6884 4127 __ beq(R0, R0, initialize_object);
aoqi@1 4128 }
aoqi@1 4129 __ delayed()->nop();
aoqi@1 4130 }
aoqi@1 4131
aoqi@1 4132 // Allocation in the shared Eden , if allowed
aoqi@1 4133 // T0 : instance size in words
aoqi@6880 4134 if(allow_shared_alloc){
aoqi@1 4135 __ bind(allocate_shared);
aoqi@6880 4136
aoqi@1 4137 Label retry;
aoqi@1 4138 Address heap_top(T1);
fujie@6884 4139 __ set64(T1, (long)Universe::heap()->top_addr());
aoqi@1 4140 __ ld(FSR, heap_top);
fujie@6884 4141
aoqi@1 4142 __ bind(retry);
fujie@6884 4143 __ set64(AT, (long)Universe::heap()->end_addr());
fujie@6884 4144 __ ld(AT, AT, 0);
aoqi@1 4145 __ dadd(T2, FSR, T0);
aoqi@1 4146 __ slt(AT, AT, T2);
aoqi@1 4147 __ bne(AT, R0, slow_case);
aoqi@1 4148 __ delayed()->nop();
aoqi@1 4149
aoqi@1 4150 // Compare FSR with the top addr, and if still equal, store the new
aoqi@1 4151 // top addr in ebx at the address of the top addr pointer. Sets ZF if was
aoqi@1 4152 // equal, and clears it otherwise. Use lock prefix for atomicity on MPs.
aoqi@1 4153 //
aoqi@1 4154 // FSR: object begin
aoqi@1 4155 // T2: object end
aoqi@1 4156 // T0: instance size in words
aoqi@1 4157
aoqi@6880 4158 // if someone beat us on the allocation, try again, otherwise continue
aoqi@1 4159 __ cmpxchg(T2, heap_top, FSR);
aoqi@1 4160 __ beq(AT, R0, retry);
aoqi@1 4161 __ delayed()->nop();
aoqi@1 4162 }
aoqi@1 4163
aoqi@1 4164 if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
aoqi@1 4165 // The object is initialized before the header. If the object size is
aoqi@1 4166 // zero, go directly to the header initialization.
aoqi@1 4167 __ bind(initialize_object);
fujie@6884 4168 __ set64(AT, - sizeof(oopDesc));
aoqi@1 4169 __ daddu(T0, T0, AT);
fujie@6884 4170 __ beq(T0, R0, initialize_header);
aoqi@1 4171 __ delayed()->nop();
aoqi@1 4172
aoqi@1 4173 // initialize remaining object fields: T0 is a multiple of 2
aoqi@6880 4174 {
aoqi@1 4175 Label loop;
aoqi@1 4176 __ dadd(T1, FSR, T0);
aoqi@1 4177 __ daddi(T1, T1, -oopSize);
aoqi@1 4178
aoqi@1 4179 __ bind(loop);
aoqi@1 4180 __ sd(R0, T1, sizeof(oopDesc) + 0 * oopSize);
aoqi@1 4181 __ bne(T1, FSR, loop); //dont clear header
aoqi@1 4182 __ delayed()->daddi(T1, T1, -oopSize);
aoqi@1 4183 }
fujie@6884 4184
aoqi@6880 4185 //klass in T3,
aoqi@1 4186 // initialize object header only.
aoqi@1 4187 __ bind(initialize_header);
aoqi@1 4188 if (UseBiasedLocking) {
aoqi@6880 4189 __ ld(AT, T3, in_bytes(Klass::prototype_header_offset()));
aoqi@6880 4190 __ sd(AT, FSR, oopDesc::mark_offset_in_bytes ());
aoqi@1 4191 } else {
fujie@6884 4192 __ set64(AT, (long)markOopDesc::prototype());
aoqi@1 4193 __ sd(AT, FSR, oopDesc::mark_offset_in_bytes());
aoqi@1 4194 }
aoqi@1 4195
aoqi@1 4196 __ store_klass_gap(FSR, R0);
aoqi@1 4197 __ store_klass(FSR, T3);
aoqi@1 4198
aoqi@1 4199 {
aoqi@1 4200 SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0);
aoqi@1 4201 // Trigger dtrace event for fastpath
aoqi@1 4202 __ push(atos);
aoqi@1 4203 __ call_VM_leaf(
aoqi@6880 4204 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), FSR);
aoqi@1 4205 __ pop(atos);
aoqi@6880 4206
aoqi@1 4207 }
aoqi@1 4208 __ b(done);
aoqi@1 4209 __ delayed()->nop();
aoqi@6880 4210 }
aoqi@6880 4211
aoqi@1 4212 // slow case
aoqi@1 4213 __ bind(slow_case);
aoqi@1 4214 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), A1, A2);
aoqi@1 4215
aoqi@1 4216 // continue
aoqi@1 4217 __ bind(done);
fujie@32 4218 __ sync();
aoqi@1 4219 }
aoqi@1 4220
aoqi@1 4221 void TemplateTable::newarray() {
aoqi@6880 4222 transition(itos, atos);
aoqi@6880 4223 __ lbu(A1, at_bcp(1));
aoqi@6880 4224 //type, count
aoqi@6880 4225 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), A1, FSR);
aoqi@6880 4226 __ sync();
aoqi@1 4227 }
aoqi@1 4228
aoqi@1 4229 void TemplateTable::anewarray() {
aoqi@1 4230 transition(itos, atos);
aoqi@16 4231 __ get_2_byte_integer_at_bcp(A2, AT, 1);
aoqi@1 4232 __ huswap(A2);
aoqi@1 4233 __ get_constant_pool(A1);
aoqi@1 4234 // cp, index, count
aoqi@1 4235 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), A1, A2, FSR);
fujie@32 4236 __ sync();
aoqi@1 4237 }
aoqi@1 4238
aoqi@1 4239 void TemplateTable::arraylength() {
aoqi@1 4240 transition(atos, itos);
aoqi@1 4241 __ null_check(FSR, arrayOopDesc::length_offset_in_bytes());
aoqi@1 4242 __ lw(FSR, FSR, arrayOopDesc::length_offset_in_bytes());
aoqi@1 4243 }
aoqi@1 4244
aoqi@1 4245 // i use T2 as ebx, T3 as ecx, T1 as edx
aoqi@1 4246 // when invoke gen_subtype_check, super in T3, sub in T2, object in FSR(it's always)
aoqi@1 4247 // T2 : sub klass
aoqi@1 4248 // T3 : cpool
aoqi@1 4249 // T3 : super klass
aoqi@1 4250 void TemplateTable::checkcast() {
aoqi@1 4251 transition(atos, atos);
aoqi@1 4252 Label done, is_null, ok_is_subtype, quicked, resolved;
aoqi@1 4253 __ beq(FSR, R0, is_null);
aoqi@1 4254 __ delayed()->nop();
aoqi@1 4255
aoqi@1 4256 // Get cpool & tags index
aoqi@1 4257 __ get_cpool_and_tags(T3, T1);
aoqi@16 4258 __ get_2_byte_integer_at_bcp(T2, AT, 1);
aoqi@1 4259 __ huswap(T2);
aoqi@1 4260
aoqi@1 4261 // See if bytecode has already been quicked
aoqi@1 4262 __ dadd(AT, T1, T2);
aoqi@1 4263 __ lb(AT, AT, Array<u1>::base_offset_in_bytes());
aoqi@1 4264 __ daddiu(AT, AT, - (int)JVM_CONSTANT_Class);
aoqi@1 4265 __ beq(AT, R0, quicked);
aoqi@1 4266 __ delayed()->nop();
aoqi@1 4267
aoqi@1 4268 /* 2012/6/2 Jin: In InterpreterRuntime::quicken_io_cc, lots of new classes may be loaded.
aoqi@1 4269 * Then, GC will move the object in V0 to another places in heap.
aoqi@1 4270 * Therefore, We should never save such an object in register.
aoqi@1 4271 * Instead, we should save it in the stack. It can be modified automatically by the GC thread.
aoqi@1 4272 * After GC, the object address in FSR is changed to a new place.
aoqi@1 4273 */
aoqi@1 4274 __ push(atos);
aoqi@1 4275 const Register thread = TREG;
aoqi@1 4276 #ifndef OPT_THREAD
aoqi@1 4277 __ get_thread(thread);
aoqi@1 4278 #endif
aoqi@1 4279 call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
aoqi@1 4280 __ get_vm_result_2(T3, thread);
aoqi@1 4281 __ pop_ptr(FSR);
aoqi@1 4282 __ b(resolved);
aoqi@1 4283 __ delayed()->nop();
aoqi@1 4284
aoqi@1 4285 // klass already in cp, get superklass in T3
aoqi@1 4286 __ bind(quicked);
aoqi@1 4287 __ dsll(AT, T2, Address::times_8);
aoqi@1 4288 __ dadd(AT, T3, AT);
aoqi@1 4289 __ ld(T3, AT, sizeof(ConstantPool));
aoqi@1 4290
aoqi@1 4291 __ bind(resolved);
aoqi@1 4292
aoqi@1 4293 // get subklass in T2
aoqi@1 4294 //add for compressedoops
aoqi@1 4295 __ load_klass(T2, FSR);
aoqi@1 4296 // Superklass in T3. Subklass in T2.
aoqi@1 4297 __ gen_subtype_check(T3, T2, ok_is_subtype);
aoqi@1 4298
aoqi@1 4299 // Come here on failure
aoqi@1 4300 // object is at FSR
aoqi@1 4301 __ jmp(Interpreter::_throw_ClassCastException_entry);
aoqi@1 4302 __ delayed()->nop();
aoqi@1 4303
aoqi@1 4304 // Come here on success
aoqi@1 4305 __ bind(ok_is_subtype);
aoqi@1 4306
aoqi@1 4307 // Collect counts on whether this check-cast sees NULLs a lot or not.
aoqi@1 4308 if (ProfileInterpreter) {
aoqi@6880 4309 __ b(done);
aoqi@6880 4310 __ delayed()->nop();
aoqi@6880 4311 __ bind(is_null);
aoqi@6880 4312 __ profile_null_seen(T3);
aoqi@1 4313 } else {
aoqi@6880 4314 __ bind(is_null);
aoqi@1 4315 }
aoqi@1 4316 __ bind(done);
aoqi@1 4317 }
aoqi@1 4318
aoqi@1 4319 // i use T3 as cpool, T1 as tags, T2 as index
aoqi@1 4320 // object always in FSR, superklass in T3, subklass in T2
aoqi@1 4321 void TemplateTable::instanceof() {
aoqi@1 4322 transition(atos, itos);
aoqi@1 4323 Label done, is_null, ok_is_subtype, quicked, resolved;
aoqi@1 4324
aoqi@1 4325 __ beq(FSR, R0, is_null);
aoqi@1 4326 __ delayed()->nop();
aoqi@1 4327
aoqi@1 4328 // Get cpool & tags index
aoqi@1 4329 __ get_cpool_and_tags(T3, T1);
aoqi@1 4330 // get index
aoqi@16 4331 __ get_2_byte_integer_at_bcp(T2, AT, 1);
aoqi@1 4332 __ hswap(T2);
aoqi@1 4333
aoqi@1 4334 // See if bytecode has already been quicked
aoqi@1 4335 // quicked
aoqi@1 4336 __ daddu(AT, T1, T2);
aoqi@1 4337 __ lb(AT, AT, Array<u1>::base_offset_in_bytes());
aoqi@1 4338 __ daddiu(AT, AT, - (int)JVM_CONSTANT_Class);
aoqi@1 4339 __ beq(AT, R0, quicked);
aoqi@1 4340 __ delayed()->nop();
aoqi@1 4341
aoqi@1 4342 __ push(atos);
aoqi@1 4343 const Register thread = TREG;
aoqi@1 4344 #ifndef OPT_THREAD
aoqi@1 4345 __ get_thread(thread);
aoqi@1 4346 #endif
aoqi@1 4347 call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
aoqi@1 4348 __ get_vm_result_2(T3, thread);
aoqi@6880 4349 __ pop_ptr(FSR);
aoqi@1 4350 __ b(resolved);
aoqi@1 4351 __ delayed()->nop();
aoqi@1 4352
aoqi@1 4353 // get superklass in T3, subklass in T2
aoqi@1 4354 __ bind(quicked);
aoqi@1 4355 __ dsll(AT, T2, Address::times_8);
aoqi@1 4356 __ daddu(AT, T3, AT);
aoqi@6880 4357 __ ld(T3, AT, sizeof(ConstantPool));
aoqi@1 4358
aoqi@1 4359 __ bind(resolved);
aoqi@1 4360 // get subklass in T2
aoqi@1 4361 //add for compressedoops
aoqi@1 4362 __ load_klass(T2, FSR);
aoqi@6880 4363
aoqi@1 4364 // Superklass in T3. Subklass in T2.
aoqi@1 4365 __ gen_subtype_check(T3, T2, ok_is_subtype);
aoqi@1 4366 // Come here on failure
aoqi@1 4367 __ b(done);
aoqi@1 4368 __ delayed(); __ move(FSR, R0);
aoqi@1 4369
aoqi@1 4370 // Come here on success
aoqi@1 4371 __ bind(ok_is_subtype);
aoqi@1 4372 __ move(FSR, 1);
aoqi@1 4373
aoqi@1 4374 // Collect counts on whether this test sees NULLs a lot or not.
aoqi@1 4375 if (ProfileInterpreter) {
aoqi@6880 4376 __ beq(R0, R0, done);
zhaixiang@9144 4377 __ delayed()->nop();
aoqi@6880 4378 __ bind(is_null);
aoqi@6880 4379 __ profile_null_seen(T3);
aoqi@1 4380 } else {
aoqi@6880 4381 __ bind(is_null); // same as 'done'
aoqi@1 4382 }
aoqi@1 4383 __ bind(done);
aoqi@1 4384 // FSR = 0: obj == NULL or obj is not an instanceof the specified klass
aoqi@1 4385 // FSR = 1: obj != NULL and obj is an instanceof the specified klass
aoqi@1 4386 }
aoqi@1 4387
aoqi@1 4388 //--------------------------------------------------------
aoqi@1 4389 //--------------------------------------------
aoqi@1 4390 // Breakpoints
aoqi@1 4391 void TemplateTable::_breakpoint() {
aoqi@6880 4392 // Note: We get here even if we are single stepping..
aoqi@6880 4393 // jbug inists on setting breakpoints at every bytecode
aoqi@6880 4394 // even if we are in single step mode.
aoqi@6880 4395
aoqi@6880 4396 transition(vtos, vtos);
aoqi@6880 4397
aoqi@6880 4398 // get the unpatched byte code
aoqi@6880 4399 __ get_method(A1);
aoqi@6880 4400 __ call_VM(NOREG,
aoqi@6880 4401 CAST_FROM_FN_PTR(address,
aoqi@6880 4402 InterpreterRuntime::get_original_bytecode_at),
aoqi@6880 4403 A1, BCP);
aoqi@6880 4404 __ move(Rnext, V0); // Jin: Rnext will be used in dispatch_only_normal
aoqi@6880 4405
aoqi@6880 4406 // post the breakpoint event
aoqi@6880 4407 __ get_method(A1);
aoqi@6880 4408 __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), A1, BCP);
aoqi@6880 4409
aoqi@6880 4410 // complete the execution of original bytecode
aoqi@6880 4411 __ dispatch_only_normal(vtos);
aoqi@6880 4412 }
aoqi@6880 4413
aoqi@6880 4414 //-----------------------------------------------------------------------------
aoqi@1 4415 // Exceptions
aoqi@1 4416
aoqi@1 4417 void TemplateTable::athrow() {
aoqi@6880 4418 transition(atos, vtos);
aoqi@6880 4419 __ null_check(FSR);
aoqi@6880 4420 __ jmp(Interpreter::throw_exception_entry());
aoqi@6880 4421 __ delayed()->nop();
aoqi@1 4422 }
aoqi@1 4423
aoqi@6880 4424 //-----------------------------------------------------------------------------
aoqi@1 4425 // Synchronization
aoqi@1 4426 //
aoqi@1 4427 // Note: monitorenter & exit are symmetric routines; which is reflected
aoqi@1 4428 // in the assembly code structure as well
aoqi@1 4429 //
aoqi@1 4430 // Stack layout:
aoqi@1 4431 //
aoqi@1 4432 // [expressions ] <--- SP = expression stack top
aoqi@1 4433 // ..
aoqi@1 4434 // [expressions ]
aoqi@1 4435 // [monitor entry] <--- monitor block top = expression stack bot
aoqi@1 4436 // ..
aoqi@1 4437 // [monitor entry]
aoqi@1 4438 // [frame data ] <--- monitor block bot
aoqi@1 4439 // ...
aoqi@1 4440 // [return addr ] <--- FP
aoqi@1 4441
aoqi@1 4442 // we use T2 as monitor entry pointer, T3 as monitor top pointer, c_rarg0 as free slot pointer
aoqi@1 4443 // object always in FSR
aoqi@1 4444 void TemplateTable::monitorenter() {
aoqi@1 4445 transition(atos, vtos);
aoqi@6880 4446
aoqi@1 4447 // check for NULL object
aoqi@1 4448 __ null_check(FSR);
aoqi@1 4449
aoqi@6880 4450 const Address monitor_block_top(FP, frame::interpreter_frame_monitor_block_top_offset
aoqi@1 4451 * wordSize);
aoqi@1 4452 const int entry_size = (frame::interpreter_frame_monitor_size()* wordSize);
aoqi@1 4453 Label allocated;
aoqi@1 4454
aoqi@1 4455 // initialize entry pointer
aoqi@1 4456 __ move(c_rarg0, R0);
aoqi@1 4457
aoqi@1 4458 // find a free slot in the monitor block (result in edx)
aoqi@6880 4459 {
aoqi@1 4460 Label entry, loop, exit, next;
aoqi@1 4461 __ ld(T2, monitor_block_top);
aoqi@1 4462 __ b(entry);
aoqi@1 4463 __ delayed()->daddi(T3, FP, frame::interpreter_frame_initial_sp_offset * wordSize);
aoqi@1 4464
aoqi@1 4465 // free slot?
aoqi@1 4466 __ bind(loop);
aoqi@1 4467 __ ld(AT, T2, BasicObjectLock::obj_offset_in_bytes());
aoqi@1 4468 __ bne(AT, R0, next);
aoqi@1 4469 __ delayed()->nop();
aoqi@1 4470 __ move(c_rarg0, T2);
aoqi@1 4471
aoqi@1 4472 __ bind(next);
aoqi@1 4473 __ beq(FSR, AT, exit);
aoqi@1 4474 __ delayed()->nop();
aoqi@1 4475 __ daddi(T2, T2, entry_size);
aoqi@1 4476
aoqi@1 4477 __ bind(entry);
aoqi@1 4478 __ bne(T3, T2, loop);
aoqi@1 4479 __ delayed()->nop();
aoqi@1 4480 __ bind(exit);
aoqi@1 4481 }
aoqi@1 4482
aoqi@1 4483 __ bne(c_rarg0, R0, allocated);
aoqi@1 4484 __ delayed()->nop();
aoqi@1 4485
aoqi@1 4486 // allocate one if there's no free slot
aoqi@6880 4487 {
aoqi@1 4488 Label entry, loop;
aoqi@1 4489 // 1. compute new pointers // SP: old expression stack top
aoqi@1 4490 __ ld(c_rarg0, monitor_block_top);
aoqi@1 4491 __ daddi(SP, SP, - entry_size);
aoqi@1 4492 __ daddi(c_rarg0, c_rarg0, - entry_size);
aoqi@1 4493 __ sd(c_rarg0, monitor_block_top);
aoqi@1 4494 __ b(entry);
aoqi@1 4495 __ delayed(); __ move(T3, SP);
aoqi@1 4496
aoqi@1 4497 // 2. move expression stack contents
aoqi@1 4498 __ bind(loop);
aoqi@1 4499 __ ld(AT, T3, entry_size);
aoqi@1 4500 __ sd(AT, T3, 0);
aoqi@6880 4501 __ daddi(T3, T3, wordSize);
aoqi@1 4502 __ bind(entry);
aoqi@1 4503 __ bne(T3, c_rarg0, loop);
aoqi@1 4504 __ delayed()->nop();
aoqi@1 4505 }
aoqi@1 4506
aoqi@1 4507 __ bind(allocated);
aoqi@6880 4508 // Increment bcp to point to the next bytecode,
aoqi@6880 4509 // so exception handling for async. exceptions work correctly.
aoqi@6880 4510 // The object has already been poped from the stack, so the
aoqi@1 4511 // expression stack looks correct.
aoqi@6880 4512 __ daddi(BCP, BCP, 1);
aoqi@1 4513 __ sd(FSR, c_rarg0, BasicObjectLock::obj_offset_in_bytes());
aoqi@1 4514 __ lock_object(c_rarg0);
aoqi@1 4515 // check to make sure this monitor doesn't cause stack overflow after locking
aoqi@1 4516 __ save_bcp(); // in case of exception
aoqi@1 4517 __ generate_stack_overflow_check(0);
aoqi@1 4518 // The bcp has already been incremented. Just need to dispatch to next instruction.
aoqi@1 4519
aoqi@1 4520 __ dispatch_next(vtos);
aoqi@1 4521 }
aoqi@1 4522
aoqi@1 4523 // T2 : top
aoqi@1 4524 // c_rarg0 : entry
aoqi@1 4525 void TemplateTable::monitorexit() {
aoqi@1 4526 transition(atos, vtos);
aoqi@1 4527
aoqi@1 4528 __ null_check(FSR);
aoqi@1 4529
aoqi@1 4530 const int entry_size =(frame::interpreter_frame_monitor_size()* wordSize);
aoqi@1 4531 Label found;
aoqi@1 4532
aoqi@1 4533 // find matching slot
aoqi@6880 4534 {
aoqi@1 4535 Label entry, loop;
aoqi@1 4536 __ ld(c_rarg0, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize);
aoqi@1 4537 __ b(entry);
aoqi@1 4538 __ delayed()->daddiu(T2, FP, frame::interpreter_frame_initial_sp_offset * wordSize);
aoqi@1 4539
aoqi@1 4540 __ bind(loop);
aoqi@1 4541 __ ld(AT, c_rarg0, BasicObjectLock::obj_offset_in_bytes());
aoqi@1 4542 __ beq(FSR, AT, found);
aoqi@1 4543 __ delayed()->nop();
aoqi@1 4544 __ daddiu(c_rarg0, c_rarg0, entry_size);
aoqi@1 4545 __ bind(entry);
aoqi@1 4546 __ bne(T2, c_rarg0, loop);
aoqi@1 4547 __ delayed()->nop();
aoqi@1 4548 }
aoqi@1 4549
aoqi@1 4550 // error handling. Unlocking was not block-structured
aoqi@1 4551 Label end;
aoqi@6880 4552 __ call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6880 4553 InterpreterRuntime::throw_illegal_monitor_state_exception));
aoqi@1 4554 __ should_not_reach_here();
aoqi@1 4555
aoqi@1 4556 // call run-time routine
aoqi@1 4557 // c_rarg0: points to monitor entry
aoqi@1 4558 __ bind(found);
aoqi@1 4559 __ move(TSR, FSR);
aoqi@1 4560 __ unlock_object(c_rarg0);
aoqi@1 4561 __ move(FSR, TSR);
aoqi@1 4562 __ bind(end);
aoqi@1 4563 }
aoqi@1 4564
aoqi@6880 4565
aoqi@6880 4566 // Wide instructions
aoqi@1 4567 void TemplateTable::wide() {
aoqi@1 4568 transition(vtos, vtos);
aoqi@1 4569 // Note: the esi increment step is part of the individual wide bytecode implementations
aoqi@1 4570 __ lbu(Rnext, at_bcp(1));
aoqi@1 4571 __ dsll(T9, Rnext, Address::times_8);
aoqi@1 4572 __ li(AT, (long)Interpreter::_wentry_point);
aoqi@1 4573 __ dadd(AT, T9, AT);
aoqi@1 4574 __ ld(T9, AT, 0);
aoqi@1 4575 __ jr(T9);
aoqi@1 4576 __ delayed()->nop();
aoqi@1 4577 }
aoqi@1 4578
aoqi@1 4579
aoqi@1 4580 void TemplateTable::multianewarray() {
aoqi@1 4581 transition(vtos, atos);
aoqi@1 4582 // last dim is on top of stack; we want address of first one:
aoqi@1 4583 // first_addr = last_addr + (ndims - 1) * wordSize
aoqi@6880 4584 __ lbu(A1, at_bcp(3)); // dimension
aoqi@6880 4585 __ daddi(A1, A1, -1);
aoqi@1 4586 __ dsll(A1, A1, Address::times_8);
aoqi@6880 4587 __ dadd(A1, SP, A1); // now A1 pointer to the count array on the stack
aoqi@1 4588 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), A1);
aoqi@1 4589 __ lbu(AT, at_bcp(3));
aoqi@1 4590 __ dsll(AT, AT, Address::times_8);
aoqi@1 4591 __ dadd(SP, SP, AT);
fujie@32 4592 __ sync();
aoqi@1 4593 }
aoqi@1 4594 #endif // !CC_INTERP

mercurial