Example #1
0
int get_outedges_num(CTXTdeclc callnodeptr call1) {
  struct hashtable *h;	
  struct hashtable_itr *itr;

  h=call1->outedges->hasht;
  itr = hashtable1_iterator(h);       
  return hashtable1_count(h);
}
int get_outedges_num(CTXTdeclc callnodeptr call1) {
  struct hashtable *h;	
  struct hashtable_itr *itr;

  h=call1->outedges->hasht;
  itr = hashtable1_iterator(h);       
  SQUASH_LINUX_COMPILER_WARN(itr) ;
  
  return hashtable1_count(h);
}
void xsb_compute_scc(SCCNode * nodes,int * dfn_stack,int node_from, int * dfn_top,
		     struct hashtable* hasht,int * dfn,int * component ) {
  struct hashtable_itr *itr;
  struct hashtable* edges_hash;
  CPtr sf;
  Integer node_to;
  int j;

  //  printf("xsb_compute_scc for %d %p %s/%d dfn %d dfn_top %d\n",
  //	 node_from,nodes[node_from].node,
  //	 get_name(TIF_PSC(subg_tif_ptr(nodes[node_from].node))),
  //	 get_arity(TIF_PSC(subg_tif_ptr(nodes[node_from].node))),*dfn,*dfn_top);
  nodes[node_from].low = nodes[node_from].dfn = (*dfn)++;
  dfn_stack[*dfn_top] = node_from;
  nodes[node_from].stack = *dfn_top;
  (*dfn_top)++;
  edges_hash = subg_callnode_ptr(nodes[node_from].node)->outedges->hasht;
  itr = hashtable1_iterator(edges_hash);       
  if (hashtable1_count(edges_hash) > 0) {
    //    printf("found %d edges\n",hashtable1_count(edges_hash));
    do {
      sf = ((callnodeptr) hashtable1_iterator_value(itr))-> goal;
      node_to = (Integer) search_some(hasht, (void *)sf);
      //      printf("edge from %p to %p (%d)\n",(void *)nodes[node_from].node,sf,node_to);
      if (nodes[node_to].dfn == 0) {
	xsb_compute_scc(nodes,dfn_stack,(int)node_to, dfn_top,hasht,dfn,component );
	if (nodes[node_to].low < nodes[node_from].low) 
	  nodes[node_from].low = nodes[node_to].low;
	}	  
	else if (nodes[node_to].dfn < nodes[node_from].dfn  && nodes[node_to].component == 0) {
	  if (nodes[node_to].low < nodes[node_from].low) { nodes[node_from].low = nodes[node_to].low; }
	}
      } while (hashtable1_iterator_advance(itr));
    //    printf("nodes[%d] low %d dfn %d\n",node_from,nodes[node_from].low, nodes[node_from].dfn);
    if (nodes[node_from].low == nodes[node_from].dfn) {
      for (j = (*dfn_top)-1 ; j >= nodes[node_from].stack ; j--) {
	//	printf(" pop %d and assign %d\n",j,*component);
	nodes[dfn_stack[j]].component = *component;
      }
      (*component)++;       *dfn_top = j+1;
    }
  } 
  else nodes[node_from].component = (*component)++;
}
/*
propagate_no_change(c)
	for c->c'
	  if(c'.deleted=false)
	     c'->falsecount>0
	       c'->falsecount--
	       if(c'->falsecount==0)
		 propagate_no_change(c')		

When invalidation is done a parameter 'falsecount' is maintained with
each call which signifies that these many predecessor calls have been
affected. So if a call A has two pred node B and C and both of them
are affected then A's falsecount is 2. Now when B is reevaluated and
turns out it has not been changed (its old and new answer table is the
same) completion of B calls propagate_no_change(B) which reduces the
falsecount of A by 1. If for example turns out that C was also not
changed the falsecount of A is going to be reduced to 0. Now when call
A is executed it's just going to do answer clause resolution.
*/
void propagate_no_change(callnodeptr c){
  callnodeptr cn;
  struct hashtable *h;	
  struct hashtable_itr *itr;
  if(IsNonNULL(c)){
    h=c->outedges->hasht;
    itr = hashtable1_iterator(h);
    if (hashtable1_count(h) > 0){
      do {
	cn= hashtable1_iterator_value(itr);
	if(cn->falsecount>0){ /* this check is required for the new dependencies that can arise bcoz of the re-evaluation */
	  cn->falsecount--;
	  if(cn->falsecount==0){
	    cn->deleted = 0;
	    propagate_no_change(cn);
	  }
	}
      } while (hashtable1_iterator_advance(itr));
    }
  }		
}
int immediate_affects_ptrlist(CTXTdeclc callnodeptr call1){
 
  VariantSF subgoal;
  int count = 0;
  CPtr oldhreg = NULL;
  struct hashtable *h;	
  struct hashtable_itr *itr;
  callnodeptr cn;
    
  reg[4] = makelist(hreg);
  new_heap_free(hreg);
  new_heap_free(hreg);
  
  if(IsNonNULL(call1)){ /* This can be called from some non incremental predicate */
    h=call1->outedges->hasht;
    
    itr = hashtable1_iterator(h);       
    if (hashtable1_count(h) > 0){
      do {
	cn = hashtable1_iterator_value(itr);
	if(IsNonNULL(cn->goal)){
	  count++;
	  subgoal = (VariantSF) cn->goal;      
	  check_glstack_overflow(4,pcreg,2); 
	  oldhreg=hreg-2;
          follow(oldhreg++) = makeint(subgoal);
	  follow(oldhreg) = makelist(hreg);
	  new_heap_free(hreg);
	  new_heap_free(hreg);
	}
      } while (hashtable1_iterator_advance(itr));
    }
    if (count>0)
      follow(oldhreg) = makenil;
    else
      reg[4] = makenil;
  }
  return unify(CTXTc reg_term(CTXTc 3),reg_term(CTXTc 4));
}
int immediate_outedges_list(CTXTdeclc callnodeptr call1){
 
  VariantSF subgoal;
  TIFptr tif;
  int j, count = 0,arity;
  Psc psc;
  CPtr oldhreg = NULL;
  struct hashtable *h;	
  struct hashtable_itr *itr;
  callnodeptr cn;
    
  reg[4] = makelist(hreg);
  new_heap_free(hreg);
  new_heap_free(hreg);
  
  if(IsNonNULL(call1)){ /* This can be called from some non incremental predicate */
    h=call1->outedges->hasht;
    
    itr = hashtable1_iterator(h);       
    if (hashtable1_count(h) > 0){
      do {
	cn = hashtable1_iterator_value(itr);
	if(IsNonNULL(cn->goal)){
	  count++;
	  subgoal = (VariantSF) cn->goal;      
	  tif = (TIFptr) subgoal->tif_ptr;
	  psc = TIF_PSC(tif);
	  arity = get_arity(psc);
	  check_glstack_overflow(4,pcreg,2+arity*200); // don't know how much for build_subgoal_args...
	  oldhreg=hreg-2;
	  if(arity>0){
	    sreg = hreg;
	    follow(oldhreg++) = makecs(sreg);
	    hreg += arity + 1;
	    new_heap_functor(sreg, psc);
	    for (j = 1; j <= arity; j++) {
	      new_heap_free(sreg);
	      cell_array1[arity-j] = cell(sreg-1);
	    }
	    build_subgoal_args(subgoal);		
	  }else{
	    follow(oldhreg++) = makestring(get_name(psc));
	  }
	  follow(oldhreg) = makelist(hreg);
	  new_heap_free(hreg);
	  new_heap_free(hreg);
	}
      } while (hashtable1_iterator_advance(itr));
    }
    if (count>0)
      follow(oldhreg) = makenil;
    else
      reg[4] = makenil;
  }else{
    xsb_warn("Called with non-incremental predicate\n");
    reg[4] = makenil;
  }

  //  printterm(stdout,call_list,100);
  return unify(CTXTc reg_term(CTXTc 3),reg_term(CTXTc 4));
}
void dfs_outedges(CTXTdeclc callnodeptr call1){
  callnodeptr cn;
  struct hashtable *h;	
  struct hashtable_itr *itr;
  int ctr = 0;

  int incr_callgraph_dfs_top = -1;
  int incr_callgraph_dfs_size; 
  IncrCallgraphDFSFrame   *incr_callgraph_dfs;

  //  printf("1) calling dfs %p; subgoal ",call1);  print_callnode(stddbg,call1); printf("\n");

  incr_callgraph_dfs =
    (IncrCallgraphDFSFrame *)  mem_alloc(10000*sizeof(IncrCallgraphDFSFrame), 
					 TABLE_SPACE);
  incr_callgraph_dfs_size = 10000;
  dfs_outedges_check_non_completed(CTXTc call1);
  if (!is_fact_in_callgraph(call1)) call1->deleted = 1;
  h=call1->outedges->hasht;
  if (hashtable1_count(h) > 0){
    //    printf("1-call1: %p \n",call1);
    push_dfs_frame(call1,0);
  }
  while (incr_callgraph_dfs_top > -1) {
    itr = 0;
    do {
      if (incr_callgraph_dfs[incr_callgraph_dfs_top].itr) {
	itr = incr_callgraph_dfs[incr_callgraph_dfs_top].itr;
	//	printf("1-top %d itr %p\n",incr_callgraph_dfs_top,itr);
	if (!hashtable1_iterator_advance(itr)) {  // last element in the hash
	  itr = 0;
	  cn = incr_callgraph_dfs[incr_callgraph_dfs_top].cn;
	  add_callnode(&affected_gl,cn);		
	  //	  printf("+ adding callnode %p\n",cn);
	  pop_dfs_frame;
	}
      }
      else {
	h=incr_callgraph_dfs[incr_callgraph_dfs_top].cn->outedges->hasht;
	if (hashtable1_count(h) > 0) {
	  itr = hashtable1_iterator(h);          // initialize
	  incr_callgraph_dfs[incr_callgraph_dfs_top].itr = itr;
	}
	else {
	  cn = incr_callgraph_dfs[incr_callgraph_dfs_top].cn;
	  add_callnode(&affected_gl,cn);		
	  //	  printf("+ adding callnode %p\n",cn);
	  pop_dfs_frame;
	}
      }
    } while (itr == 0 && incr_callgraph_dfs_top > -1);
    if (incr_callgraph_dfs_top > -1) {
      cn = hashtable1_iterator_value(itr);

      //      printf("top %d cn: %p itr: %p\n",incr_callgraph_dfs_top,cn,itr);
      //      printf("2) recursive dfs %p; subgoal ",cn);  print_callnode(stddbg,cn); printf("\n");

      cn->falsecount++;
      if (cn->deleted==0) {
	dfs_outedges_check_non_completed(CTXTc cn);
	cn->deleted = 1;
	//	h=cn->outedges->hasht;
	//	if (hashtable1_count(h) > 0) {
	  push_dfs_frame(cn,0);
	  //	}
      }
    }
  }
  mem_dealloc(incr_callgraph_dfs, incr_callgraph_dfs_size*sizeof(IncrCallgraphDFSFrame), 
	      TABLE_SPACE);
}
int  get_incr_sccs(CTXTdeclc Cell listterm) {
  Cell orig_listterm, intterm, node;
    long int node_num=0;
    int i = 0, dfn, component = 1;     int * dfn_stack; int dfn_top = 0, ret;
    SCCNode * nodes;
    struct hashtable_itr *itr;     struct hashtable* hasht; 
    XSB_Deref(listterm);
    hasht = create_hashtable1(HASH_TABLE_SIZE, hashid, equalkeys);
    orig_listterm = listterm;
    intterm = get_list_head(listterm);
    XSB_Deref(intterm);
    //    printf("listptr %p @%p\n",listptr,(CPtr) int_val(*listptr));
    insert_some(hasht,(void *) oint_val(intterm),(void *) node_num);
    node_num++; 

    listterm = get_list_tail(listterm);
    XSB_Deref(listterm);
    while (!isnil(listterm)) {
      intterm = get_list_head(listterm);
      XSB_Deref(intterm);
      node = oint_val(intterm);
      if (NULL == search_some(hasht, (void *)node)) {
	insert_some(hasht,(void *)node,(void *)node_num);
	node_num++;
      }
      listterm = get_list_tail(listterm);
      XSB_Deref(listterm);
    }
    nodes = (SCCNode *) mem_calloc(node_num, sizeof(SCCNode),OTHER_SPACE); 
    dfn_stack = (int *) mem_alloc(node_num*sizeof(int),OTHER_SPACE); 
    listterm = orig_listterm;; 
    //printf("listptr %p @%p\n",listptr,(void *)int_val(*(listptr)));
    intterm = get_list_head(listterm);
    XSB_Deref(intterm);
    nodes[0].node = (CPtr) oint_val(intterm);
    listterm = get_list_tail(listterm);
    XSB_Deref(listterm);
    i = 1;
    while (!isnil(listterm)) {
      intterm = get_list_head(listterm);
      XSB_Deref(intterm);
      node = oint_val(intterm);
      nodes[i].node = (CPtr) node;
      listterm = get_list_tail(listterm);
      XSB_Deref(listterm);
      i++;
    }
    itr = hashtable1_iterator(hasht);       
    SQUASH_LINUX_COMPILER_WARN(itr);
    //    do {
    //      printf("k %p val %p\n",hashtable1_iterator_key(itr),hashtable1_iterator_value(itr));
    //    } while (hashtable1_iterator_advance(itr));

    listterm = orig_listterm;
    //    printf("2: k %p v %p\n",(void *) int_val(*listptr),
    //	   search_some(hasht,(void *) int_val(*listptr)));

    //    while (!isnil(*listptr)) {  now all wrong...
    //      listptr = listptr + 1;
    //      node = int_val(*clref_val(listptr));
    //      printf("2: k %p v %p\n",(CPtr) node,search_some(hasht,(void *) node));
    //      listptr = listptr + 1;
    //    }
    dfn = 1;
    for (i = 0; i < node_num; i++) {
      if (nodes[i].dfn == 0) 
	xsb_compute_scc(nodes,dfn_stack,i,&dfn_top,hasht,&dfn,&component);
      //      printf("++component for node %d is %d (high %d)\n",i,nodes[i].component,component);
    }
    ret = return_scc_list(CTXTc  nodes, node_num);
    hashtable1_destroy(hasht,0);
    mem_dealloc(nodes,node_num*sizeof(SCCNode),OTHER_SPACE); 
    mem_dealloc(dfn_stack,node_num*sizeof(int),OTHER_SPACE); 
    return ret;
}