view hotspot/src/cpu/mips/vm/interpreter_mips.cpp @ 1:c1e1428eff7c

The preliminary porting to MIPS architecture. With this commit, the interpreter can pass 140/141 regression tests, 8/8 SPECjvm98 tests and 31/37 SPECjvm2008 tests. The compiler can pass 136/141 regression tests, but it can not run the benchmark of SPECjvm98 and SPECjvm2008.
author LIU Qi <liuqi82@gmail.com>
date Thu, 30 Sep 2010 13:48:16 +0800
parents
children
line wrap: on
line source

/*
 * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * Copyright 2010 Lemote, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

#include "incls/_precompiled.incl"
#include "incls/_interpreter_mips.cpp.incl"

#define __ _masm->


address AbstractInterpreterGenerator::generate_slow_signature_handler() {
	address entry = __ pc();
	//tty->print_cr("%p\t%p", entry, InterpreterRuntime::slow_signature_handler);
	// T7: method
	// T3: temporary
	// S7: pointer to locals
	// SP: begin of copied parameters area
	//__ move(S3, RA);
	__ move(T3, SP);
	__ push(RA); 
	__ call_VM(NOREG, CAST_FROM_FN_PTR(address, 
				InterpreterRuntime::slow_signature_handler), T7, LVP, T3);
	//__ move(RA, S3);
	__ pop(RA);
	__ jr(RA);
	__ delayed()->nop();
	return entry;
}


//
// Various method entries
//

address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {

	// T7: methodOop
	// V0: scratrch
	// esi: send 's sp, should we use T5 @jerome
	if (!InlineIntrinsics) return NULL; // Generate a vanilla entry
	address entry_point = __ pc();

  // These don't need a safepoint check because they aren't virtually
  // callable. We won't enter these intrinsics from compiled code.
  // If in the future we added an intrinsic which was virtually callable
  // we'd have to worry about how to safepoint so that this code is used.


  // mathematical functions inlined by compiler
  // (interpreter must provide identical implementation
  // in order to avoid monotonicity bugs when switching
  // from interpreter to compiler in the middle of some
  // computation)
  //
  // stack: [ lo(arg) ] <-- sp
  //        [ hi(arg) ]
/*
  if (Universe::is_jdk12x_version()) {
    // Note: For JDK 1.2 StrictMath doesn't exist and Math.sin/cos/sqrt are
    //       native methods. Interpreter::method_kind(...) does a check for
    //       native methods first before checking for intrinsic methods and
    //       thus will never select this entry point. Make sure it is not
    //       called accidentally since the SharedRuntime entry points will
    //       not work for JDK 1.2.
    __ should_not_reach_here();
  } else 
 */ 
  {
    // Note: For JDK 1.3 StrictMath exists and Math.sin/cos/sqrt are
    //       java methods.  Interpreter::method_kind(...) will select
    //       this entry point for the corresponding methods in JDK 1.3.
//FIXME, @jerome
	  if (TaggedStackInterpreter) {
		  __ lw(AT, SP,3*wordSize); 
		  __ push(AT);//push hi note ,SP -=wordSize 
		  __ lw(AT, SP,2*wordSize); 
		  __ push(AT);//push lo 
		  __ lwc1(F12, SP, 2 * wordSize);
		  __ lwc1(F13, SP, 3 * wordSize);
		  __ sw(RA, SP, (1) * wordSize);
		  __ sw(FP, SP, (0) * wordSize);
		  __ addi(SP, SP, 2 * wordSize);
		  __ move(FP, SP);

	  }else {
		  __ lwc1(F12, SP, 0 * wordSize);
		  __ lwc1(F13, SP, 1 * wordSize);
		  __ sw(RA, SP, (-1) * wordSize);
		  __ sw(FP, SP, (-2) * wordSize);
		  __ move(FP, SP);
		  __ addi(SP, SP, (-2) * wordSize);

	  }		
	  // [ fp     ] <-- sp
	  // [ ra     ]
	  // [ lo     ] <-- fp
	  // [ hi     ]
/*		
    switch (kind) {
      case Interpreter::java_lang_math_sin :
	__ sincos(true, true);
	break;
      case Interpreter::java_lang_math_cos :
	__ sincos(false, true);
	break;
      case Interpreter::java_lang_math_sqrt: 
	__ sqrt_d(F0, F12);
	break;
      default                              : 
	ShouldNotReachHere();
    }
*/
  //FIXME, need consider this    
	  switch (kind) {
		  case Interpreter::java_lang_math_sin :
			  __ trigfunc('s');
			  break;
		  case Interpreter::java_lang_math_cos :
			  __ trigfunc('c');
			  break;
		  case Interpreter::java_lang_math_tan :
			  __ trigfunc('t');
			  break;
		  case Interpreter::java_lang_math_sqrt: 
			  //	__ fsqrt();
			  __ sqrt_d(F0, F12);
			  break;
		  case Interpreter::java_lang_math_abs:
			  //	__ fabs();
			  __ abs_d(F0, F12);	
			  break;
		  case Interpreter::java_lang_math_log:
			  //	__ flog();
			  // Store to stack to convert 80bit precision back to 64bits
			  //	__ push_fTOS();
			  //	__ pop_fTOS();
			  break;
		  case Interpreter::java_lang_math_log10:
			  //	__ flog10();
			  // Store to stack to convert 80bit precision back to 64bits
			  //	__ push_fTOS();
			  //	__ pop_fTOS();
			  break;
		  default                              : 
			  ShouldNotReachHere();
	  }

	  // must maintain return value in F0:F1
	  __ lw(RA, FP, (-1) * wordSize);
	  //FIXME	
	  __ move(SP, T5);
	  // __ move(SP, T0);	
	  __ lw(FP, FP, (-2) * wordSize);
	  __ jr(RA);
	  __ delayed()->nop();
  }
  return entry_point;    
}


// Abstract method entry
// Attempt to execute abstract method. Throw exception
address InterpreterGenerator::generate_abstract_entry(void) {

	// T7: methodOop
	// V0: receiver (unused)
	// esi: previous interpreter state (C++ interpreter) must preserve
	// T5 : sender 's sp
	address entry_point = __ pc();

	// abstract method entry
	// throw exception
	// adjust stack to what a normal return would do

	//__ movl(esp, esi);
	__ move(SP,T5); //FIXME, why jvm6 add this @jerome
	__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
	// the call_VM checks for exception, so we should never return here.
	__ should_not_reach_here();

	return entry_point;
}


// Empty method, generate a very fast return.

address InterpreterGenerator::generate_empty_entry(void) {

	// T7: methodOop
	// V0: receiver (unused)
	// esi: previous interpreter state (C++ interpreter) must preserve
	//T5: sender 's sp , must set sp to this value on return , on mips ,now use T0,as it right?
	if (!UseFastEmptyMethods) return NULL;

	address entry_point = __ pc();

	Label slow_path;
	//  __ cmpl(Address((int)SafepointSynchronize::address_of_state(), relocInfo::none), 
	//  SafepointSynchronize::_not_synchronized);
	// __ jcc(Assembler::notEqual, slow_path);
	__ move(T6, (int)SafepointSynchronize::address_of_state());   
	__ lw(AT,T6, 0);
	// __ addi(AT,AT,-(SafepointSynchronize::_not_synchronized));
	__ move(T6, (SafepointSynchronize::_not_synchronized));   
	__ bne(AT,T6,slow_path); 
	__ delayed()->nop(); 
	// do nothing for empty methods (do not even increment invocation counter)
	// Code: _return
	// _return
	// return w/o popping parameters
	//__ jr(RA);
	//__ delayed()->nop();
	// do nothing for empty methods (do not even increment invocation counter)
	// Code: _return
	// _return
	// return w/o popping parameters
	//__ popl(eax);
	//__ movl(esp, esi);
	//__ jmp(eax);
	__ move(SP, T5);
	__ jr(RA);
	__ delayed()->nop();
	__ bind(slow_path);
	//(void) generate_asm_interpreter_entry(false);
	(void) generate_normal_entry(false);

	return entry_point;

}

// This method tells the deoptimizer how big an interpreted frame must be:
int AbstractInterpreter::size_activation(methodOop method,
                                         int tempcount,
                                         int popframe_extra_args,
                                         int moncount,
                                         int callee_param_count,
                                         int callee_locals,
                                         bool is_top_frame) {
  return layout_activation(method,
                           tempcount, popframe_extra_args, moncount,
                           callee_param_count, callee_locals,
                           (frame*) NULL, (frame*) NULL, is_top_frame);
}

void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) {

  // This code is sort of the equivalent of C2IAdapter::setup_stack_frame back in
  // the days we had adapter frames. When we deoptimize a situation where a
  // compiled caller calls a compiled caller will have registers it expects
  // to survive the call to the callee. If we deoptimize the callee the only
  // way we can restore these registers is to have the oldest interpreter
  // frame that we create restore these values. That is what this routine
  // will accomplish.

  // At the moment we have modified c2 to not have any callee save registers
  // so this problem does not exist and this routine is just a place holder.

  assert(f->is_interpreted_frame(), "must be interpreted");
}