[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

oliver at apple.com oliver at apple.com
Wed Dec 22 13:41:58 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit e4469c9faff11a42a9b00c2d03106b9d94560b9a
Author: oliver at apple.com <oliver at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Sep 23 18:49:56 2010 +0000

    Only copy captured variables into activation
    https://bugs.webkit.org/show_bug.cgi?id=46330
    
    Reviewed by Geoff Garen
    
    We now track free variable information which means that
    we no longer need to copy every variable defined in a
    function.  With this patch activations only retain those
    variables needed for correctness.  In order to interact
    safely with the inspector this means that JSActivation
    now provides its own lookup functions so it can avoid
    trying to read or write to variables that have been
    optimised out.
    
    * bytecode/CodeBlock.h:
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::BytecodeGenerator):
    * parser/Nodes.h:
    (JSC::ScopeNode::capturedVariableCount):
    (JSC::ScopeNode::captures):
    * runtime/Arguments.h:
    (JSC::JSActivation::copyRegisters):
    * runtime/Executable.cpp:
    (JSC::FunctionExecutable::FunctionExecutable):
    (JSC::FunctionExecutable::compileForCallInternal):
    (JSC::FunctionExecutable::compileForConstructInternal):
    * runtime/Executable.h:
    (JSC::FunctionExecutable::capturedVariableCount):
    * runtime/JSActivation.cpp:
    (JSC::JSActivation::markChildren):
    (JSC::JSActivation::symbolTableGet):
    (JSC::JSActivation::symbolTablePut):
    (JSC::JSActivation::getOwnPropertyNames):
    (JSC::JSActivation::symbolTablePutWithAttributes):
    * runtime/JSActivation.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68171 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 7272959..64f6f97 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,41 @@
+2010-09-22  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Only copy captured variables into activation
+        https://bugs.webkit.org/show_bug.cgi?id=46330
+
+        We now track free variable information which means that
+        we no longer need to copy every variable defined in a
+        function.  With this patch activations only retain those
+        variables needed for correctness.  In order to interact
+        safely with the inspector this means that JSActivation
+        now provides its own lookup functions so it can avoid 
+        trying to read or write to variables that have been
+        optimised out.
+
+        * bytecode/CodeBlock.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * parser/Nodes.h:
+        (JSC::ScopeNode::capturedVariableCount):
+        (JSC::ScopeNode::captures):
+        * runtime/Arguments.h:
+        (JSC::JSActivation::copyRegisters):
+        * runtime/Executable.cpp:
+        (JSC::FunctionExecutable::FunctionExecutable):
+        (JSC::FunctionExecutable::compileForCallInternal):
+        (JSC::FunctionExecutable::compileForConstructInternal):
+        * runtime/Executable.h:
+        (JSC::FunctionExecutable::capturedVariableCount):
+        * runtime/JSActivation.cpp:
+        (JSC::JSActivation::markChildren):
+        (JSC::JSActivation::symbolTableGet):
+        (JSC::JSActivation::symbolTablePut):
+        (JSC::JSActivation::getOwnPropertyNames):
+        (JSC::JSActivation::symbolTablePutWithAttributes):
+        * runtime/JSActivation.h:
+
 2010-09-23  Ismail Donmez  <ismail at namtrac.org>
 
         Reviewed by Andreas Kling.
diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h
index 766ad2a..cda4530 100644
--- a/JavaScriptCore/bytecode/CodeBlock.h
+++ b/JavaScriptCore/bytecode/CodeBlock.h
@@ -514,6 +514,7 @@ namespace JSC {
 
         int m_numCalleeRegisters;
         int m_numVars;
+        int m_numCapturedVars;
         int m_numParameters;
         bool m_isConstructor;
 
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index ab259a6..e409027 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -287,6 +287,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
 
         preserveLastVar();
     }
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
 }
 
 BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
@@ -347,16 +348,43 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
     }
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
+    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
+
+    // Captured variables and functions go first so that activations don't have
+    // to step over the non-captured locals to mark them.
+    if (functionBody->hasCapturedVariables()) {
+        for (size_t i = 0; i < functionStack.size(); ++i) {
+            FunctionBodyNode* function = functionStack[i];
+            const Identifier& ident = function->ident();
+            if (functionBody->captures(ident)) {
+                m_functions.add(ident.impl());
+                emitNewFunction(addVar(ident, false), function);
+            }
+        }
+        for (size_t i = 0; i < varStack.size(); ++i) {
+            const Identifier& ident = *varStack[i].first;
+            if (functionBody->captures(ident))
+                addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
+        }
+    }
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
         FunctionBodyNode* function = functionStack[i];
         const Identifier& ident = function->ident();
-        m_functions.add(ident.impl());
-        emitNewFunction(addVar(ident, false), function);
+        if (!functionBody->captures(ident)) {
+            m_functions.add(ident.impl());
+            emitNewFunction(addVar(ident, false), function);
+        }
     }
-
-    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
-    for (size_t i = 0; i < varStack.size(); ++i)
-        addVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+    for (size_t i = 0; i < varStack.size(); ++i) {
+        const Identifier& ident = *varStack[i].first;
+        if (!functionBody->captures(ident))
+            addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
+    }
+    
+    if (debugger)
+        codeBlock->m_numCapturedVars = codeBlock->m_numVars;
+        
 
     FunctionParameters& parameters = *functionBody->parameters();
     size_t parameterCount = parameters.size();
@@ -430,7 +458,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     for (size_t i = 0; i < numVariables; ++i)
         variables.append(*varStack[i].first);
     codeBlock->adoptVariables(variables);
-
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     preserveLastVar();
 }
 
diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h
index 2d8448c..5193fdd 100644
--- a/JavaScriptCore/parser/Nodes.h
+++ b/JavaScriptCore/parser/Nodes.h
@@ -1414,6 +1414,8 @@ namespace JSC {
         bool usesThis() const { return m_features & ThisFeature; }
         bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
         bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); }
+        size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); }
+        bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); }
 
         VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
         FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h
index d892de0..49c8b3b 100644
--- a/JavaScriptCore/runtime/Arguments.h
+++ b/JavaScriptCore/runtime/Arguments.h
@@ -225,7 +225,7 @@ namespace JSC {
         ASSERT(!d()->registerArray);
 
         size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
-        size_t numVars = d()->functionExecutable->variableCount();
+        size_t numVars = d()->functionExecutable->capturedVariableCount();
         size_t numLocals = numVars + numParametersMinusThis;
 
         if (!numLocals)
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
index e14955c..871f3e2 100644
--- a/JavaScriptCore/runtime/Executable.cpp
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -65,7 +65,7 @@ ProgramExecutable::~ProgramExecutable()
 
 FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
     : ScriptExecutable(globalData, source)
-    , m_numVariables(0)
+    , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
@@ -77,7 +77,7 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie
 
 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
     : ScriptExecutable(exec, source)
-    , m_numVariables(0)
+    , m_numCapturedVariables(0)
     , m_forceUsesArguments(forceUsesArguments)
     , m_parameters(parameters)
     , m_name(name)
@@ -197,7 +197,7 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain
     generator->generate();
     m_numParametersForCall = m_codeBlockForCall->m_numParameters;
     ASSERT(m_numParametersForCall);
-    m_numVariables = m_codeBlockForCall->m_numVars;
+    m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars;
     m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
 
     body->destroyData();
@@ -238,7 +238,7 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope
     generator->generate();
     m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters;
     ASSERT(m_numParametersForConstruct);
-    m_numVariables = m_codeBlockForConstruct->m_numVars;
+    m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars;
     m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
 
     body->destroyData();
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
index be8c43c..feab7ef 100644
--- a/JavaScriptCore/runtime/Executable.h
+++ b/JavaScriptCore/runtime/Executable.h
@@ -349,7 +349,7 @@ namespace JSC {
 
         const Identifier& name() { return m_name; }
         size_t parameterCount() const { return m_parameters->size(); }
-        unsigned variableCount() const { return m_numVariables; }
+        unsigned capturedVariableCount() const { return m_numCapturedVariables; }
         UString paramString() const;
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
 
@@ -366,7 +366,7 @@ namespace JSC {
 
         virtual PassOwnPtr<ExceptionInfo> reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
 
-        unsigned m_numVariables : 31;
+        unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
 
         RefPtr<FunctionParameters> m_parameters;
diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp
index 8cf71d0..d121518 100644
--- a/JavaScriptCore/runtime/JSActivation.cpp
+++ b/JavaScriptCore/runtime/JSActivation.cpp
@@ -62,12 +62,65 @@ void JSActivation::markChildren(MarkStack& markStack)
     size_t count = numParametersMinusThis;
     markStack.appendValues(registerArray, count);
 
-    size_t numVars = d()->functionExecutable->variableCount();
+    size_t numVars = d()->functionExecutable->capturedVariableCount();
 
     // Skip the call frame, which sits between the parameters and vars.
     markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
 }
 
+inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
+{
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+    if (!entry.isNull()) {
+        ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
+        slot.setRegisterSlot(&registerAt(entry.getIndex()));
+        return true;
+    }
+    return false;
+}
+
+inline bool JSActivation::symbolTablePut(const Identifier& propertyName, JSValue value)
+{
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+    if (entry.isNull())
+        return false;
+    if (entry.isReadOnly())
+        return true;
+    ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
+    registerAt(entry.getIndex()) = value;
+    return true;
+}
+
+void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    SymbolTable::const_iterator end = symbolTable().end();
+    for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+        ASSERT(it->second.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount()));
+        if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
+            propertyNames.add(Identifier(exec, it->first.get()));
+    }
+    // Skip the JSVariableObject implementation of getOwnPropertyNames
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+inline bool JSActivation::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    
+    SymbolTable::iterator iter = symbolTable().find(propertyName.impl());
+    if (iter == symbolTable().end())
+        return false;
+    SymbolTableEntry& entry = iter->second;
+    ASSERT(!entry.isNull());
+    if (entry.getIndex() >= static_cast<int>(d()->functionExecutable->capturedVariableCount()))
+        return false;
+    entry.setAttributes(attributes);
+    registerAt(entry.getIndex()) = value;
+    return true;
+}
+
 bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (propertyName == exec->propertyNames().arguments) {
diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h
index d5e7991..9ff9168 100644
--- a/JavaScriptCore/runtime/JSActivation.h
+++ b/JavaScriptCore/runtime/JSActivation.h
@@ -52,6 +52,7 @@ namespace JSC {
         virtual bool isActivationObject() const { return true; }
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode);
 
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
@@ -87,7 +88,13 @@ namespace JSC {
 
             RefPtr<FunctionExecutable> functionExecutable;
         };
-        
+
+        bool symbolTableGet(const Identifier&, PropertySlot&);
+        bool symbolTableGet(const Identifier&, PropertyDescriptor&);
+        bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
+        bool symbolTablePut(const Identifier&, JSValue);
+        bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
+
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list