{
    "slug": "inline_expansion",
    "term": "Inline Expansion",
    "category": "compiler",
    "difficulty": "advanced",
    "short": "A compiler optimization that replaces a function call with the body of the called function, eliminating call overhead and unlocking further optimizations.",
    "long": "In JIT runtimes such as the JVM HotSpot and V8, inlining decisions are made at runtime using profiling data: hot call sites are inlined and may be deoptimized if assumptions break. PHP 8's JIT performs more limited inlining and is far less aggressive than these mature runtimes.",
    "aliases": [
        "inlining",
        "function inlining",
        "inline functions",
        "call site inlining"
    ],
    "tags": [
        "compiler",
        "optimization",
        "jit",
        "performance",
        "code-generation"
    ],
    "misconception": "Marking a function `inline` guarantees the compiler will inline it. The keyword is only a hint; the compiler's cost model decides, and it routinely ignores or overrides such hints in both directions.",
    "why_it_matters": "Inlining is one of the highest-leverage optimizations because it both removes call overhead and exposes the callee to whole-program analysis, but over-inlining causes code bloat that degrades instruction cache performance.",
    "common_mistakes": [
        "Assuming the `inline` keyword forces inlining when it is merely a hint the optimizer may ignore.",
        "Manually inlining function bodies by hand, hurting readability for a gain the compiler already provides automatically.",
        "Expecting virtual or dynamically dispatched calls to be inlined without devirtualization or profile-guided information.",
        "Over-applying always_inline to large functions, causing code bloat and instruction cache misses that slow execution.",
        "Believing recursive functions can be fully inlined when compilers only inline a bounded depth."
    ],
    "when_to_use": [
        "Small, frequently called helpers like getters and accessors where call overhead dominates.",
        "Hot loops where inlining exposes constant folding, vectorisation, or cross-boundary register allocation.",
        "JIT runtimes inlining profiled hot call sites where runtime feedback confirms the benefit."
    ],
    "avoid_when": [
        "The function body is large, since inlining copies it to every call site and causes code bloat.",
        "Manually inlining by hand for readability-costly micro-optimizations the compiler already performs.",
        "The call target is virtual or dynamic and cannot be resolved without devirtualization."
    ],
    "related": [
        "jit_compilation_deep",
        "dead_code_elimination",
        "opcode_optimisation",
        "register_allocation",
        "aot_vs_jit"
    ],
    "prerequisites": [
        "jit_compilation_deep",
        "dead_code_elimination",
        "register_allocation"
    ],
    "refs": [
        "https://llvm.org/docs/Passes.html#inline-function-integration-inlining",
        "https://gcc.gnu.org/onlinedocs/gcc/Inline.html",
        "https://www.agner.org/optimize/optimizing_cpp.pdf"
    ],
    "bad_code": "// C: forcing inlining of a large function hurts more than it helps\n__attribute__((always_inline))\nstatic inline int process(const int *data, int n) {\n    int sum = 0;\n    for (int i = 0; i < n; i++) {\n        sum += data[i] * data[i];      // large body\n        if (data[i] < 0) sum -= 1;\n        // ... many more lines ...\n    }\n    return sum;\n}\n// Called from 40 sites: body copied 40 times -> code bloat,\n// instruction cache thrash, slower overall despite no call overhead.",
    "good_code": "// C: small hot helper, let the compiler decide\nstatic inline int square(int x) {\n    return x * x;        // tiny: a natural inlining candidate\n}\n\nint process(const int *data, int n) {\n    int sum = 0;\n    for (int i = 0; i < n; i++) {\n        sum += square(data[i]);   // compiler inlines square here,\n    }                             // then hoists/vectorises the loop\n    return sum;\n}\n// Large functions stay as real calls; the optimizer's cost model\n// inlines only where the body is small and the benefit is real.",
    "quick_fix": "Write small focused functions and let the optimizer inline them; use inline hints only when profiling proves a specific call site needs it.",
    "severity": "info",
    "effort": "medium",
    "created": "2026-06-01",
    "updated": "2026-06-01",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/inline_expansion",
        "html_url": "https://codeclaritylab.com/glossary/inline_expansion",
        "json_url": "https://codeclaritylab.com/glossary/inline_expansion.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Inline Expansion](https://codeclaritylab.com/glossary/inline_expansion) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/inline_expansion"
            }
        }
    }
}