Exemplo n.º 1
0
void LoopFinder::find_loop_exits(BlockBegin* bb, Loop* loop) {
  BlockLoopInfo* bli = get_block_info(bb);
  int loop_index = bb->loop_index();
  // search all successors and locate the ones that do not have the same loop_index
  BlockEnd* be = bb->end();
  int n = be->number_of_sux() - 1;
  for(; n >= 0; n--) {
    BlockBegin* sux = be->sux_at(n);
    BlockLoopInfo* sux_bli = get_block_info(sux);
    if (sux->loop_index() != loop_index) {
      loop->append_loop_exit(bb, sux);
    }
  }
}
Exemplo n.º 2
0
void LoopFinder::find_loop_entries(BlockBegin* bb, Loop* loop) {
  BlockLoopInfo* bli = get_block_info(bb);
  int loop_index = bb->loop_index();
  // search all predecessors and locate the ones that do not have the same loop_index
  int n = bli->nof_preds() - 1;
  assert(bli->nof_preds() >= 2, "at least two predecessors required for a loop header");
  for (; n >= 0; n--) {
    BlockBegin* pred_bb = bli->pred_no(n);
    BlockLoopInfo* pred_bli = get_block_info(pred_bb);
    if (pred_bb->loop_index() != loop_index) {
      loop->append_loop_entry(pred_bb, bb);
    }
  }
  assert(loop->nof_loopentries() > 0, "a loop must be entered from somewhere");
}
Exemplo n.º 3
0
unsigned char get_block_id_info(block_info_t * blocks, int scale, int x, int z)
{
  int majority_array[256];
  int i, j, k = 0;
  int rx, rz;

  memset(majority_array, 0, 256 * sizeof(int));

  if(z < 0 || z > pow(2, scale) * 128)
    return -1;

  rx = pow(2, scale) * x;
  rz = pow(2, scale) * z;

  for(i = 0; i < pow(2, scale); i++)
      for(j = 0; j < pow(2, scale); j++)
	{
	  block_info_t info = get_block_info(blocks, scale, rx + i, rz + j);
	  majority_array[info.blockid]++;
	}

  for((i = 0, j = -1); i < 256; i++)
    {
      if(majority_array[i] > j)
	{
	  j = majority_array[i];
	  k = i;
	}
    }
  
  return (unsigned char)k;
}
Exemplo n.º 4
0
bool RenderableChunk::isblocked(int x1, int y1, int z1, int x2, int y2, int z2) {
    // Air (0) is always "blocked"
    if(!blk[x1][y1][z1].type)
        return true;
    
    // Recipe Models are also always blocked, because they dont need to be rendered
    if (get_block_info(blk[x1][y1][z1].type)->is_model)
        return true;
    
    block_type* next = get(x2, y2, z2);
    uint16_t next_type = 0;
    if (next) {
        next_type = next->type;
    }
    // Things next to models however, are rendered (models are sexy!)
    if (get_block_info(next_type)->is_model)
        return false;
    
    // Leaves do not block any other block, including themselves
    if(get_block_info(next_type)->transparency == 1)
        return false;
    
    // Non-transparent blocks always block line of sight
    if(!get_block_info(next_type)->transparency)
        return true;
    
    // Otherwise, LOS is only blocked by blocks if the same transparency type
    return get_block_info(next_type)->transparency == get_block_info(blk[x1][y1][z1].type)->transparency;
}
Exemplo n.º 5
0
// Compute dominators for bb and 
// walk the successors of bb in depth first order
void LoopFinder::dominator_walk_sux(BlockBegin* bb, boolArray* visited) {
  // we may not visit a block that is jsr-target
  if (bb->is_set(BlockBegin::subroutine_entry_flag)) set_not_ok();
  BlockEnd*      be  = bb->end();
  BlockLoopInfo* bli = get_block_info(bb);
  visited->at_put(bb->block_id(), true);

  // compute new dominators using predecessors
  BitMap map(max_blocks());
  map.set_from(*BlockLoopInfo::all_blocks_map());
  { // Compute dominators for myself (looking at predecessors)
    int nof_preds = bli->nof_preds();
    for (int i = 0; i < nof_preds; i++) {
      BlockBegin* pred     = bli->pred_no(i);
      BitMap      pred_map = get_block_info(pred)->doms_map();
      map.set_intersection(pred_map);
    }
    // add itself
    map.at_put(bb->block_id(), true);
    
    // if the computed dominators differ from the one stored,
    // then we need another iteration
    BitMap bb_map = bli->doms_map();
    if (!bb_map.is_same(map)) {
      set_changed(true);
      bb_map.set_from(map);
    }
  }
  { // Visit all successors
    int n = be->number_of_sux();
    for (int i = 0; i < n; i++) {
      BlockBegin* sux = be->sux_at(i);
      if (!visited->at(sux->block_id())) {
        dominator_walk_sux(sux, visited);
      }
    }
  }
}
Exemplo n.º 6
0
BlockBegin* LoopFinder::insert_caching_block(LoopList* loops, BlockBegin* from, BlockBegin* to) {
  if (from->next() && from->next()->as_CachingChange() != NULL &&
      from->end()->default_sux() == to) {
    // we already have a caching change block
    // check that the precision flags are the same
#ifdef ASSERT
    CachingChange* cc = from->next()->as_CachingChange();
    assert(cc->pred_block()->is_set(BlockBegin::single_precision_flag) == from->is_set(BlockBegin::single_precision_flag), "consistency check");
    assert(cc->sux_block()->is_set(BlockBegin::single_precision_flag) == to->is_set(BlockBegin::single_precision_flag), "consistency check");
#endif
    return NULL;
  } else {
    // insert a caching change block, making it close to any single successor
    int bci = -1;
    BlockLoopInfo* bli = get_block_info(to);
    if (bli->nof_preds() == 1) {
      bci = to->bci();
    } else {
      bci = from->end()->bci();
    }
    BlockBegin* cc = new_block(to->scope(), bci);
    BlockEnd* e = new Goto(to, false);
    cc->set_end(e);
    cc->set_next(new CachingChange(from, to), bci)->set_next(e, bci);
    if (PrintLoops && Verbose) {
      tty->print_cr("Added caching block B%d (dest B%d)", cc->block_id(), to->block_id());
    }
    BlockEnd* from_end = from->end();
    from_end->substitute_sux(to, cc);
    cc->join(from_end->state());
    assert(cc->state() != NULL, "illegal operation");

    ValueStack* end_state = cc->state()->copy();
    cc->end()->set_state(end_state);
    to->join(end_state);

    assert(cc->end()->state() != NULL, "should have state");

    loops->update_loops(from, to, cc);
    return cc;
  }
}
Exemplo n.º 7
0
void LoopFinder::gather_loop_blocks(LoopList* loops) {
  int lng = loops->length();
  BitMap blocks_in_loop(max_blocks());
  for (int i = 0; i < lng; i++) {
    // for each loop do the following
    blocks_in_loop.clear();
    Loop* loop = loops->at(i);
    BlockList* ends = loop->ends();
    if (!loop->is_end(loop->start())) {
      GrowableArray<BlockBegin*>* stack = new GrowableArray<BlockBegin*>();
      blocks_in_loop.at_put(loop->start()->block_id(), true);
      
      // insert all the ends into the list
      for (int i = 0; i < ends->length(); i++) {
        blocks_in_loop.at_put(ends->at(i)->block_id()  , true);
        stack->push(ends->at(i));
      }
      
      while (!stack->is_empty()) {
        BlockBegin* bb = stack->pop();
        BlockLoopInfo* bli = get_block_info(bb);
        // push all predecessors that are not yet in loop
        int npreds = bli->nof_preds();
        for (int m = 0; m < npreds; m++) {
          BlockBegin* pred = bli->pred_no(m);
          if (!blocks_in_loop.at(pred->block_id())) {
            blocks_in_loop.at_put(pred->block_id(), true);
            loop->append_node(pred);
            stack->push(pred);
          }
        }
      }
      loop->append_node(loop->start());
    }
    // insert all the ends into the loop
    for (int i = 0; i < ends->length(); i++) {
      loop->append_node(ends->at(i));
    }
  }
}
Exemplo n.º 8
0
double get_block_h_info(block_info_t * blocks, int scale, int x, int z)
{
  int i, j, w;
  int rx, rz;
  double h = 0; 

  w = 1 << scale;
 
  if(z < 0 || z > w * 128)
    return -1;

  rx = w * x;
  rz = w * z;

  for(i = 0; i < w; i++)
      for(j = 0; j < w; j++)
	{
	  block_info_t info = get_block_info(blocks, scale, rx + i, rz + j);
	  h += (double)(info.h + 1) / (double)(w * w);
	}
  
  return h;
}
Exemplo n.º 9
0
int get_block_d_info(block_info_t * blocks, int scale, int x, int z)
{
  int i, j, w;
  int rx, rz;
  int d = 0;

  w = 1 << scale;
 
  if(z < 0 || z > w * 128)
    return -1;

  rx = w * x;
  rz = w * z;

  for(i = 0; i < w; i++)
      for(j = 0; j < w; j++)
	{
	  block_info_t info = get_block_info(blocks, scale, rx + i, rz + j);
	  d += info.d;
	}
  d /= w * w;
  
  return d;
}
Exemplo n.º 10
0
void RenderableChunk::update() {
    changed = false;
    lights.clear();
    has_lights = false;
    
    // 6 faces per cube, plus 3+3 vertices on each triangle of quad
    // but half will not be visible for some reason...don't render?
    GLbyte vertex[CX * CY * CZ * 18][3];
    // I use 2 bytes to denote block type, then 1 byte for flags
    GLbyte texture[CX * CY * CZ * 18][3];
    int i = 0;
    int merged = 0;
    bool vis = false;
    
    model_vertices.clear();
    model_normals.clear();
    model_uvs.clear();
    
    // View from negative x
    
    for(int x = CX - 1; x >= 0; x--) {
        for(int y = 0; y < CY; y++) {
            for(int z = 0; z < CZ; z++) {
                if (get_block_info(blk[x][y][z].type)->is_model) {
                    // add to
                    fill_game_models(model_vertices, model_normals, model_uvs, blk[x][y][z], x, y, z);
                }
                RenderableLight* light = &(get_block_info(blk[x][y][z].type)->light);
                if (light->should_render()) {
                    LightAndPosition light_and_pos;
                    light_and_pos.light = light;
                    // want to render the light at the center of our block
                    light_and_pos.pos = fvec3(x + 0.5f, y + 0.5f, z + 0.5f);
                    lights.push_back(light_and_pos);
                    has_lights = true;
                }
                // Line of sight blocked?
                if(isblocked(x, y, z, x - 1, y, z)) {
                    vis = false;
                    continue;
                }
                block_type type = blk[x][y][z];
                BlockOrientation flags = BlockOrientation::BACK;
                
                // Same block as previous one? Extend it.
                if(vis && z != 0 && blk[x][y][z].equals(blk[x][y][z - 1])) {
                    set_coord_and_texture(vertex, texture, i - 5, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 2, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 1, x, y + 1, z + 1, type, flags);
                    merged++;
                    // Otherwise, add a new quad.
                } else {
                    set_coord_and_texture(vertex, texture, i++, x, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z + 1, type, flags);
                }
                
                vis = true;
            }
        }
    }
    
    // View from positive x
    
    for(int x = 0; x < CX; x++) {
        for(int y = 0; y < CY; y++) {
            for(int z = 0; z < CZ; z++) {
                if(isblocked(x, y, z, x + 1, y, z)) {
                    vis = false;
                    continue;
                }
                block_type type = blk[x][y][z];
                BlockOrientation flags = BlockOrientation::FRONT;
                
                if(vis && z != 0 && blk[x][y][z].equals(blk[x][y][z - 1])) {
                    set_coord_and_texture(vertex, texture, i - 4, x + 1, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 2, x + 1, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 1, x + 1, y, z + 1, type, flags);
                    merged++;
                } else {
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z + 1, type, flags);
                }
                vis = true;
            }
        }
    }
    
    // View from negative y
    
    for(int x = 0; x < CX; x++) {
        for(int y = CY - 1; y >= 0; y--) {
            for(int z = 0; z < CZ; z++) {
                if(isblocked(x, y, z, x, y - 1, z)) {
                    vis = false;
                    continue;
                }
                block_type type = blk[x][y][z];
                BlockOrientation flags = BlockOrientation::BOTTOM;
                
                if(vis && z != 0 && blk[x][y][z].equals(blk[x][y][z - 1])) {
                    set_coord_and_texture(vertex, texture, i - 4, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 2, x + 1, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 1, x, y, z + 1, type, flags);
                    merged++;
                } else {
                    set_coord_and_texture(vertex, texture, i++, x, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y, z + 1, type, flags);
                }
                vis = true;
            }
        }
    }
    
    // View from positive y
    
    for(int x = 0; x < CX; x++) {
        for(int y = 0; y < CY; y++) {
            for(int z = 0; z < CZ; z++) {
                if(isblocked(x, y, z, x, y + 1, z)) {
                    vis = false;
                    continue;
                }
                block_type type = blk[x][y][z];
                BlockOrientation flags = BlockOrientation::TOP;
                
                if(vis && z != 0 && blk[x][y][z].equals(blk[x][y][z - 1])) {
                    set_coord_and_texture(vertex, texture, i - 5, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 2, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 1, x + 1, y + 1, z + 1, type, flags);
                    merged++;
                } else {
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z + 1, type, flags);
                }
                vis = true;
            }
        }
    }
    
    // View from negative z
    
    for(int x = 0; x < CX; x++) {
        for(int z = CZ - 1; z >= 0; z--) {
            for(int y = 0; y < CY; y++) {
                if(isblocked(x, y, z, x, y, z - 1)) {
                    vis = false;
                    continue;
                }
                block_type type = blk[x][y][z];
                BlockOrientation flags = BlockOrientation::RIGHT;
                
                if(vis && y != 0 && blk[x][y][z].equals(blk[x][y - 1][z])) {
                    set_coord_and_texture(vertex, texture, i - 5, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i - 3, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i - 2, x + 1, y + 1, z, type, flags);
                    merged++;
                } else {
                    set_coord_and_texture(vertex, texture, i++, x, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z, type, flags);
                }
                vis = true;
            }
        }
    }
    
    // View from positive z
    
    for(int x = 0; x < CX; x++) {
        for(int z = 0; z < CZ; z++) {
            for(int y = 0; y < CY; y++) {
                if(isblocked(x, y, z, x, y, z + 1)) {
                    vis = false;
                    continue;
                }
                block_type type = blk[x][y][z];
                BlockOrientation flags = BlockOrientation::LEFT;
                
                if(vis && y != 0 && blk[x][y][z].equals(blk[x][y - 1][z])) {
                    set_coord_and_texture(vertex, texture, i - 4, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 3, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i - 1, x + 1, y + 1, z + 1, type, flags);
                    merged++;
                } else {
                    set_coord_and_texture(vertex, texture, i++, x, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x, y + 1, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y, z + 1, type, flags);
                    set_coord_and_texture(vertex, texture, i++, x + 1, y + 1, z + 1, type, flags);
                }
                vis = true;
            }
        }
    }
    
    changed = false;
    elements = i;
    
    //printf("Finished generating %d elements\n", elements);
    
    // If this chunk is empty, no need to allocate a chunk slot.
    if(!elements)
        return;
    
    // If we don't have an active slot, find one
    if(chunk_slot[slot].owner != this) {
        int lru = 0;
        for(int i = 0; i < CHUNKSLOTS; i++) {
            // If there is an empty slot, use it
            if(!chunk_slot[i].owner) {
                lru = i;
                break;
            }
            // Otherwise try to find the least recently used slot
            if(chunk_slot[i].owner->lastused < chunk_slot[lru].owner->lastused)
                lru = i;
        }
        
        // If the slot is empty, create a new VBO
        if(!chunk_slot[lru].owner) {
            if (!(chunk_slot[lru].coord_vbo) || !(chunk_slot[lru].texture_vbo)) {
                glGenBuffers(1, &chunk_slot[lru].texture_vbo);
                glGenBuffers(1, &chunk_slot[lru].coord_vbo);
            }
        } else {
            // Otherwise, steal it from the previous slot owner
            chunk_slot[lru].owner->changed = true;
        }
        coord_vbo = chunk_slot[lru].coord_vbo;
        texture_vbo = chunk_slot[lru].texture_vbo;
        
        slot = lru;
        chunk_slot[slot].owner = this;
    }
    
    glBindBuffer(GL_ARRAY_BUFFER, coord_vbo);
    glBufferData(GL_ARRAY_BUFFER, elements * sizeof *vertex, vertex, GL_STATIC_DRAW);
    
    glBindBuffer(GL_ARRAY_BUFFER, texture_vbo);
    glBufferData(GL_ARRAY_BUFFER, elements * sizeof *texture, texture, GL_STATIC_DRAW);
}
Exemplo n.º 11
0
void LoopFinder::add_predecessor(BlockBegin* b, BlockBegin* pred) {
  BlockLoopInfo* bli = get_block_info(b);
  bli->add_predecessor(pred);
}
Exemplo n.º 12
0
// Returns inner loops that have may or may not have calls
LoopList* LoopFinder::find_loops(LoopList* loops, bool call_free_only) {
  LoopList* inner = new LoopList();
  LoopList* outer = new LoopList();
  int lng = loops->length();
  // First step: find loops that have no calls and no backedges
  //             in the loop except its own
  int i;
  for (i = 0; i < lng; i++) {
    Loop* loop = loops->at(i);
    int k = loop->nof_blocks() - 1;
    bool is_outer = false;
    for (; k >= 0; k--) {
      BlockBegin* b = loop->block_no(k);
      // Is this innermost loop:
      // - no block, except end block, may be a back edge start,
      //   otherwise we have an outer loop
      if (!loop->is_end(b)) {
        BlockLoopInfo* bli = get_block_info(b);
        if (bli->is_backedge_start()) {
          if (WantsLargerLoops) {
            is_outer = true;
          } else {
            loop = NULL;
          }
          break;
        }
      }
    }

    if (loop != NULL) {
      ScanBlocks scan(loop->blocks());
      ScanResult scan_result;
      scan.scan(&scan_result);
      if (!call_free_only || (!scan_result.has_calls() && !scan_result.has_slow_cases())) {
        if (is_outer) {
          outer->append(loop);
        } else {
          inner->append(loop);
        }
      } else {
#ifndef PRODUCT
        if (PrintLoops && Verbose) {
          tty->print("Discarding loop with calls: ");
          loop->print();
        }
#endif // PRODUCT
      }
    }
  }
  // find all surviving outer loops and delete any inner loops contained inside them
  if (inner->length() > 0) {
    for (i = 0; i < outer->length() ; i++) {
      Loop* loop = outer->at(i);
      int k = loop->nof_blocks() - 1;
      for (; k >= 0; k--) {
        BlockBegin* b = loop->block_no(k);
        if (!loop->is_end(b)) {
          BlockLoopInfo* bli = get_block_info(b);
          if (bli->is_backedge_start()) {
            // find the loop contained inside this loop
            int j;
            for (j = 0; j < inner->length(); j++) {
              Loop* inner_loop = inner->at(j);
              if (inner_loop->is_end(b)) {
                inner->remove(inner_loop);
                break;
              }
            }
            for (j = 0; j < outer->length(); j++) {
              Loop* outer_loop = outer->at(j);
              if (outer_loop == loop) {
                continue;
              }

              if (outer_loop->is_end(b)) {
                outer->remove(outer_loop);
                break;
              }
            }
          }
        }
      }
    }
    inner->appendAll(outer);
  }


  // Second step: if several loops have the same loop-end, select the one
  //              with fewer blocks.
  //              if several loops have the same loop-start, select the one
  //              with fewer blocks
  // now check for loops that have the same header and eliminate one
  for (i = 0; i < inner->length() ; i++) {
    Loop* current_loop = inner->at(i);
    BlockBegin* header = current_loop->start();
    for (int n = i + 1; n < inner->length(); n++) {
      Loop*  test_loop = inner->at(n);
      BlockBegin* test = test_loop->start();
      Loop* discarded = NULL;
      bool same_end = false;
      for (int e = 0; e < current_loop->ends()->length(); e++) {
        if (test_loop->is_end(current_loop->ends()->at(e))) {
          same_end = true;
        }
      }
      if (header == test_loop->start() || same_end) {
        // discard loop with fewer blocks
        if (test_loop->nof_blocks() > current_loop->nof_blocks()) {
          if (WantsLargerLoops) {
            discarded = current_loop;
          } else {
            discarded = test_loop;
          }
        } else {
          if (WantsLargerLoops) {
            discarded = test_loop;
          } else {
            discarded = current_loop;
          }
        }
        inner->remove(discarded);
#ifndef PRODUCT
        if (PrintLoops && Verbose && discarded) {
          tty->print("Discarding overlapping loop: ");
          discarded->print();
        }
#endif // PRODUCT
        // restart the computation
        i = -1;
        break;
      }
    }
  }

  if (inner->length() == 0) {
    // we removed all the loops
    if (PrintLoops && Verbose) {
      tty->print_cr("*** deleted all loops in %s", __FILE__);
    }
    set_not_ok();
    return NULL;
  } else {
    return inner;
  }
}
Exemplo n.º 13
0
void LoopFinder::compute_dominators(boolArray* visited) {
  // set up a bitmap that contains all blocks
  BitMap all_map(max_blocks());
  all_map.clear();
  for (int i = 0; i < max_blocks(); i++) all_map.at_put(i, true);
  BlockLoopInfo::set_all_blocks_map(&all_map);
  { // initialize block loop info and set all predecessors
    CreateInfoClosure c(this);
    ir()->iterate_preorder(&c);
    SetPredsClosure s(this);
    ir()->iterate_preorder(&s);
  }
  { // compute dominators
    // init dominators
    // set entry block (only one exists) and its dominators
    BlockBegin* root_bb = ir()->start();
    assert(!root_bb->is_set(BlockBegin::subroutine_entry_flag), "root may not be jsr target");

    { // initialize root dominators (only itself)
      BitMap root_doms(max_blocks());
      root_doms.clear();
      root_doms.at_put(root_bb->block_id(), true);
      BlockLoopInfo* bli = get_block_info(root_bb);
      bli->doms_map().set_from(root_doms);
    }

    // iterate until either iter_count exceeds or dominators stable
    int iter_count = 0;
    do {
      iter_count++;
      visited->at_put(root_bb->block_id(), true);
      set_changed(false);
      BlockEnd* be = root_bb->end();
      int n = be->number_of_sux();
      for (int i = 0; i < n; i++) {
        BlockBegin* sux = be->sux_at(i);
        if (!visited->at(sux->block_id())) {
          dominator_walk_sux(sux, visited);
        }
      }
      if (changed()) {
        for (int i = visited->length() - 1; i >= 0; i--) {
          visited->at_put(i, false);
        }
      }
    } while (changed() && iter_count <= max_nof_dom_iterations);
    if (iter_count == max_nof_dom_iterations) {
      if (PrintLoops) {
        tty->print_cr("could not computer dominators");
      }
      set_not_ok();
    }

    // if (PrintLoops) {
    //   tty->print_cr("  Dominators: %d iterations", iter_count);
    //   PrintBlockDominators p(this);
    //   ir()->iterate_topological(&p);
    // }
  }  
  BlockLoopInfo::set_all_blocks_map(NULL);


  // go through all blocks; if a block has not been analyzed, then check its
  // predecessors and successors: all must be also un-analyzed;
  // Note: the block may not be JSR blocks
  if (ok()) {
    _valid_doms = true;
#ifdef ASSERT
    CheckDomClosure cc(visited);
    ir()->iterate_preorder(&cc);
#endif
  }

}
Exemplo n.º 14
0
// Handle an environment's block cache request.
// BCREQ_FLUSH and BCREQ_MAP can be satisified right away.
// BCREQ_MAP_RLOCK, BCREQ_MAP_WLOCK, and BCREQ_UNLOCK manipulate the queue
//   of waiting environments.
// At most 8 IPC requests per block are queued and will be handled in the
//   order they arrive (for fairness).
// The 9th and furhter concurrent requests are ignored; a -E_AGAIN error asks
//   the sending environment to try again later.
//
static void
handle_breq(envid_t envid, int32_t breq)
{
	struct BlockInfo *bip;
	int r;

	// Extract block number and request type from request.
	blocknum_t blocknum = BCREQ_BLOCKNUM(breq);
	int reqtype = BCREQ_TYPE(breq);
	// Check request type.
	if (reqtype < BCREQ_MAP || reqtype > BCREQ_FLUSH_PIPE) {
		ipc_send(envid, -E_NOT_SUPP, 0, 0);
		return;
	}

	if (reqtype == BCREQ_FLUSH_PIPE) {
		ipc_send(envid, 0, 0, 0);
	}
	if (reqtype == BCREQ_PIPE_ATTACH) {
		struct Fd *writer;
		if ((r = fd_lookup(p[1], &writer, true)) < 0)
			ipc_send(envid, r, 0, 0);
		else
			ipc_send(envid, 0, fd2data(writer), PTE_P | PTE_W | PTE_U | PTE_SHARE);
		return;
	}

	// Handle simple requests.
	if (reqtype == BCREQ_FLUSH) {
		return;
	} else if (reqtype == BCREQ_MAP) {
		r = get_block_info(blocknum, &bip, 0);
		send_block(envid, blocknum, r >= 0 ? bip->bi_initialized : 0);
		return;
	}

	// More complex requests need the block_info pointer.
	if ((r = get_block_info(blocknum, &bip, 1)) < 0) {
		ipc_send(envid, r, 0, 0);
		return;
	}

	if (reqtype == BCREQ_INITIALIZE) {
		int old_initialized = bip->bi_initialized;
		bip->bi_initialized = 1;
		ipc_send(envid, old_initialized, 0, 0);
		return;
	}

	// Warn about one particularly simple deadlock.
	if (reqtype == BCREQ_MAP_WLOCK && bip->bi_nlocked > 0
	    && BI_REQTYPE(bip, 0) == BCREQ_MAP_WLOCK
	    && BI_ENVID(bip, 0) == envid)
		cprintf("bufcache: DEADLOCK: env [%08x] re-requests write lock on block %d!\n", envid, blocknum);

	if (reqtype == BCREQ_UNLOCK || reqtype == BCREQ_UNLOCK_FLUSH) {
		// Ensure that envid is one of the environments
		// currently locking the block
		int n = 0;
		while (n < bip->bi_nlocked && BI_ENVID(bip, n) != envid)
			++n;
		if (n == bip->bi_nlocked) {
			ipc_send(envid, -E_NOT_LOCKED, 0, 0);
			return;
		}

		BI_ENVID(bip, n) = BI_ENVID(bip, 0);
		BI_REQTYPE(bip, n) = BI_REQTYPE(bip, 0);
		++bip->bi_head;
		--bip->bi_nlocked;
		--bip->bi_count;

		r = (reqtype == BCREQ_UNLOCK ? 0 : flush_block(blocknum));
		ipc_send(envid, r, 0, 0);
		// Continue on to clear the request queue: perhaps this
		// environment's unlock reqtype lets the next environment lock

	} else if (bip->bi_count == BI_QSIZE) {
		// The queue is full; ask the environment to try again later
		ipc_send(envid, -E_AGAIN, 0, 0);
		return;

	} else {
		BI_ENVID(bip, bip->bi_count) = envid;
		BI_REQTYPE(bip, bip->bi_count) = reqtype;
		++bip->bi_count;
	}

	// Process the request queue
	while (bip->bi_nlocked < bip->bi_count) {
		// If trying to write lock, must be first attempt
		if (BI_REQTYPE(bip, bip->bi_nlocked) == BCREQ_MAP_WLOCK
		    && bip->bi_nlocked > 0)
			break;
		// If trying to read lock, any existing lock must be read
		if (BI_REQTYPE(bip, bip->bi_nlocked) == BCREQ_MAP_RLOCK
		    && bip->bi_nlocked > 0
		    && BI_REQTYPE(bip, 0) != BCREQ_MAP_RLOCK)
			break;
		// If we get here, we can grant the page to this queue element
		send_block(BI_ENVID(bip, bip->bi_nlocked), blocknum,
			   bip->bi_initialized);
		++bip->bi_nlocked;
	}
}
Exemplo n.º 15
0
static irqreturn_t chrif_int(int irq, void *dev_id)
{
    int err;
	RING_IDX rc, rp;
    int more_to_do, notify;
    chrif_request_t req;
    chrif_response_t resp;
	printk(KERN_INFO "\n------------------------------start response-------------------------------------");
    printk(KERN_DEBUG "\nxen: Dom0: chrif_int called with dev_id=%x info=%x", (unsigned int)dev_id, (unsigned int) &info);
    rc = info.ring.req_cons;
    rp = info.ring.sring->req_prod;
    printk(KERN_DEBUG "\nxen: Dom0: rc = %d rp = %d", rc, rp);

    while (rc != rp) {
        if (RING_REQUEST_CONS_OVERFLOW(&info.ring, rc))
           	break;
       	memcpy(&req, RING_GET_REQUEST(&info.ring, rc), sizeof(req));
       	resp.id = req.id;
        resp.operation = req.operation;
        resp.status = req.status + 1;
        printk(KERN_DEBUG "\nxen: Dom0: Recvd at IDX-%d: id = %d, op=%d, status=%d", rc, req.id, req.operation, req.status);
        info.ring.req_cons = ++rc;
        barrier();
                
		printk(KERN_DEBUG "\nxen: Dom0: operation:  %s", op_name(resp.operation));
      	switch(resp.operation) {
            case CHRIF_OP_OPEN:
                info.chrif_filp = filp_open(DEVICE_PATH, O_RDWR, 0);
				printk(KERN_DEBUG "\nxen: dom0: response open");
                break;
            case CHRIF_OP_READ:{
				int cnt;
                resp.rdwr.len = req.rdwr.len;
				cnt = resp.rdwr.len/4096;
                printk(KERN_DEBUG "\nxen: dom0: read %d times", cnt);
				memset(op_page->addr, 0, 4096);
              if(rd_time == 0){
				old_fs = get_fs();
				set_fs(get_ds());
			    //read data from device to page 
				err =info.chrif_filp->f_op->read(info.chrif_filp, block_buf, resp.rdwr.len, &info.chrif_filp->f_pos);	
				set_fs(old_fs);
                if(err < 0)
					printk(KERN_DEBUG "\nxen: Dom0: read %u bytes error", resp.rdwr.len);
			  }	
                memcpy(op_page->addr, block_buf+rd_time*4096, 4096);
                rd_time++;
                if(rd_time == cnt){
                    rd_time = 0;
                    memset(block_buf, 0, resp.rdwr.len);
                }
                printk(KERN_DEBUG "\nxen: dom0: response read");
				break;
            }
            case CHRIF_OP_WRITE:{
				int count;
                resp.rdwr.len = req.rdwr.len;
				count = resp.rdwr.len/4096;
                printk(KERN_DEBUG "\nxen: dom0: write %d times", count);
                //if(count == 0){ block_buf = (char *)kmalloc(resp.rdwr.len, GFP_KERNEL);}
                memcpy(block_buf+wr_time*4096, op_page->addr, 4096);
                wr_time++;
              if(wr_time == count){
                old_fs = get_fs();
				set_fs(get_ds());
				//write data from page to device  
				err = info.chrif_filp->f_op->write(info.chrif_filp, block_buf, resp.rdwr.len, &info.chrif_filp->f_pos);	
				set_fs(old_fs);
                wr_time = 0;
                if(err < 0)
					printk(KERN_DEBUG "\nxen: Dom0: write %u bytes error", resp.rdwr.len);
                memset(block_buf, 0, resp.rdwr.len);
			  }	
                //kfree(block_buf);
                printk(KERN_DEBUG "\nxen: dom0: response write");
                break;
            }    
			case CHRIF_OP_IOCTL:{
				resp.ioc_parm.cmd = req.ioc_parm.cmd;
				switch(resp.ioc_parm.cmd){
					case PDMA_IOC_START_DMA:{
						old_fs = get_fs();
						set_fs(get_ds());
						err = info.chrif_filp->f_op->unlocked_ioctl(info.chrif_filp, PDMA_IOC_START_DMA, NULL);	
						set_fs(old_fs);
					 	if(err){
							printk(KERN_DEBUG "\nxen: Dom0: start-dma ioctl failed");
							resp.status = 0;
						}else  printk(KERN_DEBUG "\nxen: Dom0: start-dma ioctl success");
						//err = call_ioctl(info.chrif_filp, PDMA_IOC_START_DMA, NULL);	
                        get_block_info();
						break;
					}
					case PDMA_IOC_STOP_DMA:{
						//err = call_ioctl(info.chrif_filp, PDMA_IOC_STOP_DMA, NULL);	
						old_fs = get_fs();
						set_fs(get_ds());
						err = info.chrif_filp->f_op->unlocked_ioctl(info.chrif_filp, PDMA_IOC_STOP_DMA, NULL);	
						set_fs(old_fs);
					 	if(err){
							printk(KERN_DEBUG "\nxen: Dom0: stop-dma ioctl failed");
							resp.status = 0;
						}else  printk(KERN_DEBUG "\nxen: Dom0: stop-dma ioctl success");
						break;
					}
					case PDMA_IOC_INFO:{
						struct pdma_info pdma_info;
						//err = call_ioctl(info.chrif_filp, PDMA_IOC_INFO, (unsigned long)&pdma_info);	
						old_fs = get_fs();
						set_fs(get_ds());
						err = info.chrif_filp->f_op->unlocked_ioctl(info.chrif_filp, PDMA_IOC_INFO, (unsigned long)&pdma_info);	
						set_fs(old_fs);
					 	if(err){
							printk(KERN_DEBUG "\nxen: Dom0: info ioctl failed");
							resp.status = 0;
						}else  printk(KERN_DEBUG "\nxen: Dom0: info ioctl success");
						resp.ioc_parm.info = pdma_info;
						break;
					}
					case PDMA_IOC_STAT:{
						struct pdma_stat pdma_stat;
						//err = call_ioctl(info.chrif_filp, PDMA_IOC_STAT, (unsigned long)&pdma_stat);	
						old_fs = get_fs();
						set_fs(get_ds());
						err = info.chrif_filp->f_op->unlocked_ioctl(info.chrif_filp, PDMA_IOC_STAT, (unsigned long)&pdma_stat);	
						set_fs(old_fs);
					 	if(err){
							printk(KERN_DEBUG "\nxen: Dom0: stat ioctl failed");
							resp.status = 0;
						}else  printk(KERN_DEBUG "\nxen: Dom0: stat ioctl success");
						resp.ioc_parm.stat = pdma_stat;
						break;
					}
					case PDMA_IOC_RW_REG:{
						struct pdma_rw_reg ctrl = req.ioc_parm.ctrl;
						//err = call_ioctl(info.chrif_filp, PDMA_IOC_RW_REG, (unsigned long)&ctrl);	
						old_fs = get_fs();
						set_fs(get_ds());
						err = info.chrif_filp->f_op->unlocked_ioctl(info.chrif_filp, PDMA_IOC_RW_REG, (unsigned long)&ctrl);	
						set_fs(old_fs);
					 	if(err){
							printk(KERN_DEBUG "\nxen: Dom0: rw-reg ioctl failed");
							resp.status = 0;
						}else  printk(KERN_DEBUG "\nxen: Dom0: rw-reg ioctl success");
						resp.ioc_parm.ctrl = ctrl;
						break;
					}
                    default:
                        printk(KERN_DEBUG "\nxen: Dom0: unknow the operation");
                        break;
				}
				printk(KERN_INFO "\nxen: Dom0: response ioctl");
				break;
			}
			case CHRIF_OP_CLOSE:
				filp_close(info.chrif_filp, NULL);
				printk(KERN_INFO "\nxen: Dom0: response close");
				break;
            default:
                printk(KERN_DEBUG "\nxen: Dom0: unknow the operation");
                break;
        }

		memcpy(RING_GET_RESPONSE(&info.ring, info.ring.rsp_prod_pvt), &resp, sizeof(resp));
       	info.ring.rsp_prod_pvt++;
		//put response and check whether or not notify domU
        RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&info.ring, notify);
        if (info.ring.rsp_prod_pvt == info.ring.req_cons) 
		{
            RING_FINAL_CHECK_FOR_REQUESTS(&info.ring, more_to_do);
       	}
		else if (RING_HAS_UNCONSUMED_REQUESTS(&info.ring)) 
		{
           	more_to_do = 1;
        }
        if (notify) 
		{
          	printk(KERN_DEBUG "\nxen:dom0:send notify to domu");
          	notify_remote_via_irq(info.irq);
       	}
    }
    return IRQ_HANDLED;
}