]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/code_blocks.hpp
io.streams.256color: faster by caching styles
[factor.git] / vm / code_blocks.hpp
index 9fbd5ee749d72c7676e70d0e7feee69a6924e987..baa0faa6c9d3554d28cfccd28598f8f1252a997a 100644 (file)
-namespace factor
-{
-
-/* The compiled code heap is structured into blocks. */
-struct code_block
-{
-       cell header;
-       cell owner; /* tagged pointer to word, quotation or f */
-       cell literals; /* tagged pointer to array or f */
-       cell relocation; /* tagged pointer to byte-array or f */
-
-       bool free_p() const
-       {
-               return header & 1 == 1;
-       }
-
-       code_block_type type() const
-       {
-               return (code_block_type)((header >> 1) & 0x3);
-       }
-
-       void set_type(code_block_type type)
-       {
-               header = ((header & ~0x7) | (type << 1));
-       }
-
-       bool pic_p() const
-       {
-               return type() == code_block_pic;
-       }
-
-       bool optimized_p() const
-       {
-               return type() == code_block_optimized;
-       }
-
-       cell size() const
-       {
-               return header & ~7;
-       }
-
-       void *xt() const
-       {
-               return (void *)(this + 1);
-       }
-
-       void flush_icache()
-       {
-               factor::flush_icache((cell)this,size());
-       }
+namespace factor {
+
+// The compiled code heap is structured into blocks.
+struct code_block {
+  // header format (bits indexed with least significant as zero):
+  // bit   0  : free?
+  // bits  1-2: type (as a code_block_type)
+  // if not free:
+  //   bits  3-23: code size / 8
+  //   bits 24-31: stack frame size / 16
+  // if free:
+  //   bits  3-end: code size / 8
+  cell header;
+  cell owner;      // tagged pointer to word, quotation or f
+  cell parameters; // tagged pointer to array or f
+  cell relocation; // tagged pointer to byte-array or f
+
+  bool free_p() const { return (header & 1) == 1; }
+
+  code_block_type type() const {
+    return (code_block_type)((header >> 1) & 0x3);
+  }
+
+  void set_type(code_block_type type) {
+    header = ((header & ~0x7) | (type << 1));
+  }
+
+  bool pic_p() const { return type() == CODE_BLOCK_PIC; }
+
+  cell size() const {
+    cell size;
+    if (free_p())
+      size = header & ~7;
+    else
+      size = header & 0xFFFFF8;
+    FACTOR_ASSERT(size > 0);
+    return size;
+  }
+
+  cell stack_frame_size() const {
+    if (free_p())
+      return 0;
+    return (header >> 20) & 0xFF0;
+  }
+
+  cell stack_frame_size_for_address(cell addr) const {
+    cell natural_frame_size = stack_frame_size();
+    // The first instruction in a code block is the prolog safepoint,
+    // and a leaf procedure code block will record a frame size of zero.
+    // If we're seeing a stack frame in either of these cases, it's a
+    // fake "leaf frame" set up by the signal handler.
+    if (natural_frame_size == 0 || addr == entry_point())
+      return LEAF_FRAME_SIZE;
+    return natural_frame_size;
+  }
+
+  void set_stack_frame_size(cell frame_size) {
+    FACTOR_ASSERT(size() < 0xFFFFFF);
+    FACTOR_ASSERT(!free_p());
+    FACTOR_ASSERT(frame_size % 16 == 0);
+    FACTOR_ASSERT(frame_size <= 0xFF0);
+    header = (header & 0xFFFFFF) | (frame_size << 20);
+  }
+
+  template <typename Fixup> cell size(Fixup fixup) const { (void)fixup; return size(); }
+
+  cell entry_point() const { return (cell)(this + 1); }
+
+  // GC info is stored at the end of the block
+  gc_info* block_gc_info() const {
+    return (gc_info*)((uint8_t*)this + size() - sizeof(gc_info));
+  }
+
+  void flush_icache() { factor::flush_icache((cell)this, size()); }
+
+  template <typename Iterator> void each_instruction_operand(Iterator& iter) {
+    if (!to_boolean(relocation))
+      return;
+
+    byte_array* rels = untag<byte_array>(relocation);
+
+    cell index = 0;
+    cell length = untag_fixnum(rels->capacity) / sizeof(relocation_entry);
+
+    for (cell i = 0; i < length; i++) {
+      relocation_entry rel = rels->data<relocation_entry>()[i];
+      iter(instruction_operand(rel, this, index));
+      index += rel.number_of_parameters();
+    }
+  }
+
+  cell offset(cell addr) const { return addr - entry_point(); }
+
+  cell address_for_offset(cell offset) const {
+    return entry_point() + offset;
+  }
+
+  cell scan(factor_vm* vm, cell addr) const;
+  cell owner_quot() const;
 };
 
+VM_C_API void undefined_symbol(void);
+
+inline code_block* word::code() const {
+  FACTOR_ASSERT(entry_point != 0);
+  return (code_block*)entry_point - 1;
+}
+
+inline code_block* quotation::code() const {
+  FACTOR_ASSERT(entry_point != 0);
+  return (code_block*)entry_point - 1;
+}
+
 }