]> gitweb.factorcode.org Git - factor.git/commitdiff
VM: storing some sample data in the heap (#337)
authorBjörn Lindqvist <bjourne@gmail.com>
Wed, 23 Nov 2016 08:44:17 +0000 (09:44 +0100)
committerBjörn Lindqvist <bjourne@gmail.com>
Wed, 23 Nov 2016 08:44:17 +0000 (09:44 +0100)
This is the first half of it. In the second half the samples array
should also be stored in the heap.

vm/objects.hpp
vm/sampling_profiler.cpp
vm/slot_visitor.hpp
vm/vm.hpp

index 3b748d0b6695db12cbb925ad42ef0f212c576312..a51e198a44c2e72999c8f66e3c7bb6a826973bb6 100644 (file)
@@ -64,10 +64,13 @@ enum special_object {
   SIGNAL_HANDLER_WORD,
   LEAF_SIGNAL_HANDLER_WORD,
   WIN_EXCEPTION_HANDLER,
-  UNUSED2,
 
-  // Incremented on every modify-code-heap call; invalidates call( inline
-  // caching
+  // Vector used by the sampling profiler to store collected call
+  // frames.
+  OBJ_SAMPLE_CALLSTACKS = 51,
+
+  // Incremented on every modify-code-heap call; invalidates call(
+  // inline caching
   REDEFINITION_COUNTER = 52,
 
   // Callback stub generation in callbacks.cpp
index 889ccbe3d81123fd5dfca3a131db37ca8792c95d..962cdc4f56f6260232592b413078c1aeaa85f4b3 100644 (file)
@@ -2,6 +2,40 @@
 
 namespace factor {
 
+// This is like the growable_array class, except the whole of it
+// exists on the Factor heap. growarr = growable array.
+static cell growarr_capacity(array *growarr) {
+  return untag_fixnum(growarr->data()[0]);
+}
+
+static cell growarr_nth(array *growarr, cell slot) {
+  return array_nth(untag<array>(growarr->data()[1]), slot);
+}
+
+// Allocates memory
+array* factor_vm::allot_growarr() {
+  data_root<array> contents(allot_array(10, false_object), this);
+  array *growarr = allot_uninitialized_array<array>(2);
+  set_array_nth(growarr, 0, tag_fixnum(0));
+  set_array_nth(growarr, 1, contents.value());
+  return growarr;
+}
+
+// Allocates memory
+void factor_vm::growarr_add(array *growarr_, cell elt_) {
+  data_root<array> growarr(growarr_, this);
+  data_root<object> elt(elt_, this);
+  data_root<array> contents(growarr.untagged()->data()[1], this);
+
+  cell count = growarr_capacity(growarr.untagged());
+  if (count == array_capacity(contents.untagged())) {
+    contents.set_untagged(reallot_array(contents.untagged(), 2 * count));
+    set_array_nth(growarr.untagged(), 1, contents.value());
+  }
+  set_array_nth(contents.untagged(), count, elt.value());
+  set_array_nth(growarr.untagged(), 0, tag_fixnum(count + 1));
+}
+
 profiling_sample_count profiling_sample_count::record_counts() volatile {
   atomic::fence();
   profiling_sample_count returned(sample_count, gc_sample_count,
@@ -31,6 +65,7 @@ profiling_sample::profiling_sample(profiling_sample_count const& counts, cell th
       callstack_begin(callstack_begin),
       callstack_end(callstack_end) { }
 
+// Allocates memory (sample_callstacks2->add)
 void factor_vm::record_sample(bool prolog_p) {
   profiling_sample_count counts = sample_counts.record_counts();
   if (counts.empty()) {
@@ -38,17 +73,20 @@ void factor_vm::record_sample(bool prolog_p) {
   }
   // Appends the callstack, which is just a sequence of quotation or
   // word references, to sample_callstacks.
-  cell begin = sample_callstacks.size();
+  cell callstacks_cell = special_objects[OBJ_SAMPLE_CALLSTACKS];
+  data_root<array> callstacks = data_root<array>(callstacks_cell, this);
+  cell begin = growarr_capacity(callstacks.untagged());
 
   bool skip_p = prolog_p;
   auto recorder = [&](cell frame_top, cell size, code_block* owner, cell addr) {
     if (skip_p)
       skip_p = false;
-    else
-      sample_callstacks.push_back(owner->owner);
+    else {
+      growarr_add(callstacks.untagged(), owner->owner);
+    }
   };
   iterate_callstack(ctx, recorder);
-  cell end = sample_callstacks.size();
+  cell end = growarr_capacity(callstacks.untagged());
 
   // Add the sample.
   cell thread = special_objects[OBJ_CURRENT_THREAD];
@@ -64,16 +102,13 @@ void factor_vm::set_sampling_profiler(fixnum rate) {
 }
 
 void factor_vm::start_sampling_profiler(fixnum rate) {
+  special_objects[OBJ_SAMPLE_CALLSTACKS] = tag<array>(allot_growarr());
   samples_per_second = rate;
   sample_counts.clear();
   // Release the memory consumed by collecting samples.
   samples.clear();
   samples.shrink_to_fit();
-  sample_callstacks.clear();
-  sample_callstacks.shrink_to_fit();
-
   samples.reserve(10 * rate);
-  sample_callstacks.reserve(100 * rate);
   atomic::store(&sampling_profiler_p, true);
   start_sampling_profiler_timer();
 }
@@ -92,42 +127,46 @@ void factor_vm::primitive_sampling_profiler() {
 void factor_vm::primitive_get_samples() {
   if (atomic::load(&sampling_profiler_p) || samples.empty()) {
     ctx->push(false_object);
-  } else {
-    data_root<array> samples_array(allot_array(samples.size(), false_object),
-                                   this);
-    std::vector<profiling_sample>::const_iterator from_iter = samples.begin();
-    cell to_i = 0;
-
-    for (; from_iter != samples.end(); ++from_iter, ++to_i) {
-      data_root<array> sample(allot_array(7, false_object), this);
-
-      set_array_nth(sample.untagged(), 0,
-                    tag_fixnum(from_iter->counts.sample_count));
-      set_array_nth(sample.untagged(), 1,
-                    tag_fixnum(from_iter->counts.gc_sample_count));
-      set_array_nth(sample.untagged(), 2,
-                    tag_fixnum(from_iter->counts.jit_sample_count));
-      set_array_nth(sample.untagged(), 3,
-                    tag_fixnum(from_iter->counts.foreign_sample_count));
-      set_array_nth(sample.untagged(), 4,
-                    tag_fixnum(from_iter->counts.foreign_thread_sample_count));
-
-      set_array_nth(sample.untagged(), 5, from_iter->thread);
-
-      cell callstack_size =
-          from_iter->callstack_end - from_iter->callstack_begin;
-      data_root<array> callstack(allot_array(callstack_size, false_object),
+    return;
+  }
+  data_root<array> samples_array(allot_array(samples.size(), false_object),
                                  this);
-
-      for (cell i = 0; i < callstack_size; i++) {
-        set_array_nth(callstack.untagged(), i,
-                      sample_callstacks[from_iter->callstack_begin + i]);
-      }
-      set_array_nth(sample.untagged(), 6, callstack.value());
-      set_array_nth(samples_array.untagged(), to_i, sample.value());
+  std::vector<profiling_sample>::const_iterator from_iter = samples.begin();
+  cell to_i = 0;
+
+  cell callstacks_cell = special_objects[OBJ_SAMPLE_CALLSTACKS];
+  data_root<array> callstacks = data_root<array>(callstacks_cell, this);
+
+  for (; from_iter != samples.end(); ++from_iter, ++to_i) {
+    data_root<array> sample(allot_array(7, false_object), this);
+
+    set_array_nth(sample.untagged(), 0,
+                  tag_fixnum(from_iter->counts.sample_count));
+    set_array_nth(sample.untagged(), 1,
+                  tag_fixnum(from_iter->counts.gc_sample_count));
+    set_array_nth(sample.untagged(), 2,
+                  tag_fixnum(from_iter->counts.jit_sample_count));
+    set_array_nth(sample.untagged(), 3,
+                  tag_fixnum(from_iter->counts.foreign_sample_count));
+    set_array_nth(sample.untagged(), 4,
+                  tag_fixnum(from_iter->counts.foreign_thread_sample_count));
+
+    set_array_nth(sample.untagged(), 5, from_iter->thread);
+
+    cell callstack_size =
+        from_iter->callstack_end - from_iter->callstack_begin;
+    data_root<array> callstack(allot_array(callstack_size, false_object),
+                               this);
+
+    for (cell i = 0; i < callstack_size; i++) {
+      cell block_owner = growarr_nth(callstacks.untagged(),
+                                     from_iter->callstack_begin + i);
+      set_array_nth(callstack.untagged(), i, block_owner);
     }
-    ctx->push(samples_array.value());
+    set_array_nth(sample.untagged(), 6, callstack.value());
+    set_array_nth(samples_array.untagged(), to_i, sample.value());
   }
+  ctx->push(samples_array.value());
 }
 
 }
index d1320c868f9b01ace7207db62fd118a3ef7c3f0f..1d6b9255c7f4e40b8ac4cd9190126f6e0330bb2d 100644 (file)
@@ -214,10 +214,6 @@ template <typename Fixup> void slot_visitor<Fixup>::visit_all_roots() {
     iter->second = visit_pointer(iter->second);
   }
 
-  FACTOR_FOR_EACH(parent->sample_callstacks) {
-    visit_handle(&*iter);
-  }
-
   FACTOR_FOR_EACH(parent->samples) {
     visit_handle(&iter->thread);
   }
index e165233d38ebe31bb13e76a6f59a0be7eb6d5a33..2911e0b4537c2d5ace82111113eb9ebd28630a50 100644 (file)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -86,7 +86,6 @@ struct factor_vm {
 
   // State kept by the sampling profiler
   std::vector<profiling_sample> samples;
-  std::vector<cell> sample_callstacks;
   volatile profiling_sample_count sample_counts;
 
   // GC is off during heap walking
@@ -193,6 +192,8 @@ struct factor_vm {
   void set_sampling_profiler(fixnum rate);
   void primitive_sampling_profiler();
   void primitive_get_samples();
+  array* allot_growarr();
+  void growarr_add(array *growarr_, cell value);
 
   // errors
   void general_error(vm_error_type error, cell arg1, cell arg2);