| 604 | } |
| 605 | |
| 606 | void LuaEngine::countHook(lua_State* state, lua_Debug* ar) { |
| 607 | starAssert(ar->event == LUA_HOOKCOUNT); |
| 608 | lua_checkstack(state, 4); |
| 609 | |
| 610 | auto self = luaEnginePtr(state); |
| 611 | |
| 612 | // If the instruction count is 0, that means in this sequence of calls, |
| 613 | // we have not hit a debug hook yet. Since we don't know the state of |
| 614 | // the internal lua instruction counter at the start, we don't know how |
| 615 | // many instructions have been executed, only that it is >= 1 and <= |
| 616 | // m_instructionMeasureInterval, so we pick the low estimate. |
| 617 | if (self->m_instructionCount == 0) |
| 618 | self->m_instructionCount = 1; |
| 619 | else |
| 620 | self->m_instructionCount += self->m_instructionMeasureInterval; |
| 621 | |
| 622 | if (self->m_instructionLimit != 0 && self->m_instructionCount > self->m_instructionLimit) { |
| 623 | lua_pushlightuserdata(state, &s_luaInstructionLimitExceptionKey); |
| 624 | lua_error(state); |
| 625 | } |
| 626 | |
| 627 | if (self->m_profilingEnabled) { |
| 628 | // find bottom of the stack |
| 629 | // ar will contain the stack info from the last call that returns 1 |
| 630 | int stackLevel = -1; |
| 631 | while (lua_getstack(state, stackLevel + 1, ar) == 1) |
| 632 | stackLevel++; |
| 633 | |
| 634 | shared_ptr<LuaProfileEntry> parentEntry = nullptr; |
| 635 | while (true) { |
| 636 | // Get the 'n' name info and 'S' source info |
| 637 | if (lua_getinfo(state, "nS", ar) == 0) |
| 638 | break; |
| 639 | |
| 640 | auto key = make_tuple(String(ar->short_src), (unsigned)ar->linedefined); |
| 641 | auto& entryMap = parentEntry ? parentEntry->calls : self->m_profileEntries; |
| 642 | if (!entryMap.contains(key)) { |
| 643 | auto e = make_shared<LuaProfileEntry>(); |
| 644 | e->source = ar->short_src; |
| 645 | e->sourceLine = ar->linedefined; |
| 646 | entryMap.set(key, e); |
| 647 | } |
| 648 | auto entry = entryMap.get(key); |
| 649 | |
| 650 | // metadata |
| 651 | if (!entry->name && ar->name) |
| 652 | entry->name = String(ar->name); |
| 653 | if (!entry->nameScope && String() != ar->namewhat) |
| 654 | entry->nameScope = String(ar->namewhat); |
| 655 | |
| 656 | // Only add timeTaken to the self time for the function we are actually |
| 657 | // in, not parent functions |
| 658 | if (stackLevel == 0) { |
| 659 | entry->totalTime += 1; |
| 660 | entry->selfTime += 1; |
| 661 | } else { |
| 662 | entry->totalTime += 1; |
| 663 | } |
nothing calls this directly
no test coverage detected