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; }
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. } } }
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; } }