changeset 15603:44272909d926

Stop JIT on interrupt * jit-ir.cc (jit_call::needs_release): Move to cc file and do not release artificial assigns. (jit_error_check::variable_to_strign): New function. (jit_error_check::print): Move to cc file and improve output. * jit-ir.h (jit_call::needs_release): Move to cc file. (jit_error_check::variable): New enum. (jit_error_check::variable_to_string): New declaration. (jit_error_check::jit_error_check): Add variable argument and new overload. (jit_error_check::check_variable, jit_error_check::has_check_for): New function. (jit_error_check::check_for): Ensure has_check_for is true. (jit_error_check::print): Move to cc file. (jit_error_check::check_alive): Always true if has_check_for is false. (jit_error_check::mvariable): New variable. * jit-typeinfo.cc (jit_typeinfo::jit_typeinfo): Initialize loctave_interrupt_state and fix name of cast to any. (jit_typeinfo::do_insert_interrupt_check): New function. * jit-typeinfo.h (jit_typeinfo::insert_interrupt_check): New function. (jit_typeinfo::do_insert_interrupt_check): New declaration. (jit_typeinfo::loctave_interrupt_state): New variable. * pt-jit.cc (jit_convert::visit_simple_for_command, jit_convert::visit_while_command): Check interrupt state. (jit_convert::create_check_impl): Specify var_error_state check. (jit_convert_llvm::visit): Generate var_interrupt error check. (jit_function_info::execute, jit_info::execute): Call octave_quit.
author Max Brister <max@2bass.com>
date Sun, 04 Nov 2012 21:11:33 -0700
parents f3e339aee38f
children ac86b891e45a
files libinterp/interp-core/jit-ir.cc libinterp/interp-core/jit-ir.h libinterp/interp-core/jit-typeinfo.cc libinterp/interp-core/jit-typeinfo.h libinterp/interp-core/pt-jit.cc
diffstat 5 files changed, 149 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/interp-core/jit-ir.cc	Sun Nov 04 20:09:23 2012 -0700
+++ b/libinterp/interp-core/jit-ir.cc	Sun Nov 04 21:11:33 2012 -0700
@@ -698,6 +698,23 @@
 
 // -------------------- jit_call --------------------
 bool
+jit_call::needs_release (void) const
+{
+  if (type () && jit_typeinfo::get_release (type ()).valid ())
+    {
+      for (jit_use *use = first_use (); use; use = use->next ())
+        {
+          jit_assign *assign = dynamic_cast<jit_assign *> (use->user ());
+          if (assign && assign->artificial ())
+            return false;
+        }
+
+      return true;
+    }
+  return false;
+}
+
+bool
 jit_call::infer (void)
 {
   // FIXME: explain algorithm
@@ -726,6 +743,33 @@
   return false;
 }
 
+// -------------------- jit_error_check --------------------
+std::string
+jit_error_check::variable_to_string (variable v)
+{
+  switch (v)
+    {
+    case var_error_state:
+      return "error_state";
+    case var_interrupt:
+      return "interrupt";
+    default:
+      panic_impossible ();
+    }
+}
+
+std::ostream&
+jit_error_check::print (std::ostream& os, size_t indent) const
+{
+  print_indent (os, indent) << "error_check " << variable_to_string (mvariable)
+                            << ", ";
+
+  if (has_check_for ())
+    os << "<for> " << *check_for () << ", ";
+  print_successor (os << "<normal> ", 1) << ", ";
+  return print_successor (os << "<error> ", 0);
+}
+
 // -------------------- jit_magic_end --------------------
 jit_magic_end::context::context (jit_factory& factory, jit_value *avalue,
                                  size_t aindex, size_t acount)
--- a/libinterp/interp-core/jit-ir.h	Sun Nov 04 20:09:23 2012 -0700
+++ b/libinterp/interp-core/jit-ir.h	Sun Nov 04 21:11:33 2012 -0700
@@ -1176,10 +1176,7 @@
     return moperation.overload (argument_types ());
   }
 
-  virtual bool needs_release (void) const
-  {
-    return type () && jit_typeinfo::get_release (type ()).valid ();
-  }
+  virtual bool needs_release (void) const;
 
   virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
   {
@@ -1212,27 +1209,47 @@
 jit_error_check : public jit_terminator
 {
 public:
-  jit_error_check (jit_call *acheck_for, jit_block *normal, jit_block *error)
-    : jit_terminator (2, error, normal, acheck_for) {}
+  // Which variable is the error check for?
+  enum variable
+    {
+      var_error_state,
+      var_interrupt
+    };
+
+  static std::string variable_to_string (variable v);
+
+  jit_error_check (variable var, jit_call *acheck_for, jit_block *normal,
+                   jit_block *error)
+    : jit_terminator (2, error, normal, acheck_for), mvariable (var) {}
+
+  jit_error_check (variable var, jit_block *normal, jit_block *error)
+    : jit_terminator (2, error, normal), mvariable (var) {}
+
+  variable check_variable (void) const { return mvariable; }
+
+  bool has_check_for (void) const
+  {
+    return argument_count () == 3;
+  }
 
   jit_call *check_for (void) const
   {
+    assert (has_check_for ());
     return static_cast<jit_call *> (argument (2));
   }
 
-  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const
-  {
-    print_indent (os, indent) << "error_check " << *check_for () << ", ";
-    print_successor (os, 1) << ", ";
-    return print_successor (os, 0);
-  }
+  virtual std::ostream& print (std::ostream& os, size_t indent = 0) const;
 
   JIT_VALUE_ACCEPT;
 protected:
   virtual bool check_alive (size_t idx) const
   {
+    if (! has_check_for ())
+      return true;
     return idx == 1 ? true : check_for ()->can_error ();
   }
+private:
+  variable mvariable;
 };
 
 // for now only handles the 1D case
--- a/libinterp/interp-core/jit-typeinfo.cc	Sun Nov 04 20:09:23 2012 -0700
+++ b/libinterp/interp-core/jit-typeinfo.cc	Sun Nov 04 21:11:33 2012 -0700
@@ -1110,6 +1110,15 @@
   engine->addGlobalMapping (lerror_state,
                             reinterpret_cast<void *> (&error_state));
 
+  // sig_atomic_type is going to be some sort of integer
+  sig_atomic_type = llvm::Type::getIntNTy (context, sizeof(sig_atomic_t) * 8);
+  loctave_interrupt_state
+    = new llvm::GlobalVariable (*module, sig_atomic_type, false,
+                                llvm::GlobalValue::ExternalLinkage, 0,
+                                "octave_interrupt_state");
+  engine->addGlobalMapping (loctave_interrupt_state,
+                            reinterpret_cast<void *> (&octave_interrupt_state));
+
   // generic call function
   {
     jit_type *int_t = intN (sizeof (octave_builtin::fcn) * 8);
@@ -1799,7 +1808,7 @@
   casts[scalar->type_id ()].stash_name ("(scalar)");
   casts[complex->type_id ()].stash_name ("(complex)");
   casts[matrix->type_id ()].stash_name ("(matrix)");
-  casts[any->type_id ()].stash_name ("(range)");
+  casts[range->type_id ()].stash_name ("(range)");
 
   // cast any <- matrix
   fn = create_function (jit_convention::external, "octave_jit_cast_any_matrix",
@@ -2078,6 +2087,14 @@
   return abuilder.CreateLoad (lerror_state);
 }
 
+llvm::Value *
+jit_typeinfo::do_insert_interrupt_check (llvm::IRBuilderD& abuilder)
+{
+  llvm::LoadInst *val = abuilder.CreateLoad (loctave_interrupt_state);
+  val->setVolatile (true);
+  return abuilder.CreateICmpSGT (val, abuilder.getInt32 (0));
+}
+
 void
 jit_typeinfo::add_builtin (const std::string& name)
 {
--- a/libinterp/interp-core/jit-typeinfo.h	Sun Nov 04 20:09:23 2012 -0700
+++ b/libinterp/interp-core/jit-typeinfo.h	Sun Nov 04 21:11:33 2012 -0700
@@ -566,6 +566,11 @@
     return instance->do_insert_error_check (bld);
   }
 
+  static llvm::Value *insert_interrupt_check (llvm::IRBuilderD& bld)
+  {
+    return instance->do_insert_interrupt_check (bld);
+  }
+
   static const jit_operation& end (void)
   {
     return instance->end_fn;
@@ -692,6 +697,8 @@
 
   llvm::Value *do_insert_error_check (llvm::IRBuilderD& bld);
 
+  llvm::Value *do_insert_interrupt_check (llvm::IRBuilderD& bld);
+
   void add_builtin (const std::string& name);
 
   void register_intrinsic (const std::string& name, size_t id,
@@ -747,6 +754,9 @@
   int next_id;
 
   llvm::GlobalVariable *lerror_state;
+  llvm::GlobalVariable *loctave_interrupt_state;
+
+  llvm::Type *sig_atomic_type;
 
   std::vector<jit_type*> id_to_type;
   jit_type *any;
--- a/libinterp/interp-core/pt-jit.cc	Sun Nov 04 20:09:23 2012 -0700
+++ b/libinterp/interp-core/pt-jit.cc	Sun Nov 04 21:11:33 2012 -0700
@@ -403,6 +403,9 @@
   jit_block *check_block = factory.create<jit_block> ("for_check");
   blocks.push_back (check_block);
 
+  jit_block *interrupt_check = factory.create<jit_block> ("for_interrupt");
+  blocks.push_back (interrupt_check);
+
   if (! all_breaking)
     block->append (factory.create<jit_branch> (check_block));
   finish_breaks (check_block, continues);
@@ -415,7 +418,14 @@
   block->append (factory.create<jit_assign> (iterator, iter_inc));
   check = block->append (factory.create<jit_call> (jit_typeinfo::for_check,
                                                    control, iterator));
-  block->append (factory.create<jit_cond_branch> (check, body, tail));
+  block->append (factory.create<jit_cond_branch> (check, interrupt_check,
+                                                  tail));
+
+  block = interrupt_check;
+  jit_error_check *ec
+    = factory.create<jit_error_check> (jit_error_check::var_interrupt,
+                                       body, final_block);
+  block->append (ec);
 
   // breaks will go to our tail
   blocks.push_back (tail);
@@ -834,10 +844,22 @@
     }
 
   finish_breaks (tail, breaks);
-  finish_breaks (cond_check, continues);
-
-  if (! all_breaking)
-    block->append (factory.create<jit_branch> (cond_check));
+
+  if (! all_breaking || continues.size ())
+    {
+      jit_block *interrupt_check
+        = factory.create<jit_block> ("interrupt_check");
+      blocks.push_back (interrupt_check);
+      finish_breaks (interrupt_check, continues);
+      if (! all_breaking)
+        block->append (factory.create<jit_branch> (interrupt_check));
+
+      block = interrupt_check;
+      jit_error_check *ec
+        = factory.create<jit_error_check> (jit_error_check::var_interrupt,
+                                           cond_check, final_block);
+      block->append (ec);
+    }
 
   blocks.push_back (tail);
   block = tail;
@@ -871,8 +893,9 @@
   block->append (ret);
 
   jit_block *normal = factory.create<jit_block> (block->name ());
-  jit_error_check *check = factory.create<jit_error_check> (ret, normal,
-                                                            final_block);
+  jit_error_check *check
+    = factory.create<jit_error_check> (jit_error_check::var_error_state, ret,
+                                       normal, final_block);
   block->append (check);
   blocks.push_back (normal);
   block = normal;
@@ -1365,7 +1388,20 @@
 void
 jit_convert_llvm::visit (jit_error_check& check)
 {
-  llvm::Value *cond = jit_typeinfo::insert_error_check (builder);
+  llvm::Value *cond;
+
+  switch (check.check_variable ())
+    {
+    case jit_error_check::var_error_state:
+      cond = jit_typeinfo::insert_error_check (builder);
+      break;
+    case jit_error_check::var_interrupt:
+      cond = jit_typeinfo::insert_interrupt_check (builder);
+      break;
+    default:
+      panic_impossible ();
+    }
+
   llvm::Value *br = builder.CreateCondBr (cond, check.successor_llvm (0),
                                           check.successor_llvm (1));
   check.stash_llvm (br);
@@ -2080,6 +2116,8 @@
   if (ret)
     retval(0) = octave_value (ret);
 
+  octave_quit ();
+
   return true;
 }
 
@@ -2148,6 +2186,8 @@
         symbol_table::varref (arguments[i].first) = real_arguments[i];
     }
 
+  octave_quit ();
+
   return true;
 }