Example #1
0
code_block* callback_heap::add(cell owner, cell return_rewind) {
  /* code_template is a 2-tuple where the first element contains the
     relocations and the second a byte array of compiled assembly
     code. The code assumes that there are four relocations on x86 and
     three on ppc. */
  tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
  tagged<byte_array> insns(array_nth(code_template.untagged(), 1));
  cell size = array_capacity(insns.untagged());

  cell bump = align(size + sizeof(code_block), data_alignment);
  code_block* stub = allocator->allot(bump);
  if (!stub) {
    parent->general_error(ERROR_CALLBACK_SPACE_OVERFLOW,
                          false_object,
                          false_object);
  }
  stub->header = bump & ~7;
  stub->owner = owner;
  stub->parameters = false_object;
  stub->relocation = false_object;

  memcpy((void*)stub->entry_point(), insns->data<void>(), size);

  /* Store VM pointer in two relocations. */
  store_callback_operand(stub, 0, (cell)parent);
  store_callback_operand(stub, 2, (cell)parent);

  /* On x86, the RET instruction takes an argument which depends on
     the callback's calling convention */
  if (return_takes_param_p())
    store_callback_operand(stub, 3, return_rewind);

  update(stub);
  return stub;
}
Example #2
0
code_block *callback_heap::add(cell owner, cell return_rewind)
{
	tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
	tagged<byte_array> insns(array_nth(code_template.untagged(),1));
	cell size = array_capacity(insns.untagged());

	cell bump = align(size + sizeof(code_block),data_alignment);
	if(here + bump > seg->end) fatal_error("Out of callback space",0);

	free_heap_block *free_block = (free_heap_block *)here;
	free_block->make_free(bump);
	here += bump;

	code_block *stub = (code_block *)free_block;
	stub->owner = owner;
	stub->parameters = false_object;
	stub->relocation = false_object;

	memcpy(stub->entry_point(),insns->data<void>(),size);

	/* Store VM pointer */
	store_callback_operand(stub,0,(cell)parent);

	cell index;

	if(setup_seh_p())
	{
		store_callback_operand(stub,1);
		index = 1;
	}
	else
		index = 0;

	/* Store VM pointer */
	store_callback_operand(stub,index + 2,(cell)parent);

	/* On x86, the RET instruction takes an argument which depends on
	the callback's calling convention */
	if(return_takes_param_p())
		store_callback_operand(stub,index + 3,return_rewind);

	update(stub);

	return stub;
}
Example #3
0
code_block* callback_heap::add(cell owner, cell return_rewind) {
  tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
  tagged<byte_array> insns(array_nth(code_template.untagged(), 1));
  cell size = array_capacity(insns.untagged());

  cell bump = align(size + sizeof(code_block), data_alignment);
  code_block* stub = allocator->allot(bump);
  if (!stub) {
    parent->general_error(ERROR_CALLBACK_SPACE_OVERFLOW,
                          false_object,
                          false_object);
  }

  stub->header = bump & ~7;
  stub->owner = owner;
  stub->parameters = false_object;
  stub->relocation = false_object;

  memcpy((void*)stub->entry_point(), insns->data<void>(), size);

  /* Store VM pointer */
  store_callback_operand(stub, 0, (cell)parent);

  cell index;

  if (setup_seh_p()) {
    store_callback_operand(stub, 1);
    index = 1;
  } else
    index = 0;

  /* Store VM pointer */
  store_callback_operand(stub, index + 2, (cell) parent);

  /* On x86, the RET instruction takes an argument which depends on
     the callback's calling convention */
  if (return_takes_param_p())
    store_callback_operand(stub, index + 3, return_rewind);

  update(stub);

  return stub;
}
Example #4
0
void callback_heap::update(code_block* stub) {
  word* w = (word*)UNTAG(stub->owner);
  store_callback_operand(stub, 1, w->entry_point);
  stub->flush_icache();
}
Example #5
0
void callback_heap::update(code_block* stub) {
  store_callback_operand(stub, setup_seh_p() ? 2 : 1,
                         (cell)callback_entry_point(stub));
  stub->flush_icache();
}