[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 14:07:28 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit f312e22a50dbca241843de9702d42a6597deb6f7
Author: oliver at apple.com <oliver at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Oct 4 22:43:18 2010 +0000

    2010-10-04  Oliver Hunt  <oliver at 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):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@69045 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 75a5f5b..b1bcd7c 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,70 @@
+2010-10-04  Oliver Hunt  <oliver at 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):
+
 2010-10-04  Adam Barth  <abarth at webkit.org>
 
         Reviewed by Sam Weinig.
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 675d26d..8e78bbc 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -2407,6 +2407,7 @@
 			isa = PBXProject;
 			buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
 			compatibilityVersion = "Xcode 2.4";
+			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				English,
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 6c0696e..a2b863d 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -34,6 +34,7 @@
 #include "Debugger.h"
 #include "Interpreter.h"
 #include "JIT.h"
+#include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSStaticScopeObject.h"
 #include "JSValue.h"
@@ -485,9 +486,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] enter\n", location);
             break;
         }
-        case op_enter_with_activation: {
+        case op_create_activation: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data());
+            printf("[%4d] create_activation %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_create_arguments: {
@@ -722,9 +723,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             int id0 = (++it)->u.operand;
             JSValue scope = JSValue((++it)->u.jsCell);
             ++it;
-            int depth = it[2].u.operand;
+            int depth = (++it)->u.operand;
             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);
-            it += 3;
             break;
         }
         case op_get_scoped_var: {
@@ -1542,6 +1542,10 @@ bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
     ASSERT(!m_rareData || !m_rareData->m_exceptionHandlers.size());
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     if (m_needsFullScopeChain) {
+        if (codeType() == FunctionCode && !callFrame->r(activationRegister()).jsValue()) {
+            createActivation(callFrame);
+            scopeChain = callFrame->scopeChain();
+        }
         ScopeChain sc(scopeChain);
         int scopeDelta = sc.localDepth();
         if (m_codeType == EvalCode)
@@ -1765,4 +1769,14 @@ void CodeBlock::shrinkToFit()
     }
 }
 
+void CodeBlock::createActivation(CallFrame* callFrame)
+{
+    ASSERT(codeType() == FunctionCode);
+    ASSERT(needsFullScopeChain());
+    ASSERT(!callFrame->r(activationRegister()).jsValue());
+    JSActivation* activation = new (callFrame) JSActivation(callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
+    callFrame->r(activationRegister()) = JSValue(activation);
+    callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
+}
+
 } // namespace JSC
diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h
index cda4530..86971cb 100644
--- a/JavaScriptCore/bytecode/CodeBlock.h
+++ b/JavaScriptCore/bytecode/CodeBlock.h
@@ -408,6 +408,15 @@ namespace JSC {
             ASSERT(usesArguments());
             return m_argumentsRegister;
         }
+        void setActivationRegister(int activationRegister)
+        {
+            m_activationRegister = activationRegister;
+        }
+        int activationRegister()
+        {
+            ASSERT(needsFullScopeChain());
+            return m_activationRegister;
+        }
         bool usesArguments() const { return m_argumentsRegister != -1; }
 
         CodeType codeType() const { return m_codeType; }
@@ -420,6 +429,8 @@ namespace JSC {
         unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
         unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
 
+        void createActivation(CallFrame*);
+
 #if ENABLE(INTERPRETER)
         void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
         void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
@@ -548,6 +559,7 @@ namespace JSC {
 
         int m_thisRegister;
         int m_argumentsRegister;
+        int m_activationRegister;
 
         bool m_needsFullScopeChain;
         bool m_usesEval;
diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h
index 03f6573..3f6b213 100644
--- a/JavaScriptCore/bytecode/Opcode.h
+++ b/JavaScriptCore/bytecode/Opcode.h
@@ -39,7 +39,7 @@ namespace JSC {
 
     #define FOR_EACH_OPCODE_ID(macro) \
         macro(op_enter, 1) \
-        macro(op_enter_with_activation, 2) \
+        macro(op_create_activation, 2) \
         macro(op_init_lazy_reg, 2) \
         macro(op_create_arguments, 2) \
         macro(op_create_this, 3) \
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index 986709b..4c6e1f3 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -214,6 +214,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
     , m_nextGlobalIndex(-1)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
+    , m_hasCreatedActivation(true)
     , m_firstLazyFunction(0)
     , m_lastLazyFunction(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
@@ -306,6 +307,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
     , m_codeType(FunctionCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
+    , m_hasCreatedActivation(false)
     , m_firstLazyFunction(0)
     , m_lastLazyFunction(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
@@ -319,13 +321,13 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
         m_codeBlock->setNeedsFullScopeChain(true);
 
     codeBlock->setGlobalData(m_globalData);
-
+    
+    emitOpcode(op_enter);
     if (m_codeBlock->needsFullScopeChain()) {
         m_activationRegister = addVar();
-        emitOpcode(op_enter_with_activation);
-        instructions().append(m_activationRegister->index());
-    } else
-        emitOpcode(op_enter);
+        emitInitLazyRegister(m_activationRegister);
+        m_codeBlock->setActivationRegister(m_activationRegister->index());
+    }
 
     // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
     // object, if created.
@@ -356,11 +358,17 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
 
     // Captured variables and functions go first so that activations don't have
     // to step over the non-captured locals to mark them.
+    m_hasCreatedActivation = false;
     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)) {
+                if (!m_hasCreatedActivation) {
+                    m_hasCreatedActivation = true;
+                    emitOpcode(op_create_activation);
+                    instructions().append(m_activationRegister->index());
+                }
                 m_functions.add(ident.impl());
                 emitNewFunction(addVar(ident, false), function);
             }
@@ -371,7 +379,13 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
                 addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
         }
     }
-    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables();
+    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !debugger;
+    if (!canLazilyCreateFunctions && !m_hasCreatedActivation) {
+        m_hasCreatedActivation = true;
+        emitOpcode(op_create_activation);
+        instructions().append(m_activationRegister->index());
+    }
+
     codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     m_firstLazyFunction = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
@@ -399,7 +413,6 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
     
     if (debugger)
         codeBlock->m_numCapturedVars = codeBlock->m_numVars;
-        
 
     FunctionParameters& parameters = *functionBody->parameters();
     size_t parameterCount = parameters.size();
@@ -448,6 +461,7 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     , m_codeType(EvalCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
+    , m_hasCreatedActivation(true)
     , m_firstLazyFunction(0)
     , m_lastLazyFunction(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
@@ -1504,6 +1518,7 @@ RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBody
 
 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck)
 {
+    createActivationIfNecessary();
     emitOpcode(op_new_func);
     instructions().append(dst->index());
     instructions().append(index);
@@ -1523,7 +1538,8 @@ RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExp
 {
     FunctionBodyNode* function = n->body();
     unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
-
+    
+    createActivationIfNecessary();
     emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
     instructions().append(index);
@@ -1545,6 +1561,16 @@ void BytecodeGenerator::createArgumentsIfNecessary()
     instructions().append(m_codeBlock->argumentsRegister());
 }
 
+void BytecodeGenerator::createActivationIfNecessary()
+{
+    if (m_hasCreatedActivation)
+        return;
+    if (!m_codeBlock->needsFullScopeChain())
+        return;
+    emitOpcode(op_create_activation);
+    instructions().append(m_activationRegister->index());
+}
+
 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
     return emitCall(op_call_eval, dst, func, callArguments, divot, startOffset, endOffset);
diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
index 861711a..b6047ae 100644
--- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h
+++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h
@@ -518,6 +518,7 @@ namespace JSC {
         RegisterID* emitThrowExpressionTooDeepException();
 
         void createArgumentsIfNecessary();
+        void createActivationIfNecessary();
         RegisterID* createLazyRegisterIfNecessary(RegisterID*);
 
         bool m_shouldEmitDebugHooks;
@@ -558,6 +559,7 @@ namespace JSC {
 
         int m_globalVarStorageOffset;
 
+        bool m_hasCreatedActivation;
         int m_firstLazyFunction;
         int m_lastLazyFunction;
         HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 5943ece..fedc3b7 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -127,6 +127,12 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator end = scopeChain->end();
     ASSERT(iter != end);
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (callFrame->r(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
     while (skip--) {
         ++iter;
         ASSERT(iter != end);
@@ -140,6 +146,7 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
             exceptionValue = callFrame->globalData().exception;
             if (exceptionValue)
                 return false;
+            ASSERT(result);
             callFrame->r(dst) = JSValue(result);
             return true;
         }
@@ -203,6 +210,12 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator end = scopeChain->end();
     ASSERT(iter != end);
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (callFrame->r(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
     while (skip--) {
         JSObject* o = *iter;
         if (o->hasCustomProperties()) {
@@ -214,6 +227,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
                     exceptionValue = callFrame->globalData().exception;
                     if (exceptionValue)
                         return false;
+                    ASSERT(result);
                     callFrame->r(dst) = JSValue(result);
                     return true;
                 }
@@ -230,6 +244,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
     
     if (structure == globalObject->structure()) {
         callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
+        ASSERT(callFrame->r(dst).jsValue());
         return true;
     }
 
@@ -243,6 +258,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
             globalObject->structure()->ref();
             vPC[3] = globalObject->structure();
             vPC[4] = slot.cachedOffset();
+            ASSERT(result);
             callFrame->r(dst) = JSValue(result);
             return true;
         }
@@ -250,6 +266,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
         exceptionValue = callFrame->globalData().exception;
         if (exceptionValue)
             return false;
+        ASSERT(result);
         callFrame->r(dst) = JSValue(result);
         return true;
     }
@@ -263,6 +280,7 @@ NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vP
     int dst = vPC[1].u.operand;
     int property = vPC[2].u.operand;
     callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
+    ASSERT(callFrame->r(dst).jsValue());
 }
 
 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
@@ -535,6 +553,10 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
 
     // If this call frame created an activation or an 'arguments' object, tear it off.
     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
+        if (!callFrame->r(oldCodeBlock->activationRegister()).jsValue()) {
+            oldCodeBlock->createActivation(callFrame);
+            scopeChain = callFrame->scopeChain();
+        }
         while (!scopeChain->object->inherits(&JSActivation::info))
             scopeChain = scopeChain->pop();
         JSActivation* activation = asActivation(scopeChain->object);
@@ -646,7 +668,10 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
     // Unwind the scope chain within the exception handler's call frame.
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChain sc(scopeChain);
-    int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
+    int scopeDelta = 0;
+    if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode 
+        || callFrame->r(codeBlock->activationRegister()).jsValue())
+        scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
     ASSERT(scopeDelta >= 0);
     while (scopeDelta--)
         scopeChain = scopeChain->pop();
@@ -1518,6 +1543,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
+        
         callFrame->r(dst) = callFrame->r(src);
 
         vPC += OPCODE_LENGTH(op_mov);
@@ -2327,6 +2353,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
         ASSERT(iter != end);
+        ASSERT(codeBlock == callFrame->codeBlock());
+        bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+        ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+            if (callFrame->r(codeBlock->activationRegister()).jsValue())
+                ++iter;
+        }
         while (skip--) {
             ++iter;
             ASSERT(iter != end);
@@ -2334,6 +2367,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ASSERT((*iter)->isVariableObject());
         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
         callFrame->r(dst) = scope->registerAt(index);
+        ASSERT(callFrame->r(dst).jsValue());
         vPC += OPCODE_LENGTH(op_get_scoped_var);
         NEXT_INSTRUCTION();
     }
@@ -2348,7 +2382,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
+        ASSERT(codeBlock == callFrame->codeBlock());
         ASSERT(iter != end);
+        bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+        ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+            if (callFrame->r(codeBlock->activationRegister()).jsValue())
+                ++iter;
+        }
         while (skip--) {
             ++iter;
             ASSERT(iter != end);
@@ -2356,6 +2397,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         ASSERT((*iter)->isVariableObject());
         JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
+        ASSERT(callFrame->r(value).jsValue());
         scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
         vPC += OPCODE_LENGTH(op_put_scoped_var);
         NEXT_INSTRUCTION();
@@ -3658,7 +3700,7 @@ skip_id_custom_self:
         int dst = vPC[1].u.operand;
         int func = vPC[2].u.operand;
         int shouldCheck = vPC[3].u.operand;
-
+        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
         if (!shouldCheck || !callFrame->r(dst).jsValue())
             callFrame->r(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
 
@@ -3675,7 +3717,8 @@ skip_id_custom_self:
         */
         int dst = vPC[1].u.operand;
         int funcIndex = vPC[2].u.operand;
-
+        
+        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
         FunctionExecutable* function = codeBlock->functionExpr(funcIndex);
         JSFunction* func = function->make(callFrame, callFrame->scopeChain());
 
@@ -3711,7 +3754,8 @@ skip_id_custom_self:
         int func = vPC[1].u.operand;
         int argCount = vPC[2].u.operand;
         int registerOffset = vPC[3].u.operand;
-
+        
+        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
         JSValue funcVal = callFrame->r(func).jsValue();
 
         Register* newCallFrame = callFrame->registers() + registerOffset;
@@ -3980,15 +4024,17 @@ skip_id_custom_self:
            This opcode appears before op_ret in functions that require full scope chains.
         */
 
-        int src1 = vPC[1].u.operand;
-        int src2 = vPC[2].u.operand;
+        int activation = vPC[1].u.operand;
+        int arguments = vPC[2].u.operand;
         ASSERT(codeBlock->needsFullScopeChain());
+        JSValue activationValue = callFrame->r(activation).jsValue();
+        if (activationValue) {
+            asActivation(activationValue)->copyRegisters();
 
-        JSActivation* activation = asActivation(callFrame->r(src1).jsValue());
-        activation->copyRegisters();
-
-        if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src2)).jsValue())
-            asArguments(arguments)->setActivation(activation);
+            if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())
+                asArguments(argumentsValue)->setActivation(asActivation(activationValue));
+        } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue())
+            asArguments(argumentsValue)->copyRegisters();
 
         vPC += OPCODE_LENGTH(op_tear_off_activation);
         NEXT_INSTRUCTION();
@@ -4026,7 +4072,7 @@ skip_id_custom_self:
 
         int result = vPC[1].u.operand;
 
-        if (callFrame->codeBlock()->needsFullScopeChain())
+        if (callFrame->codeBlock()->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue())
             callFrame->scopeChain()->deref();
 
         JSValue returnValue = callFrame->r(result).jsValue();
@@ -4067,7 +4113,7 @@ skip_id_custom_self:
 
         int result = vPC[1].u.operand;
 
-        if (codeBlock->needsFullScopeChain())
+        if (codeBlock->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue())
             callFrame->scopeChain()->deref();
 
         JSValue returnValue = callFrame->r(result).jsValue();
@@ -4103,25 +4149,20 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_enter);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_enter_with_activation) {
-        /* enter_with_activation dst(r)
-
-           Initializes local variables to undefined, creates an activation object,
-           places it in dst, and pushes it onto the scope chain.
+    DEFINE_OPCODE(op_create_activation) {
+        /* create_activation dst(r)
 
-           This opcode appears only at the beginning of a code block.
+           If the activation object for this callframe has not yet been created,
+           this creates it and writes it back to dst.
         */
 
-        size_t i = 0;
-        for (size_t count = codeBlock->m_numVars; i < count; ++i)
-            callFrame->r(i) = jsUndefined();
-
-        int dst = vPC[1].u.operand;
-        JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
-        callFrame->r(dst) = JSValue(activation);
-        callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
-
-        vPC += OPCODE_LENGTH(op_enter_with_activation);
+        int activationReg = vPC[1].u.operand;
+        if (!callFrame->r(activationReg).jsValue()) {
+            JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
+            callFrame->r(activationReg) = JSValue(activation);
+            callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
+        }
+        vPC += OPCODE_LENGTH(op_create_activation);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_callee) {
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index a508d0c..f3e9e62 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -234,7 +234,7 @@ void JIT::privateCompileMainPass()
 #endif
         DEFINE_OP(op_end)
         DEFINE_OP(op_enter)
-        DEFINE_OP(op_enter_with_activation)
+        DEFINE_OP(op_create_activation)
         DEFINE_OP(op_eq)
         DEFINE_OP(op_eq_null)
         DEFINE_OP(op_get_by_id)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 6b2e70e..8cb2055 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -744,7 +744,7 @@ namespace JSC {
         void emit_op_div(Instruction*);
         void emit_op_end(Instruction*);
         void emit_op_enter(Instruction*);
-        void emit_op_enter_with_activation(Instruction*);
+        void emit_op_create_activation(Instruction*);
         void emit_op_eq(Instruction*);
         void emit_op_eq_null(Instruction*);
         void emit_op_get_by_id(Instruction*);
diff --git a/JavaScriptCore/jit/JITCall32_64.cpp b/JavaScriptCore/jit/JITCall32_64.cpp
index e4005ae..daf5d2d 100644
--- a/JavaScriptCore/jit/JITCall32_64.cpp
+++ b/JavaScriptCore/jit/JITCall32_64.cpp
@@ -108,9 +108,11 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
     unsigned dst = currentInstruction[1].u.operand;
 
     // We could JIT generate the deref, only calling out to C when the refcount hits zero.
-    if (m_codeBlock->needsFullScopeChain())
+    if (m_codeBlock->needsFullScopeChain()) {
+        Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
         JITStubCall(this, cti_op_ret_scopeChain).call();
-
+        activationNotCreated.link(this);
+    }
     emitLoad(dst, regT1, regT0);
     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
@@ -125,8 +127,11 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
     unsigned thisReg = currentInstruction[2].u.operand;
 
     // We could JIT generate the deref, only calling out to C when the refcount hits zero.
-    if (m_codeBlock->needsFullScopeChain())
+    if (m_codeBlock->needsFullScopeChain()) {
+        Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
         JITStubCall(this, cti_op_ret_scopeChain).call();
+        activationNotCreated.link(this);
+    }
 
     emitLoad(result, regT1, regT0);
     Jump notJSCell = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index c81932a..718548a 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -337,6 +337,7 @@ void JIT::emit_op_end(Instruction* currentInstruction)
 {
     if (m_codeBlock->needsFullScopeChain())
         JITStubCall(this, cti_op_end).call();
+
     ASSERT(returnValueRegister != callFrameRegister);
     emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
     restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
@@ -467,6 +468,15 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
     int skip = currentInstruction[3].u.operand;
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
 
@@ -481,6 +491,15 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
     emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
 
@@ -490,10 +509,16 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
 {
+    unsigned activation = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    Jump activationCreated = branchTestPtr(NonZero, addressFor(activation));
+    Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments));
+    activationCreated.link(this);
     JITStubCall stubCall(this, cti_op_tear_off_activation);
-    stubCall.addArgument(currentInstruction[1].u.operand, regT2);
-    stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand), regT2);
+    stubCall.addArgument(activation, regT2);
+    stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2);
     stubCall.call();
+    argumentsNotCreated.link(this);
 }
 
 void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
@@ -510,9 +535,11 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
     // We could JIT generate the deref, only calling out to C when the refcount hits zero.
-    if (m_codeBlock->needsFullScopeChain())
+    if (m_codeBlock->needsFullScopeChain()) {
+        Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
         JITStubCall(this, cti_op_ret_scopeChain).call();
-
+        activationNotCreated.link(this);
+    }
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -534,8 +561,11 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
 void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
     // We could JIT generate the deref, only calling out to C when the refcount hits zero.
-    if (m_codeBlock->needsFullScopeChain())
+    if (m_codeBlock->needsFullScopeChain()) {
+        Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
         JITStubCall(this, cti_op_ret_scopeChain).call();
+        activationNotCreated.link(this);
+    }
 
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
@@ -1185,16 +1215,14 @@ void JIT::emit_op_enter(Instruction*)
 
 }
 
-void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
+void JIT::emit_op_create_activation(Instruction* currentInstruction)
 {
-    // Even though CTI doesn't use them, we initialize our constant
-    // registers to zap stale pointers, to avoid unnecessarily prolonging
-    // object lifetime and increasing GC pressure.
-    size_t count = m_codeBlock->m_numVars;
-    for (size_t j = 0; j < count; ++j)
-        emitInitRegister(j);
-
+    unsigned dst = currentInstruction[1].u.operand;
+    
+    Jump activationCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
     JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
+    emitPutVirtualRegister(dst);
+    activationCreated.link(this);
 }
 
 void JIT::emit_op_create_arguments(Instruction* currentInstruction)
@@ -1559,6 +1587,18 @@ void JIT::emit_op_resolve_global_dynamic(Instruction* currentInstruction)
     int skip = currentInstruction[5].u.operand;
     
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
+    
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
+        addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+        activationNotCreated.link(this);
+    }
     while (skip--) {
         loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
         addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get()));
diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp
index ad3b558..fad85e4 100644
--- a/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -610,6 +610,15 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
     int skip = currentInstruction[3].u.operand;
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
 
@@ -631,6 +640,15 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
     emitLoad(value, regT1, regT0);
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag));
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
 
@@ -644,10 +662,16 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
 {
+    unsigned activation = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag));
+    Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), Imm32(JSValue::EmptyValueTag));
+    activationCreated.link(this);
     JITStubCall stubCall(this, cti_op_tear_off_activation);
     stubCall.addArgument(currentInstruction[1].u.operand);
     stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand));
     stubCall.call();
+    argumentsNotCreated.link(this);
 }
 
 void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
@@ -1467,11 +1491,13 @@ void JIT::emit_op_enter(Instruction*)
         emitStore(i, jsUndefined());
 }
 
-void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
+void JIT::emit_op_create_activation(Instruction* currentInstruction)
 {
-    emit_op_enter(currentInstruction);
-
-    JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
+    unsigned activation = currentInstruction[1].u.operand;
+    
+    Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag));
+    JITStubCall(this, cti_op_push_activation).call(activation);
+    activationCreated.link(this);
 }
 
 void JIT::emit_op_create_arguments(Instruction* currentInstruction)
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index f1ec079..07adc68 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1906,7 +1906,8 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
+    
+    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
 }
 
@@ -2213,6 +2214,12 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
+    JSValue activationValue = stackFrame.args[0].jsValue();
+    if (!activationValue) {
+        if (JSValue v = stackFrame.args[1].jsValue())
+            asArguments(v)->copyRegisters();
+        return;
+    }
     JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
     activation->copyRegisters();
     if (JSValue v = stackFrame.args[1].jsValue())
@@ -2685,6 +2692,13 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator end = scopeChain->end();
     ASSERT(iter != end);
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (callFrame->r(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
     while (skip--) {
         ++iter;
         ASSERT(iter != end);
@@ -2700,7 +2714,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
         }
     } while (++iter != end);
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
     unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
     stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
     VM_THROW_EXCEPTION();
@@ -3049,6 +3062,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
 
     FunctionExecutable* function = stackFrame.args[0].function();
     JSFunction* func = function->make(callFrame, callFrame->scopeChain());
+    ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->r(callFrame->codeBlock()->activationRegister()).jsValue());
 
     /* 
         The Identifier in a FunctionExpression can be referenced from inside
@@ -3155,6 +3169,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
+    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
 
     CallFrame* callFrame = stackFrame.callFrame;
     RegisterFile* registerFile = stackFrame.registerFile;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list