< prev index next >

src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp

Print this page

        

@@ -44,10 +44,11 @@
 #include "runtime/synchronizer.hpp"
 #include "runtime/timer.hpp"
 #include "runtime/vframeArray.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/macros.hpp"
+#include "classfile/systemDictionary.hpp"
 
 #define __ _masm->
 
 // Size of interpreter code.  Increase if too small.  Interpreter will
 // fail with a guarantee ("not enough space for interpreter generation");

@@ -196,12 +197,16 @@
   } else if (state == dtos) {
     __ MacroAssembler::verify_FPU(UseSSE >= 2 ? 0 : 1, "generate_return_entry_for in interpreter");
   }
 #endif // _LP64
 
+  // __ stop("12121212");
+
   // Restore stack bottom in case i2c adjusted stack
   __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+  // __ addq(rsp, rbp); // XXXXXXXX see generate_fixed_frame
+
   // and NULL it as marker that esp is now tos until next java call
   __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
 
   __ restore_bcp();
   __ restore_locals();

@@ -652,18 +657,20 @@
 //      rdx: cp cache
 void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
   // initialize fixed part of activation frame
   __ push(rax);        // save return address
   __ enter();          // save old & set new rbp
+  __ subq(rbcp, rbp); // must be added to rbp to get the old one.
   __ push(rbcp);        // set sender sp
+
   __ push((int)NULL_WORD); // leave last_sp as null
   __ movptr(rbcp, Address(rbx, Method::const_offset()));      // get ConstMethod*
   __ lea(rbcp, Address(rbcp, ConstMethod::codes_offset())); // get codebase
   __ push(rbx);        // save Method*
   // Get mirror and store it in the frame as GC root for this Method*
   __ load_mirror(rdx, rbx);
-  __ push(rdx);
+  __ push(rdx); // oop
   if (ProfileInterpreter) {
     Label method_data_continue;
     __ movptr(rdx, Address(rbx, in_bytes(Method::method_data_offset())));
     __ testptr(rdx, rdx);
     __ jcc(Assembler::zero, method_data_continue);

@@ -676,22 +683,218 @@
 
   __ movptr(rdx, Address(rbx, Method::const_offset()));
   __ movptr(rdx, Address(rdx, ConstMethod::constants_offset()));
   __ movptr(rdx, Address(rdx, ConstantPool::cache_offset_in_bytes()));
   __ push(rdx); // set constant pool cache
-  __ push(rlocals); // set locals pointer
+  // __ push(rlocals); // set locals pointer
+  __ mov(rdx, rlocals);
+  __ subq(rdx, rbp);
+  __ push(rdx); // set locals pointer
   if (native_call) {
     __ push(0); // no bcp
   } else {
     __ push(rbcp); // set bcp
   }
   __ push(0); // reserve word for pointer to expression stack bottom
   __ movptr(Address(rsp, 0), rsp); // set expression stack bottom
 }
 
+void TemplateInterpreterGenerator::generate_continuation_frame(bool native_call, AbstractInterpreter::MethodKind kind) {
+  // rdx = no. of additional locals
+  // rcx = size of parameters
+  // rbx = Method*
+  // free registers: rax, 
+
+  if (kind == AbstractInterpreter::java_lang_continuation_getStack) {
+    // return;
+  }
+
+  // total overhead size: entry_size + (saved rbp through expr stack
+  // bottom).  be sure to change this if you add/subtract anything
+  // to/from the overhead area
+  const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
+  const int overhead = -(frame::interpreter_frame_initial_sp_offset * wordSize) + entry_size;
+  assert(overhead > 0, "overhead is 0 or negative");
+  // test if we're in a continuation
+  Label done, done0;
+  Register cont = r10;
+  const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+  NOT_LP64(__ get_thread(thread));
+
+  __ movptr(cont, Address(thread, in_bytes(JavaThread::continuation_offset())));
+  __ testl(cont, cont);
+  __ jcc(Assembler::zero, done);
+
+  Register array = r11, index_rsp = r13; // index_rbp = r10; (r12 is taken)
+  __ continuation_save_registers(cont, array, index_rsp);
+
+  __ load_heap_oop(array, Address(cont, java_lang_Continuation::stack_offset));
+  __ lea(array, Address(array, arrayOopDesc::base_offset_in_bytes(T_INT)));
+
+  __ movptr(index_rsp, rsp);
+  __ subq(index_rsp, array); // now index is the offset _in bytes_ into the array
+
+  __ cmpl(index_rsp, overhead);  
+  __ jcc(Assembler::above, done0); // fast path
+
+  // slow path -- call getStack to allocate a new stack for us
+
+  // Done by continuation_exit:
+  __ shrq(index_rsp, 2); // now index is the (int) index into the array
+
+  // __ movq(index_rbp, rbp);
+  // __ subq(index_rbp, array);
+  // __ shrq(index_rbp, 2); // now index is the (int) index into the array
+
+  __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
+  __ call_VM(cont, CAST_FROM_FN_PTR(address, InterpreterRuntime::get_continuation_stack), cont, index_rsp, rdx);
+
+  __ stop("generate_continuation_frame slow 1111");
+  // Done by continuation_enter:
+  // __ load_heap_oop(array, Address(cont, java_lang_Continuation::stack_offset)); // now array is the new array
+  // __ lea(rsp, Address(array, index_rsp, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)));
+  // __ lea(rbp, Address(array, index_rbp, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_INT)));
+
+  __ bind(done0);  
+  __ continuation_restore_registers(cont, array, index_rsp);
+
+  __ bind(done);
+}
+
 // End of helpers
 
+/*address TemplateInterpreterGenerator::generate_Continuation_run_entry(void) {
+  address entry = __ pc();
+  
+  // CallInfo callinfo;
+  // Klass* recvrKlass = SystemDictionary::resolve_or_null(vmSymbols::java_lang_Continuation(), NULL); // SystemDictionary::Continuation_klass();
+  // LinkInfo link_info(recvrKlass, vmSymbols::enter_name(), vmSymbols::continuationEnter_signature());
+  // LinkResolver::resolve_special_call(callinfo, Handle(), link_info, NULL);
+  // methodHandle method = callinfo.selected_method();
+  // assert(method.not_null(), "should have thrown exception");
+
+  const Address constMethod(rbx, Method::const_offset());
+  // const Address access_flags(rbx, Method::access_flags_offset());
+
+  __ movptr(rdx, constMethod);
+
+  const Address size_of_parameters(rdx, ConstMethod::size_of_parameters_offset());
+  // const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset());
+
+  __ load_unsigned_short(rcx, size_of_parameters);
+  __ subl(rdx, rdx);// rdx = 0 = no. of additional locals
+  
+  // rbx: Method*
+  // rcx: size of parameters
+  // rbcp: sender_sp (could differ from sp+wordSize if we were called via c2i )
+
+  // see if we've got enough room on the stack for locals plus overhead.
+  // generate_stack_overflow_check();
+
+  __ pop(rax); // get return address
+
+  // compute beginning of parameters
+  __ lea(rlocals, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize));
+  __ movptr(rax, Address(rlocals, 0)); // Address(rsp, wordSize)
+
+  // rax: local 0
+  Register recv = rax;
+  __ push(recv);
+
+  Register rmethod = rbx; // Method* must be rbx for interpreter calling convention
+  __ movptr(rmethod, AddressLiteral((address)&java_lang_Continuation::stack_method, RelocationHolder::none), NULL);
+  
+    // load return address
+    //const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
+    ExternalAddress table(entry);
+    __ movptr(rdx, table);
+  // push return address
+  __ push(rdx); // ???? AddressLiteral(__ pc(), RelocationHolder::none)
+
+  // initialize fixed part of activation frame
+  // __ enter(); // remove if generate_fixed_frame
+  // generate_fixed_frame(false);
+
+  // __ stop("zzzz");
+
+  __ jump_from_interpreted(rmethod, rax);
+
+
+  return entry;
+}*/
+
+
+// Method entry for java.lang.Continuation.run.
+address TemplateInterpreterGenerator::generate_Continuation_run_entry(void) {
+  address entry = __ pc();
+
+  const Address constMethod(rbx, Method::const_offset());
+  // const Address access_flags(rbx, Method::access_flags_offset());
+
+  __ movptr(rdx, constMethod);
+
+  const Address size_of_parameters(rdx,
+                                   ConstMethod::size_of_parameters_offset());
+  // const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset());
+
+  __ load_unsigned_short(rcx, size_of_parameters);
+  __ subl(rdx, rdx);// rdx = 0 = no. of additional locals
+
+  // rbx: Method*
+  // rcx: size of parameters
+  // rbcp: sender_sp (could differ from sp+wordSize if we were called via c2i )
+
+  // see if we've got enough room on the stack for locals plus overhead.
+  generate_stack_overflow_check();
+
+  // rbx: Method*
+  // rcx: size of parameters
+  // rbcp: sender sp
+  
+  __ pop(rax); // get return address
+
+  // compute beginning of parameters
+  __ lea(rlocals, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize));
+
+  // add 2 zero-initialized slots for native calls
+  // initialize result_handler slot
+  __ push((int) NULL_WORD);
+  // slot for oop temp
+  // (static native method holder mirror/jni oop result)
+  __ push((int) NULL_WORD);
+
+  // initialize fixed part of activation frame
+  generate_fixed_frame(false);
+
+  __ movptr(rax, Address(rlocals, 0)); // Address(rsp, wordSize)
+
+  // rax: local 0
+  
+  // const int target_offset = java_lang_Continuation::target_offset;
+  // guarantee(target_offset > 0, "target offset not initialized");
+
+  // Load the value of the referent field.
+  // const Address field_address(rax, target_offset);
+  // __ load_heap_oop(rcx, field_address);
+
+  // const Register thread = rcx;
+  // __ get_thread(thread);
+  // __ set_last_Java_frame(thread, noreg, noreg, NULL);
+  // __ reset_last_Java_frame(thread, false);
+
+  Register rarg1 = rax;
+  __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::enter_continuation), rarg1);
+
+  // __ get_thread(thread);
+  // __ reset_last_Java_frame(thread, false);
+
+  __ remove_activation(vtos, rbcp);
+  __ jmp(rbcp);
+
+  return entry;
+}
+
 // Method entry for java.lang.ref.Reference.get.
 address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
 #if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1

@@ -1036,10 +1239,11 @@
 #ifndef _LP64
    __ get_thread(thread);
    __ lea(t, Address(thread, JavaThread::jni_environment_offset()));
    __ movptr(Address(rsp, 0), t);
 
+   __ stop("LOOM XXX"); // assert not called
    // set_last_Java_frame_before_call
    // It is enough that the pc()
    // points into the right code segment. It does not have to be the correct return pc.
    __ set_last_Java_frame(thread, noreg, rbp, __ pc());
 #else

@@ -1317,11 +1521,13 @@
 
   // remove activation
   __ movptr(t, Address(rbp,
                        frame::interpreter_frame_sender_sp_offset *
                        wordSize)); // get sender sp
+  // __ addq(t, rbp);
   __ leave();                                // remove frame anchor
+  // __ stop("k9k9k9k9");
   __ pop(rdi);                               // get return address
   __ mov(rsp, t);                            // set sp to sender sp
   __ jmp(rdi);
 
   if (inc_counter) {

@@ -1352,28 +1558,31 @@
   __ should_not_reach_here();
 
   return entry_point;
 }
 
+address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
+  return generate_normal_entry(synchronized, AbstractInterpreter::zerolocals);
+}
+
 //
 // Generic interpreted method entry to (asm) interpreter
 //
-address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
+address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized, AbstractInterpreter::MethodKind kind) {
   // determine code generation flags
   bool inc_counter  = UseCompiler || CountCompiledCalls || LogTouchedMethods;
 
   // ebx: Method*
-  // rbcp: sender sp
+  // rbcp: sender sp (set in InterpreterMacroAssembler::prepare_to_jump_from_interpreted / generate_call_stub)
   address entry_point = __ pc();
 
   const Address constMethod(rbx, Method::const_offset());
   const Address access_flags(rbx, Method::access_flags_offset());
   const Address size_of_parameters(rdx,
                                    ConstMethod::size_of_parameters_offset());
   const Address size_of_locals(rdx, ConstMethod::size_of_locals_offset());
 
-
   // get parameter size (always needed)
   __ movptr(rdx, constMethod);
   __ load_unsigned_short(rcx, size_of_parameters);
 
   // rbx: Method*

@@ -1385,15 +1594,25 @@
 
   // YYY
 //   __ incrementl(rdx);
 //   __ andl(rdx, -2);
 
+  generate_continuation_frame(false, kind);
+
   // see if we've got enough room on the stack for locals plus overhead.
   generate_stack_overflow_check();
 
   // get return address
-  __ pop(rax);
+  __ pop(rax); // saved from rax in generate_fixed_frame
+
+  if (kind == AbstractInterpreter::java_lang_continuation_enter) {
+    Register cont = r10;
+    const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+    NOT_LP64(__ get_thread(thread));
+    __ movptr(cont, Address(thread, in_bytes(JavaThread::continuation_offset())));
+    __ push(cont); // ensure that the first parameter (this) is on the stack
+  }
 
   // compute beginning of parameters
   __ lea(rlocals, Address(rsp, rcx, Interpreter::stackElementScale(), -wordSize));
 
   // rdx - # of additional locals

@@ -1411,10 +1630,14 @@
   }
 
   // initialize fixed part of activation frame
   generate_fixed_frame(false);
 
+  // if (kind == AbstractInterpreter::java_lang_continuation_getStack) {
+  //   __ stop("23232323");
+  // }
+
   // make sure method is not native & not abstract
 #ifdef ASSERT
   __ movl(rax, access_flags);
   {
     Label L;

@@ -1459,13 +1682,20 @@
   }
 
   Label continue_after_compile;
   __ bind(continue_after_compile);
 
+  Label no_cont;
+  __ movptr(r11, Address(r15_thread, in_bytes(JavaThread::continuation_offset())));
+  __ testl(r11, r11);
+  __ jcc(Assembler::zero, no_cont);
+
   // check for synchronized interpreted methods
   bang_stack_shadow_pages(false);
 
+  __ bind(no_cont);
+
   // reset the _do_not_unlock_if_synchronized flag
   NOT_LP64(__ get_thread(thread));
   __ movbool(do_not_unlock_if_synchronized, false);
 
   // check for synchronized methods

@@ -1503,12 +1733,20 @@
 #endif
 
   // jvmti support
   __ notify_method_entry();
 
+  // if (kind == AbstractInterpreter::java_lang_continuation_getStack) {
+  //   __ stop("78787878787");
+  // }
+
   __ dispatch_next(vtos);
 
+  if (kind == AbstractInterpreter::java_lang_continuation_getStack) {
+    __ stop("9090909090909");
+  }
+
   // invocation counter overflow
   if (inc_counter) {
     if (ProfileInterpreter) {
       // We have decided to profile this method in the interpreter
       __ bind(profile_method);
< prev index next >