aslopt.c revision 151937
1/******************************************************************************
2 *
3 * Module Name: aslopt- Compiler optimizations
4 *              $Revision: 1.21 $
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#include <contrib/dev/acpica/compiler/aslcompiler.h>
119#include "aslcompiler.y.h"
120
121#include <contrib/dev/acpica/acparser.h>
122#include <contrib/dev/acpica/amlcode.h>
123#include <contrib/dev/acpica/acnamesp.h>
124
125
126#define _COMPONENT          ACPI_COMPILER
127        ACPI_MODULE_NAME    ("aslopt")
128
129
130static UINT32 OptTotal = 0;
131
132/* Local prototypes */
133
134static ACPI_STATUS
135OptSearchToRoot (
136    ACPI_PARSE_OBJECT       *Op,
137    ACPI_WALK_STATE         *WalkState,
138    ACPI_NAMESPACE_NODE     *CurrentNode,
139    ACPI_NAMESPACE_NODE     *TargetNode,
140    ACPI_BUFFER             *TargetPath,
141    char                    **NewPath);
142
143static ACPI_STATUS
144OptBuildShortestPath (
145    ACPI_PARSE_OBJECT       *Op,
146    ACPI_WALK_STATE         *WalkState,
147    ACPI_NAMESPACE_NODE     *CurrentNode,
148    ACPI_NAMESPACE_NODE     *TargetNode,
149    ACPI_BUFFER             *CurrentPath,
150    ACPI_BUFFER             *TargetPath,
151    ACPI_SIZE               AmlNameStringLength,
152    UINT8                   IsDeclaration,
153    char                    **ReturnNewPath);
154
155static ACPI_STATUS
156OptOptimizeNameDeclaration (
157    ACPI_PARSE_OBJECT       *Op,
158    ACPI_WALK_STATE         *WalkState,
159    ACPI_NAMESPACE_NODE     *CurrentNode,
160    ACPI_NAMESPACE_NODE     *TargetNode,
161    char                    *AmlNameString,
162    char                    **NewPath);
163
164
165/*******************************************************************************
166 *
167 * FUNCTION:    OptSearchToRoot
168 *
169 * PARAMETERS:  Op                  - Current parser op
170 *              WalkState           - Current state
171 *              CurrentNode         - Where we are in the namespace
172 *              TargetNode          - Node to which we are referring
173 *              TargetPath          - External full path to the target node
174 *              NewPath             - Where the optimized path is returned
175 *
176 * RETURN:      Status
177 *
178 * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI
179 *              name utilizing the search-to-root name resolution algorithm
180 *              that is used by AML interpreters.
181 *
182 ******************************************************************************/
183
184static ACPI_STATUS
185OptSearchToRoot (
186    ACPI_PARSE_OBJECT       *Op,
187    ACPI_WALK_STATE         *WalkState,
188    ACPI_NAMESPACE_NODE     *CurrentNode,
189    ACPI_NAMESPACE_NODE     *TargetNode,
190    ACPI_BUFFER             *TargetPath,
191    char                    **NewPath)
192{
193    ACPI_NAMESPACE_NODE     *Node;
194    ACPI_GENERIC_STATE      ScopeInfo;
195    ACPI_STATUS             Status;
196    char                    *Path;
197
198
199    ACPI_FUNCTION_NAME ("OptSearchToRoot");
200
201
202    /*
203     * Check if search-to-root can be utilized.  Use the last NameSeg of
204     * the NamePath and 1) See if can be found and 2) If found, make
205     * sure that it is the same node that we want.  If there is another
206     * name in the search path before the one we want, the nodes will
207     * not match, and we cannot use this optimization.
208     */
209    Path = &(((char *) TargetPath->Pointer)[TargetPath->Length -
210                                            ACPI_NAME_SIZE]),
211    ScopeInfo.Scope.Node = CurrentNode;
212
213    /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */
214
215    Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
216                    ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
217                    WalkState, &(Node));
218    if (ACPI_FAILURE (Status))
219    {
220        return (Status);
221    }
222
223    /*
224     * We found the name, but we must check to make sure that the node
225     * matches.  Otherwise, there is another identical name in the search
226     * path that precludes the use of this optimization.
227     */
228    if (Node != TargetNode)
229    {
230        /*
231         * This means that another object with the same name was found first,
232         * and we cannot use this optimization.
233         */
234        return (AE_NOT_FOUND);
235    }
236
237    /* Found the node, we can use this optimization */
238
239    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
240        "NAMESEG:   %-24s", Path));
241
242    /* We must allocate a new string for the name (TargetPath gets deleted) */
243
244    *NewPath = ACPI_MEM_CALLOCATE (ACPI_NAME_SIZE + 1);
245    ACPI_STRCPY (*NewPath, Path);
246
247    if (ACPI_STRNCMP (*NewPath, "_T_", 3))
248    {
249        AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op,
250                *NewPath);
251    }
252
253    return (AE_OK);
254}
255
256
257/*******************************************************************************
258 *
259 * FUNCTION:    OptBuildShortestPath
260 *
261 * PARAMETERS:  Op                  - Current parser op
262 *              WalkState           - Current state
263 *              CurrentNode         - Where we are in the namespace
264 *              TargetNode          - Node to which we are referring
265 *              CurrentPath         - External full path to the current node
266 *              TargetPath          - External full path to the target node
267 *              AmlNameStringLength - Length of the original namepath
268 *              IsDeclaration       - TRUE for declaration, FALSE for reference
269 *              ReturnNewPath       - Where the optimized path is returned
270 *
271 * RETURN:      Status
272 *
273 * DESCRIPTION: Build an optimal NamePath using carats
274 *
275 ******************************************************************************/
276
277static ACPI_STATUS
278OptBuildShortestPath (
279    ACPI_PARSE_OBJECT       *Op,
280    ACPI_WALK_STATE         *WalkState,
281    ACPI_NAMESPACE_NODE     *CurrentNode,
282    ACPI_NAMESPACE_NODE     *TargetNode,
283    ACPI_BUFFER             *CurrentPath,
284    ACPI_BUFFER             *TargetPath,
285    ACPI_SIZE               AmlNameStringLength,
286    UINT8                   IsDeclaration,
287    char                    **ReturnNewPath)
288{
289    UINT32                  NumCommonSegments;
290    UINT32                  MaxCommonSegments;
291    ACPI_NATIVE_UINT        Index;
292    UINT32                  NumCarats;
293    ACPI_NATIVE_UINT        i;
294    char                    *NewPath;
295    char                    *NewPathExternal;
296    ACPI_NAMESPACE_NODE     *Node;
297    ACPI_GENERIC_STATE      ScopeInfo;
298    ACPI_STATUS             Status;
299    BOOLEAN                 SubPath = FALSE;
300
301
302    ACPI_FUNCTION_NAME ("OptBuildShortestPath");
303
304
305    ScopeInfo.Scope.Node = CurrentNode;
306
307    /*
308     * Determine the maximum number of NameSegs that the Target and Current paths
309     * can possibly have in common.  (To optimize, we have to have at least 1)
310     *
311     * Note: The external NamePath string lengths are always a multiple of 5
312     * (ACPI_NAME_SIZE + separator)
313     */
314    MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
315    if (CurrentPath->Length < TargetPath->Length)
316    {
317        MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
318    }
319
320    /*
321     * Determine how many NameSegs the two paths have in common.
322     * (Starting from the root)
323     */
324    for (NumCommonSegments = 0;
325         NumCommonSegments < MaxCommonSegments;
326         NumCommonSegments++)
327    {
328        /* Compare two single NameSegs */
329
330        if (ACPI_STRNCMP (
331            &((char *) TargetPath->Pointer)[(NumCommonSegments *
332                                             ACPI_PATH_SEGMENT_LENGTH) + 1],
333            &((char *) CurrentPath->Pointer)[(NumCommonSegments *
334                                              ACPI_PATH_SEGMENT_LENGTH) + 1],
335            ACPI_NAME_SIZE))
336        {
337            /* Mismatch */
338
339            break;
340        }
341    }
342
343    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %d",
344        NumCommonSegments));
345
346    /* There must be at least 1 common NameSeg in order to optimize */
347
348    if (NumCommonSegments == 0)
349    {
350        return (AE_NOT_FOUND);
351    }
352
353    if (NumCommonSegments == MaxCommonSegments)
354    {
355        if (CurrentPath->Length == TargetPath->Length)
356        {
357            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
358            return (AE_NOT_FOUND);
359        }
360        else
361        {
362            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
363            SubPath = TRUE;
364        }
365    }
366
367    /* Determine how many prefix Carats are required */
368
369    NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
370                NumCommonSegments;
371
372    /*
373     * Construct a new target string
374     */
375    NewPathExternal = ACPI_MEM_CALLOCATE (TargetPath->Length + NumCarats + 1);
376
377    /* Insert the Carats into the Target string */
378
379    for (i = 0; i < NumCarats; i++)
380    {
381        NewPathExternal[i] = '^';
382    }
383
384    /*
385     * Copy only the necessary (optimal) segments from the original
386     * target string
387     */
388    Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
389
390    /* Special handling for exact subpath in a name declaration */
391
392    if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length))
393    {
394        /*
395         * The current path is longer than the target, and the target is a
396         * subpath of the current path. We must include one more NameSeg of
397         * the target path
398         */
399        Index -= ACPI_PATH_SEGMENT_LENGTH;
400
401        /* Special handling for Scope() operator */
402
403        if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
404        {
405            NewPathExternal[i] = '^';
406            i++;
407            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
408        }
409    }
410
411    /* Make sure we haven't gone off the end of the target path */
412
413    if (Index > TargetPath->Length)
414    {
415        Index = TargetPath->Length;
416    }
417
418
419    ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]);
420    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
421
422    /*
423     * Internalize the new target string and check it against the original
424     * string to make sure that this is in fact an optimization. If the
425     * original string is already optimal, there is no point in continuing.
426     */
427    Status = AcpiNsInternalizeName (NewPathExternal, &NewPath);
428
429    if (ACPI_FAILURE (Status))
430    {
431        AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
432            ASL_NO_ABORT);
433        ACPI_MEM_FREE (NewPathExternal);
434        return (Status);
435    }
436
437    if (ACPI_STRLEN (NewPath) >= AmlNameStringLength)
438    {
439        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
440            " NOT SHORTER (New %d old %d)",
441            ACPI_STRLEN (NewPath), AmlNameStringLength));
442        ACPI_MEM_FREE (NewPathExternal);
443        return (AE_NOT_FOUND);
444    }
445
446    /*
447     * Check to make sure that the optimization finds the node we are
448     * looking for.  This is simply a sanity check on the new
449     * path that has been created.
450     */
451    Status = AcpiNsLookup (&ScopeInfo,  NewPath,
452                    ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
453                    ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
454    if (ACPI_SUCCESS (Status))
455    {
456        /* Found the namepath, but make sure the node is correct */
457
458        if (Node == TargetNode)
459        {
460            /* The lookup matched the node, accept this optimization */
461
462            AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
463                Op, NewPathExternal);
464            *ReturnNewPath = NewPath;
465        }
466        else
467        {
468            /* Node is not correct, do not use this optimization */
469
470            Status = AE_NOT_FOUND;
471            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
472            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
473                "Not using optimized name - found wrong node");
474        }
475    }
476    else
477    {
478        /* The lookup failed, we obviously cannot use this optimization */
479
480        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
481        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
482            "Not using optimized name - did not find node");
483    }
484
485    ACPI_MEM_FREE (NewPathExternal);
486    return (Status);
487}
488
489
490/*******************************************************************************
491 *
492 * FUNCTION:    OptOptimizeNameDeclaration
493 *
494 * PARAMETERS:  Op                  - Current parser op
495 *              WalkState           - Current state
496 *              CurrentNode         - Where we are in the namespace
497 *              AmlNameString       - Unoptimized namepath
498 *              NewPath             - Where the optimized path is returned
499 *
500 * RETURN:      Status. AE_OK If path is optimized
501 *
502 * DESCRIPTION: Perform a simple optimization of removing an extraneous
503 *              backslash prefix if we are already at the root scope.
504 *
505 ******************************************************************************/
506
507static ACPI_STATUS
508OptOptimizeNameDeclaration (
509    ACPI_PARSE_OBJECT       *Op,
510    ACPI_WALK_STATE         *WalkState,
511    ACPI_NAMESPACE_NODE     *CurrentNode,
512    ACPI_NAMESPACE_NODE     *TargetNode,
513    char                    *AmlNameString,
514    char                    **NewPath)
515{
516    ACPI_STATUS             Status;
517    char                    *NewPathExternal;
518    ACPI_GENERIC_STATE      ScopeInfo;
519    ACPI_NAMESPACE_NODE     *Node;
520
521
522    ACPI_FUNCTION_TRACE ("OptOptimizeNameDeclaration");
523
524
525    if (((CurrentNode == AcpiGbl_RootNode) ||
526        (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
527            (AmlNameString[0] == '\\'))
528    {
529        /*
530         * The current scope is the root, and the namepath has a root prefix
531         * that is therefore extraneous.  Remove it.
532         */
533        *NewPath = &AmlNameString[1];
534
535        /* Debug output */
536
537        Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
538                    NULL, &NewPathExternal);
539        if (ACPI_FAILURE (Status))
540        {
541            AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
542                ASL_NO_ABORT);
543            return (Status);
544        }
545
546        /*
547         * Check to make sure that the optimization finds the node we are
548         * looking for.  This is simply a sanity check on the new
549         * path that has been created.
550         */
551        ScopeInfo.Scope.Node = CurrentNode;
552        Status = AcpiNsLookup (&ScopeInfo, *NewPath,
553                        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
554                        ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
555        if (ACPI_SUCCESS (Status))
556        {
557            /* Found the namepath, but make sure the node is correct */
558
559            if (Node == TargetNode)
560            {
561                /* The lookup matched the node, accept this optimization */
562
563                AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
564                    Op, NewPathExternal);
565
566                ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
567                    "AT ROOT:   %-24s", NewPathExternal));
568            }
569            else
570            {
571                /* Node is not correct, do not use this optimization */
572
573                Status = AE_NOT_FOUND;
574                ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
575                    " ***** WRONG NODE"));
576                AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
577                    "Not using optimized name - found wrong node");
578            }
579        }
580        else
581        {
582            /* The lookup failed, we obviously cannot use this optimization */
583
584            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
585                " ***** NOT FOUND"));
586            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
587                "Not using optimized name - did not find node");
588        }
589
590        ACPI_MEM_FREE (NewPathExternal);
591        return (Status);
592    }
593
594    /* Could not optimize */
595
596    return (AE_NOT_FOUND);
597}
598
599
600/*******************************************************************************
601 *
602 * FUNCTION:    OptOptimizeNamePath
603 *
604 * PARAMETERS:  Op                  - Current parser op
605 *              Flags               - Opcode info flags
606 *              WalkState           - Current state
607 *              AmlNameString       - Unoptimized namepath
608 *              TargetNode          - Node to which AmlNameString refers
609 *
610 * RETURN:      None.  If path is optimized, the Op is updated with new path
611 *
612 * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
613 *              Must take into account both the current location in the
614 *              namespace and the actual reference path.
615 *
616 ******************************************************************************/
617
618void
619OptOptimizeNamePath (
620    ACPI_PARSE_OBJECT       *Op,
621    UINT32                  Flags,
622    ACPI_WALK_STATE         *WalkState,
623    char                    *AmlNameString,
624    ACPI_NAMESPACE_NODE     *TargetNode)
625{
626    ACPI_STATUS             Status;
627    ACPI_BUFFER             TargetPath;
628    ACPI_BUFFER             CurrentPath;
629    ACPI_SIZE               AmlNameStringLength;
630    ACPI_NAMESPACE_NODE     *CurrentNode;
631    char                    *ExternalNameString;
632    char                    *NewPath = NULL;
633    ACPI_SIZE               HowMuchShorter;
634    ACPI_PARSE_OBJECT       *NextOp;
635
636
637    ACPI_FUNCTION_TRACE ("OptOptimizeNamePath");
638
639
640    /* This is an optional optimization */
641
642    if (!Gbl_ReferenceOptimizationFlag)
643    {
644        return_VOID;
645    }
646
647    /* Various required items */
648
649    if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
650    {
651        return_VOID;
652    }
653
654    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "%5d [%12.12s] [%12.12s] ",
655        Op->Asl.LogicalLineNumber,
656        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
657        AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
658
659    if (!(Flags & (AML_NAMED | AML_CREATE)))
660    {
661        if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
662        {
663            /* We don't want to fuss with actual name declaration nodes here */
664
665            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
666                "******* NAME DECLARATION\n"));
667            return_VOID;
668        }
669    }
670
671    /*
672     * The original path must be longer than one NameSeg (4 chars) for there
673     * to be any possibility that it can be optimized to a shorter string
674     */
675    AmlNameStringLength = ACPI_STRLEN (AmlNameString);
676    if (AmlNameStringLength <= ACPI_NAME_SIZE)
677    {
678        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
679            "NAMESEG %4.4s\n", AmlNameString));
680        return_VOID;
681    }
682
683    /*
684     * We need to obtain the node that represents the current scope -- where
685     * we are right now in the namespace.  We will compare this path
686     * against the Namepath, looking for commonality.
687     */
688    CurrentNode = AcpiGbl_RootNode;
689    if (WalkState->ScopeInfo)
690    {
691        CurrentNode = WalkState->ScopeInfo->Scope.Node;
692    }
693
694    if (Flags & (AML_NAMED | AML_CREATE))
695    {
696        /* This is the declaration of a new name */
697
698        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME"));
699
700        /*
701         * The node of interest is the parent of this node
702         * (the containing scope)
703         */
704        CurrentNode = Op->Asl.Parent->Asl.Node;
705        if (!CurrentNode)
706        {
707            CurrentNode = AcpiGbl_RootNode;
708        }
709    }
710    else
711    {
712        /* This is a reference to an existing named object */
713
714        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REF "));
715    }
716
717    /*
718     * Obtain the full paths to the two nodes that we are interested in
719     * (Target and current namespace location) in external
720     * format -- something we can easily manipulate
721     */
722    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
723    Status = AcpiNsHandleToPathname (TargetNode, &TargetPath);
724    if (ACPI_FAILURE (Status))
725    {
726        AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
727            ASL_NO_ABORT);
728        return_VOID;
729    }
730    TargetPath.Length--;    /* Subtract one for null terminator */
731
732    /* CurrentPath is the path to this scope (where we are in the namespace) */
733
734    CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
735    Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath);
736    if (ACPI_FAILURE (Status))
737    {
738        AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
739            ASL_NO_ABORT);
740        return_VOID;
741    }
742    CurrentPath.Length--;   /* Subtract one for null terminator */
743
744    /* Debug output only */
745
746    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
747                NULL, &ExternalNameString);
748    if (ACPI_FAILURE (Status))
749    {
750        AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
751            ASL_NO_ABORT);
752        return_VOID;
753    }
754
755    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
756        "%37s (%2d) ==> %-32s(%2d) %-32s",
757        (char *) CurrentPath.Pointer, CurrentPath.Length,
758        (char *) TargetPath.Pointer, TargetPath.Length, ExternalNameString));
759
760    ACPI_MEM_FREE (ExternalNameString);
761
762    /*
763     * Attempt an optmization depending on the type of namepath
764     */
765    if (Flags & (AML_NAMED | AML_CREATE))
766    {
767        /*
768         * This is a named opcode and the namepath is a name declaration, not
769         * a reference.
770         */
771        Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
772                    TargetNode, AmlNameString, &NewPath);
773        if (ACPI_FAILURE (Status))
774        {
775            /*
776             * 2) now attempt to
777             *    optimize the namestring with carats (up-arrow)
778             */
779            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
780                            TargetNode, &CurrentPath, &TargetPath,
781                            AmlNameStringLength, 1, &NewPath);
782        }
783    }
784    else
785    {
786        /*
787         * This is a reference to an existing named object
788         *
789         * 1) Check if search-to-root can be utilized using the last
790         *    NameSeg of the NamePath
791         */
792        Status = OptSearchToRoot (Op, WalkState, CurrentNode,
793                        TargetNode, &TargetPath, &NewPath);
794        if (ACPI_FAILURE (Status))
795        {
796            /*
797             * 2) Search-to-root could not be used, now attempt to
798             *    optimize the namestring with carats (up-arrow)
799             */
800            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
801                            TargetNode, &CurrentPath, &TargetPath,
802                            AmlNameStringLength, 0, &NewPath);
803        }
804    }
805
806    /*
807     * Success from above indicates that the NamePath was successfully
808     * optimized.  We need to update the parse op with the new name
809     */
810    if (ACPI_SUCCESS (Status))
811    {
812        HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath));
813        OptTotal += HowMuchShorter;
814
815        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " REDUCED %2d (%d)",
816            HowMuchShorter, OptTotal));
817
818        if (Flags & AML_NAMED)
819        {
820            if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
821            {
822                /*
823                 * ALIAS is the only oddball opcode, the name declaration
824                 * (alias name) is the second operand
825                 */
826                Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
827                Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath);
828            }
829            else
830            {
831                Op->Asl.Child->Asl.Value.String = NewPath;
832                Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath);
833            }
834        }
835        else if (Flags & AML_CREATE)
836        {
837            /* Name must appear as the last parameter */
838
839            NextOp = Op->Asl.Child;
840            while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
841            {
842                NextOp = NextOp->Asl.Next;
843            }
844            /* Update the parse node with the new NamePath */
845
846            NextOp->Asl.Value.String = NewPath;
847            NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath);
848        }
849        else
850        {
851            /* Update the parse node with the new NamePath */
852
853            Op->Asl.Value.String = NewPath;
854            Op->Asl.AmlLength = ACPI_STRLEN (NewPath);
855        }
856    }
857    else
858    {
859        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
860    }
861
862    /* Cleanup path buffers */
863
864    ACPI_MEM_FREE (TargetPath.Pointer);
865    ACPI_MEM_FREE (CurrentPath.Pointer);
866
867    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
868    return_VOID;
869}
870
871