changeset 27:b7ec29b378c9

Update codes to support deoptimization.
author Ao Qi <aoqi@loongson.cn>
date Thu, 11 Nov 2010 19:59:55 +0800
parents 82bf91673f25
children f4c60f770c45
files hotspot/src/cpu/mips/vm/assembler_mips.cpp hotspot/src/cpu/mips/vm/assembler_mips.hpp hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.hpp hotspot/src/cpu/mips/vm/frame_mips.cpp hotspot/src/cpu/mips/vm/sharedRuntime_mips.cpp hotspot/src/share/vm/runtime/deoptimization.cpp hotspot/src/share/vm/runtime/sharedRuntime.cpp
diffstat 8 files changed, 175 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/src/cpu/mips/vm/assembler_mips.cpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/assembler_mips.cpp	Thu Nov 11 19:59:55 2010 +0800
@@ -1063,7 +1063,9 @@
   pop_CPU_state();
 */
 	
-	save_registers(this);
+	//save_registers(this);
+	pushad();
+	addi(SP, SP, -4);
 	sw(A0, SP, -1 * wordSize);
 	move(A0, (int)msg);
 	addi(SP, SP, -1 * wordSize);
@@ -1071,9 +1073,44 @@
 	delayed()->nop();
 	addi(SP, SP, 1 * wordSize);
 	lw(A0, SP, -1 * wordSize);
-	restore_registers(this);
+	addi(SP, SP, 4);
+	popad();
+	//restore_registers(this);
 }
 
+#ifndef PRODUCT
+//FIXME cannot print sp
+void MacroAssembler::print_reg(Register reg) {
+  pushad();
+  push(FP);
+  char* a = new char[50];
+  sprintf(a, "%s: 0x",reg->name());
+  move(A0, (int)a);
+  call(CAST_FROM_FN_PTR(address, SharedRuntime::print_str),relocInfo::runtime_call_type);
+  delayed()->nop();
+  pop(FP);
+  popad();
+
+  pushad();
+  push(FP);
+  move(A0, reg);
+  call(CAST_FROM_FN_PTR(address, SharedRuntime::print_int),relocInfo::runtime_call_type);
+  delayed()->nop();
+  pop(FP);
+  popad();
+
+  pushad();
+  push(FP);
+  char* b = new char[50];
+  sprintf(b, " pc: %p\n",pc());
+  move(A0, (int)b);
+  call(CAST_FROM_FN_PTR(address, SharedRuntime::print_str),relocInfo::runtime_call_type);
+  delayed()->nop();
+  pop(FP);
+  popad();
+}
+#endif
+
 void MacroAssembler::increment(Register reg, int imm) {
 	if (!imm) return;
 	if (is_simm16(imm)) {
--- a/hotspot/src/cpu/mips/vm/assembler_mips.hpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/assembler_mips.hpp	Thu Nov 11 19:59:55 2010 +0800
@@ -1365,6 +1365,9 @@
   static void debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip, char* msg);
   static void debug64(char* msg, int64_t pc, int64_t regs[]);
 
+#ifndef PRODUCT
+  void print_reg(Register reg);
+#endif
   //void os_breakpoint();
 
   void untested()                                { stop("untested"); }
--- a/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.cpp	Thu Nov 11 19:59:55 2010 +0800
@@ -433,10 +433,9 @@
  
 	compilation()->offsets()->set_value(CodeOffsets::Deopt, code_offset());
  
-	InternalAddress here(__ pc());
-	//FIXE:: may be wrong, Address_Literal
-	__ lw(AT, __ as_Address(here) );
-	__ push(AT);
+	__ jmp(SharedRuntime::deopt_blob()->unpack());
+	__ delayed()->nop(); 
+ 
 	assert(code_offset() - offset <= deopt_handler_size, "overflow");
  	__ end_a_stub();
 
--- a/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.hpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/c1_LIRAssembler_mips.hpp	Thu Nov 11 19:59:55 2010 +0800
@@ -51,5 +51,5 @@
 
   enum { call_stub_size = NOT_LP64(24) LP64_ONLY(28),
          exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
-         deopt_handler_size = NOT_LP64(12) LP64_ONLY(17)
+         deopt_handler_size = NOT_LP64(16) LP64_ONLY(17)
        };
--- a/hotspot/src/cpu/mips/vm/frame_mips.cpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/frame_mips.cpp	Thu Nov 11 19:59:55 2010 +0800
@@ -82,7 +82,30 @@
 	if (TracePcPatching) {
 		tty->print_cr("patch_pc at address  0x%x [0x%x -> 0x%x] ", &((address *)_sp)[-1], ((address *)_sp)[-1], pc);
 	}
-	((address *)_sp)[-1] = _pc = pc; 
+
+	RegisterMap map((JavaThread *)thread, false);
+	frame check = ((JavaThread *)thread)->last_frame();
+	if (id() != check.id())
+	{
+		while (id() != check.sender(&map).id()) {
+			check = check.sender(&map);
+		}
+		if (check.is_interpreted_frame())
+			*(check.fp() + 1) = (int)pc;
+		else
+			((address *)_sp)[-1]  = pc; 
+	}
+
+	_cb = CodeCache::find_blob(pc);
+	if (_cb != NULL && _cb->is_nmethod() && ((nmethod*)_cb)->is_deopt_pc(_pc)) {
+		address orig = (((nmethod*)_cb)->get_original_pc(this));
+		assert(orig == _pc, "expected original to be stored before patching");
+		_deopt_state = is_deoptimized;
+		// leave _pc as is
+	} else {
+		_deopt_state = not_deoptimized;
+		_pc = pc;
+	}
 }
 
 bool frame::is_interpreted_frame() const  {
--- a/hotspot/src/cpu/mips/vm/sharedRuntime_mips.cpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/cpu/mips/vm/sharedRuntime_mips.cpp	Thu Nov 11 19:59:55 2010 +0800
@@ -3212,64 +3212,59 @@
   // allocate space for the code
   ResourceMark rm;
   // setup code generation tools
-  //int pad = VerifyThread ? 512 : 0;// Extra slop space for more verify code
- // CodeBuffer*     buffer             = new CodeBuffer(2048+pad, 512, 0, 0, 0, false);
   CodeBuffer     buffer ("deopt_blob", 2048, 2048);
   MacroAssembler* masm  = new MacroAssembler( & buffer);
-//int frame_size, exception_offset, reexecute_offset;
   int frame_size_in_words;
   OopMap* map = NULL;
- // Account for the extra args we place on the stack
- // by the time we call fetch_unroll_info
- const int additional_words = 2; // deopt kind, thread
- OopMapSet *oop_maps = new OopMapSet();
+  // Account for the extra args we place on the stack
+  // by the time we call fetch_unroll_info
+  const int additional_words = 2; // deopt kind, thread
+
+  OopMapSet *oop_maps = new OopMapSet();
+
   address start = __ pc();
   Label cont;
-  	// we use S3 for DeOpt reason register
-	Register reason = S3;
-	// use S1 for thread register
-	Register thread = TREG;
-	// use S7 for fetch_unroll_info returned UnrollBlock
-	Register unroll = S7;
+  // we use S3 for DeOpt reason register
+  Register reason = S3;
+  // use S1 for thread register
+  Register thread = TREG;
+  // use S7 for fetch_unroll_info returned UnrollBlock
+  Register unroll = S7;
   // Prolog for non exception case!
-   // Correct the return address we were given.
- //FIXME, return address is on the tos or Ra? 
-  __ addi(RA, RA, - (NativeCall::return_address_offset));
-// Save everything in sight.
+  // Correct the return address we were given.
+  //FIXME, return address is on the tos or Ra? 
+  __ lw(RA, FP, (-1) * wordSize);
+  // Save everything in sight.
   map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words);
-  __ move(AT, Deoptimization::Unpack_deopt);
-  __ push(AT); 
+  // Normal deoptimization
+  __ move(reason, Deoptimization::Unpack_deopt);
   __ b(cont);
   __ delayed()->nop();
 
   int reexecute_offset = __ pc() - start;
+
    // Reexecute case
    // return address is the pc describes what bci to do re-execute at
+
    // No need to update map as each call to save_live_registers will produce identical oopmap
-  
   (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words);
-  // __ pushl(Deoptimization::Unpack_reexecute);
-  // __ jmp(cont);
-     __ move(AT, Deoptimization::Unpack_reexecute); 
-     __ push(AT); 
-     __ b(cont);
-     __ delayed()->nop();
-    
-int   exception_offset = __ pc() - start;
- // Prolog for exception case
+  __ move(reason, Deoptimization::Unpack_reexecute); 
+  __ b(cont);
+  __ delayed()->nop();
+
+  int   exception_offset = __ pc() - start;
+  // Prolog for exception case
 
   // all registers are dead at this entry point, except for eax and
   // edx which contain the exception oop and exception pc
   // respectively.  Set them in TLS and fall thru to the
   // unpack_with_exception_in_tls entry point.
-  //__ get_thread(edi);
+  
   __ get_thread(thread);
-  //__ movl(Address(edi, JavaThread::exception_pc_offset()), edx);
   __ sw(V1, thread, in_bytes(JavaThread::exception_pc_offset())); 
-  //  __ movl(Address(edi, JavaThread::exception_oop_offset()), eax);
   __ sw(V0, thread, in_bytes(JavaThread::exception_oop_offset()));
   int exception_in_tls_offset = __ pc() - start;
-// new implementation because exception oop is now passed in JavaThread
+  // new implementation because exception oop is now passed in JavaThread
 
   // Prolog for exception case
   // All registers must be preserved because they might be used by LinearScan
@@ -3281,47 +3276,36 @@
   // It will be patched later with the throwing pc. The correct value is not 
   // available now because loading it from memory would destroy registers.
    //__ pushl(0);
- //It is no need here, because in save_live_register, we saved the return address(RA)  
- //FIXME here, do mips need patch the return address on stack? 
- // __ push(ZERO);
-  // Save everything in sight.
+   //It is no need here, because in save_live_register, we saved the return address(RA)  
+   //FIXME here, do mips need patch the return address on stack? 
+   // __ push(ZERO);
+   // Save everything in sight.
   // No need to update map as each call to save_live_registers will produce identical oopmap
   (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words);
 
   // Now it is safe to overwrite any register
   // store the correct deoptimization type
- // __ pushl(Deoptimization::Unpack_exception); 
-   __ move(AT, Deoptimization::Unpack_exception);
-   __ push(AT); 
-   // load throwing pc from JavaThread and patch it as the return address 
+  __ move(reason, Deoptimization::Unpack_exception);
+  // load throwing pc from JavaThread and patch it as the return address 
   // of the current frame. Then clear the field in JavaThread
- // __ get_thread(edi);
   __ get_thread(thread);
-//  __ movl(edx, Address(edi, JavaThread::exception_pc_offset()));
   __ lw(V1, thread, in_bytes(JavaThread::exception_pc_offset()));
-//we should save on the stack or register? 
-  // __ movl(Address(ebp, wordSize), edx); 
-   __ move(RA, V1); 
- // __ movl(Address(edi, JavaThread::exception_pc_offset()), NULL_WORD);
-   __ sw(ZERO, thread, in_bytes(JavaThread::exception_pc_offset()));
-
-  
+  //we should save on the stack or register? 
+  __ move(RA, V1); 
+  __ sw(ZERO, thread, in_bytes(JavaThread::exception_pc_offset()));
+
+
 #ifdef ASSERT
   // verify that there is really an exception oop in JavaThread
- // __ movl(eax, Address(edi, JavaThread::exception_oop_offset()));
-   __ lw(AT, thread, in_bytes(JavaThread::exception_oop_offset()));
-   //__ verify_oop(eax);
-   __ verify_oop(AT);
+  __ lw(AT, thread, in_bytes(JavaThread::exception_oop_offset()));
+  __ verify_oop(AT);
   // verify that there is no pending exception
   Label no_pending_exception;
-//  __ movl(eax, Address(edi, Thread::pending_exception_offset()));
   __ lw(AT, thread, in_bytes(Thread::pending_exception_offset()));
-  //__ testl(eax, eax);
-  //__ jcc(Assembler::zero, no_pending_exception);
- __ beq(AT, ZERO, no_pending_exception); 
- __ delayed()->nop(); 
- __ stop("must not have pending exception here");
- __ bind(no_pending_exception);
+  __ beq(AT, ZERO, no_pending_exception); 
+  __ delayed()->nop(); 
+  __ stop("must not have pending exception here");
+  __ bind(no_pending_exception);
 #endif
   __ bind(cont);
   // Compiled code leaves the floating point stack dirty, empty it.
@@ -3330,28 +3314,17 @@
 
   // Call C code.  Need thread and this frame, but NOT official VM entry
   // crud.  We cannot block on this call, no GC can happen.  
- 
- 
-  
-  // All callee save registers or return value registers are saved at this poin
-  // Compiled code may leave the floating point stack dirty, empty it.
-
-  // Call fetch_unroll_info().  Need thread and this frame, but NOT official VM entry - cannot block on
-  // this call, no GC can happen.  Call should capture return values.
 #ifndef OPT_THREAD
   __ get_thread(thread);
 #endif
+  __ move(A0, thread);
+  __ addiu(SP, SP, -2 * wordSize);
 
   __ set_last_Java_frame(thread, NOREG, NOREG, NULL);
 
-  __ sw(SP, thread, in_bytes(JavaThread::last_Java_sp_offset()));
-  // push the one argument (relative to the oopmap)
-  //	__ addiu(SP, SP, - 2*wordSize);
-  __ addiu(SP, SP, - wordSize);
-  __ move(AT, -8);
-  __ andr(SP, SP, AT);	
-  __ move(A0, thread);
- 
+  // Call fetch_unroll_info().  Need thread and this frame, but NOT official VM entry - cannot block on
+  // this call, no GC can happen.  Call should capture return values.
+
   __ relocate(relocInfo::internal_pc_type); 
   {	
     int save_pc = (int)__ pc() +  12 + NativeCall::return_address_offset;
@@ -3365,20 +3338,19 @@
   __ jalr(T9);
   __ delayed()->nop();
   oop_maps->add_gc_map(__ pc() - start, map);
-  // pop the arg so now frame offsets (slots) don't include any arg.
-  __ lw(SP, thread, in_bytes(JavaThread::last_Java_sp_offset()));
+  __ addiu(SP, SP, 2 * wordSize);
+  __ get_thread(thread);
   __ reset_last_Java_frame(thread, false, true);
 
   // Load UnrollBlock into S7
   __ move(unroll, V0);
 
-  // Store frame locals in registers or memory
 
   // Move the unpack kind to a safe place in the UnrollBlock because
   // we are very short of registers
 
   Address unpack_kind(unroll, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes());
-  __ pop(reason);	
+  //__ pop(reason);	
   __ sw(reason, unpack_kind);
   // save the unpack_kind value
   // Retrieve the possible live values (return values)
@@ -3397,35 +3369,29 @@
   __ verify_oop(V0);
 
   // Overwrite the result registers with the exception results.
-  //__ movl(Address(esp, RegisterSaver::eaxOffset()*wordSize), eax);
   __ sw(V0, SP, RegisterSaver::v0Offset()*wordSize); 
-//	__ movl(Address(esp, RegisterSaver::edxOffset()*wordSize), edx);
   __ sw(V1, SP, RegisterSaver::v1Offset()*wordSize);
   
   __ bind(noException);
 
-//	__ lw(V0, SP, V0_off * wordSize);
-//	__ lw(V1, SP, V1_off * wordSize);
-	//__ lwc1(F0, SP, F0_off * wordSize);
-	//__ lwc1(F1, SP, (F0_off + 1) * wordSize);
 
   // Stack is back to only having register save data on the stack.
   // Now restore the result registers. Everything else is either dead or captured
   // in the vframeArray.
 
   RegisterSaver::restore_result_registers(masm);
-   // All of the register save area has been popped of the stack. Only the
+  // All of the register save area has been popped of the stack. Only the
   // return address remains.
   // Pop all the frames we must move/replace. 
- // Frame picture (youngest to oldest)
+  // Frame picture (youngest to oldest)
   // 1: self-frame (no frame link)
   // 2: deopting frame  (no frame link)
   // 3: caller of deopting frame (could be compiled/interpreted). 
-  // 
+  //
   // Note: by leaving the return address of self-frame on the stack
   // and using the size of frame 2 to adjust the stack
   // when we are done the return to frame 3 will still be on the stack.
-  
+
   // register for the sender's sp
   Register sender_sp = T5;
   // register for frame pcs
@@ -3436,66 +3402,56 @@
   Register count = T3;
 	
   // Pop deoptimized frame
-  //__ addl(esp,Address(edi,Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset_in_bytes()));
   __ lw(AT, unroll, Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset_in_bytes());
   __ add(SP, SP, AT);
   // sp should be pointing at the return address to the caller (3)
-  // Load array of frame pcs into ECX
-  //__ movl(ecx,Address(edi,Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes()));
-  // Load array of frame pcs into T5
+ 
+  // Load array of frame pcs into T4
   __ lw(pcs, unroll, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes());
-  //__ popl(esi); // trash the old pc
-  //FIXME , do mips need trach the old pc
-  __ addi(SP, SP, wordSize);
-  // Load array of frame sizes into ESI
-//  __ movl(esi,Address(edi,Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes()));
- // Load array of frame sizes into T6
+  __ addi(SP, SP, wordSize);  // trash the old pc
+  // Load array of frame sizes into T6
   __ lw(sizes, unroll, Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes());
 
  
- 
- Address counter(unroll, Deoptimization::UnrollBlock::counter_temp_offset_in_bytes());
-  //__ movl(ebx, Address(edi, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes()));
-  //__ movl(counter, ebx);
-   // Load count of frams into T3
+
+  // Load count of frams into T3
   __ lw(count, unroll, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes());
-  __ sw(count, counter);
   // Pick up the initial fp we should save
- // __ movl(ebp, Address(edi, Deoptimization::UnrollBlock::initial_fp_offset_in_bytes()));
   __ lw(FP, unroll,  Deoptimization::UnrollBlock::initial_fp_offset_in_bytes());
    // Now adjust the caller's stack to make up for the extra locals
   // but record the original sp so that we can save it in the skeletal interpreter
   // frame and the stack walking of interpreter_sender will get the unextended sp
   // value and not the "real" sp value.
-  __ move(sender_sp, SP); 
+  __ move(sender_sp, SP);
   __ lw(AT, unroll, Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes());
   __ sub(SP, SP, AT);
-			
+
   // Push interpreter frames in a loop
   Label loop;
-   __ bind(loop);
-   __ lw(T2, sizes, 0);		// Load frame size
-   __ lw(AT, pcs, 0);  	       // save return address
-   __ sw(AT, SP, (-1) * wordSize);	
-   __ sw(FP, SP, (-2) * wordSize);
-   __ addi(FP, SP, (-2) * wordSize);	// save old & set new FP
-   __ sub(SP, SP, T2); 			// Prolog!
+  __ bind(loop);
+  __ lw(T2, sizes, 0);		// Load frame size
+  __ lw(AT, pcs, 0);  	       // save return address
+  __ addi(T2, T2, -2*wordSize);           // we'll push pc and rbp, by hand
+  __ push2(AT, FP);			
+  __ move(FP, SP);
+  __ sub(SP, SP, T2); 			// Prolog!
   // This value is corrected by layout_activation_impl
-   __ sw(ZERO, FP, frame::interpreter_frame_last_sp_offset * wordSize); 
-   __ sw(sender_sp, FP, frame::interpreter_frame_sender_sp_offset * wordSize);// Make it walkable
-   __ move(sender_sp, SP);	// pass to next frame
-   __ addi(count, count, -1); 	// decrement counter
-   __ addi(sizes, sizes, 4); 	// Bump array pointer (sizes)
-   __ bne(count, ZERO, loop);
-   __ delayed()->addi(pcs, pcs, 4); 	// Bump array pointer (pcs)
-   __ lw(AT, pcs, 0);
-   __ sw(AT, SP, (-1) * wordSize); 	// save final return address
+  __ sw(ZERO, FP, frame::interpreter_frame_last_sp_offset * wordSize); 
+  __ sw(sender_sp, FP, frame::interpreter_frame_sender_sp_offset * wordSize);// Make it walkable
+  __ move(sender_sp, SP);	// pass to next frame
+  __ addi(count, count, -1); 	// decrement counter
+  __ addi(sizes, sizes, 4); 	// Bump array pointer (sizes)
+  __ bne(count, ZERO, loop);
+  __ delayed()->addi(pcs, pcs, 4); 	// Bump array pointer (pcs)
+  __ lw(AT, pcs, 0);
   // Re-push self-frame
-   __ sw(FP, SP, (-2) * wordSize);
-   __ addi(FP, SP, - 2 * wordSize);	// save old & set new ebp
-   __ addi(SP, SP, -(frame_size_in_words - additional_words) * wordSize);
-	
-   // Restore frame locals after moving the frame
+  __ addi(SP, SP, - 2 * wordSize);	// save old & set new FP
+  __ sw(FP, SP, 0 * wordSize);          // save final return address
+  __ sw(AT, SP, 1 * wordSize);
+  __ move(FP, SP);
+  __ addi(SP, SP, -(frame_size_in_words - additional_words) * wordSize);
+
+  // Restore frame locals after moving the frame
   __ sw(V0, SP, RegisterSaver::v0Offset() * wordSize);
   __ sw(V1, SP, RegisterSaver::v1Offset() * wordSize);
   __ swc1(F0, SP, RegisterSaver::fpResultOffset()* wordSize);// Pop float stack and store in local
@@ -3504,13 +3460,13 @@
   
   // Call unpack_frames().  Need thread and this frame, but NOT official VM entry - cannot block on
   // this call, no GC can happen.
-  __ set_last_Java_frame(thread, NOREG, FP, NULL);
-  __ sw(SP, thread, in_bytes(JavaThread::last_Java_sp_offset()));
   __ move(A1, reason);	// exec_mode
+  __ get_thread(thread);
   __ move(A0, thread);	// thread
-  __ addi(SP, SP, (-2) *wordSize);
-  __ move(AT, -8);
-  __ andr(SP, SP, AT);	
+  //__ addi(SP, SP, (-2) *wordSize);
+
+  // set last_Java_sp, last_Java_fp
+  __ set_last_Java_frame(thread, NOREG, FP, NULL);
   __ relocate(relocInfo::internal_pc_type); 
   {	
     int save_pc = (int)__ pc() +  12 + NativeCall::return_address_offset;
@@ -3519,6 +3475,7 @@
   }
   __ sw(AT, thread, in_bytes(JavaThread::last_Java_pc_offset()));
 	
+	//__ call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), relocInfo::runtime_call_type);
   __ lui(T9, Assembler::split_high((int)Deoptimization::unpack_frames));
   __ addiu(T9, T9, Assembler::split_low((int)Deoptimization::unpack_frames));
   __ jalr(T9);			
@@ -3526,49 +3483,32 @@
   // Set an oopmap for the call site
   oop_maps->add_gc_map(__ offset(), new OopMap( frame_size_in_words , 0));
 
+  //__ addi(SP, SP, 2 * wordSize);
 	
+  __ get_thread(thread);
   __ lw(SP, thread, in_bytes(JavaThread::last_Java_sp_offset()));
   __ reset_last_Java_frame(thread, false, false);
-  
+
   // Collect return values
   __ lw(V0, SP, (RegisterSaver::v0Offset() + additional_words +1) * wordSize);
   __ lw(V1, SP, (RegisterSaver::v1Offset() + additional_words +1) * wordSize);
-//FIXME, 
+  //FIXME, 
   // Clear floating point stack before returning to interpreter
-   __ empty_FPU_stack();
-//FIXME, we should consider about float and double
+  __ empty_FPU_stack();
+  //FIXME, we should consider about float and double
   // Push a float or double return value if necessary.
-/*
-   Label no_double_value, yes_double_value;
-  __ lw(T1, SP, ret_type*wordSize);
-  __ move(AT, T_DOUBLE); 
-  __ beq(AT, T1, yes_double_value);
-  __ delayed();
-
-  __ move(AT, T_FLOAT);
-  __ bne(AT, T1, no_double_value);
-  __ delayed()->nop();
-
-  __ bind(yes_double_value);
-  __ lwc1(F0, SP, F0_off * wordSize);
-  __ lwc1(F1, SP, (F0_off + 1) * wordSize);
-  __ bind(no_double_value);
-#endif
-*/ 
-  __ leave();
+  //__ leave();
+  __ move(SP, FP);
+  __ lw(RA, SP, 1 * wordSize);
+  __ lw(FP, SP, 0 * wordSize);
 
   // Jump to interpreter
   __ jr(RA);
   __ delayed()->nop();
 
- // frame_size            = reg_save_frame_size + 2;
   masm->flush();
-  //_deopt_blob = DeoptimizationBlob::create(buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size);
   _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
-  //deopt_with_exception_entry_for_patch = _deopt_blob->unpack() + patching_exception_offset;
   _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
- //jerome_for_debug 
-//  _deopt_blob->print();
 }
 
 #ifdef COMPILER2
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Nov 11 19:59:55 2010 +0800
@@ -357,7 +357,7 @@
                                       frame_sizes,
                                       frame_pcs,
                                       return_type);
-#if defined(IA32) || defined(AMD64)
+#if defined(IA32) || defined(AMD64) || defined(MIPS32)
   // We need a way to pass fp to the unpacking code so the skeletal frames
   // come out correct. This is only needed for x86 because of c2 using ebp
   // as an allocatable register. So this update is useless (and harmless)
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Tue Nov 09 13:21:20 2010 +0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu Nov 11 19:59:55 2010 +0800
@@ -111,7 +111,7 @@
 }
 
 void SharedRuntime::print_int(int i) {
-	tty->print("T0 = %x\n", i);
+	tty->print("%x", i);
 }
 
 void SharedRuntime::print_str(char *str) {