• rossberg@chromium.org's avatar
    Get rid of static module allocation, do it in code. · ce05280b
    rossberg@chromium.org authored
    Modules now have their own local scope, represented by their own context.
    Module instance objects have an accessor for every export that forwards
    access to the respective slot from the module's context. (Exports that are
    modules themselves, however, are simple data properties.)
    
    All modules have a _hosting_ scope/context, which (currently) is the
    (innermost) enclosing global scope. To deal with recursion, nested modules
    are hosted by the same scope as global ones.
    
    For every (global or nested) module literal, the hosting context has an
    internal slot that points directly to the respective module context. This
    enables quick access to (statically resolved) module members by 2-dimensional
    access through the hosting context. For example,
    
      module A {
        let x;
        module B { let y; }
      }
      module C { let z; }
    
    allocates contexts as follows:
    
    [header| .A | .B | .C | A | C ]  (global)
              |    |    |
              |    |    +-- [header| z ]  (module)
              |    |
              |    +------- [header| y ]  (module)
              |
              +------------ [header| x | B ]  (module)
    
    Here, .A, .B, .C are the internal slots pointing to the hosted module
    contexts, whereas A, B, C hold the actual instance objects (note that every
    module context also points to the respective instance object through its
    extension slot in the header).
    
    To deal with arbitrary recursion and aliases between modules,
    they are created and initialized in several stages. Each stage applies to
    all modules in the hosting global scope, including nested ones.
    
    1. Allocate: for each module _literal_, allocate the module contexts and
       respective instance object and wire them up. This happens in the
       PushModuleContext runtime function, as generated by AllocateModules
       (invoked by VisitDeclarations in the hosting scope).
    
    2. Bind: for each module _declaration_ (i.e. literals as well as aliases),
       assign the respective instance object to respective local variables. This
       happens in VisitModuleDeclaration, and uses the instance objects created
       in the previous stage.
       For each module _literal_, this phase also constructs a module descriptor
       for the next stage. This happens in VisitModuleLiteral.
    
    3. Populate: invoke the DeclareModules runtime function to populate each
       _instance_ object with accessors for it exports. This is generated by
       DeclareModules (invoked by VisitDeclarations in the hosting scope again),
       and uses the descriptors generated in the previous stage.
    
    4. Initialize: execute the module bodies (and other code) in sequence. This
       happens by the separate statements generated for module bodies. To reenter
       the module scopes properly, the parser inserted ModuleStatements.
    
    R=mstarzinger@chromium.org,svenpanne@chromium.org
    BUG=
    
    Review URL: https://codereview.chromium.org/11093074
    
    git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13033 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
    ce05280b
test-decls.cc 23.7 KB