Пример #1
0
inline void unpack_first_frame(char* &current_pc, frame &current, CodeIterator &c) {
  // first vframe in the array
  if (nlr_through_unpacking) {
    // NLR is comming through unpacked vframes
    current_pc = c.interpreter_return_point();
    // current_pc points to a normal return point in the interpreter.
	// To find the nlr return point we first compute the nlr offset.
    current_pc = ic_info_at(current_pc)->NLR_target();
    current.set_hp(c.next_hp());
  } else if (redo_the_send) {
    // Deoptimizing uncommon trap
    current_pc = Interpreter::redo_bytecode_after_deoptimization();
    current.set_hp(c.next_hp());
	redo_send_offset = c.next_hp() - c.hp();
    redo_the_send = false;
  } else {
    // Normal case
    current_pc = c.interpreter_return_point(true);
    current.set_hp(c.next_hp());

    if (c.is_message_send()) {
	  number_of_arguments_through_unpacking = c.ic()->nof_arguments();
    } else if (c.is_primitive_call()) {
      number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters();
    } else if (c.is_dll_call()) {
      // The callee should not pop the argument since a DLL call is like a c function call.
      // The continuation code for the DLL call will pop the arguments!
      number_of_arguments_through_unpacking = 0;
    }
  }
}
Пример #2
0
// Called from assembler in unpack_unoptimized_frames.
// Based on the statics (old_sp, old_fp, and frame_array) this function unpacks
// the array into interpreter frames.
// Returning from this function should activate the most recent deoptimized frame.
extern "C" void unpack_frame_array() {
  BlockScavenge bs;
  ResourceMark rm;

  int* pc_addr = (int*) new_sp - 1;
  assert(*pc_addr = -1, "just checking");

  if (TraceDeoptimization) {
    std->print("[Unpacking]");
    if (nlr_through_unpacking) {
      std->print(" NLR %s", (nlr_home == (int) cur_fp) ? "inside" : "outside");
    }
    std->cr();
    std->print(" - array ");
    frame_array->print_value();
    std->print_cr(" @ 0x%lx", old_fp);
  }

  bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp;
  bool nlr_target_found     = false; // For verification

  // link for the current frame
  int* link_addr = (int*) new_sp - 2;

  oop* current_sp = new_sp;
  int  pos        = 3;
  int  length     = frame_array->length();
  bool first = true;
  frame current;
  // unpack one frame at at time from most recent to least recent
  do {
    oop receiver     = frame_array->obj_at(pos++);
    methodOop method = methodOop(frame_array->obj_at(pos++));
    assert(method->is_method(), "expecting method");

    smiOop bci_obj = smiOop(frame_array->obj_at(pos++));
    assert(bci_obj->is_smi(), "expecting smi");
    int bci        = bci_obj->value();

    smiOop locals_obj = smiOop(frame_array->obj_at(pos++));
    assert(locals_obj->is_smi(), "expecting smi");
    int locals   = locals_obj->value();

    current = frame(current_sp, (int*) current_sp + locals + 2);

    // fill in the locals
    for (int index = 0; index < locals; index++) {
      current.set_temp(index, frame_array->obj_at(pos++));
    }

    CodeIterator c(method, bci);

    char* current_pc;

    if (first) {
      // first vframe in the array
      if (nlr_through_unpacking) {
        // NLR is comming through unpacked vframes
        current_pc = c.interpreter_return_point();
        // current_pc points to a normal return point in the interpreter.
	// To find the nlr return point we first compute the nlr offset.
        current_pc = ic_info_at(current_pc)->NLR_target();
        current.set_hp(c.next_hp());
      } else if (redo_the_send) {
        // Deoptimizing uncommon trap
        current_pc = (char*) redo_bytecode_after_deoptimization;
        current.set_hp(c.next_hp());
	redo_send_offset = c.next_hp() - c.hp();
        redo_the_send = false;
      } else {
        // Normal case
        current_pc = c.interpreter_return_point(true);
        current.set_hp(c.next_hp());
 
        if (c.is_message_send()) {
	  number_of_arguments_through_unpacking = c.ic()->nof_arguments();	  
        } else if (c.is_primitive_call()) {
          number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters();
	} else if (c.is_dll_call()) {
	  // The callee should not pop the argument since a DLL call is like a c function call.
	  // The continuation code for the DLL call will pop the arguments!
          number_of_arguments_through_unpacking = 0;
	}
      }
    } else {
      current_pc = c.interpreter_return_point();
      current.set_hp(c.next_hp());
    }
    current.set_receiver(receiver);

    current.patch_pc(current_pc);
    current.patch_fp(current.fp());
    
    // Revive the contexts
    if (!method->is_blockMethod() && method->activation_has_context()) {
      contextOop con = contextOop(current.temp(0));
      assert(con->is_context(), "must be context");
      oop frame_oop = oop(current.fp());
      con->set_parent(frame_oop);

      if (nlr_through_unpacking && nlr_home == (int) cur_fp) {
        if (nlr_home_context == con) {
	  // This frame is the target of the NLR
	  // set nlr_home to frame pointer of current frame
	  nlr_home = (int) current.fp();
	  // compute number of arguments to pop
          nlr_home_id = ~method->number_of_arguments();
          nlr_target_found = true;
	  // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id);
        }
      }
    }

    if (TraceDeoptimization) {
      frame v(current_sp, current.fp(), current_pc);
      v.print_for_deoptimization(std);
    }

    first = false;
    // Next pc
    current_sp += frame::interpreter_frame_size(locals);

  } while (pos <= length);

  if (must_find_nlr_target && !nlr_target_found) {
    fatal("Target for NLR not found when unpacking frame");
  }

  assert (current_sp == old_sp, "We have not reached the end");
  current.set_link(old_fp);
}