Title: [127939] trunk/Source/_javascript_Core
Revision
127939
Author
[email protected]
Date
2012-09-07 16:59:10 -0700 (Fri, 07 Sep 2012)

Log Message

Refactored bytecode generator initialization to support moving captured vars around
https://bugs.webkit.org/show_bug.cgi?id=96159

Reviewed by Gavin Barraclough.

This patch separates the stages of allocating registers, declaring identifiers
in the symbol table, and initializing registers, so you can change
allocation decisions without breaking the world.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator): Call a set of helper functions
instead of inlining all the code, to help clarity.

(JSC::BytecodeGenerator::allocateCapturedVars):
(JSC::BytecodeGenerator::allocateUncapturedVars):
(JSC::BytecodeGenerator::allocateActivationVar):
(JSC::BytecodeGenerator::allocateArgumentsVars):
(JSC::BytecodeGenerator::allocateCalleeVarUndeclared):
(JSC::BytecodeGenerator::declareParameters):
(JSC::BytecodeGenerator::declareCallee):
(JSC::BytecodeGenerator::initCalleeVar):
(JSC::BytecodeGenerator::initArgumentsVars):
(JSC::BytecodeGenerator::initActivationVar):
(JSC::BytecodeGenerator::initThisParameter):
(JSC::BytecodeGenerator::initFunctionDeclarations):
(JSC::BytecodeGenerator::declareParameter):
(JSC::BytecodeGenerator::createLazyRegisterIfNecessary):
(JSC::BytecodeGenerator::createActivationIfNecessary): Factored these
helper functions out from pre-existing code.

* bytecompiler/BytecodeGenerator.h:
(BytecodeGenerator):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createFuncDeclStatement):
(JSC::ASTBuilder::addVar):
* parser/Nodes.h:
(JSC::DeclarationStacks::VarDeclaration::VarDeclaration):
(VarDeclaration):
(JSC::DeclarationStacks::FunctionDeclaration::FunctionDeclaration):
(FunctionDeclaration): Declaration stacks get a little more data now,
to support allocating registers before putting things in the symbol
table. I'm convinced that we should eventually just expand the symbol
table to understand these things.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (127938 => 127939)


--- trunk/Source/_javascript_Core/ChangeLog	2012-09-07 23:58:47 UTC (rev 127938)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-09-07 23:59:10 UTC (rev 127939)
@@ -1,3 +1,49 @@
+2012-09-07  Geoffrey Garen  <[email protected]>
+
+        Refactored bytecode generator initialization to support moving captured vars around
+        https://bugs.webkit.org/show_bug.cgi?id=96159
+
+        Reviewed by Gavin Barraclough.
+
+        This patch separates the stages of allocating registers, declaring identifiers
+        in the symbol table, and initializing registers, so you can change
+        allocation decisions without breaking the world.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator): Call a set of helper functions
+        instead of inlining all the code, to help clarity.
+
+        (JSC::BytecodeGenerator::allocateCapturedVars):
+        (JSC::BytecodeGenerator::allocateUncapturedVars):
+        (JSC::BytecodeGenerator::allocateActivationVar):
+        (JSC::BytecodeGenerator::allocateArgumentsVars):
+        (JSC::BytecodeGenerator::allocateCalleeVarUndeclared):
+        (JSC::BytecodeGenerator::declareParameters):
+        (JSC::BytecodeGenerator::declareCallee):
+        (JSC::BytecodeGenerator::initCalleeVar):
+        (JSC::BytecodeGenerator::initArgumentsVars):
+        (JSC::BytecodeGenerator::initActivationVar):
+        (JSC::BytecodeGenerator::initThisParameter):
+        (JSC::BytecodeGenerator::initFunctionDeclarations):
+        (JSC::BytecodeGenerator::declareParameter):
+        (JSC::BytecodeGenerator::createLazyRegisterIfNecessary):
+        (JSC::BytecodeGenerator::createActivationIfNecessary): Factored these
+        helper functions out from pre-existing code.
+
+        * bytecompiler/BytecodeGenerator.h:
+        (BytecodeGenerator):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createFuncDeclStatement):
+        (JSC::ASTBuilder::addVar):
+        * parser/Nodes.h:
+        (JSC::DeclarationStacks::VarDeclaration::VarDeclaration):
+        (VarDeclaration):
+        (JSC::DeclarationStacks::FunctionDeclaration::FunctionDeclaration):
+        (FunctionDeclaration): Declaration stacks get a little more data now,
+        to support allocating registers before putting things in the symbol
+        table. I'm convinced that we should eventually just expand the symbol
+        table to understand these things.
+
 2012-09-07  Mark Lam  <[email protected]>
 
         Fix a llint C++ interpreter bugs.

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (127938 => 127939)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2012-09-07 23:58:47 UTC (rev 127938)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2012-09-07 23:59:10 UTC (rev 127939)
@@ -278,9 +278,6 @@
     , m_codeType(GlobalCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
-    , m_hasCreatedActivation(true)
-    , m_firstLazyFunction(0)
-    , m_lastLazyFunction(0)
     , m_globalData(scope->globalData())
     , m_lastOpcodeID(op_end)
 #ifndef NDEBUG
@@ -320,7 +317,7 @@
     globalObject->addRegisters(newGlobals);
 
     for (size_t i = 0; i < functionStack.size(); ++i) {
-        FunctionBodyNode* function = functionStack[i];
+        FunctionBodyNode* function = functionStack[i].node;
         bool propertyDidExist = 
             globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
         
@@ -332,15 +329,239 @@
     }
 
     for (size_t i = 0; i < varStack.size(); ++i) {
-        if (globalObject->hasProperty(exec, *varStack[i].first))
+        if (globalObject->hasProperty(exec, *varStack[i].name))
             continue;
         addGlobalVar(
-            *varStack[i].first,
-            (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
+            *varStack[i].name,
+            (varStack[i].attributes & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
             NotFunctionOrNotSpecializable);
     }
 }
 
+void BytecodeGenerator::allocateCapturedVars()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+    if (!node->hasCapturedVariables())
+        return;
+
+    DeclarationStacks::FunctionStack& functionStack = node->functionStack();
+    for (size_t i = 0; i < functionStack.size(); ++i) {
+        if (!node->captures(functionStack[i].node->ident()))
+            continue;
+        functionStack[i].reg = addVar(functionStack[i].node->ident(), false);
+        m_functions.add(functionStack[i].node->ident().impl());
+    }
+
+    DeclarationStacks::VarStack& varStack = node->varStack();
+    for (size_t i = 0; i < varStack.size(); ++i) {
+        if (!node->captures(*varStack[i].name))
+            continue;
+        varStack[i].reg = addVar(*varStack[i].name, varStack[i].attributes & DeclarationStacks::IsConstant);
+    }
+}
+
+void BytecodeGenerator::allocateUncapturedVars()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    DeclarationStacks::FunctionStack& functionStack = node->functionStack();
+    for (size_t i = 0; i < functionStack.size(); ++i) {
+        if (node->captures(functionStack[i].node->ident()))
+            continue;
+        functionStack[i].reg = addVar(functionStack[i].node->ident(), false);
+        m_functions.add(functionStack[i].node->ident().impl());
+    }
+
+    DeclarationStacks::VarStack& varStack = node->varStack();
+    for (size_t i = 0; i < varStack.size(); ++i) {
+        if (node->captures(*varStack[i].name))
+            continue;
+        varStack[i].reg = addVar(*varStack[i].name, varStack[i].attributes & DeclarationStacks::IsConstant);
+    }
+}
+
+void BytecodeGenerator::allocateActivationVar()
+{
+    if (!m_codeBlock->needsFullScopeChain())
+        return;
+
+    m_activationRegister = addVar();
+    m_codeBlock->setActivationRegister(m_activationRegister->index());
+}
+
+void BytecodeGenerator::allocateArgumentsVars()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
+    // object, if created.
+    if (!m_codeBlock->needsFullScopeChain() && !node->usesArguments())
+        return;
+
+    RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
+    RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
+
+    // We can save a little space by hard-coding the knowledge that the two
+    // 'arguments' values are stored in consecutive registers, and storing
+    // only the index of the assignable one.
+    m_codeBlock->setArgumentsRegister(argumentsRegister->index());
+    ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister()));
+}
+
+void BytecodeGenerator::allocateCalleeVarUndeclared()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    if (node->ident().isNull() || !node->functionNameIsInScope())
+        return;
+
+    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
+    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
+        return;
+
+    if (!node->captures(node->ident())) {
+        m_calleeRegister.setIndex(RegisterFile::Callee);
+        return;
+    }
+
+    m_calleeRegister.setIndex(addVar()->index());
+}
+
+void BytecodeGenerator::declareParameters()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+    FunctionParameters& parameters = *node->parameters();
+    m_parameters.grow(parameters.size() + 1); // reserve space for "this"
+
+    // Add "this" as a parameter
+    int nextParameterIndex = CallFrame::thisArgumentOffset();
+    m_thisRegister.setIndex(nextParameterIndex--);
+    m_codeBlock->addParameter();
+    
+    for (size_t i = 0; i < parameters.size(); ++i)
+        declareParameter(parameters[i], nextParameterIndex--);
+}
+
+void BytecodeGenerator::declareCallee()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    if (node->ident().isNull() || !node->functionNameIsInScope())
+        return;
+
+    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
+    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
+        return;
+
+    symbolTable().add(node->ident().impl(), SymbolTableEntry(m_calleeRegister.index(), ReadOnly));
+}
+
+void BytecodeGenerator::initCalleeVar()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    if (node->ident().isNull() || !node->functionNameIsInScope())
+        return;
+
+    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
+    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
+        emitOpcode(op_push_name_scope);
+        instructions().append(addConstant(node->ident()));
+        instructions().append(RegisterFile::Callee);
+        instructions().append(ReadOnly | DontDelete);
+
+        // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
+        m_scope.set(*globalData(),
+            JSNameScope::create(
+                m_scope->globalObject()->globalExec(),
+                node->ident(),
+                jsUndefined(),
+                ReadOnly | DontDelete,
+                m_scope.get()
+            )
+        );
+
+        return;
+    }
+
+    if (!node->captures(node->ident()))
+        return;
+
+    // Move the callee into the captured section of the stack.
+    RegisterID callee(RegisterFile::Callee);
+    emitMove(&m_calleeRegister, &callee);
+}
+
+void BytecodeGenerator::initArgumentsVars()
+{
+    if (!m_codeBlock->usesArguments())
+        return;
+
+    int argumentsRegister = m_codeBlock->argumentsRegister();
+    int unmodifiedArgumentsRegister = JSC::unmodifiedArgumentsRegister(argumentsRegister);
+
+    prependComment("unmodified arguments");
+    emitInitLazyRegister(&registerFor(unmodifiedArgumentsRegister));
+    prependComment("arguments");
+    emitInitLazyRegister(&registerFor(argumentsRegister));
+
+    if ((m_codeBlock->usesArguments() && m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
+        emitOpcode(op_create_arguments);
+        instructions().append(m_codeBlock->argumentsRegister());
+    }
+}
+
+void BytecodeGenerator::initActivationVar()
+{
+    if (!m_codeBlock->needsFullScopeChain())
+        return;
+
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    emitInitLazyRegister(m_activationRegister);
+
+    bool canLazilyCreateFunctions = !node->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
+    if (canLazilyCreateFunctions)
+        return;
+
+    emitOpcode(op_create_activation);
+    instructions().append(m_activationRegister->index());
+}
+
+void BytecodeGenerator::initThisParameter()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    if (isConstructor()) {
+        prependComment("'this' because we are a Constructor function");
+        emitOpcode(op_create_this);
+        instructions().append(m_thisRegister.index());
+    } else if (!m_codeBlock->isStrictMode() && (node->usesThis() || m_codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
+        ValueProfile* profile = ""
+        instructions().append(m_thisRegister.index());
+        instructions().append(profile);
+    }
+}
+
+void BytecodeGenerator::initFunctionDeclarations()
+{
+    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
+
+    const DeclarationStacks::FunctionStack& functionStack = node->functionStack();
+    bool canLazilyCreateFunctions = !node->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
+    for (size_t i = 0; i < functionStack.size(); ++i) {
+        FunctionBodyNode* function = functionStack[i].node;
+        const Identifier& ident = function->ident();
+        RegisterID* reg = &registerFor(symbolTable().get(ident.impl()).getIndex());
+        if (node->captures(ident) || ident == propertyNames().arguments || !canLazilyCreateFunctions)
+            emitNewFunction(reg, function);
+        else {
+            emitInitLazyRegister(reg);
+            m_lazyFunctions.set(reg->index(), function);
+        }
+    }
+}
+
 BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, JSScope* scope, SymbolTable* symbolTable, CodeBlock* codeBlock, CompilationKind)
     : m_shouldEmitDebugHooks(scope->globalObject()->debugger())
     , m_shouldEmitProfileHooks(scope->globalObject()->globalObjectMethodTable()->supportsProfiling(scope->globalObject()))
@@ -359,9 +580,6 @@
     , m_codeType(FunctionCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
-    , m_hasCreatedActivation(false)
-    , m_firstLazyFunction(0)
-    , m_lastLazyFunction(0)
     , m_globalData(scope->globalData())
     , m_lastOpcodeID(op_end)
 #ifndef NDEBUG
@@ -376,142 +594,26 @@
         m_codeBlock->setNeedsFullScopeChain(true);
 
     codeBlock->setGlobalData(m_globalData);
-    
-    prependComment("entering Function block");
-    emitOpcode(op_enter);
-    if (m_codeBlock->needsFullScopeChain()) {
-        m_activationRegister = addVar();
-        prependComment("activation for Full Scope Chain");
-        emitInitLazyRegister(m_activationRegister);
-        m_codeBlock->setActivationRegister(m_activationRegister->index());
-    }
 
-    // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
-    // object, if created.
-    if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {
-        RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
-        RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
-
-        // We can save a little space by hard-coding the knowledge that the two
-        // 'arguments' values are stored in consecutive registers, and storing
-        // only the index of the assignable one.
-        codeBlock->setArgumentsRegister(argumentsRegister->index());
-        ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
-
-        prependComment("arguments for Full Scope Chain");
-        emitInitLazyRegister(argumentsRegister);
-        prependComment("unmodified arguments for Full Scope Chain");
-        emitInitLazyRegister(unmodifiedArgumentsRegister);
-        
-        if (m_codeBlock->isStrictMode()) {
-            prependComment("create arguments for strict mode");
-            emitOpcode(op_create_arguments);
-            instructions().append(argumentsRegister->index());
-        }
-
-        // The debugger currently retrieves the arguments object from an activation rather than pulling
-        // it from a call frame.  In the long-term it should stop doing that (<rdar://problem/6911886>),
-        // but for now we force eager creation of the arguments object when debugging.
-        if (m_shouldEmitDebugHooks) {
-            prependComment("create arguments for debug hooks");
-            emitOpcode(op_create_arguments);
-            instructions().append(argumentsRegister->index());
-        }
-    }
-
-    RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var.
-
-    const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
-    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
-
-    // Captured variables and functions go first so that activations don't have
-    // to step over the non-captured locals to mark them.
-    m_hasCreatedActivation = false;
-    if (functionBody->hasCapturedVariables()) {
-        for (size_t i = 0; i < functionStack.size(); ++i) {
-            FunctionBodyNode* function = functionStack[i];
-            const Identifier& ident = function->ident();
-            if (functionBody->captures(ident)) {
-                if (!m_hasCreatedActivation) {
-                    m_hasCreatedActivation = true;
-                    prependComment("activation for captured vars");
-                    emitOpcode(op_create_activation);
-                    instructions().append(m_activationRegister->index());
-                }
-                m_functions.add(ident.impl());
-                prependComment("captured function var");
-                emitNewFunction(addVar(ident, false), function);
-            }
-        }
-        for (size_t i = 0; i < varStack.size(); ++i) {
-            const Identifier& ident = *varStack[i].first;
-            if (functionBody->captures(ident))
-                addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
-        }
-    }
-    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
-    if (!canLazilyCreateFunctions && !m_hasCreatedActivation) {
-        m_hasCreatedActivation = true;
-        prependComment("cannot lazily create functions");
-        emitOpcode(op_create_activation);
-        instructions().append(m_activationRegister->index());
-    }
-
+    allocateArgumentsVars();
+    allocateActivationVar();
+    allocateCalleeVarUndeclared();
+    allocateCapturedVars();
     codeBlock->m_numCapturedVars = codeBlock->m_numVars;
-
-    m_firstLazyFunction = codeBlock->m_numVars;
-    for (size_t i = 0; i < functionStack.size(); ++i) {
-        FunctionBodyNode* function = functionStack[i];
-        const Identifier& ident = function->ident();
-        if (!functionBody->captures(ident)) {
-            m_functions.add(ident.impl());
-            RefPtr<RegisterID> reg = addVar(ident, false);
-            // Don't lazily create functions that override the name 'arguments'
-            // as this would complicate lazy instantiation of actual arguments.
-            prependComment("a function that override 'arguments'");
-            if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
-                emitNewFunction(reg.get(), function);
-            else {
-                emitInitLazyRegister(reg.get());
-                m_lazyFunctions.set(reg->index(), function);
-            }
-        }
-    }
-    m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
-    for (size_t i = 0; i < varStack.size(); ++i) {
-        const Identifier& ident = *varStack[i].first;
-        if (!functionBody->captures(ident))
-            addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
-    }
-
-    if (m_shouldEmitDebugHooks)
+    allocateUncapturedVars();
+    if (m_shouldEmitDebugHooks) // FIXME: What about eval?
         codeBlock->m_numCapturedVars = codeBlock->m_numVars;
-
-    FunctionParameters& parameters = *functionBody->parameters();
-    m_parameters.grow(parameters.size() + 1); // reserve space for "this"
-
-    // Add "this" as a parameter
-    int nextParameterIndex = CallFrame::thisArgumentOffset();
-    m_thisRegister.setIndex(nextParameterIndex--);
-    m_codeBlock->addParameter();
-    
-    for (size_t i = 0; i < parameters.size(); ++i)
-        addParameter(parameters[i], nextParameterIndex--);
-
     preserveLastVar();
 
-    // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration.
-    addCallee(functionBody, calleeRegister);
+    declareParameters(); // Parameters lose to functions
+    declareCallee(); // Callee loses to everything
 
-    if (isConstructor()) {
-        prependComment("'this' because we are a Constructor function");
-        emitOpcode(op_create_this);
-        instructions().append(m_thisRegister.index());
-    } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
-        ValueProfile* profile = ""
-        instructions().append(m_thisRegister.index());
-        instructions().append(profile);
-    }
+    emitOpcode(op_enter);
+    initArgumentsVars();
+    initActivationVar();
+    initCalleeVar();
+    initThisParameter();
+    initFunctionDeclarations();
 }
 
 BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, JSScope* scope, SymbolTable* symbolTable, EvalCodeBlock* codeBlock, CompilationKind)
@@ -532,9 +634,6 @@
     , m_codeType(EvalCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
-    , m_hasCreatedActivation(true)
-    , m_firstLazyFunction(0)
-    , m_lastLazyFunction(0)
     , m_globalData(scope->globalData())
     , m_lastOpcodeID(op_end)
 #ifndef NDEBUG
@@ -555,14 +654,14 @@
 
     const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i)
-        m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i]));
+        m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i].node));
 
     const DeclarationStacks::VarStack& varStack = evalNode->varStack();
     unsigned numVariables = varStack.size();
     Vector<Identifier> variables;
     variables.reserveCapacity(numVariables);
     for (size_t i = 0; i < numVariables; ++i)
-        variables.append(*varStack[i].first);
+        variables.append(*varStack[i].name);
     codeBlock->adoptVariables(variables);
     codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     preserveLastVar();
@@ -580,55 +679,8 @@
     return reg;
 }
 
-RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
+void BytecodeGenerator::declareParameter(const Identifier& ident, int parameterIndex)
 {
-    if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope())
-        return 0;
-
-    m_calleeRegister.setIndex(RegisterFile::Callee);
-
-    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
-    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
-        emitOpcode(op_push_name_scope);
-        instructions().append(addConstant(functionBodyNode->ident()));
-        instructions().append(m_calleeRegister.index());
-        instructions().append(ReadOnly | DontDelete);
-
-        // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
-        m_scope.set(*globalData(),
-            JSNameScope::create(
-                m_scope->globalObject()->globalExec(),
-                functionBodyNode->ident(),
-                jsUndefined(),
-                ReadOnly | DontDelete,
-                m_scope.get()
-            )
-        );
-        return 0;
-    }
-
-    if (!functionBodyNode->captures(functionBodyNode->ident()))
-        return &m_calleeRegister;
-
-    // Move the callee into the captured section of the stack.
-    return emitMove(addVar(), &m_calleeRegister);
-}
-
-void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister)
-{
-    if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope())
-        return;
-
-    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
-    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
-        return;
-
-    ASSERT(calleeRegister);
-    symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly));
-}
-
-void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex)
-{
     // Parameters overwrite var declarations, but not function declarations.
     StringImpl* rep = ident.impl();
     if (!m_functions.contains(rep)) {
@@ -671,9 +723,11 @@
 
 RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
 {
-    if (m_lastLazyFunction <= reg->index() || reg->index() < m_firstLazyFunction)
+    FunctionBodyNode* node = m_lazyFunctions.get(reg->index());
+    if (!node)
         return reg;
-    emitLazyNewFunction(reg, m_lazyFunctions.get(reg->index()));
+
+    emitLazyNewFunction(reg, node);
     return reg;
 }
 
@@ -1949,10 +2003,8 @@
 
 void BytecodeGenerator::createActivationIfNecessary()
 {
-    if (m_hasCreatedActivation)
+    if (!m_codeBlock->needsFullScopeChain() || m_codeType != FunctionCode)
         return;
-    if (!m_codeBlock->needsFullScopeChain())
-        return;
     emitOpcode(op_create_activation);
     instructions().append(m_activationRegister->index());
 }

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (127938 => 127939)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2012-09-07 23:58:47 UTC (rev 127938)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2012-09-07 23:59:10 UTC (rev 127939)
@@ -614,11 +614,22 @@
         // Returns the index of the added var.
         enum ConstantMode { IsConstant, IsVariable };
         enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
+        enum VarType { Captured, NotCaptured };
         int addGlobalVar(const Identifier&, ConstantMode, FunctionMode);
+        void declareParameter(const Identifier&, int parameterIndex);
 
-        void addParameter(const Identifier&, int parameterIndex);
-        RegisterID* resolveCallee(FunctionBodyNode*);
-        void addCallee(FunctionBodyNode*, RegisterID*);
+        void allocateCapturedVars();
+        void allocateUncapturedVars();
+        void allocateActivationVar();
+        void allocateArgumentsVars();
+        void allocateCalleeVarUndeclared();
+        void declareParameters();
+        void declareCallee();
+        void initCalleeVar();
+        void initArgumentsVars();
+        void initActivationVar();
+        void initThisParameter();
+        void initFunctionDeclarations();
 
         void preserveLastVar();
         bool shouldAvoidResolveGlobal();
@@ -738,9 +749,6 @@
 
         int m_globalVarStorageOffset;
 
-        bool m_hasCreatedActivation;
-        int m_firstLazyFunction;
-        int m_lastLazyFunction;
         HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
         typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
         FunctionOffsetMap m_functionOffsets;

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (127938 => 127939)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2012-09-07 23:58:47 UTC (rev 127938)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2012-09-07 23:59:10 UTC (rev 127939)
@@ -314,7 +314,7 @@
         FuncDeclNode* decl = new (m_globalData) FuncDeclNode(location, *name, body, m_sourceCode->subExpression(openBracePos, closeBracePos, bodyStartLine), parameters);
         if (*name == m_globalData->propertyNames->arguments)
             usesArguments();
-        m_scope.m_funcDeclarations->data.append(decl->body());
+        m_scope.m_funcDeclarations->data.append(DeclarationStacks::FunctionDeclaration(decl->body()));
         body->setLoc(bodyStartLine, bodyEndLine, location.column);
         return decl;
     }
@@ -508,7 +508,7 @@
     {
         if (m_globalData->propertyNames->arguments == *ident)
             usesArguments();
-        m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs));
+        m_scope.m_varDeclarations->data.append(DeclarationStacks::VarDeclaration(ident, attrs));
     }
 
     ExpressionNode* combineCommaNodes(const JSTokenLocation& location, ExpressionNode* list, ExpressionNode* init)

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (127938 => 127939)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2012-09-07 23:58:47 UTC (rev 127938)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2012-09-07 23:59:10 UTC (rev 127939)
@@ -85,9 +85,29 @@
     typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
 
     namespace DeclarationStacks {
+        struct VarDeclaration {
+            VarDeclaration(const Identifier* name, unsigned attributes)
+                : name(name)
+                , attributes(attributes)
+                , reg(0)
+            {
+            }
+            const Identifier* name;
+            unsigned attributes;
+            RegisterID* reg;
+        };
+        struct FunctionDeclaration {
+            explicit FunctionDeclaration(FunctionBodyNode* node)
+                : node(node)
+                , reg(0)
+            {
+            }
+            FunctionBodyNode* node;
+            RegisterID* reg;
+        };
         enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
-        typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
-        typedef Vector<FunctionBodyNode*> FunctionStack;
+        typedef Vector<VarDeclaration> VarStack;
+        typedef Vector<FunctionDeclaration> FunctionStack;
     }
 
     struct SwitchInfo {
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to