src/cpu/mips/vm/c1_MacroAssembler_mips.cpp

Fri, 29 Apr 2016 00:06:10 +0800

author
aoqi
date
Fri, 29 Apr 2016 00:06:10 +0800
changeset 1
2d8a650513c2
child 29
6c147e7e4605
permissions
-rw-r--r--

Added MIPS 64-bit port.

     1 /*
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     8  * published by the Free Software Foundation.
     9  *
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    13  * version 2 for more details (a copy is included in the LICENSE file that
    14  * accompanied this code).
    15  *
    16  * You should have received a copy of the GNU General Public License version
    17  * 2 along with this work; if not, write to the Free Software Foundation,
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    19  *
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * or visit www.oracle.com if you need additional information or have any
    22  * questions.
    23  *
    24  */
    26 #include "precompiled.hpp"
    27 #include "c1/c1_MacroAssembler.hpp"
    28 #include "c1/c1_Runtime1.hpp"
    29 #include "classfile/systemDictionary.hpp"
    30 #include "gc_interface/collectedHeap.hpp"
    31 #include "interpreter/interpreter.hpp"
    32 #include "oops/arrayOop.hpp"
    33 #include "oops/markOop.hpp"
    34 #include "runtime/basicLock.hpp"
    35 #include "runtime/biasedLocking.hpp"
    36 #include "runtime/os.hpp"
    37 #include "runtime/stubRoutines.hpp"
    39 int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr,Register scratch, Label& slow_case) {
    40   const int aligned_mask = BytesPerWord -1;
    41   const int hdr_offset = oopDesc::mark_offset_in_bytes();
    43   // hdr is just a temperary register, it cannot be AT, however
    44   if ( hdr == NOREG ) {
    45     hdr = T8;
    46   }
    48   assert_different_registers(hdr, obj, disp_hdr);
    49   Label done;
    50   // The following move must be the first instruction of emitted since debug
    51   // information may be generated for it.
    52   // Load object header
    53   int null_check_offset = -1;
    54   verify_oop(obj);
    56   // save object being locked into the BasicObjectLock
    57   st_ptr(obj, disp_hdr, BasicObjectLock::obj_offset_in_bytes());
    58   if (UseBiasedLocking) {
    59     assert(scratch != noreg, "should have scratch register at this point");
    60     null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, 
    61 	done, &slow_case);
    62   } else {
    63     null_check_offset = offset();
    64   }
    66   // Load object header
    67   ld_ptr(hdr, obj, hdr_offset); 
    68   // and mark it as unlocked
    69   ori(hdr, hdr, markOopDesc::unlocked_value);
    70   // save unlocked object header into the displaced header location on the stack
    71   sd(hdr, disp_hdr, 0);
    73   // test if object header is still the same (i.e. unlocked), and if so, store the
    74   // displaced header address in the object header - if it is not the same, get the
    75   // object header instead
    76   //if (os::is_MP()) MacroAssembler::lock(); // must be immediately before cmpxchg!
    77   cmpxchg(disp_hdr, Address(obj, hdr_offset), hdr);
    78   // if the object header was the same, we're done
    79   if (PrintBiasedLockingStatistics) {
    80     //cond_incl(Assembler::equal, 
    81     //Address((int) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none));
    82     // cond_incl(Assembler::equal, 
    83     // Address((int) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none));
    85   }
    88   bne(AT, R0, done);
    89   delayed()->nop();
    90   // if the object header was not the same, it is now in the hdr register
    91   // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
    92   //
    93   // 1) (hdr & aligned_mask) == 0
    94   // 2) SP <= hdr
    95   // 3) hdr <= SP + page_size
    96   //
    97   // these 3 tests can be done by evaluating the following expression:
    98   //
    99   // (hdr - SP) & (aligned_mask - page_size)
   100   //
   101   // assuming both the stack pointer and page_size have their least
   102   // significant 2 bits cleared and page_size is a power of 2
   103   sub(hdr, hdr, SP);
   104   move(AT, aligned_mask - os::vm_page_size());
   105   andr(hdr, hdr, AT);
   106   // for recursive locking, the result is zero => save it in the displaced header
   107   // location (NULL in the displaced hdr location indicates recursive locking)
   108   st_ptr(hdr, disp_hdr, 0);
   109   // otherwise we don't care about the result and handle locking via runtime call
   110   bne_far(hdr, R0, slow_case);
   111   delayed()->nop();
   112   // done
   113   bind(done);
   114   return null_check_offset;
   115 }
   118 void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
   119   const int aligned_mask = BytesPerWord -1;
   120   const int hdr_offset = oopDesc::mark_offset_in_bytes();
   122   // hdr is just a temparay register, however, it cannot be AT
   123   if ( hdr == NOREG ) {
   124     hdr = T8;
   125   }
   127   assert_different_registers(hdr, obj, disp_hdr);
   128   assert(BytesPerWord == 8, "adjust aligned_mask and code");
   129   Label done;
   130   if (UseBiasedLocking) {
   131     // load object
   132     ld_ptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));
   133     biased_locking_exit(obj, hdr, done);
   134   }
   138   // load displaced header
   139   ld_ptr(hdr, disp_hdr, 0);
   140   // if the loaded hdr is NULL we had recursive locking
   141   // if we had recursive locking, we are done
   142   beq(hdr, R0, done);
   143   delayed()->nop();
   144   // load object
   145   if(!UseBiasedLocking){
   146     ld_ptr(obj, disp_hdr, BasicObjectLock::obj_offset_in_bytes());
   147   }
   149   verify_oop(obj);
   150   // test if object header is pointing to the displaced header, and if so, restore
   151   // the displaced header in the object - if the object header is not pointing to
   152   // the displaced header, get the object header instead
   153   //if (os::is_MP()) MacroAssembler::lock(); // must be immediately before cmpxchg!
   154   cmpxchg(hdr, Address(obj, hdr_offset), disp_hdr);
   155   // if the object header was not pointing to the displaced header,
   156   // we do unlocking via runtime call
   157   beq_far(AT, R0, slow_case);
   158   delayed()->nop();
   159   // done
   160   bind(done);
   161 }
   165 // Defines obj, preserves var_size_in_bytes
   166 void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {
   167   if (UseTLAB) {
   168     tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
   169   } else {
   170     eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
   171   }
   172 }
   174 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1 , Register t2) {
   175   assert_different_registers(obj, klass, len, AT);
   177   if (UseBiasedLocking && !len->is_valid()) {
   178     assert_different_registers(obj, klass, len, t1, t2);
   179     ld_ptr(t1, klass, in_bytes(Klass::prototype_header_offset()));
   180     st_ptr(t1, obj, oopDesc::mark_offset_in_bytes());
   181   } else {
   182     li(AT, (intptr_t)markOopDesc::prototype());
   183     st_ptr(AT, obj, oopDesc::mark_offset_in_bytes());
   184   }	
   185   //st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
   186 #ifdef _LP64
   187   if (UseCompressedOops) {
   188     move(AT, klass);
   189     store_klass(obj, AT);
   190   } else
   191 #endif
   192   {
   193     st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
   194   }
   196   if (len->is_valid()) {
   197     sw(len, obj, arrayOopDesc::length_offset_in_bytes());
   198   }
   199 #ifdef _LP64
   200   else if (UseCompressedOops) {
   201     store_klass_gap(obj, R0);
   202   }
   204 #endif
   205 }
   207 // preserves obj, destroys len_in_bytes
   208 void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {
   209   Label done;
   210   Register ptr = t1;
   211   assert_different_registers(obj, ptr, len_in_bytes);
   212   assert((hdr_size_in_bytes & (BytesPerWord - 1)) == 0, 
   213       "header size is not a multiple of BytesPerWord");
   214   Register index = len_in_bytes;
   216 //tty->print_cr("C1_MacroAssembler::initialize_body LEN=0x%x, hdr_size=0x%x", len_in_bytes, hdr_size_in_bytes);
   217   assert(is_simm16(hdr_size_in_bytes), "change this code");
   218   addi(index, index, - hdr_size_in_bytes);
   219   beq(index, R0, done);
   220   delayed();
   222   // initialize topmost word, divide index by 2, check if odd and test if zero
   223   // note: for the remaining code to work, index must be a multiple of BytesPerWord
   224 #ifdef ASSERT
   225   { 
   226     Label L;
   227     andi(AT, index, BytesPerWord - 1);
   228     beq(AT, R0, L);
   229     delayed()->nop();
   230     stop("index is not a multiple of BytesPerWord");
   231     bind(L);
   232   }
   233 #endif
   234   // index could have been not a multiple of 8 (i.e., bit 2 was set)
   235   { 
   236     Label even;
   237     // note: if index was a multiple of 8, than it cannot
   238     //       be 0 now otherwise it must have been 0 before
   239     //       => if it is even, we don't need to check for 0 again
   240 #ifdef _LP64
   241     andi(AT, index, 8);
   242     shr(index, 4);
   243     shl(index, 4);
   244 #else
   245     andi(AT, index, 4);
   246     shr(index, 3);
   247     shl(index, 3);
   248 #endif
   249     beq(AT, R0, even);
   250     delayed()->add(ptr, obj, index);
   251     // clear topmost word (no jump needed if conditional assignment would work here)
   252     st_ptr(R0, ptr, hdr_size_in_bytes); 
   253     // index could be 0 now, need to check again
   254     beq(index, R0, done);
   255     delayed()->nop();
   256     bind(even);
   257   }
   258   // initialize remaining object fields: edx is a multiple of 2 now
   259   { 
   260     Label loop;
   261     bind(loop);
   262     st_ptr(R0, ptr, hdr_size_in_bytes - 1*BytesPerWord);
   263     st_ptr(R0, ptr, hdr_size_in_bytes - 2*BytesPerWord);
   265     addi(index, index, - 2 * wordSize);
   266     bne(index, R0, loop);
   267     delayed()->addi(ptr, ptr, - 2 * wordSize);
   268   }
   270   // done
   271   bind(done);
   272 }
   274 void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {
   275   //assert(obj == rax, "obj must be in rax, for cmpxchg");
   276   assert(obj != t1 && obj != t2 && t1 != t2, "registers must be different"); // XXX really?
   277   assert(header_size >= 0 && object_size >= header_size, "illegal sizes");
   279   try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);
   281   initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2);
   282 }
   284 void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) {
   285 	assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
   286 			"con_size_in_bytes is not multiple of alignment");
   287 	//Merged from b25
   288 	const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
   290 	//  initialize_header(obj, klass, NOREG);
   291 	initialize_header(obj, klass, NOREG,t1,t2);
   293 	// clear rest of allocated space
   294 	const Register index = t2;
   295 	//FIXME, x86 changed the value in jdk6 
   296 	// const int threshold = hdr_size_in_bytes + 36;   
   297 	// // approximate break even point for code size (see comments below)
   298 	const int threshold = 6 * BytesPerWord;   
   299 	// approximate break even point for code size (see comments below)
   300 	if (var_size_in_bytes != NOREG) {
   301 		move(index, var_size_in_bytes);
   302 		initialize_body(obj, index, hdr_size_in_bytes, t1);
   303 	} else if (con_size_in_bytes <= threshold) {
   304 		// use explicit null stores
   305 		// code size = 4*n bytes (n = number of fields to clear)
   307 		for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord) { 
   308 			st_ptr(R0, obj, i);
   309 		}
   313 	} else if(con_size_in_bytes > hdr_size_in_bytes) {
   314 		// use loop to null out the fields
   315 		// code size = 32 bytes for even n (n = number of fields to clear)
   316 		// initialize last object field first if odd number of fields
   317 		assert( ((con_size_in_bytes - hdr_size_in_bytes) >> 3)!=0, "change code here");
   319 #ifdef _LP64
   320 		move(index, (con_size_in_bytes - hdr_size_in_bytes) >> 4);
   321 		sll(t1, index, 4);
   322 #else
   323 		move(index, (con_size_in_bytes - hdr_size_in_bytes) >> 3);
   324 		sll(t1, index, 3);
   325 #endif
   326 		add(t1, obj, t1);
   328 		// initialize last object field if constant size is odd
   329 #ifdef _LP64
   330 		if (! UseCompressedOops)
   331 		{
   332 		    if (((con_size_in_bytes - hdr_size_in_bytes) & 8) != 0) {
   333 			sd(R0, t1, hdr_size_in_bytes);
   334 		    }
   335 		} else if (UseCompressedOops) {
   336 		    int extra = (con_size_in_bytes - hdr_size_in_bytes) % 16;
   337 		    while (extra != 0) {
   338 			sw(R0, t1, hdr_size_in_bytes + extra - 4);
   339 			extra -= 4;
   340 		    }
   341 		}
   342 #else
   343 		if (((con_size_in_bytes - hdr_size_in_bytes) & 4) != 0) {
   344 			sw(R0, t1, hdr_size_in_bytes);
   345 		}
   346 #endif
   347 		// initialize remaining object fields: edx is a multiple of 2
   348 		{ 
   349 			Label loop;
   350 			bind(loop);
   351 			st_ptr(R0, t1, hdr_size_in_bytes - (1*BytesPerWord));
   352 			st_ptr(R0, t1, hdr_size_in_bytes - (2*BytesPerWord));
   353 			addi(index, index, -1);
   354 			bne(index, R0, loop);
   355 			delayed()->addi(t1, t1, - 2 * wordSize);
   356 		}
   357 	}
   359 	if (DTraceAllocProbes) {
   360 		//assert(obj == eax, "must be");
   361 		call(CAST_FROM_FN_PTR(address,
   362 	             Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), relocInfo::runtime_call_type);
   363 		delayed()->nop(); 
   364 	}
   365 	verify_oop(obj);
   366 }
   368 void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, Register t3,int header_size, 
   369 					int scale, Register klass, Label& slow_case) {
   370 	assert(obj == V0, "obj must be in V0 for cmpxchg");
   371 	assert_different_registers(obj, len, t1, t2, t3,klass, AT);
   373         // determine alignment mask
   374 	assert(BytesPerWord == 8, "must be a multiple of 2 for masking code to work");
   376          // check for negative or excessive length
   377          //const int max_length = 0x00FFFFFF;
   378          //      move(AT, max_length);
   379         move(AT, max_array_allocation_length);
   380 	sltu(AT, AT, len);
   381 	bne_far(AT, R0, slow_case);
   382 	delayed()->nop();
   384 	const Register arr_size = t3;
   385 	// align object end
   386 	move(arr_size, header_size * BytesPerWord + MinObjAlignmentInBytesMask);
   387 	sll(AT, len, scale);
   388 	add(arr_size, arr_size, AT);
   389 	move(AT, ~MinObjAlignmentInBytesMask);
   390 	andr(arr_size, arr_size, AT);
   392 	try_allocate(obj, arr_size, 0, t1, t2, slow_case);
   394 	initialize_header(obj, klass, len,t1,t2);
   396          // clear rest of allocated space
   397 	const Register len_zero = len;
   398 	initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
   399 	if (DTraceAllocProbes) {
   400 		// assert(obj == eax, "must be");
   401 		call(CAST_FROM_FN_PTR(address,
   402 		Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
   403 					relocInfo::runtime_call_type);
   404 		delayed()->nop();
   405 	}
   407 	verify_oop(obj);
   408 }
   411 void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
   412 	verify_oop(receiver);
   413 	// explicit NULL check not needed since load from [klass_offset] causes a trap  
   414 	// check against inline cache
   415 	assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
   416 	///cmpl(iCache, Address(receiver, oopDesc::klass_offset_in_bytes())); 
   417 	// if icache check fails, then jump to runtime routine
   418 	// Note: RECEIVER must still contain the receiver!
   419 	Label L;
   420 #ifdef _LP64
   421 	//ld_ptr(AT, receiver, oopDesc::klass_offset_in_bytes());
   422 	//add for compressedoops
   423 	load_klass(AT, receiver);
   424 #else
   425 	lw(AT, receiver, oopDesc::klass_offset_in_bytes());
   426 #endif
   427 	beq(AT, iCache, L);
   428 	delayed()->nop();
   429 	//	jmp(Runtime1::entry_for(Runtime1::handle_ic_miss_id), relocInfo::runtime_call_type);
   430         jmp(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type);
   431 	delayed()->nop();
   432 	bind(L);
   433 	// assert(UseCompressedOops, "check alignment in emit_method_entry");
   434 }
   435 /*
   436 void C1_MacroAssembler::method_exit(bool restore_frame) {
   437 	if (restore_frame) {
   438 		leave();
   439 	} 
   440 	jr(RA);
   441 	delayed()->nop();
   442 }*/
   445 void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
   446   // Make sure there is enough stack space for this method's activation.
   447   // Note that we do this before doing an enter(). This matches the
   448   // ordering of C2's stack overflow check / esp decrement and allows
   449   // the SharedRuntime stack overflow handling to be consistent
   450   // between the two compilers.
   451   	generate_stack_overflow_check(frame_size_in_bytes);
   453 	enter();
   454 //FIXME
   455 #ifdef TIERED
   456     // c2 leaves fpu stack dirty. Clean it on entry
   457  //  if (UseSSE < 2 ) {
   458        empty_FPU_stack();
   459   //  }
   460 #endif // TIERED
   462   decrement(SP, frame_size_in_bytes); // does not emit code for frame_size == 0
   463 }
   465 void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) {
   466   if (C1Breakpoint) int3();
   467   inline_cache_check(receiver, ic_klass);
   468 }
   471 void C1_MacroAssembler::verified_entry() {
   472   if (C1Breakpoint)int3();
   473   // build frame
   474   verify_FPU(0, "method_entry");
   475 }
   478 #ifndef PRODUCT
   479 void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
   480 	if (!VerifyOops) return;
   481 	//  verify_oop_addr(Address(esp, stack_offset));
   482 	verify_oop_addr(Address(SP, stack_offset));
   483 }
   485 void C1_MacroAssembler::verify_not_null_oop(Register r) {
   486 	if (!VerifyOops) return;
   487 	Label not_null;
   488 	// testl(r, r);
   489 	//jcc(Assembler::notZero, not_null);
   490 	bne(r,R0,not_null); 
   491 	delayed()->nop();  
   492 	stop("non-null oop required");
   493 	bind(not_null);
   494 	verify_oop(r);
   495 }
   497 void C1_MacroAssembler::invalidate_registers(bool inv_v0, bool inv_v1, bool inv_t3, bool inv_t7, bool inv_s0, bool inv_s7) {
   498 #ifdef ASSERT
   499 	/*  if (inv_eax) movl(eax, 0xDEAD);
   500 	    if (inv_ebx) movl(ebx, 0xDEAD);
   501 	    if (inv_ecx) movl(ecx, 0xDEAD);
   502 	    if (inv_edx) movl(edx, 0xDEAD);
   503 	    if (inv_esi) movl(esi, 0xDEAD);
   504 	    if (inv_edi) movl(edi, 0xDEAD);
   505 	    */
   506 	//if (inv_v0) move(V0, 0xDEAD);
   507 	//if (inv_v1) move(V1, 0xDEAD);
   508 	//if (inv_t3) move(T3, 0xDEAD);
   509 	//if (inv_t7) move(T7, 0xDEAD);
   510 	//if (inv_s0) move(S0, 0xDEAD);
   511 	//if (inv_s7) move(S7, 0xDEAD);
   512 #endif
   513 }
   514 #endif // ifndef PRODUCT

mercurial