1 /******************************************************************************
   2  *
   3  * Module Name: aslopt- Compiler optimizations
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 
  45 #include "aslcompiler.h"
  46 #include "aslcompiler.y.h"
  47 
  48 #include "acparser.h"
  49 #include "amlcode.h"
  50 #include "acnamesp.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_COMPILER
  54         ACPI_MODULE_NAME    ("aslopt")
  55 
  56 
  57 static UINT32 OptTotal = 0;
  58 
  59 /* Local prototypes */
  60 
  61 static ACPI_STATUS
  62 OptSearchToRoot (
  63     ACPI_PARSE_OBJECT       *Op,
  64     ACPI_WALK_STATE         *WalkState,
  65     ACPI_NAMESPACE_NODE     *CurrentNode,
  66     ACPI_NAMESPACE_NODE     *TargetNode,
  67     ACPI_BUFFER             *TargetPath,
  68     char                    **NewPath);
  69 
  70 static ACPI_STATUS
  71 OptBuildShortestPath (
  72     ACPI_PARSE_OBJECT       *Op,
  73     ACPI_WALK_STATE         *WalkState,
  74     ACPI_NAMESPACE_NODE     *CurrentNode,
  75     ACPI_NAMESPACE_NODE     *TargetNode,
  76     ACPI_BUFFER             *CurrentPath,
  77     ACPI_BUFFER             *TargetPath,
  78     ACPI_SIZE               AmlNameStringLength,
  79     UINT8                   IsDeclaration,
  80     char                    **ReturnNewPath);
  81 
  82 static ACPI_STATUS
  83 OptOptimizeNameDeclaration (
  84     ACPI_PARSE_OBJECT       *Op,
  85     ACPI_WALK_STATE         *WalkState,
  86     ACPI_NAMESPACE_NODE     *CurrentNode,
  87     ACPI_NAMESPACE_NODE     *TargetNode,
  88     char                    *AmlNameString,
  89     char                    **NewPath);
  90 
  91 
  92 /*******************************************************************************
  93  *
  94  * FUNCTION:    OptSearchToRoot
  95  *
  96  * PARAMETERS:  Op                  - Current parser op
  97  *              WalkState           - Current state
  98  *              CurrentNode         - Where we are in the namespace
  99  *              TargetNode          - Node to which we are referring
 100  *              TargetPath          - External full path to the target node
 101  *              NewPath             - Where the optimized path is returned
 102  *
 103  * RETURN:      Status
 104  *
 105  * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI
 106  *              name utilizing the search-to-root name resolution algorithm
 107  *              that is used by AML interpreters.
 108  *
 109  ******************************************************************************/
 110 
 111 static ACPI_STATUS
 112 OptSearchToRoot (
 113     ACPI_PARSE_OBJECT       *Op,
 114     ACPI_WALK_STATE         *WalkState,
 115     ACPI_NAMESPACE_NODE     *CurrentNode,
 116     ACPI_NAMESPACE_NODE     *TargetNode,
 117     ACPI_BUFFER             *TargetPath,
 118     char                    **NewPath)
 119 {
 120     ACPI_NAMESPACE_NODE     *Node;
 121     ACPI_GENERIC_STATE      ScopeInfo;
 122     ACPI_STATUS             Status;
 123     char                    *Path;
 124 
 125 
 126     ACPI_FUNCTION_NAME (OptSearchToRoot);
 127 
 128 
 129     /*
 130      * Check if search-to-root can be utilized. Use the last NameSeg of
 131      * the NamePath and 1) See if can be found and 2) If found, make
 132      * sure that it is the same node that we want. If there is another
 133      * name in the search path before the one we want, the nodes will
 134      * not match, and we cannot use this optimization.
 135      */
 136     Path = &(((char *) TargetPath->Pointer)[TargetPath->Length -
 137                                             ACPI_NAME_SIZE]),
 138     ScopeInfo.Scope.Node = CurrentNode;
 139 
 140     /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */
 141 
 142     Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
 143                     ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
 144                     WalkState, &(Node));
 145     if (ACPI_FAILURE (Status))
 146     {
 147         return (Status);
 148     }
 149 
 150     /*
 151      * We found the name, but we must check to make sure that the node
 152      * matches. Otherwise, there is another identical name in the search
 153      * path that precludes the use of this optimization.
 154      */
 155     if (Node != TargetNode)
 156     {
 157         /*
 158          * This means that another object with the same name was found first,
 159          * and we cannot use this optimization.
 160          */
 161         return (AE_NOT_FOUND);
 162     }
 163 
 164     /* Found the node, we can use this optimization */
 165 
 166     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 167         "NAMESEG:   %-24s", Path));
 168 
 169     /* We must allocate a new string for the name (TargetPath gets deleted) */
 170 
 171     *NewPath = ACPI_ALLOCATE_ZEROED (ACPI_NAME_SIZE + 1);
 172     ACPI_STRCPY (*NewPath, Path);
 173 
 174     if (ACPI_STRNCMP (*NewPath, "_T_", 3))
 175     {
 176         AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op,
 177                 *NewPath);
 178     }
 179 
 180     return (AE_OK);
 181 }
 182 
 183 
 184 /*******************************************************************************
 185  *
 186  * FUNCTION:    OptBuildShortestPath
 187  *
 188  * PARAMETERS:  Op                  - Current parser op
 189  *              WalkState           - Current state
 190  *              CurrentNode         - Where we are in the namespace
 191  *              TargetNode          - Node to which we are referring
 192  *              CurrentPath         - External full path to the current node
 193  *              TargetPath          - External full path to the target node
 194  *              AmlNameStringLength - Length of the original namepath
 195  *              IsDeclaration       - TRUE for declaration, FALSE for reference
 196  *              ReturnNewPath       - Where the optimized path is returned
 197  *
 198  * RETURN:      Status
 199  *
 200  * DESCRIPTION: Build an optimal NamePath using carats
 201  *
 202  ******************************************************************************/
 203 
 204 static ACPI_STATUS
 205 OptBuildShortestPath (
 206     ACPI_PARSE_OBJECT       *Op,
 207     ACPI_WALK_STATE         *WalkState,
 208     ACPI_NAMESPACE_NODE     *CurrentNode,
 209     ACPI_NAMESPACE_NODE     *TargetNode,
 210     ACPI_BUFFER             *CurrentPath,
 211     ACPI_BUFFER             *TargetPath,
 212     ACPI_SIZE               AmlNameStringLength,
 213     UINT8                   IsDeclaration,
 214     char                    **ReturnNewPath)
 215 {
 216     UINT32                  NumCommonSegments;
 217     UINT32                  MaxCommonSegments;
 218     UINT32                  Index;
 219     UINT32                  NumCarats;
 220     UINT32                  i;
 221     char                    *NewPath;
 222     char                    *NewPathExternal;
 223     ACPI_NAMESPACE_NODE     *Node;
 224     ACPI_GENERIC_STATE      ScopeInfo;
 225     ACPI_STATUS             Status;
 226     BOOLEAN                 SubPath = FALSE;
 227 
 228 
 229     ACPI_FUNCTION_NAME (OptBuildShortestPath);
 230 
 231 
 232     ScopeInfo.Scope.Node = CurrentNode;
 233 
 234     /*
 235      * Determine the maximum number of NameSegs that the Target and Current paths
 236      * can possibly have in common. (To optimize, we have to have at least 1)
 237      *
 238      * Note: The external NamePath string lengths are always a multiple of 5
 239      * (ACPI_NAME_SIZE + separator)
 240      */
 241     MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
 242     if (CurrentPath->Length < TargetPath->Length)
 243     {
 244         MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
 245     }
 246 
 247     /*
 248      * Determine how many NameSegs the two paths have in common.
 249      * (Starting from the root)
 250      */
 251     for (NumCommonSegments = 0;
 252          NumCommonSegments < MaxCommonSegments;
 253          NumCommonSegments++)
 254     {
 255         /* Compare two single NameSegs */
 256 
 257         if (!ACPI_COMPARE_NAME (
 258             &((char *) TargetPath->Pointer)[
 259                 (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1],
 260             &((char *) CurrentPath->Pointer)[
 261                 (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1]))
 262         {
 263             /* Mismatch */
 264 
 265             break;
 266         }
 267     }
 268 
 269     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u",
 270         NumCommonSegments));
 271 
 272     /* There must be at least 1 common NameSeg in order to optimize */
 273 
 274     if (NumCommonSegments == 0)
 275     {
 276         return (AE_NOT_FOUND);
 277     }
 278 
 279     if (NumCommonSegments == MaxCommonSegments)
 280     {
 281         if (CurrentPath->Length == TargetPath->Length)
 282         {
 283             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
 284             return (AE_NOT_FOUND);
 285         }
 286         else
 287         {
 288             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
 289             SubPath = TRUE;
 290         }
 291     }
 292 
 293     /* Determine how many prefix Carats are required */
 294 
 295     NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
 296                 NumCommonSegments;
 297 
 298     /*
 299      * Construct a new target string
 300      */
 301     NewPathExternal = ACPI_ALLOCATE_ZEROED (
 302         TargetPath->Length + NumCarats + 1);
 303 
 304     /* Insert the Carats into the Target string */
 305 
 306     for (i = 0; i < NumCarats; i++)
 307     {
 308         NewPathExternal[i] = AML_PARENT_PREFIX;
 309     }
 310 
 311     /*
 312      * Copy only the necessary (optimal) segments from the original
 313      * target string
 314      */
 315     Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
 316 
 317     /* Special handling for exact subpath in a name declaration */
 318 
 319     if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length))
 320     {
 321         /*
 322          * The current path is longer than the target, and the target is a
 323          * subpath of the current path. We must include one more NameSeg of
 324          * the target path
 325          */
 326         Index -= ACPI_PATH_SEGMENT_LENGTH;
 327 
 328         /* Special handling for Scope() operator */
 329 
 330         if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
 331         {
 332             NewPathExternal[i] = AML_PARENT_PREFIX;
 333             i++;
 334             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
 335         }
 336     }
 337 
 338     /* Make sure we haven't gone off the end of the target path */
 339 
 340     if (Index > TargetPath->Length)
 341     {
 342         Index = TargetPath->Length;
 343     }
 344 
 345     ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]);
 346     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
 347 
 348     /*
 349      * Internalize the new target string and check it against the original
 350      * string to make sure that this is in fact an optimization. If the
 351      * original string is already optimal, there is no point in continuing.
 352      */
 353     Status = AcpiNsInternalizeName (NewPathExternal, &NewPath);
 354     if (ACPI_FAILURE (Status))
 355     {
 356         AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
 357             ASL_NO_ABORT);
 358         ACPI_FREE (NewPathExternal);
 359         return (Status);
 360     }
 361 
 362     if (ACPI_STRLEN (NewPath) >= AmlNameStringLength)
 363     {
 364         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 365             " NOT SHORTER (New %u old %u)",
 366             (UINT32) ACPI_STRLEN (NewPath), (UINT32) AmlNameStringLength));
 367         ACPI_FREE (NewPathExternal);
 368         return (AE_NOT_FOUND);
 369     }
 370 
 371     /*
 372      * Check to make sure that the optimization finds the node we are
 373      * looking for. This is simply a sanity check on the new
 374      * path that has been created.
 375      */
 376     Status = AcpiNsLookup (&ScopeInfo,  NewPath,
 377                     ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
 378                     ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
 379     if (ACPI_SUCCESS (Status))
 380     {
 381         /* Found the namepath, but make sure the node is correct */
 382 
 383         if (Node == TargetNode)
 384         {
 385             /* The lookup matched the node, accept this optimization */
 386 
 387             AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
 388                 Op, NewPathExternal);
 389             *ReturnNewPath = NewPath;
 390         }
 391         else
 392         {
 393             /* Node is not correct, do not use this optimization */
 394 
 395             Status = AE_NOT_FOUND;
 396             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
 397             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
 398                 "Not using optimized name - found wrong node");
 399         }
 400     }
 401     else
 402     {
 403         /* The lookup failed, we obviously cannot use this optimization */
 404 
 405         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
 406         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
 407             "Not using optimized name - did not find node");
 408     }
 409 
 410     ACPI_FREE (NewPathExternal);
 411     return (Status);
 412 }
 413 
 414 
 415 /*******************************************************************************
 416  *
 417  * FUNCTION:    OptOptimizeNameDeclaration
 418  *
 419  * PARAMETERS:  Op                  - Current parser op
 420  *              WalkState           - Current state
 421  *              CurrentNode         - Where we are in the namespace
 422  *              AmlNameString       - Unoptimized namepath
 423  *              NewPath             - Where the optimized path is returned
 424  *
 425  * RETURN:      Status. AE_OK If path is optimized
 426  *
 427  * DESCRIPTION: Perform a simple optimization of removing an extraneous
 428  *              backslash prefix if we are already at the root scope.
 429  *
 430  ******************************************************************************/
 431 
 432 static ACPI_STATUS
 433 OptOptimizeNameDeclaration (
 434     ACPI_PARSE_OBJECT       *Op,
 435     ACPI_WALK_STATE         *WalkState,
 436     ACPI_NAMESPACE_NODE     *CurrentNode,
 437     ACPI_NAMESPACE_NODE     *TargetNode,
 438     char                    *AmlNameString,
 439     char                    **NewPath)
 440 {
 441     ACPI_STATUS             Status;
 442     char                    *NewPathExternal;
 443     ACPI_NAMESPACE_NODE     *Node;
 444 
 445 
 446     ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration);
 447 
 448 
 449     if (((CurrentNode == AcpiGbl_RootNode) ||
 450         (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
 451             (ACPI_IS_ROOT_PREFIX (AmlNameString[0])))
 452     {
 453         /*
 454          * The current scope is the root, and the namepath has a root prefix
 455          * that is therefore extraneous. Remove it.
 456          */
 457         *NewPath = &AmlNameString[1];
 458 
 459         /* Debug output */
 460 
 461         Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
 462                     NULL, &NewPathExternal);
 463         if (ACPI_FAILURE (Status))
 464         {
 465             AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
 466                 ASL_NO_ABORT);
 467             return (Status);
 468         }
 469 
 470         /*
 471          * Check to make sure that the optimization finds the node we are
 472          * looking for. This is simply a sanity check on the new
 473          * path that has been created.
 474          *
 475          * We know that we are at the root, so NULL is used for the scope.
 476          */
 477         Status = AcpiNsLookup (NULL, *NewPath,
 478                         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
 479                         ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
 480         if (ACPI_SUCCESS (Status))
 481         {
 482             /* Found the namepath, but make sure the node is correct */
 483 
 484             if (Node == TargetNode)
 485             {
 486                 /* The lookup matched the node, accept this optimization */
 487 
 488                 AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
 489                     Op, NewPathExternal);
 490 
 491                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 492                     "AT ROOT:   %-24s", NewPathExternal));
 493             }
 494             else
 495             {
 496                 /* Node is not correct, do not use this optimization */
 497 
 498                 Status = AE_NOT_FOUND;
 499                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 500                     " ***** WRONG NODE"));
 501                 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
 502                     "Not using optimized name - found wrong node");
 503             }
 504         }
 505         else
 506         {
 507             /* The lookup failed, we obviously cannot use this optimization */
 508 
 509             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 510                 " ***** NOT FOUND"));
 511             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
 512                 "Not using optimized name - did not find node");
 513         }
 514 
 515         ACPI_FREE (NewPathExternal);
 516         return (Status);
 517     }
 518 
 519     /* Could not optimize */
 520 
 521     return (AE_NOT_FOUND);
 522 }
 523 
 524 
 525 /*******************************************************************************
 526  *
 527  * FUNCTION:    OptOptimizeNamePath
 528  *
 529  * PARAMETERS:  Op                  - Current parser op
 530  *              Flags               - Opcode info flags
 531  *              WalkState           - Current state
 532  *              AmlNameString       - Unoptimized namepath
 533  *              TargetNode          - Node to which AmlNameString refers
 534  *
 535  * RETURN:      None. If path is optimized, the Op is updated with new path
 536  *
 537  * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
 538  *              Must take into account both the current location in the
 539  *              namespace and the actual reference path.
 540  *
 541  ******************************************************************************/
 542 
 543 void
 544 OptOptimizeNamePath (
 545     ACPI_PARSE_OBJECT       *Op,
 546     UINT32                  Flags,
 547     ACPI_WALK_STATE         *WalkState,
 548     char                    *AmlNameString,
 549     ACPI_NAMESPACE_NODE     *TargetNode)
 550 {
 551     ACPI_STATUS             Status;
 552     ACPI_BUFFER             TargetPath;
 553     ACPI_BUFFER             CurrentPath;
 554     ACPI_SIZE               AmlNameStringLength;
 555     ACPI_NAMESPACE_NODE     *CurrentNode;
 556     char                    *ExternalNameString;
 557     char                    *NewPath = NULL;
 558     ACPI_SIZE               HowMuchShorter;
 559     ACPI_PARSE_OBJECT       *NextOp;
 560 
 561 
 562     ACPI_FUNCTION_TRACE (OptOptimizeNamePath);
 563 
 564 
 565     /* This is an optional optimization */
 566 
 567     if (!Gbl_ReferenceOptimizationFlag)
 568     {
 569         return_VOID;
 570     }
 571 
 572     /* Various required items */
 573 
 574     if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
 575     {
 576         return_VOID;
 577     }
 578 
 579     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 580         "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ",
 581         Op->Asl.LogicalLineNumber,
 582         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
 583         AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
 584 
 585     if (!(Flags & (AML_NAMED | AML_CREATE)))
 586     {
 587         if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
 588         {
 589             /* We don't want to fuss with actual name declaration nodes here */
 590 
 591             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 592                 "******* NAME DECLARATION\n"));
 593             return_VOID;
 594         }
 595     }
 596 
 597     /*
 598      * The original path must be longer than one NameSeg (4 chars) for there
 599      * to be any possibility that it can be optimized to a shorter string
 600      */
 601     AmlNameStringLength = ACPI_STRLEN (AmlNameString);
 602     if (AmlNameStringLength <= ACPI_NAME_SIZE)
 603     {
 604         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 605             "NAMESEG %4.4s\n", AmlNameString));
 606         return_VOID;
 607     }
 608 
 609     /*
 610      * We need to obtain the node that represents the current scope -- where
 611      * we are right now in the namespace. We will compare this path
 612      * against the Namepath, looking for commonality.
 613      */
 614     CurrentNode = AcpiGbl_RootNode;
 615     if (WalkState->ScopeInfo)
 616     {
 617         CurrentNode = WalkState->ScopeInfo->Scope.Node;
 618     }
 619 
 620     if (Flags & (AML_NAMED | AML_CREATE))
 621     {
 622         /* This is the declaration of a new name */
 623 
 624         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n"));
 625 
 626         /*
 627          * The node of interest is the parent of this node (the containing
 628          * scope). The actual namespace node may be up more than one level
 629          * of parse op or it may not exist at all (if we traverse back
 630          * up to the root.)
 631          */
 632         NextOp = Op->Asl.Parent;
 633         while (NextOp && (!NextOp->Asl.Node))
 634         {
 635             NextOp = NextOp->Asl.Parent;
 636         }
 637         if (NextOp && NextOp->Asl.Node)
 638         {
 639             CurrentNode = NextOp->Asl.Node;
 640         }
 641         else
 642         {
 643             CurrentNode = AcpiGbl_RootNode;
 644         }
 645     }
 646     else
 647     {
 648         /* This is a reference to an existing named object */
 649 
 650         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n"));
 651     }
 652 
 653     /*
 654      * Obtain the full paths to the two nodes that we are interested in
 655      * (Target and current namespace location) in external
 656      * format -- something we can easily manipulate
 657      */
 658     TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
 659     Status = AcpiNsHandleToPathname (TargetNode, &TargetPath);
 660     if (ACPI_FAILURE (Status))
 661     {
 662         AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
 663             ASL_NO_ABORT);
 664         return_VOID;
 665     }
 666     TargetPath.Length--;    /* Subtract one for null terminator */
 667 
 668     /* CurrentPath is the path to this scope (where we are in the namespace) */
 669 
 670     CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
 671     Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath);
 672     if (ACPI_FAILURE (Status))
 673     {
 674         AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
 675             ASL_NO_ABORT);
 676         return_VOID;
 677     }
 678     CurrentPath.Length--;   /* Subtract one for null terminator */
 679 
 680     /* Debug output only */
 681 
 682     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
 683                 NULL, &ExternalNameString);
 684     if (ACPI_FAILURE (Status))
 685     {
 686         AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
 687             ASL_NO_ABORT);
 688         return_VOID;
 689     }
 690 
 691     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 692         "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n",
 693         (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer,
 694         (UINT32) TargetPath.Length, (char *) TargetPath.Pointer,
 695         ExternalNameString));
 696 
 697     ACPI_FREE (ExternalNameString);
 698 
 699     /*
 700      * Attempt an optmization depending on the type of namepath
 701      */
 702     if (Flags & (AML_NAMED | AML_CREATE))
 703     {
 704         /*
 705          * This is a named opcode and the namepath is a name declaration, not
 706          * a reference.
 707          */
 708         Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
 709                     TargetNode, AmlNameString, &NewPath);
 710         if (ACPI_FAILURE (Status))
 711         {
 712             /*
 713              * 2) now attempt to
 714              *    optimize the namestring with carats (up-arrow)
 715              */
 716             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
 717                             TargetNode, &CurrentPath, &TargetPath,
 718                             AmlNameStringLength, 1, &NewPath);
 719         }
 720     }
 721     else
 722     {
 723         /*
 724          * This is a reference to an existing named object
 725          *
 726          * 1) Check if search-to-root can be utilized using the last
 727          *    NameSeg of the NamePath
 728          */
 729         Status = OptSearchToRoot (Op, WalkState, CurrentNode,
 730                         TargetNode, &TargetPath, &NewPath);
 731         if (ACPI_FAILURE (Status))
 732         {
 733             /*
 734              * 2) Search-to-root could not be used, now attempt to
 735              *    optimize the namestring with carats (up-arrow)
 736              */
 737             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
 738                             TargetNode, &CurrentPath, &TargetPath,
 739                             AmlNameStringLength, 0, &NewPath);
 740         }
 741     }
 742 
 743     /*
 744      * Success from above indicates that the NamePath was successfully
 745      * optimized. We need to update the parse op with the new name
 746      */
 747     if (ACPI_SUCCESS (Status))
 748     {
 749         HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath));
 750         OptTotal += HowMuchShorter;
 751 
 752         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
 753             " REDUCED BY %2u (TOTAL SAVED %2u)",
 754             (UINT32) HowMuchShorter, OptTotal));
 755 
 756         if (Flags & AML_NAMED)
 757         {
 758             if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
 759             {
 760                 /*
 761                  * ALIAS is the only oddball opcode, the name declaration
 762                  * (alias name) is the second operand
 763                  */
 764                 Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
 765                 Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath);
 766             }
 767             else
 768             {
 769                 Op->Asl.Child->Asl.Value.String = NewPath;
 770                 Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath);
 771             }
 772         }
 773         else if (Flags & AML_CREATE)
 774         {
 775             /* Name must appear as the last parameter */
 776 
 777             NextOp = Op->Asl.Child;
 778             while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
 779             {
 780                 NextOp = NextOp->Asl.Next;
 781             }
 782             /* Update the parse node with the new NamePath */
 783 
 784             NextOp->Asl.Value.String = NewPath;
 785             NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath);
 786         }
 787         else
 788         {
 789             /* Update the parse node with the new NamePath */
 790 
 791             Op->Asl.Value.String = NewPath;
 792             Op->Asl.AmlLength = ACPI_STRLEN (NewPath);
 793         }
 794     }
 795     else
 796     {
 797         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
 798     }
 799 
 800     /* Cleanup path buffers */
 801 
 802     ACPI_FREE (TargetPath.Pointer);
 803     ACPI_FREE (CurrentPath.Pointer);
 804 
 805     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
 806     return_VOID;
 807 }