Changeset 69045 in webkit


Ignore:
Timestamp:
Oct 4, 2010 3:43:18 PM (13 years ago)
Author:
oliver@apple.com
Message:

2010-10-04 Oliver Hunt <oliver@apple.com>

Reviewed by Geoff Garen.

Lazily create activation objects
https://bugs.webkit.org/show_bug.cgi?id=47107

Make it possible to lazily create the activation object
for a function that needs one. This allows us to reduce
the overhead of entering a function that may require
an activation in some cases, but not always.

This does make exception handling a little more complex as
it's now necessary to verify that a callframes activation
has been created, and create it if not, in all of the
paths used in exception handling.

We also need to add logic to check for the existence of
the activation in the scoped_var opcodes, as well as
op_ret, op_ret_object_or_this and op_tearoff_activation
so that we can avoid creating an activation unnecesarily
on function exit.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): (JSC::CodeBlock::createActivation):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::setActivationRegister): (JSC::CodeBlock::activationRegister):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::emitNewFunctionInternal): (JSC::BytecodeGenerator::emitNewFunctionExpression): (JSC::BytecodeGenerator::createActivationIfNecessary):
  • bytecompiler/BytecodeGenerator.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolveSkip): (JSC::Interpreter::resolveGlobalDynamic): (JSC::Interpreter::resolveBase): (JSC::Interpreter::unwindCallFrame): (JSC::Interpreter::throwException): (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JIT.h:
  • jit/JITCall32_64.cpp: (JSC::JIT::emit_op_ret): (JSC::JIT::emit_op_ret_object_or_this):
  • jit/JITOpcodes.cpp: (JSC::JIT::emit_op_end): (JSC::JIT::emit_op_get_scoped_var): (JSC::JIT::emit_op_put_scoped_var): (JSC::JIT::emit_op_tear_off_activation): (JSC::JIT::emit_op_ret): (JSC::JIT::emit_op_ret_object_or_this): (JSC::JIT::emit_op_create_activation): (JSC::JIT::emit_op_resolve_global_dynamic):
  • jit/JITOpcodes32_64.cpp: (JSC::JIT::emit_op_get_scoped_var): (JSC::JIT::emit_op_put_scoped_var): (JSC::JIT::emit_op_tear_off_activation): (JSC::JIT::emit_op_create_activation):
  • jit/JITStubs.cpp: (JSC::DEFINE_STUB_FUNCTION):
Location:
trunk/JavaScriptCore
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r69038 r69045  
     12010-10-04  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Lazily create activation objects
     6        https://bugs.webkit.org/show_bug.cgi?id=47107
     7
     8        Make it possible to lazily create the activation object
     9        for a function that needs one.  This allows us to reduce
     10        the overhead of entering a function that may require
     11        an activation in some cases, but not always.
     12
     13        This does make exception handling a little more complex as
     14        it's now necessary to verify that a callframes activation
     15        has been created, and create it if not, in all of the
     16        paths used in exception handling.
     17
     18        We also need to add logic to check for the existence of
     19        the activation in the scoped_var opcodes, as well as
     20        op_ret, op_ret_object_or_this and op_tearoff_activation
     21        so that we can avoid creating an activation unnecesarily
     22        on function exit.
     23
     24        * bytecode/CodeBlock.cpp:
     25        (JSC::CodeBlock::dump):
     26        (JSC::CodeBlock::reparseForExceptionInfoIfNecessary):
     27        (JSC::CodeBlock::createActivation):
     28        * bytecode/CodeBlock.h:
     29        (JSC::CodeBlock::setActivationRegister):
     30        (JSC::CodeBlock::activationRegister):
     31        * bytecode/Opcode.h:
     32        * bytecompiler/BytecodeGenerator.cpp:
     33        (JSC::BytecodeGenerator::BytecodeGenerator):
     34        (JSC::BytecodeGenerator::emitNewFunctionInternal):
     35        (JSC::BytecodeGenerator::emitNewFunctionExpression):
     36        (JSC::BytecodeGenerator::createActivationIfNecessary):
     37        * bytecompiler/BytecodeGenerator.h:
     38        * interpreter/Interpreter.cpp:
     39        (JSC::Interpreter::resolveSkip):
     40        (JSC::Interpreter::resolveGlobalDynamic):
     41        (JSC::Interpreter::resolveBase):
     42        (JSC::Interpreter::unwindCallFrame):
     43        (JSC::Interpreter::throwException):
     44        (JSC::Interpreter::privateExecute):
     45        * jit/JIT.cpp:
     46        (JSC::JIT::privateCompileMainPass):
     47        * jit/JIT.h:
     48        * jit/JITCall32_64.cpp:
     49        (JSC::JIT::emit_op_ret):
     50        (JSC::JIT::emit_op_ret_object_or_this):
     51        * jit/JITOpcodes.cpp:
     52        (JSC::JIT::emit_op_end):
     53        (JSC::JIT::emit_op_get_scoped_var):
     54        (JSC::JIT::emit_op_put_scoped_var):
     55        (JSC::JIT::emit_op_tear_off_activation):
     56        (JSC::JIT::emit_op_ret):
     57        (JSC::JIT::emit_op_ret_object_or_this):
     58        (JSC::JIT::emit_op_create_activation):
     59        (JSC::JIT::emit_op_resolve_global_dynamic):
     60        * jit/JITOpcodes32_64.cpp:
     61        (JSC::JIT::emit_op_get_scoped_var):
     62        (JSC::JIT::emit_op_put_scoped_var):
     63        (JSC::JIT::emit_op_tear_off_activation):
     64        (JSC::JIT::emit_op_create_activation):
     65        * jit/JITStubs.cpp:
     66        (JSC::DEFINE_STUB_FUNCTION):
     67
    1682010-10-04  Adam Barth  <abarth@webkit.org>
    269
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r67265 r69045  
    24082408                        buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
    24092409                        compatibilityVersion = "Xcode 2.4";
     2410                        developmentRegion = English;
    24102411                        hasScannedForEncodings = 1;
    24112412                        knownRegions = (
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r68339 r69045  
    3535#include "Interpreter.h"
    3636#include "JIT.h"
     37#include "JSActivation.h"
    3738#include "JSFunction.h"
    3839#include "JSStaticScopeObject.h"
     
    486487            break;
    487488        }
    488         case op_enter_with_activation: {
    489             int r0 = (++it)->u.operand;
    490             printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data());
     489        case op_create_activation: {
     490            int r0 = (++it)->u.operand;
     491            printf("[%4d] create_activation %s\n", location, registerName(exec, r0).data());
    491492            break;
    492493        }
     
    723724            JSValue scope = JSValue((++it)->u.jsCell);
    724725            ++it;
    725             int depth = it[2].u.operand;
     726            int depth = (++it)->u.operand;
    726727            printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth);
    727             it += 3;
    728728            break;
    729729        }
     
    15431543    ScopeChainNode* scopeChain = callFrame->scopeChain();
    15441544    if (m_needsFullScopeChain) {
     1545        if (codeType() == FunctionCode && !callFrame->r(activationRegister()).jsValue()) {
     1546            createActivation(callFrame);
     1547            scopeChain = callFrame->scopeChain();
     1548        }
    15451549        ScopeChain sc(scopeChain);
    15461550        int scopeDelta = sc.localDepth();
     
    17661770}
    17671771
     1772void CodeBlock::createActivation(CallFrame* callFrame)
     1773{
     1774    ASSERT(codeType() == FunctionCode);
     1775    ASSERT(needsFullScopeChain());
     1776    ASSERT(!callFrame->r(activationRegister()).jsValue());
     1777    JSActivation* activation = new (callFrame) JSActivation(callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
     1778    callFrame->r(activationRegister()) = JSValue(activation);
     1779    callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
     1780}
     1781
    17681782} // namespace JSC
  • trunk/JavaScriptCore/bytecode/CodeBlock.h

    r68171 r69045  
    409409            return m_argumentsRegister;
    410410        }
     411        void setActivationRegister(int activationRegister)
     412        {
     413            m_activationRegister = activationRegister;
     414        }
     415        int activationRegister()
     416        {
     417            ASSERT(needsFullScopeChain());
     418            return m_activationRegister;
     419        }
    411420        bool usesArguments() const { return m_argumentsRegister != -1; }
    412421
     
    420429        unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
    421430        unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
     431
     432        void createActivation(CallFrame*);
    422433
    423434#if ENABLE(INTERPRETER)
     
    549560        int m_thisRegister;
    550561        int m_argumentsRegister;
     562        int m_activationRegister;
    551563
    552564        bool m_needsFullScopeChain;
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r68338 r69045  
    4040    #define FOR_EACH_OPCODE_ID(macro) \
    4141        macro(op_enter, 1) \
    42         macro(op_enter_with_activation, 2) \
     42        macro(op_create_activation, 2) \
    4343        macro(op_init_lazy_reg, 2) \
    4444        macro(op_create_arguments, 2) \
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r68339 r69045  
    215215    , m_nextConstantOffset(0)
    216216    , m_globalConstantIndex(0)
     217    , m_hasCreatedActivation(true)
    217218    , m_firstLazyFunction(0)
    218219    , m_lastLazyFunction(0)
     
    307308    , m_nextConstantOffset(0)
    308309    , m_globalConstantIndex(0)
     310    , m_hasCreatedActivation(false)
    309311    , m_firstLazyFunction(0)
    310312    , m_lastLazyFunction(0)
     
    320322
    321323    codeBlock->setGlobalData(m_globalData);
    322 
     324   
     325    emitOpcode(op_enter);
    323326    if (m_codeBlock->needsFullScopeChain()) {
    324327        m_activationRegister = addVar();
    325         emitOpcode(op_enter_with_activation);
    326         instructions().append(m_activationRegister->index());
    327     } else
    328         emitOpcode(op_enter);
     328        emitInitLazyRegister(m_activationRegister);
     329        m_codeBlock->setActivationRegister(m_activationRegister->index());
     330    }
    329331
    330332    // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
     
    357359    // Captured variables and functions go first so that activations don't have
    358360    // to step over the non-captured locals to mark them.
     361    m_hasCreatedActivation = false;
    359362    if (functionBody->hasCapturedVariables()) {
    360363        for (size_t i = 0; i < functionStack.size(); ++i) {
     
    362365            const Identifier& ident = function->ident();
    363366            if (functionBody->captures(ident)) {
     367                if (!m_hasCreatedActivation) {
     368                    m_hasCreatedActivation = true;
     369                    emitOpcode(op_create_activation);
     370                    instructions().append(m_activationRegister->index());
     371                }
    364372                m_functions.add(ident.impl());
    365373                emitNewFunction(addVar(ident, false), function);
     
    372380        }
    373381    }
    374     bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables();
     382    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !debugger;
     383    if (!canLazilyCreateFunctions && !m_hasCreatedActivation) {
     384        m_hasCreatedActivation = true;
     385        emitOpcode(op_create_activation);
     386        instructions().append(m_activationRegister->index());
     387    }
     388
    375389    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
    376390    m_firstLazyFunction = codeBlock->m_numVars;
     
    400414    if (debugger)
    401415        codeBlock->m_numCapturedVars = codeBlock->m_numVars;
    402        
    403416
    404417    FunctionParameters& parameters = *functionBody->parameters();
     
    449462    , m_nextConstantOffset(0)
    450463    , m_globalConstantIndex(0)
     464    , m_hasCreatedActivation(true)
    451465    , m_firstLazyFunction(0)
    452466    , m_lastLazyFunction(0)
     
    15051519RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck)
    15061520{
     1521    createActivationIfNecessary();
    15071522    emitOpcode(op_new_func);
    15081523    instructions().append(dst->index());
     
    15241539    FunctionBodyNode* function = n->body();
    15251540    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
    1526 
     1541   
     1542    createActivationIfNecessary();
    15271543    emitOpcode(op_new_func_exp);
    15281544    instructions().append(r0->index());
     
    15441560    emitOpcode(op_create_arguments);
    15451561    instructions().append(m_codeBlock->argumentsRegister());
     1562}
     1563
     1564void BytecodeGenerator::createActivationIfNecessary()
     1565{
     1566    if (m_hasCreatedActivation)
     1567        return;
     1568    if (!m_codeBlock->needsFullScopeChain())
     1569        return;
     1570    emitOpcode(op_create_activation);
     1571    instructions().append(m_activationRegister->index());
    15461572}
    15471573
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r68899 r69045  
    519519
    520520        void createArgumentsIfNecessary();
     521        void createActivationIfNecessary();
    521522        RegisterID* createLazyRegisterIfNecessary(RegisterID*);
    522523
     
    559560        int m_globalVarStorageOffset;
    560561
     562        bool m_hasCreatedActivation;
    561563        int m_firstLazyFunction;
    562564        int m_lastLazyFunction;
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r68455 r69045  
    128128    ScopeChainIterator end = scopeChain->end();
    129129    ASSERT(iter != end);
     130    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
     131    ASSERT(skip || !checkTopLevel);
     132    if (checkTopLevel && skip--) {
     133        if (callFrame->r(codeBlock->activationRegister()).jsValue())
     134            ++iter;
     135    }
    130136    while (skip--) {
    131137        ++iter;
     
    141147            if (exceptionValue)
    142148                return false;
     149            ASSERT(result);
    143150            callFrame->r(dst) = JSValue(result);
    144151            return true;
     
    204211    ScopeChainIterator end = scopeChain->end();
    205212    ASSERT(iter != end);
     213    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
     214    ASSERT(skip || !checkTopLevel);
     215    if (checkTopLevel && skip--) {
     216        if (callFrame->r(codeBlock->activationRegister()).jsValue())
     217            ++iter;
     218    }
    206219    while (skip--) {
    207220        JSObject* o = *iter;
     
    215228                    if (exceptionValue)
    216229                        return false;
     230                    ASSERT(result);
    217231                    callFrame->r(dst) = JSValue(result);
    218232                    return true;
     
    231245    if (structure == globalObject->structure()) {
    232246        callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
     247        ASSERT(callFrame->r(dst).jsValue());
    233248        return true;
    234249    }
     
    244259            vPC[3] = globalObject->structure();
    245260            vPC[4] = slot.cachedOffset();
     261            ASSERT(result);
    246262            callFrame->r(dst) = JSValue(result);
    247263            return true;
     
    251267        if (exceptionValue)
    252268            return false;
     269        ASSERT(result);
    253270        callFrame->r(dst) = JSValue(result);
    254271        return true;
     
    264281    int property = vPC[2].u.operand;
    265282    callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
     283    ASSERT(callFrame->r(dst).jsValue());
    266284}
    267285
     
    536554    // If this call frame created an activation or an 'arguments' object, tear it off.
    537555    if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
     556        if (!callFrame->r(oldCodeBlock->activationRegister()).jsValue()) {
     557            oldCodeBlock->createActivation(callFrame);
     558            scopeChain = callFrame->scopeChain();
     559        }
    538560        while (!scopeChain->object->inherits(&JSActivation::info))
    539561            scopeChain = scopeChain->pop();
     
    647669    ScopeChainNode* scopeChain = callFrame->scopeChain();
    648670    ScopeChain sc(scopeChain);
    649     int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
     671    int scopeDelta = 0;
     672    if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode
     673        || callFrame->r(codeBlock->activationRegister()).jsValue())
     674        scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
    650675    ASSERT(scopeDelta >= 0);
    651676    while (scopeDelta--)
     
    15191544        int dst = vPC[1].u.operand;
    15201545        int src = vPC[2].u.operand;
     1546       
    15211547        callFrame->r(dst) = callFrame->r(src);
    15221548
     
    23282354        ScopeChainIterator end = scopeChain->end();
    23292355        ASSERT(iter != end);
     2356        ASSERT(codeBlock == callFrame->codeBlock());
     2357        bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
     2358        ASSERT(skip || !checkTopLevel);
     2359    if (checkTopLevel && skip--) {
     2360            if (callFrame->r(codeBlock->activationRegister()).jsValue())
     2361                ++iter;
     2362        }
    23302363        while (skip--) {
    23312364            ++iter;
     
    23352368        JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
    23362369        callFrame->r(dst) = scope->registerAt(index);
     2370        ASSERT(callFrame->r(dst).jsValue());
    23372371        vPC += OPCODE_LENGTH(op_get_scoped_var);
    23382372        NEXT_INSTRUCTION();
     
    23492383        ScopeChainIterator iter = scopeChain->begin();
    23502384        ScopeChainIterator end = scopeChain->end();
     2385        ASSERT(codeBlock == callFrame->codeBlock());
    23512386        ASSERT(iter != end);
     2387        bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
     2388        ASSERT(skip || !checkTopLevel);
     2389    if (checkTopLevel && skip--) {
     2390            if (callFrame->r(codeBlock->activationRegister()).jsValue())
     2391                ++iter;
     2392        }
    23522393        while (skip--) {
    23532394            ++iter;
     
    23572398        ASSERT((*iter)->isVariableObject());
    23582399        JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
     2400        ASSERT(callFrame->r(value).jsValue());
    23592401        scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
    23602402        vPC += OPCODE_LENGTH(op_put_scoped_var);
     
    36593701        int func = vPC[2].u.operand;
    36603702        int shouldCheck = vPC[3].u.operand;
    3661 
     3703        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
    36623704        if (!shouldCheck || !callFrame->r(dst).jsValue())
    36633705            callFrame->r(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
     
    36763718        int dst = vPC[1].u.operand;
    36773719        int funcIndex = vPC[2].u.operand;
    3678 
     3720       
     3721        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
    36793722        FunctionExecutable* function = codeBlock->functionExpr(funcIndex);
    36803723        JSFunction* func = function->make(callFrame, callFrame->scopeChain());
     
    37123755        int argCount = vPC[2].u.operand;
    37133756        int registerOffset = vPC[3].u.operand;
    3714 
     3757       
     3758        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
    37153759        JSValue funcVal = callFrame->r(func).jsValue();
    37163760
     
    39814025        */
    39824026
    3983         int src1 = vPC[1].u.operand;
    3984         int src2 = vPC[2].u.operand;
     4027        int activation = vPC[1].u.operand;
     4028        int arguments = vPC[2].u.operand;
    39854029        ASSERT(codeBlock->needsFullScopeChain());
    3986 
    3987         JSActivation* activation = asActivation(callFrame->r(src1).jsValue());
    3988         activation->copyRegisters();
    3989 
    3990         if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src2)).jsValue())
    3991             asArguments(arguments)->setActivation(activation);
     4030        JSValue activationValue = callFrame->r(activation).jsValue();
     4031        if (activationValue) {
     4032            asActivation(activationValue)->copyRegisters();
     4033
     4034            if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())
     4035                asArguments(argumentsValue)->setActivation(asActivation(activationValue));
     4036        } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())
     4037            asArguments(argumentsValue)->copyRegisters();
    39924038
    39934039        vPC += OPCODE_LENGTH(op_tear_off_activation);
     
    40274073        int result = vPC[1].u.operand;
    40284074
    4029         if (callFrame->codeBlock()->needsFullScopeChain())
     4075        if (callFrame->codeBlock()->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue())
    40304076            callFrame->scopeChain()->deref();
    40314077
     
    40684114        int result = vPC[1].u.operand;
    40694115
    4070         if (codeBlock->needsFullScopeChain())
     4116        if (codeBlock->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue())
    40714117            callFrame->scopeChain()->deref();
    40724118
     
    41044150        NEXT_INSTRUCTION();
    41054151    }
    4106     DEFINE_OPCODE(op_enter_with_activation) {
    4107         /* enter_with_activation dst(r)
    4108 
    4109            Initializes local variables to undefined, creates an activation object,
    4110            places it in dst, and pushes it onto the scope chain.
    4111 
    4112            This opcode appears only at the beginning of a code block.
    4113         */
    4114 
    4115         size_t i = 0;
    4116         for (size_t count = codeBlock->m_numVars; i < count; ++i)
    4117             callFrame->r(i) = jsUndefined();
    4118 
    4119         int dst = vPC[1].u.operand;
    4120         JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
    4121         callFrame->r(dst) = JSValue(activation);
    4122         callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
    4123 
    4124         vPC += OPCODE_LENGTH(op_enter_with_activation);
     4152    DEFINE_OPCODE(op_create_activation) {
     4153        /* create_activation dst(r)
     4154
     4155           If the activation object for this callframe has not yet been created,
     4156           this creates it and writes it back to dst.
     4157        */
     4158
     4159        int activationReg = vPC[1].u.operand;
     4160        if (!callFrame->r(activationReg).jsValue()) {
     4161            JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
     4162            callFrame->r(activationReg) = JSValue(activation);
     4163            callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
     4164        }
     4165        vPC += OPCODE_LENGTH(op_create_activation);
    41254166        NEXT_INSTRUCTION();
    41264167    }
  • trunk/JavaScriptCore/jit/JIT.cpp

    r68338 r69045  
    235235        DEFINE_OP(op_end)
    236236        DEFINE_OP(op_enter)
    237         DEFINE_OP(op_enter_with_activation)
     237        DEFINE_OP(op_create_activation)
    238238        DEFINE_OP(op_eq)
    239239        DEFINE_OP(op_eq_null)
  • trunk/JavaScriptCore/jit/JIT.h

    r68338 r69045  
    745745        void emit_op_end(Instruction*);
    746746        void emit_op_enter(Instruction*);
    747         void emit_op_enter_with_activation(Instruction*);
     747        void emit_op_create_activation(Instruction*);
    748748        void emit_op_eq(Instruction*);
    749749        void emit_op_eq_null(Instruction*);
  • trunk/JavaScriptCore/jit/JITCall32_64.cpp

    r67990 r69045  
    109109
    110110    // We could JIT generate the deref, only calling out to C when the refcount hits zero.
    111     if (m_codeBlock->needsFullScopeChain())
     111    if (m_codeBlock->needsFullScopeChain()) {
     112        Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
    112113        JITStubCall(this, cti_op_ret_scopeChain).call();
    113 
     114        activationNotCreated.link(this);
     115    }
    114116    emitLoad(dst, regT1, regT0);
    115117    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
     
    126128
    127129    // We could JIT generate the deref, only calling out to C when the refcount hits zero.
    128     if (m_codeBlock->needsFullScopeChain())
     130    if (m_codeBlock->needsFullScopeChain()) {
     131        Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
    129132        JITStubCall(this, cti_op_ret_scopeChain).call();
     133        activationNotCreated.link(this);
     134    }
    130135
    131136    emitLoad(result, regT1, regT0);
  • trunk/JavaScriptCore/jit/JITOpcodes.cpp

    r68339 r69045  
    338338    if (m_codeBlock->needsFullScopeChain())
    339339        JITStubCall(this, cti_op_end).call();
     340
    340341    ASSERT(returnValueRegister != callFrameRegister);
    341342    emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
     
    468469
    469470    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
     471    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
     472    ASSERT(skip || !checkTopLevel);
     473    if (checkTopLevel && skip--) {
     474        Jump activationNotCreated;
     475        if (checkTopLevel)
     476            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
     477        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
     478        activationNotCreated.link(this);
     479    }
    470480    while (skip--)
    471481        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
     
    482492    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
    483493    emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
     494    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
     495    ASSERT(skip || !checkTopLevel);
     496    if (checkTopLevel && skip--) {
     497        Jump activationNotCreated;
     498        if (checkTopLevel)
     499            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
     500        loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
     501        activationNotCreated.link(this);
     502    }
    484503    while (skip--)
    485504        loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
     
    491510void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
    492511{
     512    unsigned activation = currentInstruction[1].u.operand;
     513    unsigned arguments = currentInstruction[2].u.operand;
     514    Jump activationCreated = branchTestPtr(NonZero, addressFor(activation));
     515    Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments));
     516    activationCreated.link(this);
    493517    JITStubCall stubCall(this, cti_op_tear_off_activation);
    494     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
    495     stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand), regT2);
     518    stubCall.addArgument(activation, regT2);
     519    stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2);
    496520    stubCall.call();
     521    argumentsNotCreated.link(this);
    497522}
    498523
     
    511536{
    512537    // We could JIT generate the deref, only calling out to C when the refcount hits zero.
    513     if (m_codeBlock->needsFullScopeChain())
     538    if (m_codeBlock->needsFullScopeChain()) {
     539        Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
    514540        JITStubCall(this, cti_op_ret_scopeChain).call();
    515 
     541        activationNotCreated.link(this);
     542    }
    516543    ASSERT(callFrameRegister != regT1);
    517544    ASSERT(regT1 != returnValueRegister);
     
    535562{
    536563    // We could JIT generate the deref, only calling out to C when the refcount hits zero.
    537     if (m_codeBlock->needsFullScopeChain())
     564    if (m_codeBlock->needsFullScopeChain()) {
     565        Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
    538566        JITStubCall(this, cti_op_ret_scopeChain).call();
     567        activationNotCreated.link(this);
     568    }
    539569
    540570    ASSERT(callFrameRegister != regT1);
     
    11861216}
    11871217
    1188 void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
    1189 {
    1190     // Even though CTI doesn't use them, we initialize our constant
    1191     // registers to zap stale pointers, to avoid unnecessarily prolonging
    1192     // object lifetime and increasing GC pressure.
    1193     size_t count = m_codeBlock->m_numVars;
    1194     for (size_t j = 0; j < count; ++j)
    1195         emitInitRegister(j);
    1196 
     1218void JIT::emit_op_create_activation(Instruction* currentInstruction)
     1219{
     1220    unsigned dst = currentInstruction[1].u.operand;
     1221   
     1222    Jump activationCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
    11971223    JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
     1224    emitPutVirtualRegister(dst);
     1225    activationCreated.link(this);
    11981226}
    11991227
     
    15601588   
    15611589    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
     1590   
     1591    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
     1592    ASSERT(skip || !checkTopLevel);
     1593    if (checkTopLevel && skip--) {
     1594        Jump activationNotCreated;
     1595        if (checkTopLevel)
     1596            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
     1597        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
     1598        addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get()));
     1599        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
     1600        activationNotCreated.link(this);
     1601    }
    15621602    while (skip--) {
    15631603        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
  • trunk/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r68338 r69045  
    611611
    612612    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
     613    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
     614    ASSERT(skip || !checkTopLevel);
     615    if (checkTopLevel && skip--) {
     616        Jump activationNotCreated;
     617        if (checkTopLevel)
     618            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
     619        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
     620        activationNotCreated.link(this);
     621    }
    613622    while (skip--)
    614623        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
     
    632641
    633642    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
     643    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
     644    ASSERT(skip || !checkTopLevel);
     645    if (checkTopLevel && skip--) {
     646        Jump activationNotCreated;
     647        if (checkTopLevel)
     648            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
     649        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
     650        activationNotCreated.link(this);
     651    }
    634652    while (skip--)
    635653        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
     
    645663void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
    646664{
     665    unsigned activation = currentInstruction[1].u.operand;
     666    unsigned arguments = currentInstruction[2].u.operand;
     667    Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag));
     668    Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), Imm32(JSValue::EmptyValueTag));
     669    activationCreated.link(this);
    647670    JITStubCall stubCall(this, cti_op_tear_off_activation);
    648671    stubCall.addArgument(currentInstruction[1].u.operand);
    649672    stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand));
    650673    stubCall.call();
     674    argumentsNotCreated.link(this);
    651675}
    652676
     
    14681492}
    14691493
    1470 void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
    1471 {
    1472     emit_op_enter(currentInstruction);
    1473 
    1474     JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
     1494void JIT::emit_op_create_activation(Instruction* currentInstruction)
     1495{
     1496    unsigned activation = currentInstruction[1].u.operand;
     1497   
     1498    Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag));
     1499    JITStubCall(this, cti_op_push_activation).call(activation);
     1500    activationCreated.link(this);
    14751501}
    14761502
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r67943 r69045  
    19071907{
    19081908    STUB_INIT_STACK_FRAME(stackFrame);
    1909 
     1909   
     1910    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
    19101911    return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
    19111912}
     
    22142215
    22152216    ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
     2217    JSValue activationValue = stackFrame.args[0].jsValue();
     2218    if (!activationValue) {
     2219        if (JSValue v = stackFrame.args[1].jsValue())
     2220            asArguments(v)->copyRegisters();
     2221        return;
     2222    }
    22162223    JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
    22172224    activation->copyRegisters();
     
    26862693    ScopeChainIterator end = scopeChain->end();
    26872694    ASSERT(iter != end);
     2695    CodeBlock* codeBlock = callFrame->codeBlock();
     2696    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
     2697    ASSERT(skip || !checkTopLevel);
     2698    if (checkTopLevel && skip--) {
     2699        if (callFrame->r(codeBlock->activationRegister()).jsValue())
     2700            ++iter;
     2701    }
    26882702    while (skip--) {
    26892703        ++iter;
     
    27012715    } while (++iter != end);
    27022716
    2703     CodeBlock* codeBlock = callFrame->codeBlock();
    27042717    unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
    27052718    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
     
    30503063    FunctionExecutable* function = stackFrame.args[0].function();
    30513064    JSFunction* func = function->make(callFrame, callFrame->scopeChain());
     3065    ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->r(callFrame->codeBlock()->activationRegister()).jsValue());
    30523066
    30533067    /*
     
    31563170{
    31573171    STUB_INIT_STACK_FRAME(stackFrame);
     3172    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
    31583173
    31593174    CallFrame* callFrame = stackFrame.callFrame;
Note: See TracChangeset for help on using the changeset viewer.