Changeset 183789 in webkit


Ignore:
Timestamp:
May 4, 2015 8:27:09 PM (9 years ago)
Author:
saambarati1@gmail.com
Message:

Global functions should be initialized as JSFunctions in byte code
https://bugs.webkit.org/show_bug.cgi?id=144178

Reviewed by Geoffrey Garen.

This patch makes the initialization of global functions more explicit by
moving initialization into bytecode. It also prepares JSC for having ES6
style lexical scoping because initializing global functions in bytecode
easily allows global functions to be initialized with the proper scope that
will have access to global lexical variables. Global lexical variables
should be visible to global functions but don't live on the global object.

  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedProgramCodeBlock::visitChildren):

  • bytecode/UnlinkedCodeBlock.h:
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):

  • bytecompiler/BytecodeGenerator.h:
  • runtime/Executable.cpp:

(JSC::ProgramExecutable::initializeGlobalProperties):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::addGlobalVar):
(JSC::JSGlobalObject::addFunction):

  • runtime/JSGlobalObject.h:
Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r183787 r183789  
     12015-05-04  Saam Barati  <saambarati1@gmail.com>
     2
     3        Global functions should be initialized as JSFunctions in byte code
     4        https://bugs.webkit.org/show_bug.cgi?id=144178
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch makes the initialization of global functions more explicit by
     9        moving initialization into bytecode. It also prepares JSC for having ES6
     10        style lexical scoping because initializing global functions in bytecode
     11        easily allows global functions to be initialized with the proper scope that
     12        will have access to global lexical variables. Global lexical variables
     13        should be visible to global functions but don't live on the global object.
     14
     15        * bytecode/UnlinkedCodeBlock.cpp:
     16        (JSC::UnlinkedProgramCodeBlock::visitChildren):
     17        * bytecode/UnlinkedCodeBlock.h:
     18        * bytecompiler/BytecodeGenerator.cpp:
     19        (JSC::BytecodeGenerator::generate):
     20        (JSC::BytecodeGenerator::BytecodeGenerator):
     21        * bytecompiler/BytecodeGenerator.h:
     22        * runtime/Executable.cpp:
     23        (JSC::ProgramExecutable::initializeGlobalProperties):
     24        * runtime/JSGlobalObject.cpp:
     25        (JSC::JSGlobalObject::addGlobalVar):
     26        (JSC::JSGlobalObject::addFunction):
     27        * runtime/JSGlobalObject.h:
     28
    1292015-05-04  Filip Pizlo  <fpizlo@apple.com>
    230
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp

    r183570 r183789  
    472472    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    473473    Base::visitChildren(thisObject, visitor);
    474     for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
    475         visitor.append(&thisObject->m_functionDeclarations[i].second);
    476474}
    477475
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r183570 r183789  
    655655    static void destroy(JSCell*);
    656656
    657     void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
    658     {
    659         m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
    660     }
    661 
    662657    void addVariableDeclaration(const Identifier& name, bool isConstant)
    663658    {
     
    666661
    667662    typedef Vector<std::pair<Identifier, bool>> VariableDeclations;
    668     typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations;
    669663
    670664    const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
    671     const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
    672665
    673666    static void visitChildren(JSCell*, SlotVisitor&);
     
    680673
    681674    VariableDeclations m_varDeclarations;
    682     FunctionDeclations m_functionDeclarations;
    683675
    684676public:
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r183570 r183789  
    7878    {
    7979        RefPtr<RegisterID> temp = newTemporary();
    80         for (FunctionBodyNode* functionBody : m_functionsToInitialize) {
     80        RefPtr<RegisterID> globalScope = scopeRegister(); // FIXME: With lexical scoping, this won't always be the global object: https://bugs.webkit.org/show_bug.cgi?id=142944
     81        for (auto functionPair : m_functionsToInitialize) {
     82            FunctionBodyNode* functionBody = functionPair.first;
     83            FunctionVariableType functionType = functionPair.second;
    8184            emitNewFunction(temp.get(), functionBody);
    82             initializeVariable(variable(functionBody->ident()), temp.get());
     85            if (functionType == NormalFunctionVariable)
     86                initializeVariable(variable(functionBody->ident()) , temp.get());
     87            else if (functionType == GlobalFunctionVariable)
     88                emitPutToScope(globalScope.get(), Variable(functionBody->ident()), temp.get(), ThrowIfNotFound);
     89            else
     90                RELEASE_ASSERT_NOT_REACHED();
    8391        }
    8492    }
     
    164172    for (size_t i = 0; i < functionStack.size(); ++i) {
    165173        FunctionBodyNode* function = functionStack[i];
    166         UnlinkedFunctionExecutable* unlinkedFunction = makeFunction(function);
    167         codeBlock->addFunctionDeclaration(*m_vm, function->ident(), unlinkedFunction);
     174        m_functionsToInitialize.append(std::make_pair(function, GlobalFunctionVariable));
    168175    }
    169176
     
    385392        const Identifier& ident = function->ident();
    386393        createVariable(ident, varKind(ident.impl()), IsVariable);
    387         m_functionsToInitialize.append(function);
     394        m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
    388395    }
    389396    for (auto& entry : functionNode->varStack()) {
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r183570 r183789  
    745745        Vector<TryContext> m_tryContextStack;
    746746        Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
    747         Vector<FunctionBodyNode*> m_functionsToInitialize;
     747        enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
     748        Vector<std::pair<FunctionBodyNode*, FunctionVariableType>> m_functionsToInitialize;
    748749        bool m_needToInitializeArguments { false };
    749750       
  • trunk/Source/JavaScriptCore/runtime/Executable.cpp

    r182759 r183789  
    511511
    512512    const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
    513     const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
    514 
    515     for (size_t i = 0; i < functionDeclarations.size(); ++i) {
    516         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
    517         JSValue value = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, m_source), scope);
    518         globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
     513
     514    for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
     515        UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
     516        ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
     517        globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());
    519518        if (vm.typeProfiler() || vm.controlFlowProfiler()) {
    520519            vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(),
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r183785 r183789  
    503503}
    504504
    505 JSGlobalObject::NewGlobalVar JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode)
     505void JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode)
    506506{
    507507    ConcurrentJITLocker locker(symbolTable()->m_lock);
    508508    SymbolTableEntry entry = symbolTable()->get(locker, ident.impl());
    509     if (!entry.isNull()) {
    510         NewGlobalVar result;
    511         result.offset = entry.scopeOffset();
    512         result.set = entry.watchpointSet();
    513         return result;
    514     }
     509    if (!entry.isNull())
     510        return;
    515511   
    516512    ScopeOffset offset = symbolTable()->takeNextScopeOffset(locker);
     
    524520    ScopeOffset offsetForAssert = addVariables(1);
    525521    RELEASE_ASSERT(offsetForAssert == offset);
    526 
    527     NewGlobalVar var;
    528     var.offset = offset;
    529     var.set = newEntry.watchpointSet();
    530     return var;
    531 }
    532 
    533 void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName, JSValue value)
     522}
     523
     524void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName)
    534525{
    535526    VM& vm = exec->vm();
    536527    removeDirect(vm, propertyName); // Newly declared functions overwrite existing properties.
    537     NewGlobalVar var = addGlobalVar(propertyName, IsVariable);
    538     variableAt(var.offset).set(exec->vm(), this, value);
    539     if (var.set)
    540         var.set->touch(VariableWriteFireDetail(this, propertyName));
     528    addGlobalVar(propertyName, IsVariable);
    541529}
    542530
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r183787 r183789  
    339339    }
    340340
    341     struct NewGlobalVar {
    342         ScopeOffset offset;
    343         WatchpointSet* set;
    344     };
    345     NewGlobalVar addGlobalVar(const Identifier&, ConstantMode);
     341    void addGlobalVar(const Identifier&, ConstantMode);
    346342
    347343public:
     
    375371            addGlobalVar(propertyName, IsConstant);
    376372    }
    377     void addFunction(ExecState*, const Identifier&, JSValue);
     373    void addFunction(ExecState*, const Identifier&);
    378374
    379375    // The following accessors return pristine values, even if a script
Note: See TracChangeset for help on using the changeset viewer.