Пример #1
0
static int
classifyPrimitive(CallExpr *call, bool inLocal)
{
  int is = classifyPrimitive(call);

  // If it's in a local block, it's always local.
  is = setLocal(is, inLocal);

  return is;
}
Пример #2
0
static int
markFastSafeFn(FnSymbol *fn, int recurse, std::set<FnSymbol*>& visited) {

  // First, handle functions we've already visited.
  if (visited.count(fn) != 0) {
    if (fn->hasFlag(FLAG_FAST_ON))
      return FAST_AND_LOCAL;
    if (fn->hasFlag(FLAG_LOCAL_FN))
      return LOCAL_NOT_FAST;
    return NOT_FAST_NOT_LOCAL;
  }

  // Now, add fn to the set of visited functions,
  // since we will categorize it now.
  visited.insert(fn);

  // Next, classify extern functions
  if (fn->hasFlag(FLAG_EXTERN)) {
    if (fn->hasFlag(FLAG_FAST_ON_SAFE_EXTERN)) {
      // Make sure the FAST_ON and LOCAL_FN flags are set.
      fn->addFlag(FLAG_FAST_ON);
      fn->addFlag(FLAG_LOCAL_FN);
      return FAST_AND_LOCAL;
    } else if(fn->hasFlag(FLAG_LOCAL_FN)) {
      return LOCAL_NOT_FAST;
    } else {
      // Other extern functions are not fast or local.
      return NOT_FAST_NOT_LOCAL;
    }
  }

  // Next, go through function bodies.
  // We will set maybefast=false if we see something in the function
  //  that is local but not suitable for a signal handler
  //  (mostly allocation or locking).
  // We will return NOT_FAST_NOT_LOCAL immediately if we see something
  // in the function that is not local.
  bool maybefast = true;

  if (fn->hasFlag(FLAG_NON_BLOCKING))
    maybefast = false;

  std::vector<CallExpr*> calls;

  collectCallExprs(fn, calls);

  for_vector(CallExpr, call, calls) {
    bool inLocal = fn->hasFlag(FLAG_LOCAL_FN) || inLocalBlock(call);

    if (call->primitive) {
      int is = classifyPrimitive(call, inLocal);

      if (!isLocal(is)) {
        // FAST_NOT_LOCAL or NOT_FAST_NOT_LOCAL
        return NOT_FAST_NOT_LOCAL;
      }

      // is == FAST_AND_LOCAL requires no action
      if (is == LOCAL_NOT_FAST) {
        maybefast = false;
      }

    } else {
      if (recurse<=0 || !call->isResolved()) {
        // didn't resolve or past too much recursion.
        // No function calls allowed
        return NOT_FAST_NOT_LOCAL;

      } else {
        // Handle nested 'on' statements
        if (call->resolvedFunction()->hasFlag(FLAG_ON_BLOCK)) {
          if (inLocal) {
            maybefast = false;
          } else {
            return NOT_FAST_NOT_LOCAL;
          }
        }

        // is the call to a fast/local function?
        int is = markFastSafeFn(call->resolvedFunction(),
                                recurse - 1,
                                visited);

        // Remove NOT_LOCAL parts if it's in a local block
        is = setLocal(is, inLocal);

        if (!isLocal(is)) {
          return NOT_FAST_NOT_LOCAL;
        }

        if (is == LOCAL_NOT_FAST) {
          maybefast = false;
        }
        // otherwise, possibly still fast.
      }
    }
  }
Пример #3
0
void ATOM_AABBTreeBuilder::workOnItem (ATOM_AABBTree::PrimitiveType prim, WorkingItem &item, unsigned maxLeafPrimitiveCount, int maxDepth)
{
	unsigned numPrimitives = item.primitives.size();

	item.aabb.beginExtend ();

	for (unsigned i = 0; i < numPrimitives; ++i)
	{
		unsigned primitive = item.primitives[i];
		const unsigned short *idx = &_extractedIndices[primitive*3];
		item.aabb.extend (_vertices[idx[0]]);
		item.aabb.extend (_vertices[idx[1]]);
		item.aabb.extend (_vertices[idx[2]]);
	}

	item.prim = 0;
	item.numPrims = numPrimitives;
	if (numPrimitives <= maxLeafPrimitiveCount || (maxDepth >= 0 && item.depth > maxDepth))
	{
		item.left = -1;
		item.right = -1;
		item.prim = allocPrimitiveList (numPrimitives);

		for (unsigned i = 0; i < numPrimitives; ++i)
		{
			_leafPrimitiveLists[item.prim + i] = item.primitives[i];
		}
		return;
	}

	const ATOM_Vector3f &bboxMin = item.aabb.getMin();
	const ATOM_Vector3f &bboxMax = item.aabb.getMax();
	ATOM_Vector3f bboxCenter = item.aabb.getCenter();

	ATOM_Vector3f extents = item.aabb.getExtents ();
	int axis = 0;
	if (extents[1] > extents[0]) axis = 1;
	if (extents[2] > extents[axis]) axis = 2;

	float middle = calcAvgPoint (item, axis);
	WorkingItem *left = 0;
	WorkingItem *right = 0;

	for (unsigned i = 0; i < numPrimitives; ++i)
	{
		unsigned primitive = item.primitives[i];
		float minval, maxval;
		int result = classifyPrimitive (primitive, axis, middle, minval, maxval);
		if (result == 0)
		{
			if (!left)
			{
				left = new WorkingItem;
				left->depth = item.depth + 1;
				left->aabb.setMin (bboxMin);
				if (axis == 0)
				{
					left->aabb.setMax (ATOM_Vector3f((maxval > bboxCenter.x) ? maxval : bboxCenter.x, bboxMax.y, bboxMax.z));
				}
				else if (axis == 1)
				{
					left->aabb.setMax (ATOM_Vector3f(bboxMin.x, (maxval > bboxCenter.y) ? maxval : bboxCenter.y, bboxMax.z));
				}
				else
				{
					left->aabb.setMax (ATOM_Vector3f(bboxMin.x, bboxMin.y, (maxval > bboxCenter.z) ? maxval : bboxCenter.z));
				}
			}
			left->primitives.push_back (primitive);
		}
		else
		{
			if (!right)
			{
				right = new WorkingItem;
				right->depth = item.depth + 1;
				right->aabb.setMax (bboxMax);
				if (axis == 0)
				{
					right->aabb.setMin (ATOM_Vector3f((minval < bboxCenter.x) ? minval : bboxCenter.x, bboxMin.y, bboxMin.z));
				}
				else if (axis == 1)
				{
					right->aabb.setMin (ATOM_Vector3f(bboxMin.x, (minval < bboxCenter.y) ? minval : bboxCenter.y, bboxMin.z));
				}
				else
				{
					right->aabb.setMin (ATOM_Vector3f(bboxMin.x, bboxMin.y, (minval < bboxCenter.z) ? minval : bboxCenter.z));
				}
			}
			right->primitives.push_back (primitive);
		}
	}

	if (left && !right)
	{
		assert (left->primitives.size() == numPrimitives);
		right = new WorkingItem;
		right->depth = item.depth + 1;
		right->aabb = left->aabb;
		unsigned le = numPrimitives / 2;
		unsigned start = numPrimitives - le;
		right->primitives.resize(le);
		for (unsigned n = 0; n < le; ++n)
		{
			right->primitives[n] = left->primitives[start+n];
		}
		left->primitives.resize (start);
	}
	else if (right && !left)
	{
		assert (right->primitives.size() == numPrimitives);
		left = new WorkingItem;
		left->depth = item.depth + 1;
		left->aabb = right->aabb;
		unsigned le = numPrimitives / 2;
		unsigned start = numPrimitives - le;
		left->primitives.resize (le);
		for (unsigned n = 0; n < le; ++n)
		{
			left->primitives[n] = right->primitives[start+n];
		}
		right->primitives.resize (start);
	}

	if (left)
	{
		item.left = _items.size();
		_items.push_back (left);
	}
	else
	{
		item.left = -1;
	}

	if (right)
	{
		item.right = _items.size();
		_items.push_back (right);
	}
	else
	{
		item.right = -1;
	}
}