FreeBSD/sys/contrib/dev/acpica/compiler/aslopt.c
/*******************************************************************************
 *
 * FUNCTION:    OptOptimizeNamePath
 *
 * PARAMETERS:  Op                  - Current parser op
 *              Flags               - Opcode info flags
 *              WalkState           - Current state
 *              AmlNameString       - Unoptimized namepath
 *              TargetNode          - Node to which AmlNameString refers
 *
 * RETURN:      None. If path is optimized, the Op is updated with new path
 *
 * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
 *              Must take into account both the current location in the
 *              namespace and the actual reference path.
 *
 ******************************************************************************/


None. If path is optimized, the Op is updated with new path

Optimize a Named Declaration or Reference to the minimal length.
Must take into account both the current location in the
namespace and the actual reference path.
None . If path is optimized the Op is updated with new path Optimize a Named Declaration or Reference to the minimal length . Must take into account both the current location in the namespace and the actual reference path .
void
OptOptimizeNamePath (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Flags,
    ACPI_WALK_STATE         *WalkState,
    char                    *AmlNameString,
    ACPI_NAMESPACE_NODE     *TargetNode)
{
    ACPI_STATUS             Status;
    ACPI_BUFFER             TargetPath;
    ACPI_BUFFER             CurrentPath;
    ACPI_SIZE               AmlNameStringLength;
    ACPI_NAMESPACE_NODE     *CurrentNode;
    char                    *ExternalNameString;
    char                    *NewPath = NULL;
    ACPI_SIZE               HowMuchShorter;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_FUNCTION_TRACE (OptOptimizeNamePath);
    if (!Gbl_ReferenceOptimizationFlag)
    {
        return_VOID;
    }
    if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
    {
        return_VOID;
    }
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
        "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ",
        Op->Asl.LogicalLineNumber,
        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
        AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
    if (!(Flags & (AML_NAMED | AML_CREATE)))
    {
        if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
                "******* NAME DECLARATION\n"));
            return_VOID;
        }
    }
    AmlNameStringLength = strlen (AmlNameString);
    if (AmlNameStringLength <= ACPI_NAME_SIZE)
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
            "NAMESEG %4.4s\n", AmlNameString));
        return_VOID;
    }
    CurrentNode = AcpiGbl_RootNode;
    if (WalkState->ScopeInfo)
    {
        CurrentNode = WalkState->ScopeInfo->Scope.Node;
    }
    if (Flags & (AML_NAMED | AML_CREATE))
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n"));
        NextOp = Op->Asl.Parent;
        while (NextOp && (!NextOp->Asl.Node))
        {
            NextOp = NextOp->Asl.Parent;
        }
        if (NextOp && NextOp->Asl.Node)
        {
            CurrentNode = NextOp->Asl.Node;
        }
        else
        {
            CurrentNode = AcpiGbl_RootNode;
        }
    }
    else
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n"));
    }
    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    Status = AcpiNsHandleToPathname (TargetNode, &TargetPath, FALSE);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
            ASL_NO_ABORT);
        return_VOID;
    }
    TargetPath.Length--;    
    CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath, FALSE);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
            ASL_NO_ABORT);
        return_VOID;
    }
    CurrentPath.Length--;   
    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
        NULL, &ExternalNameString);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
            ASL_NO_ABORT);
        return_VOID;
    }
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
        "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n",
        (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer,
        (UINT32) TargetPath.Length, (char *) TargetPath.Pointer,
        ExternalNameString));
    ACPI_FREE (ExternalNameString);
    if (Flags & (AML_NAMED | AML_CREATE))
    {
        Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
            TargetNode, AmlNameString, &NewPath);
        if (ACPI_FAILURE (Status))
        {
            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
                TargetNode, &CurrentPath, &TargetPath,
                AmlNameStringLength, 1, &NewPath);
        }
    }
    else
    {
        Status = OptSearchToRoot (Op, WalkState, CurrentNode,
            TargetNode, &TargetPath, &NewPath);
        if (ACPI_FAILURE (Status))
        {
            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
                TargetNode, &CurrentPath, &TargetPath,
                AmlNameStringLength, 0, &NewPath);
        }
    }
    if (ACPI_SUCCESS (Status))
    {
        HowMuchShorter = (AmlNameStringLength - strlen (NewPath));
        OptTotal += HowMuchShorter;
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
            " REDUCED BY %2u (TOTAL SAVED %2u)",
            (UINT32) HowMuchShorter, OptTotal));
        if (Flags & AML_NAMED)
        {
            if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
            {
                Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
                Op->Asl.Child->Asl.Next->Asl.AmlLength = strlen (NewPath);
            }
            else
            {
                Op->Asl.Child->Asl.Value.String = NewPath;
                Op->Asl.Child->Asl.AmlLength = strlen (NewPath);
            }
        }
        else if (Flags & AML_CREATE)
        {
            NextOp = Op->Asl.Child;
            while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
            {
                NextOp = NextOp->Asl.Next;
            }
            NextOp->Asl.Value.String = NewPath;
            NextOp->Asl.AmlLength = strlen (NewPath);
        }
        else
        {
            Op->Asl.Value.String = NewPath;
            Op->Asl.AmlLength = strlen (NewPath);
        }
    }
    else
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
    }
    ACPI_FREE (TargetPath.Pointer);
    ACPI_FREE (CurrentPath.Pointer);
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
    return_VOID;
}
void OptOptimizeNamePath ( ACPI_PARSE_OBJECT * Op , UINT32 Flags , ACPI_WALK_STATE * WalkState , char * AmlNameString , ACPI_NAMESPACE_NODE * TargetNode ) { ACPI_STATUS Status ; ACPI_BUFFER TargetPath ; ACPI_BUFFER CurrentPath ; ACPI_SIZE AmlNameStringLength ; ACPI_NAMESPACE_NODE * CurrentNode ; char * ExternalNameString ; char * NewPath = NULL ; ACPI_SIZE HowMuchShorter ; ACPI_PARSE_OBJECT * NextOp ; ACPI_FUNCTION_TRACE ( OptOptimizeNamePath ) ; if ( ! Gbl_ReferenceOptimizationFlag ) { return_VOID ; } if ( ! TargetNode || ! WalkState || ! AmlNameString || ! Op -> Common . Parent ) { return_VOID ; } ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " , Op -> Asl . LogicalLineNumber , AcpiPsGetOpcodeName ( Op -> Common . Parent -> Common . AmlOpcode ) , AcpiPsGetOpcodeName ( Op -> Common . AmlOpcode ) ) ) ; if ( ! ( Flags & ( AML_NAMED | AML_CREATE ) ) ) { if ( Op -> Asl . CompileFlags & NODE_IS_NAME_DECLARATION ) { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " \n " ) ) ; return_VOID ; } } AmlNameStringLength = strlen ( AmlNameString ) ; if ( AmlNameStringLength <= ACPI_NAME_SIZE ) { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " \n " , AmlNameString ) ) ; return_VOID ; } CurrentNode = AcpiGbl_RootNode ; if ( WalkState -> ScopeInfo ) { CurrentNode = WalkState -> ScopeInfo -> Scope . Node ; } if ( Flags & ( AML_NAMED | AML_CREATE ) ) { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " \n " ) ) ; NextOp = Op -> Asl . Parent ; while ( NextOp && ( ! NextOp -> Asl . Node ) ) { NextOp = NextOp -> Asl . Parent ; } if ( NextOp && NextOp -> Asl . Node ) { CurrentNode = NextOp -> Asl . Node ; } else { CurrentNode = AcpiGbl_RootNode ; } } else { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " \n " ) ) ; } TargetPath . Length = ACPI_ALLOCATE_LOCAL_BUFFER ; Status = AcpiNsHandleToPathname ( TargetNode , & TargetPath , FALSE ) ; if ( ACPI_FAILURE ( Status ) ) { AslCoreSubsystemError ( Op , Status , " " , ASL_NO_ABORT ) ; return_VOID ; } TargetPath . Length -- ; CurrentPath . Length = ACPI_ALLOCATE_LOCAL_BUFFER ; Status = AcpiNsHandleToPathname ( CurrentNode , & CurrentPath , FALSE ) ; if ( ACPI_FAILURE ( Status ) ) { AslCoreSubsystemError ( Op , Status , " " , ASL_NO_ABORT ) ; return_VOID ; } CurrentPath . Length -- ; Status = AcpiNsExternalizeName ( ACPI_UINT32_MAX , AmlNameString , NULL , & ExternalNameString ) ; if ( ACPI_FAILURE ( Status ) ) { AslCoreSubsystemError ( Op , Status , " " , ASL_NO_ABORT ) ; return_VOID ; } ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " \n " , ( UINT32 ) CurrentPath . Length , ( char * ) CurrentPath . Pointer , ( UINT32 ) TargetPath . Length , ( char * ) TargetPath . Pointer , ExternalNameString ) ) ; ACPI_FREE ( ExternalNameString ) ; if ( Flags & ( AML_NAMED | AML_CREATE ) ) { Status = OptOptimizeNameDeclaration ( Op , WalkState , CurrentNode , TargetNode , AmlNameString , & NewPath ) ; if ( ACPI_FAILURE ( Status ) ) { Status = OptBuildShortestPath ( Op , WalkState , CurrentNode , TargetNode , & CurrentPath , & TargetPath , AmlNameStringLength , 1 , & NewPath ) ; } } else { Status = OptSearchToRoot ( Op , WalkState , CurrentNode , TargetNode , & TargetPath , & NewPath ) ; if ( ACPI_FAILURE ( Status ) ) { Status = OptBuildShortestPath ( Op , WalkState , CurrentNode , TargetNode , & CurrentPath , & TargetPath , AmlNameStringLength , 0 , & NewPath ) ; } } if ( ACPI_SUCCESS ( Status ) ) { HowMuchShorter = ( AmlNameStringLength - strlen ( NewPath ) ) ; OptTotal += HowMuchShorter ; ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " , ( UINT32 ) HowMuchShorter , OptTotal ) ) ; if ( Flags & AML_NAMED ) { if ( Op -> Asl . AmlOpcode == AML_ALIAS_OP ) { Op -> Asl . Child -> Asl . Next -> Asl . Value . String = NewPath ; Op -> Asl . Child -> Asl . Next -> Asl . AmlLength = strlen ( NewPath ) ; } else { Op -> Asl . Child -> Asl . Value . String = NewPath ; Op -> Asl . Child -> Asl . AmlLength = strlen ( NewPath ) ; } } else if ( Flags & AML_CREATE ) { NextOp = Op -> Asl . Child ; while ( ! ( NextOp -> Asl . CompileFlags & NODE_IS_NAME_DECLARATION ) ) { NextOp = NextOp -> Asl . Next ; } NextOp -> Asl . Value . String = NewPath ; NextOp -> Asl . AmlLength = strlen ( NewPath ) ; } else { Op -> Asl . Value . String = NewPath ; Op -> Asl . AmlLength = strlen ( NewPath ) ; } } else { ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " " ) ) ; } ACPI_FREE ( TargetPath . Pointer ) ; ACPI_FREE ( CurrentPath . Pointer ) ; ACPI_DEBUG_PRINT_RAW ( ( ACPI_DB_OPTIMIZATIONS , " \n " ) ) ; return_VOID ; }
FUNCTION:    OptOptimizeNamePath
 PARAMETERS:  Op                  - Current parser op
              Flags               - Opcode info flags
              WalkState           - Current state
              AmlNameString       - Unoptimized namepath
              TargetNode          - Node to which AmlNameString refers
FUNCTION : OptOptimizeNamePath PARAMETERS : Op - Current parser op Flags - Opcode info flags WalkState - Current state AmlNameString - Unoptimized namepath TargetNode - Node to which AmlNameString refers
/* This is an optional optimization */ /* Various required items */ /* We don't want to fuss with actual name declaration nodes here */ /*
     * The original path must be longer than one NameSeg (4 chars) for there
     * to be any possibility that it can be optimized to a shorter string
     */ /*
     * We need to obtain the node that represents the current scope -- where
     * we are right now in the namespace. We will compare this path
     * against the Namepath, looking for commonality.
     */ /* This is the declaration of a new name */ /*
         * The node of interest is the parent of this node (the containing
         * scope). The actual namespace node may be up more than one level
         * of parse op or it may not exist at all (if we traverse back
         * up to the root.)
         */ /* This is a reference to an existing named object */ /*
     * Obtain the full paths to the two nodes that we are interested in
     * (Target and current namespace location) in external
     * format -- something we can easily manipulate
     */ /* Subtract one for null terminator */ /* CurrentPath is the path to this scope (where we are in the namespace) */ /* Subtract one for null terminator */ /* Debug output only */ /*
     * Attempt an optmization depending on the type of namepath
     */ /*
         * This is a named opcode and the namepath is a name declaration, not
         * a reference.
         */ /*
             * 2) now attempt to
             *    optimize the namestring with carats (up-arrow)
             */ /*
         * This is a reference to an existing named object
         *
         * 1) Check if search-to-root can be utilized using the last
         *    NameSeg of the NamePath
         */ /*
             * 2) Search-to-root could not be used, now attempt to
             *    optimize the namestring with carats (up-arrow)
             */ /*
     * Success from above indicates that the NamePath was successfully
     * optimized. We need to update the parse op with the new name
     */ /*
                 * ALIAS is the only oddball opcode, the name declaration
                 * (alias name) is the second operand
                 */ /* Name must appear as the last parameter */ /* Update the parse node with the new NamePath */ /* Update the parse node with the new NamePath */ /* Cleanup path buffers */