Changeset 33541 in webkit


Ignore:
Timestamp:
May 16, 2008 5:27:52 PM (16 years ago)
Author:
oliver@apple.com
Message:

Bug 19076: SquirrelFish: RegisterFile can be corrupted if implictly reenter global scope with no declared vars
<https://bugs.webkit.org/show_bug.cgi?id=19076>

Reviewed by Geoff

Don't delay allocation of initial global RegisterFile, as we can't guarantee we will be able
to allocate the global 'this' register safely at any point after initialisation of the Global
Object.

Unfortunately this initial allocation caused a regression of 0.2-0.3%, however this patch adds
support for the static slot optimisation for the global Math object which brings it to a 0.3%
progression.

Location:
branches/squirrelfish
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • branches/squirrelfish/JavaScriptCore/ChangeLog

    r33517 r33541  
     12008-05-16  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Geoff.
     4
     5        Bug 19076: SquirrelFish: RegisterFile can be corrupted if implictly reenter global scope with no declared vars
     6        <https://bugs.webkit.org/show_bug.cgi?id=19076>
     7
     8        Don't delay allocation of initial global RegisterFile, as we can't guarantee we will be able
     9        to allocate the global 'this' register safely at any point after initialisation of the Global
     10        Object.
     11
     12        Unfortunately this initial allocation caused a regression of 0.2-0.3%, however this patch adds
     13        support for the static slot optimisation for the global Math object which brings it to a 0.3%
     14        progression.
     15
     16        * VM/CodeGenerator.cpp:
     17        (KJS::CodeGenerator::programCodeThis):
     18        (KJS::CodeGenerator::CodeGenerator):
     19        (KJS::CodeGenerator::addParameter):
     20        * VM/CodeGenerator.h:
     21        * VM/Machine.cpp:
     22        (KJS::Machine::execute):
     23        * kjs/ExecState.h:
     24        * kjs/JSGlobalObject.cpp:
     25        (KJS::JSGlobalObject::reset):
     26        * kjs/JSGlobalObject.h:
     27        (KJS::JSGlobalObject::GlobalPropertyInfo::GlobalPropertyInfo):
     28        (KJS::JSGlobalObject::addStaticGlobals):
     29        * kjs/nodes.cpp:
     30
    1312008-05-16  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
    232
  • branches/squirrelfish/JavaScriptCore/VM/CodeGenerator.cpp

    r33484 r33541  
    163163}
    164164
     165RegisterID* CodeGenerator::programCodeThis()
     166{
     167    static RegisterID programThis(Machine::ProgramCodeThisRegister);
     168    return &programThis;
     169}
     170
    165171CodeGenerator::CodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock, VarStack& varStack, FunctionStack& functionStack, bool canCreateVariables)
    166172    : m_shouldEmitDebugHooks(!!debugger)
     
    178184{
    179185    // Global code can inherit previously defined symbols.
    180     if (int size = symbolTable->size()) {
    181         // re-add "this" to symbol table
    182         ASSERT(!symbolTable->contains(m_propertyNames->thisIdentifier.ustring().rep()));
    183         symbolTable->add(m_propertyNames->thisIdentifier.ustring().rep(), Machine::ProgramCodeThisRegister);
    184         ++size;
    185 
    186         // Add previously defined symbols to bookkeeping.
    187         m_locals.resize(size);
    188         SymbolTable::iterator end = symbolTable->end();
    189         for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
    190             m_locals[localsIndex(it->second.getIndex())].setIndex(it->second.getIndex());
    191 
    192         // Shift new symbols so they get stored prior to previously defined symbols.
    193         m_nextVar -= size;
    194     } else
    195         addVar(m_propertyNames->thisIdentifier, false); // No need to make "this" a true parameter, since it's not passed by our caller.
     186    int size = symbolTable->size() + 1; // + 1 slot for  "this"
     187    m_thisRegister = programCodeThis();
     188
     189    // Add previously defined symbols to bookkeeping.
     190    m_locals.resize(size);
     191    SymbolTable::iterator end = symbolTable->end();
     192    for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
     193        m_locals[localsIndex(it->second.getIndex())].setIndex(it->second.getIndex());
     194
     195    // Shift new symbols so they get stored prior to previously defined symbols.
     196    m_nextVar -= size;
    196197
    197198    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(scopeChain.bottom());
     
    232233    , m_scopeNode(functionBody)
    233234    , m_codeBlock(codeBlock)
     235    , m_thisRegister(0)
    234236    , m_finallyDepth(0)
    235237    , m_dynamicScopeDepth(0)
     
    260262    m_locals.resize(localsIndex(m_nextParameter) + 1);
    261263
    262     addParameter(m_propertyNames->thisIdentifier);
     264    m_thisRegister = addParameter(m_propertyNames->thisIdentifier);
    263265    for (size_t i = 0; i < parameters.size(); ++i) {
    264266        addParameter(parameters[i]);
     
    272274    , m_scopeNode(evalNode)
    273275    , m_codeBlock(codeBlock)
     276    , m_thisRegister(0)
    274277    , m_finallyDepth(0)
    275278    , m_dynamicScopeDepth(0)
     
    279282    , m_propertyNames(CommonIdentifiers::shared())
    280283{
    281     addVar(m_propertyNames->thisIdentifier, false);
     284    addVar(m_propertyNames->thisIdentifier, m_thisRegister, false);
    282285   
    283286    for (size_t i = 0; i < varStack.size(); ++i)
     
    295298}
    296299
    297 void CodeGenerator::addParameter(const Identifier& ident)
     300RegisterID* CodeGenerator::addParameter(const Identifier& ident)
    298301{
    299302    // Parameters overwrite var declarations, but not function declarations,
    300303    // in the symbol table.
     304    RegisterID* result = 0;
    301305    UString::Rep* rep = ident.ustring().rep();
    302306    if (!m_functions.contains(rep)) {
    303307        symbolTable().set(rep, m_nextParameter);
    304308        m_locals[localsIndex(m_nextParameter)].setIndex(m_nextParameter);
     309        result = &(m_locals[localsIndex(m_nextParameter)]);
    305310    }
    306311   
     
    309314    ++m_nextParameter;
    310315    ++m_codeBlock->numParameters;
     316    return result;
    311317}
    312318
  • branches/squirrelfish/JavaScriptCore/VM/CodeGenerator.h

    r33484 r33541  
    9494        RegisterID* registerForLocalConstInit(const Identifier&);
    9595
     96        // Returns the register storing "this"
     97        RegisterID* thisRegister() { return m_thisRegister; }
     98
    9699        bool isLocalConstant(const Identifier&);
    97100
     
    289292        bool addVar(const Identifier&, RegisterID*&, bool isConstant);
    290293
    291         void addParameter(const Identifier&);
     294        RegisterID* addParameter(const Identifier&);
    292295
    293296        unsigned addConstant(FuncDeclNode*);
     
    312315       
    313316        HashSet<RefPtr<UString::Rep>, IdentifierRepHash> m_functions;
    314 
     317        static RegisterID* programCodeThis();
     318        RegisterID* m_thisRegister;
    315319        SegmentedVector<RegisterID, 512> m_locals;
    316320        SegmentedVector<RegisterID, 512> m_temporaries;
  • branches/squirrelfish/JavaScriptCore/VM/Machine.cpp

    r33484 r33541  
    594594
    595595    RegisterFile* registerFile = registerFileStack->pushGlobalRegisterFile();
     596    ASSERT(registerFile->numGlobalSlots());
    596597    CodeBlock* codeBlock = &programNode->code(scopeChain, !registerFileStack->inImplicitCall());
    597598    registerFile->addGlobalSlots(codeBlock->numVars);
  • branches/squirrelfish/JavaScriptCore/kjs/ExecState.h

    r33421 r33541  
    7575        // Global object in which the current script was defined. (Can differ
    7676        // from dynamicGlobalObject() during function calls across frames.)
    77         JSGlobalObject* ExecState::lexicalGlobalObject() const
     77        JSGlobalObject* lexicalGlobalObject() const
    7878        {
    7979            return m_scopeChain->globalObject();
  • branches/squirrelfish/JavaScriptCore/kjs/JSGlobalObject.cpp

    r33346 r33541  
    258258    _prop.clear();
    259259    registerFileStack().current()->clear();
     260    registerFileStack().current()->addGlobalSlots(1);
    260261    symbolTable().clear();
    261262
     
    378379
    379380    // Set global values.
    380 
    381     putDirect("Math", new MathObjectImp(exec, d()->objectPrototype), DontEnum);
    382     putDirect("NaN", jsNaN(), DontEnum | DontDelete);
    383     putDirect("Infinity", jsNumber(Inf), DontEnum | DontDelete);
    384     putDirect("undefined", jsUndefined(), DontEnum | DontDelete);
     381    GlobalPropertyInfo staticGlobals[] = {
     382        GlobalPropertyInfo("Math", new MathObjectImp(exec, d()->objectPrototype), DontEnum | DontDelete),
     383        GlobalPropertyInfo("NaN", jsNaN(), DontEnum | DontDelete),
     384        GlobalPropertyInfo("Infinity", jsNumber(Inf), DontEnum | DontDelete),
     385        GlobalPropertyInfo("undefined", jsUndefined(), DontEnum | DontDelete)
     386    };
     387
     388    addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
    385389
    386390    // Set global functions.
  • branches/squirrelfish/JavaScriptCore/kjs/JSGlobalObject.h

    r33346 r33541  
    264264        JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
    265265
     266        struct GlobalPropertyInfo {
     267            GlobalPropertyInfo(const Identifier& i, JSValue* v, unsigned a)
     268                : identifier(i)
     269                , value(v)
     270                , attributes(a)
     271            {
     272            }
     273
     274            const Identifier& identifier;
     275            JSValue* value;
     276            unsigned attributes;
     277        };
     278        void addStaticGlobals(GlobalPropertyInfo*, int count);
     279
    266280        bool checkTimeout();
    267281        void resetTimeoutCheck();
     
    269283        static JSGlobalObject* s_head;
    270284    };
     285
     286    inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
     287    {
     288        RegisterFile* registerFile = registerFileStack().current();
     289        ASSERT(registerFile->safeForReentry() && registerFile->isGlobal() && !registerFile->size());
     290        int index = -registerFile->numGlobalSlots() - 1;
     291        registerFile->addGlobalSlots(count);
     292        for (int i = 0; i < count; ++i) {
     293            ASSERT(globals[i].attributes & DontDelete);
     294            SymbolTableEntry newEntry(index, globals[i].attributes);
     295            symbolTable().add(globals[i].identifier.ustring().rep(), newEntry);
     296            valueAt(index) = globals[i].value;
     297            --index;
     298        }
     299    }
    271300
    272301    inline bool JSGlobalObject::timedOut()
  • branches/squirrelfish/JavaScriptCore/kjs/nodes.cpp

    r33517 r33541  
    585585RegisterID* ThisNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    586586{
    587     RegisterID* r0 = generator.registerForLocal(generator.propertyNames().thisIdentifier);
    588     return generator.moveToDestinationIfNeeded(dst, r0);
     587    return generator.moveToDestinationIfNeeded(dst, generator.thisRegister());
    589588}
    590589
  • branches/squirrelfish/LayoutTests/ChangeLog

    r33517 r33541  
     12008-05-16  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Geoff
     4
     5        Bug 19076: SquirrelFish: RegisterFile can be corrupted if implictly reenter global scope with no declared vars
     6        <https://bugs.webkit.org/show_bug.cgi?id=19076>
     7
     8        Test that we can re-enter safely.
     9
     10        * fast/js/direct-entry-to-function-code-expected.txt: Added.
     11        * fast/js/direct-entry-to-function-code.html: Added.
     12
    1132008-05-16  Cameron Zwarich  <cwzwarich@uwaterloo.ca>
    214
Note: See TracChangeset for help on using the changeset viewer.