]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/callbacks.cpp
webapps.wiki: adding search bar
[factor.git] / vm / callbacks.cpp
index 784352b72293a45f24fc957bb835aefbcacbf090..492e7a9884c302b27d5b89e6d21aac619a88ccc2 100644 (file)
@@ -2,11 +2,19 @@
 
 namespace factor {
 
+bool return_takes_param_p() {
+#if defined(FACTOR_X86) || defined(FACTOR_AMD64)
+  return true;
+#else
+  return false;
+#endif
+}
+
 callback_heap::callback_heap(cell size, factor_vm* parent) {
   seg = new segment(size, true);
   if (!seg)
     fatal_error("Out of memory in callback_heap constructor", size);
-  allocator = new bump_allocator<code_block>(size, seg->start);
+  allocator = new free_list_allocator<code_block>(size, seg->start);
   this->parent = parent;
 
 }
@@ -16,27 +24,6 @@ callback_heap::~callback_heap() {
   allocator = NULL;
   delete seg;
   seg = NULL;
-
-}
-
-void factor_vm::init_callbacks(cell size) {
-  callbacks = new callback_heap(size, this);
-}
-
-bool callback_heap::setup_seh_p() {
-#if defined(WINDOWS) && defined(FACTOR_X86)
-  return true;
-#else
-  return false;
-#endif
-}
-
-bool callback_heap::return_takes_param_p() {
-#if defined(FACTOR_X86) || defined(FACTOR_AMD64)
-  return true;
-#else
-  return false;
-#endif
 }
 
 instruction_operand callback_heap::callback_operand(code_block* stub,
@@ -49,91 +36,75 @@ instruction_operand callback_heap::callback_operand(code_block* stub,
   return instruction_operand(entry, stub, 0);
 }
 
-void callback_heap::store_callback_operand(code_block* stub, cell index) {
-  parent->store_external_address(callback_operand(stub, index));
-}
-
 void callback_heap::store_callback_operand(code_block* stub, cell index,
                                            cell value) {
-  callback_operand(stub, index).store_value(value);
+  instruction_operand op = callback_operand(stub, index);
+  op.store_value(value);
 }
 
 void callback_heap::update(code_block* stub) {
-  store_callback_operand(stub, setup_seh_p() ? 2 : 1,
-                         (cell)callback_entry_point(stub));
+  word* w = untag<word>(stub->owner);
+  store_callback_operand(stub, 1, w->entry_point);
   stub->flush_icache();
 }
 
 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);
-  if (allocator->here + bump > allocator->end) {
+  code_block* stub = allocator->allot(bump);
+  if (!stub) {
     parent->general_error(ERROR_CALLBACK_SPACE_OVERFLOW,
                           false_object,
                           false_object);
   }
-
-  code_block* stub = allocator->allot(bump);
-  stub->header = bump | 1;
+  stub->header = bump & ~7;
   stub->owner = owner;
   stub->parameters = false_object;
   stub->relocation = false_object;
 
-  memcpy(stub->entry_point(), insns->data<void>(), size);
+  memcpy((void*)stub->entry_point(), insns->data<void>(), size);
 
-  /* Store VM pointer */
+  // Store VM pointer in two relocations.
   store_callback_operand(stub, 0, (cell)parent);
+  store_callback_operand(stub, 2, (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 */
+  // 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);
+    store_callback_operand(stub, 3, return_rewind);
 
   update(stub);
-
   return stub;
 }
 
-struct callback_updater {
-  callback_heap* callbacks;
-
-  explicit callback_updater(callback_heap* callbacks)
-      : callbacks(callbacks) {}
-
-  void operator()(object* stub) {
-    callbacks->update((code_block*)stub);
-  }
-};
-
-void callback_heap::update() {
-  callback_updater updater(this);
-  parent->each_object(allocator, updater);
-}
-
-/* Allocates memory */
+// Allocates memory (add(), allot_alien())
 void factor_vm::primitive_callback() {
   cell return_rewind = to_cell(ctx->pop());
   tagged<word> w(ctx->pop());
+  check_tagged(w);
 
-  w.untag_check(this);
-
-  void* func = callbacks->add(w.value(), return_rewind)->entry_point();
+  cell func = callbacks->add(w.value(), return_rewind)->entry_point();
   CODE_TO_FUNCTION_POINTER_CALLBACK(this, func);
   ctx->push(allot_alien(func));
 }
 
+void factor_vm::primitive_free_callback() {
+  void* entry_point = alien_offset(ctx->pop());
+  code_block* stub = (code_block*)entry_point - 1;
+  callbacks->allocator->free(stub);
+}
+
+// Allocates memory
+void factor_vm::primitive_callback_room() {
+  allocator_room room = callbacks->allocator->as_allocator_room();
+  ctx->push(tag<byte_array>(byte_array_from_value(&room)));
+}
+
 }