Changeset 127939 in webkit


Ignore:
Timestamp:
Sep 7, 2012, 4:59:10 PM (13 years ago)
Author:
[email protected]
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.

Location:
trunk/Source/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r127938 r127939  
     12012-09-07  Geoffrey Garen  <[email protected]>
     2
     3        Refactored bytecode generator initialization to support moving captured vars around
     4        https://bugs.webkit.org/show_bug.cgi?id=96159
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        This patch separates the stages of allocating registers, declaring identifiers
     9        in the symbol table, and initializing registers, so you can change
     10        allocation decisions without breaking the world.
     11
     12        * bytecompiler/BytecodeGenerator.cpp:
     13        (JSC::BytecodeGenerator::BytecodeGenerator): Call a set of helper functions
     14        instead of inlining all the code, to help clarity.
     15
     16        (JSC::BytecodeGenerator::allocateCapturedVars):
     17        (JSC::BytecodeGenerator::allocateUncapturedVars):
     18        (JSC::BytecodeGenerator::allocateActivationVar):
     19        (JSC::BytecodeGenerator::allocateArgumentsVars):
     20        (JSC::BytecodeGenerator::allocateCalleeVarUndeclared):
     21        (JSC::BytecodeGenerator::declareParameters):
     22        (JSC::BytecodeGenerator::declareCallee):
     23        (JSC::BytecodeGenerator::initCalleeVar):
     24        (JSC::BytecodeGenerator::initArgumentsVars):
     25        (JSC::BytecodeGenerator::initActivationVar):
     26        (JSC::BytecodeGenerator::initThisParameter):
     27        (JSC::BytecodeGenerator::initFunctionDeclarations):
     28        (JSC::BytecodeGenerator::declareParameter):
     29        (JSC::BytecodeGenerator::createLazyRegisterIfNecessary):
     30        (JSC::BytecodeGenerator::createActivationIfNecessary): Factored these
     31        helper functions out from pre-existing code.
     32
     33        * bytecompiler/BytecodeGenerator.h:
     34        (BytecodeGenerator):
     35        * parser/ASTBuilder.h:
     36        (JSC::ASTBuilder::createFuncDeclStatement):
     37        (JSC::ASTBuilder::addVar):
     38        * parser/Nodes.h:
     39        (JSC::DeclarationStacks::VarDeclaration::VarDeclaration):
     40        (VarDeclaration):
     41        (JSC::DeclarationStacks::FunctionDeclaration::FunctionDeclaration):
     42        (FunctionDeclaration): Declaration stacks get a little more data now,
     43        to support allocating registers before putting things in the symbol
     44        table. I'm convinced that we should eventually just expand the symbol
     45        table to understand these things.
     46
    1472012-09-07  Mark Lam  <[email protected]>
    248
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r127810 r127939  
    279279    , m_nextConstantOffset(0)
    280280    , m_globalConstantIndex(0)
    281     , m_hasCreatedActivation(true)
    282     , m_firstLazyFunction(0)
    283     , m_lastLazyFunction(0)
    284281    , m_globalData(scope->globalData())
    285282    , m_lastOpcodeID(op_end)
     
    321318
    322319    for (size_t i = 0; i < functionStack.size(); ++i) {
    323         FunctionBodyNode* function = functionStack[i];
     320        FunctionBodyNode* function = functionStack[i].node;
    324321        bool propertyDidExist =
    325322            globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties.
     
    333330
    334331    for (size_t i = 0; i < varStack.size(); ++i) {
    335         if (globalObject->hasProperty(exec, *varStack[i].first))
     332        if (globalObject->hasProperty(exec, *varStack[i].name))
    336333            continue;
    337334        addGlobalVar(
    338             *varStack[i].first,
    339             (varStack[i].second & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
     335            *varStack[i].name,
     336            (varStack[i].attributes & DeclarationStacks::IsConstant) ? IsConstant : IsVariable,
    340337            NotFunctionOrNotSpecializable);
     338    }
     339}
     340
     341void BytecodeGenerator::allocateCapturedVars()
     342{
     343    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     344    if (!node->hasCapturedVariables())
     345        return;
     346
     347    DeclarationStacks::FunctionStack& functionStack = node->functionStack();
     348    for (size_t i = 0; i < functionStack.size(); ++i) {
     349        if (!node->captures(functionStack[i].node->ident()))
     350            continue;
     351        functionStack[i].reg = addVar(functionStack[i].node->ident(), false);
     352        m_functions.add(functionStack[i].node->ident().impl());
     353    }
     354
     355    DeclarationStacks::VarStack& varStack = node->varStack();
     356    for (size_t i = 0; i < varStack.size(); ++i) {
     357        if (!node->captures(*varStack[i].name))
     358            continue;
     359        varStack[i].reg = addVar(*varStack[i].name, varStack[i].attributes & DeclarationStacks::IsConstant);
     360    }
     361}
     362
     363void BytecodeGenerator::allocateUncapturedVars()
     364{
     365    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     366
     367    DeclarationStacks::FunctionStack& functionStack = node->functionStack();
     368    for (size_t i = 0; i < functionStack.size(); ++i) {
     369        if (node->captures(functionStack[i].node->ident()))
     370            continue;
     371        functionStack[i].reg = addVar(functionStack[i].node->ident(), false);
     372        m_functions.add(functionStack[i].node->ident().impl());
     373    }
     374
     375    DeclarationStacks::VarStack& varStack = node->varStack();
     376    for (size_t i = 0; i < varStack.size(); ++i) {
     377        if (node->captures(*varStack[i].name))
     378            continue;
     379        varStack[i].reg = addVar(*varStack[i].name, varStack[i].attributes & DeclarationStacks::IsConstant);
     380    }
     381}
     382
     383void BytecodeGenerator::allocateActivationVar()
     384{
     385    if (!m_codeBlock->needsFullScopeChain())
     386        return;
     387
     388    m_activationRegister = addVar();
     389    m_codeBlock->setActivationRegister(m_activationRegister->index());
     390}
     391
     392void BytecodeGenerator::allocateArgumentsVars()
     393{
     394    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     395
     396    // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
     397    // object, if created.
     398    if (!m_codeBlock->needsFullScopeChain() && !node->usesArguments())
     399        return;
     400
     401    RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
     402    RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
     403
     404    // We can save a little space by hard-coding the knowledge that the two
     405    // 'arguments' values are stored in consecutive registers, and storing
     406    // only the index of the assignable one.
     407    m_codeBlock->setArgumentsRegister(argumentsRegister->index());
     408    ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister()));
     409}
     410
     411void BytecodeGenerator::allocateCalleeVarUndeclared()
     412{
     413    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     414
     415    if (node->ident().isNull() || !node->functionNameIsInScope())
     416        return;
     417
     418    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
     419    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
     420        return;
     421
     422    if (!node->captures(node->ident())) {
     423        m_calleeRegister.setIndex(RegisterFile::Callee);
     424        return;
     425    }
     426
     427    m_calleeRegister.setIndex(addVar()->index());
     428}
     429
     430void BytecodeGenerator::declareParameters()
     431{
     432    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     433    FunctionParameters& parameters = *node->parameters();
     434    m_parameters.grow(parameters.size() + 1); // reserve space for "this"
     435
     436    // Add "this" as a parameter
     437    int nextParameterIndex = CallFrame::thisArgumentOffset();
     438    m_thisRegister.setIndex(nextParameterIndex--);
     439    m_codeBlock->addParameter();
     440   
     441    for (size_t i = 0; i < parameters.size(); ++i)
     442        declareParameter(parameters[i], nextParameterIndex--);
     443}
     444
     445void BytecodeGenerator::declareCallee()
     446{
     447    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     448
     449    if (node->ident().isNull() || !node->functionNameIsInScope())
     450        return;
     451
     452    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
     453    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
     454        return;
     455
     456    symbolTable().add(node->ident().impl(), SymbolTableEntry(m_calleeRegister.index(), ReadOnly));
     457}
     458
     459void BytecodeGenerator::initCalleeVar()
     460{
     461    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     462
     463    if (node->ident().isNull() || !node->functionNameIsInScope())
     464        return;
     465
     466    // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
     467    if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
     468        emitOpcode(op_push_name_scope);
     469        instructions().append(addConstant(node->ident()));
     470        instructions().append(RegisterFile::Callee);
     471        instructions().append(ReadOnly | DontDelete);
     472
     473        // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
     474        m_scope.set(*globalData(),
     475            JSNameScope::create(
     476                m_scope->globalObject()->globalExec(),
     477                node->ident(),
     478                jsUndefined(),
     479                ReadOnly | DontDelete,
     480                m_scope.get()
     481            )
     482        );
     483
     484        return;
     485    }
     486
     487    if (!node->captures(node->ident()))
     488        return;
     489
     490    // Move the callee into the captured section of the stack.
     491    RegisterID callee(RegisterFile::Callee);
     492    emitMove(&m_calleeRegister, &callee);
     493}
     494
     495void BytecodeGenerator::initArgumentsVars()
     496{
     497    if (!m_codeBlock->usesArguments())
     498        return;
     499
     500    int argumentsRegister = m_codeBlock->argumentsRegister();
     501    int unmodifiedArgumentsRegister = JSC::unmodifiedArgumentsRegister(argumentsRegister);
     502
     503    prependComment("unmodified arguments");
     504    emitInitLazyRegister(&registerFor(unmodifiedArgumentsRegister));
     505    prependComment("arguments");
     506    emitInitLazyRegister(&registerFor(argumentsRegister));
     507
     508    if ((m_codeBlock->usesArguments() && m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
     509        emitOpcode(op_create_arguments);
     510        instructions().append(m_codeBlock->argumentsRegister());
     511    }
     512}
     513
     514void BytecodeGenerator::initActivationVar()
     515{
     516    if (!m_codeBlock->needsFullScopeChain())
     517        return;
     518
     519    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     520
     521    emitInitLazyRegister(m_activationRegister);
     522
     523    bool canLazilyCreateFunctions = !node->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
     524    if (canLazilyCreateFunctions)
     525        return;
     526
     527    emitOpcode(op_create_activation);
     528    instructions().append(m_activationRegister->index());
     529}
     530
     531void BytecodeGenerator::initThisParameter()
     532{
     533    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     534
     535    if (isConstructor()) {
     536        prependComment("'this' because we are a Constructor function");
     537        emitOpcode(op_create_this);
     538        instructions().append(m_thisRegister.index());
     539    } else if (!m_codeBlock->isStrictMode() && (node->usesThis() || m_codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
     540        ValueProfile* profile = emitProfiledOpcode(op_convert_this);
     541        instructions().append(m_thisRegister.index());
     542        instructions().append(profile);
     543    }
     544}
     545
     546void BytecodeGenerator::initFunctionDeclarations()
     547{
     548    FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode);
     549
     550    const DeclarationStacks::FunctionStack& functionStack = node->functionStack();
     551    bool canLazilyCreateFunctions = !node->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
     552    for (size_t i = 0; i < functionStack.size(); ++i) {
     553        FunctionBodyNode* function = functionStack[i].node;
     554        const Identifier& ident = function->ident();
     555        RegisterID* reg = &registerFor(symbolTable().get(ident.impl()).getIndex());
     556        if (node->captures(ident) || ident == propertyNames().arguments || !canLazilyCreateFunctions)
     557            emitNewFunction(reg, function);
     558        else {
     559            emitInitLazyRegister(reg);
     560            m_lazyFunctions.set(reg->index(), function);
     561        }
    341562    }
    342563}
     
    360581    , m_nextConstantOffset(0)
    361582    , m_globalConstantIndex(0)
    362     , m_hasCreatedActivation(false)
    363     , m_firstLazyFunction(0)
    364     , m_lastLazyFunction(0)
    365583    , m_globalData(scope->globalData())
    366584    , m_lastOpcodeID(op_end)
     
    377595
    378596    codeBlock->setGlobalData(m_globalData);
    379    
    380     prependComment("entering Function block");
     597
     598    allocateArgumentsVars();
     599    allocateActivationVar();
     600    allocateCalleeVarUndeclared();
     601    allocateCapturedVars();
     602    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     603    allocateUncapturedVars();
     604    if (m_shouldEmitDebugHooks) // FIXME: What about eval?
     605        codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     606    preserveLastVar();
     607
     608    declareParameters(); // Parameters lose to functions
     609    declareCallee(); // Callee loses to everything
     610
    381611    emitOpcode(op_enter);
    382     if (m_codeBlock->needsFullScopeChain()) {
    383         m_activationRegister = addVar();
    384         prependComment("activation for Full Scope Chain");
    385         emitInitLazyRegister(m_activationRegister);
    386         m_codeBlock->setActivationRegister(m_activationRegister->index());
    387     }
    388 
    389     // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
    390     // object, if created.
    391     if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {
    392         RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
    393         RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
    394 
    395         // We can save a little space by hard-coding the knowledge that the two
    396         // 'arguments' values are stored in consecutive registers, and storing
    397         // only the index of the assignable one.
    398         codeBlock->setArgumentsRegister(argumentsRegister->index());
    399         ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
    400 
    401         prependComment("arguments for Full Scope Chain");
    402         emitInitLazyRegister(argumentsRegister);
    403         prependComment("unmodified arguments for Full Scope Chain");
    404         emitInitLazyRegister(unmodifiedArgumentsRegister);
    405        
    406         if (m_codeBlock->isStrictMode()) {
    407             prependComment("create arguments for strict mode");
    408             emitOpcode(op_create_arguments);
    409             instructions().append(argumentsRegister->index());
    410         }
    411 
    412         // The debugger currently retrieves the arguments object from an activation rather than pulling
    413         // it from a call frame.  In the long-term it should stop doing that (<rdar://problem/6911886>),
    414         // but for now we force eager creation of the arguments object when debugging.
    415         if (m_shouldEmitDebugHooks) {
    416             prependComment("create arguments for debug hooks");
    417             emitOpcode(op_create_arguments);
    418             instructions().append(argumentsRegister->index());
    419         }
    420     }
    421 
    422     RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var.
    423 
    424     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
    425     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
    426 
    427     // Captured variables and functions go first so that activations don't have
    428     // to step over the non-captured locals to mark them.
    429     m_hasCreatedActivation = false;
    430     if (functionBody->hasCapturedVariables()) {
    431         for (size_t i = 0; i < functionStack.size(); ++i) {
    432             FunctionBodyNode* function = functionStack[i];
    433             const Identifier& ident = function->ident();
    434             if (functionBody->captures(ident)) {
    435                 if (!m_hasCreatedActivation) {
    436                     m_hasCreatedActivation = true;
    437                     prependComment("activation for captured vars");
    438                     emitOpcode(op_create_activation);
    439                     instructions().append(m_activationRegister->index());
    440                 }
    441                 m_functions.add(ident.impl());
    442                 prependComment("captured function var");
    443                 emitNewFunction(addVar(ident, false), function);
    444             }
    445         }
    446         for (size_t i = 0; i < varStack.size(); ++i) {
    447             const Identifier& ident = *varStack[i].first;
    448             if (functionBody->captures(ident))
    449                 addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
    450         }
    451     }
    452     bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
    453     if (!canLazilyCreateFunctions && !m_hasCreatedActivation) {
    454         m_hasCreatedActivation = true;
    455         prependComment("cannot lazily create functions");
    456         emitOpcode(op_create_activation);
    457         instructions().append(m_activationRegister->index());
    458     }
    459 
    460     codeBlock->m_numCapturedVars = codeBlock->m_numVars;
    461 
    462     m_firstLazyFunction = codeBlock->m_numVars;
    463     for (size_t i = 0; i < functionStack.size(); ++i) {
    464         FunctionBodyNode* function = functionStack[i];
    465         const Identifier& ident = function->ident();
    466         if (!functionBody->captures(ident)) {
    467             m_functions.add(ident.impl());
    468             RefPtr<RegisterID> reg = addVar(ident, false);
    469             // Don't lazily create functions that override the name 'arguments'
    470             // as this would complicate lazy instantiation of actual arguments.
    471             prependComment("a function that override 'arguments'");
    472             if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
    473                 emitNewFunction(reg.get(), function);
    474             else {
    475                 emitInitLazyRegister(reg.get());
    476                 m_lazyFunctions.set(reg->index(), function);
    477             }
    478         }
    479     }
    480     m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
    481     for (size_t i = 0; i < varStack.size(); ++i) {
    482         const Identifier& ident = *varStack[i].first;
    483         if (!functionBody->captures(ident))
    484             addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
    485     }
    486 
    487     if (m_shouldEmitDebugHooks)
    488         codeBlock->m_numCapturedVars = codeBlock->m_numVars;
    489 
    490     FunctionParameters& parameters = *functionBody->parameters();
    491     m_parameters.grow(parameters.size() + 1); // reserve space for "this"
    492 
    493     // Add "this" as a parameter
    494     int nextParameterIndex = CallFrame::thisArgumentOffset();
    495     m_thisRegister.setIndex(nextParameterIndex--);
    496     m_codeBlock->addParameter();
    497    
    498     for (size_t i = 0; i < parameters.size(); ++i)
    499         addParameter(parameters[i], nextParameterIndex--);
    500 
    501     preserveLastVar();
    502 
    503     // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration.
    504     addCallee(functionBody, calleeRegister);
    505 
    506     if (isConstructor()) {
    507         prependComment("'this' because we are a Constructor function");
    508         emitOpcode(op_create_this);
    509         instructions().append(m_thisRegister.index());
    510     } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) {
    511         ValueProfile* profile = emitProfiledOpcode(op_convert_this);
    512         instructions().append(m_thisRegister.index());
    513         instructions().append(profile);
    514     }
     612    initArgumentsVars();
     613    initActivationVar();
     614    initCalleeVar();
     615    initThisParameter();
     616    initFunctionDeclarations();
    515617}
    516618
     
    533635    , m_nextConstantOffset(0)
    534636    , m_globalConstantIndex(0)
    535     , m_hasCreatedActivation(true)
    536     , m_firstLazyFunction(0)
    537     , m_lastLazyFunction(0)
    538637    , m_globalData(scope->globalData())
    539638    , m_lastOpcodeID(op_end)
     
    556655    const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
    557656    for (size_t i = 0; i < functionStack.size(); ++i)
    558         m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i]));
     657        m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i].node));
    559658
    560659    const DeclarationStacks::VarStack& varStack = evalNode->varStack();
     
    563662    variables.reserveCapacity(numVariables);
    564663    for (size_t i = 0; i < numVariables; ++i)
    565         variables.append(*varStack[i].first);
     664        variables.append(*varStack[i].name);
    566665    codeBlock->adoptVariables(variables);
    567666    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     
    581680}
    582681
    583 RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode)
    584 {
    585     if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope())
    586         return 0;
    587 
    588     m_calleeRegister.setIndex(RegisterFile::Callee);
    589 
    590     // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
    591     if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) {
    592         emitOpcode(op_push_name_scope);
    593         instructions().append(addConstant(functionBodyNode->ident()));
    594         instructions().append(m_calleeRegister.index());
    595         instructions().append(ReadOnly | DontDelete);
    596 
    597         // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime.
    598         m_scope.set(*globalData(),
    599             JSNameScope::create(
    600                 m_scope->globalObject()->globalExec(),
    601                 functionBodyNode->ident(),
    602                 jsUndefined(),
    603                 ReadOnly | DontDelete,
    604                 m_scope.get()
    605             )
    606         );
    607         return 0;
    608     }
    609 
    610     if (!functionBodyNode->captures(functionBodyNode->ident()))
    611         return &m_calleeRegister;
    612 
    613     // Move the callee into the captured section of the stack.
    614     return emitMove(addVar(), &m_calleeRegister);
    615 }
    616 
    617 void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister)
    618 {
    619     if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope())
    620         return;
    621 
    622     // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name.
    623     if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks)
    624         return;
    625 
    626     ASSERT(calleeRegister);
    627     symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly));
    628 }
    629 
    630 void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex)
     682void BytecodeGenerator::declareParameter(const Identifier& ident, int parameterIndex)
    631683{
    632684    // Parameters overwrite var declarations, but not function declarations.
     
    672724RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
    673725{
    674     if (m_lastLazyFunction <= reg->index() || reg->index() < m_firstLazyFunction)
     726    FunctionBodyNode* node = m_lazyFunctions.get(reg->index());
     727    if (!node)
    675728        return reg;
    676     emitLazyNewFunction(reg, m_lazyFunctions.get(reg->index()));
     729
     730    emitLazyNewFunction(reg, node);
    677731    return reg;
    678732}
     
    19502004void BytecodeGenerator::createActivationIfNecessary()
    19512005{
    1952     if (m_hasCreatedActivation)
    1953         return;
    1954     if (!m_codeBlock->needsFullScopeChain())
     2006    if (!m_codeBlock->needsFullScopeChain() || m_codeType != FunctionCode)
    19552007        return;
    19562008    emitOpcode(op_create_activation);
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r127810 r127939  
    615615        enum ConstantMode { IsConstant, IsVariable };
    616616        enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable };
     617        enum VarType { Captured, NotCaptured };
    617618        int addGlobalVar(const Identifier&, ConstantMode, FunctionMode);
    618 
    619         void addParameter(const Identifier&, int parameterIndex);
    620         RegisterID* resolveCallee(FunctionBodyNode*);
    621         void addCallee(FunctionBodyNode*, RegisterID*);
     619        void declareParameter(const Identifier&, int parameterIndex);
     620
     621        void allocateCapturedVars();
     622        void allocateUncapturedVars();
     623        void allocateActivationVar();
     624        void allocateArgumentsVars();
     625        void allocateCalleeVarUndeclared();
     626        void declareParameters();
     627        void declareCallee();
     628        void initCalleeVar();
     629        void initArgumentsVars();
     630        void initActivationVar();
     631        void initThisParameter();
     632        void initFunctionDeclarations();
    622633
    623634        void preserveLastVar();
     
    739750        int m_globalVarStorageOffset;
    740751
    741         bool m_hasCreatedActivation;
    742         int m_firstLazyFunction;
    743         int m_lastLazyFunction;
    744752        HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
    745753        typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
  • trunk/Source/JavaScriptCore/parser/ASTBuilder.h

    r127654 r127939  
    315315        if (*name == m_globalData->propertyNames->arguments)
    316316            usesArguments();
    317         m_scope.m_funcDeclarations->data.append(decl->body());
     317        m_scope.m_funcDeclarations->data.append(DeclarationStacks::FunctionDeclaration(decl->body()));
    318318        body->setLoc(bodyStartLine, bodyEndLine, location.column);
    319319        return decl;
     
    509509        if (m_globalData->propertyNames->arguments == *ident)
    510510            usesArguments();
    511         m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs));
     511        m_scope.m_varDeclarations->data.append(DeclarationStacks::VarDeclaration(ident, attrs));
    512512    }
    513513
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r127810 r127939  
    8686
    8787    namespace DeclarationStacks {
     88        struct VarDeclaration {
     89            VarDeclaration(const Identifier* name, unsigned attributes)
     90                : name(name)
     91                , attributes(attributes)
     92                , reg(0)
     93            {
     94            }
     95            const Identifier* name;
     96            unsigned attributes;
     97            RegisterID* reg;
     98        };
     99        struct FunctionDeclaration {
     100            explicit FunctionDeclaration(FunctionBodyNode* node)
     101                : node(node)
     102                , reg(0)
     103            {
     104            }
     105            FunctionBodyNode* node;
     106            RegisterID* reg;
     107        };
    88108        enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
    89         typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
    90         typedef Vector<FunctionBodyNode*> FunctionStack;
     109        typedef Vector<VarDeclaration> VarStack;
     110        typedef Vector<FunctionDeclaration> FunctionStack;
    91111    }
    92112
Note: See TracChangeset for help on using the changeset viewer.