Title: [183789] trunk/Source/_javascript_Core
Revision
183789
Author
[email protected]
Date
2015-05-04 20:27:09 -0700 (Mon, 04 May 2015)

Log 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:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (183788 => 183789)


--- trunk/Source/_javascript_Core/ChangeLog	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-05-05 03:27:09 UTC (rev 183789)
@@ -1,3 +1,31 @@
+2015-05-04  Saam Barati  <[email protected]>
+
+        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:
+
 2015-05-04  Filip Pizlo  <[email protected]>
 
         Large array shouldn't be slow

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (183788 => 183789)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2015-05-05 03:27:09 UTC (rev 183789)
@@ -471,8 +471,6 @@
     UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
-    for (size_t i = 0, end = thisObject->m_functionDeclarations.size(); i != end; i++)
-        visitor.append(&thisObject->m_functionDeclarations[i].second);
 }
 
 UnlinkedCodeBlock::~UnlinkedCodeBlock()

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (183788 => 183789)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h	2015-05-05 03:27:09 UTC (rev 183789)
@@ -654,21 +654,14 @@
 
     static void destroy(JSCell*);
 
-    void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
-    {
-        m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
-    }
-
     void addVariableDeclaration(const Identifier& name, bool isConstant)
     {
         m_varDeclarations.append(std::make_pair(name, isConstant));
     }
 
     typedef Vector<std::pair<Identifier, bool>> VariableDeclations;
-    typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations;
 
     const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
-    const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
@@ -679,7 +672,6 @@
     }
 
     VariableDeclations m_varDeclarations;
-    FunctionDeclations m_functionDeclarations;
 
 public:
     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (183788 => 183789)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-05-05 03:27:09 UTC (rev 183789)
@@ -77,9 +77,17 @@
 
     {
         RefPtr<RegisterID> temp = newTemporary();
-        for (FunctionBodyNode* functionBody : m_functionsToInitialize) {
+        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 
+        for (auto functionPair : m_functionsToInitialize) {
+            FunctionBodyNode* functionBody = functionPair.first;
+            FunctionVariableType functionType = functionPair.second;
             emitNewFunction(temp.get(), functionBody);
-            initializeVariable(variable(functionBody->ident()), temp.get());
+            if (functionType == NormalFunctionVariable)
+                initializeVariable(variable(functionBody->ident()) , temp.get());
+            else if (functionType == GlobalFunctionVariable)
+                emitPutToScope(globalScope.get(), Variable(functionBody->ident()), temp.get(), ThrowIfNotFound);
+            else
+                RELEASE_ASSERT_NOT_REACHED();
         }
     }
     
@@ -163,8 +171,7 @@
 
     for (size_t i = 0; i < functionStack.size(); ++i) {
         FunctionBodyNode* function = functionStack[i];
-        UnlinkedFunctionExecutable* unlinkedFunction = makeFunction(function);
-        codeBlock->addFunctionDeclaration(*m_vm, function->ident(), unlinkedFunction);
+        m_functionsToInitialize.append(std::make_pair(function, GlobalFunctionVariable));
     }
 
     for (size_t i = 0; i < varStack.size(); ++i)
@@ -384,7 +391,7 @@
     for (FunctionBodyNode* function : functionNode->functionStack()) {
         const Identifier& ident = function->ident();
         createVariable(ident, varKind(ident.impl()), IsVariable);
-        m_functionsToInitialize.append(function);
+        m_functionsToInitialize.append(std::make_pair(function, NormalFunctionVariable));
     }
     for (auto& entry : functionNode->varStack()) {
         ConstantMode constantMode = modeForIsConstant(entry.second & DeclarationStacks::IsConstant);

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (183788 => 183789)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2015-05-05 03:27:09 UTC (rev 183789)
@@ -744,7 +744,8 @@
         Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
         Vector<TryContext> m_tryContextStack;
         Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
-        Vector<FunctionBodyNode*> m_functionsToInitialize;
+        enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
+        Vector<std::pair<FunctionBodyNode*, FunctionVariableType>> m_functionsToInitialize;
         bool m_needToInitializeArguments { false };
         
         Vector<TryRange> m_tryRanges;

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (183788 => 183789)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2015-05-05 03:27:09 UTC (rev 183789)
@@ -510,12 +510,11 @@
     BatchedTransitionOptimizer optimizer(vm, globalObject);
 
     const UnlinkedProgramCodeBlock::VariableDeclations& variableDeclarations = unlinkedCodeBlock->variableDeclarations();
-    const UnlinkedProgramCodeBlock::FunctionDeclations& functionDeclarations = unlinkedCodeBlock->functionDeclarations();
 
-    for (size_t i = 0; i < functionDeclarations.size(); ++i) {
-        UnlinkedFunctionExecutable* unlinkedFunctionExecutable = functionDeclarations[i].second.get();
-        JSValue value = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, m_source), scope);
-        globalObject->addFunction(callFrame, functionDeclarations[i].first, value);
+    for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
+        UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
+        ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
+        globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());
         if (vm.typeProfiler() || vm.controlFlowProfiler()) {
             vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(), 
                 unlinkedFunctionExecutable->typeProfilingStartOffset(), 

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (183788 => 183789)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-05-05 03:27:09 UTC (rev 183789)
@@ -502,16 +502,12 @@
     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
 }
 
-JSGlobalObject::NewGlobalVar JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode)
+void JSGlobalObject::addGlobalVar(const Identifier& ident, ConstantMode constantMode)
 {
     ConcurrentJITLocker locker(symbolTable()->m_lock);
     SymbolTableEntry entry = symbolTable()->get(locker, ident.impl());
-    if (!entry.isNull()) {
-        NewGlobalVar result;
-        result.offset = entry.scopeOffset();
-        result.set = entry.watchpointSet();
-        return result;
-    }
+    if (!entry.isNull())
+        return;
     
     ScopeOffset offset = symbolTable()->takeNextScopeOffset(locker);
     SymbolTableEntry newEntry(VarOffset(offset), (constantMode == IsConstant) ? ReadOnly : 0);
@@ -523,21 +519,13 @@
     
     ScopeOffset offsetForAssert = addVariables(1);
     RELEASE_ASSERT(offsetForAssert == offset);
-
-    NewGlobalVar var;
-    var.offset = offset;
-    var.set = newEntry.watchpointSet();
-    return var;
 }
 
-void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName, JSValue value)
+void JSGlobalObject::addFunction(ExecState* exec, const Identifier& propertyName)
 {
     VM& vm = exec->vm();
     removeDirect(vm, propertyName); // Newly declared functions overwrite existing properties.
-    NewGlobalVar var = addGlobalVar(propertyName, IsVariable);
-    variableAt(var.offset).set(exec->vm(), this, value);
-    if (var.set)
-        var.set->touch(VariableWriteFireDetail(this, propertyName));
+    addGlobalVar(propertyName, IsVariable);
 }
 
 static inline JSObject* lastInPrototypeChain(JSObject* object)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (183788 => 183789)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2015-05-05 03:22:35 UTC (rev 183788)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2015-05-05 03:27:09 UTC (rev 183789)
@@ -338,11 +338,7 @@
         setGlobalThis(vm, thisValue);
     }
 
-    struct NewGlobalVar {
-        ScopeOffset offset;
-        WatchpointSet* set;
-    };
-    NewGlobalVar addGlobalVar(const Identifier&, ConstantMode);
+    void addGlobalVar(const Identifier&, ConstantMode);
 
 public:
     JS_EXPORT_PRIVATE ~JSGlobalObject();
@@ -374,7 +370,7 @@
         if (!hasProperty(exec, propertyName))
             addGlobalVar(propertyName, IsConstant);
     }
-    void addFunction(ExecState*, const Identifier&, JSValue);
+    void addFunction(ExecState*, const Identifier&);
 
     // The following accessors return pristine values, even if a script 
     // replaces the global object's associated property.
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to