Instead of watchpointing activation allocation, we should watchpoint entry into functions that have captured variables
https://bugs.webkit.org/show_bug.cgi?id=125052

Reviewed by Mark Hahnenberg.
        
This makes us watch function entry rather than activation creation. We only incur the
costs of doing so for functions that have captured variables, and only on the first two
entries into the function. This means that closure variable constant inference will
naturally work even for local uses of the captured variable, like:
        
    (function(){
        var blah = 42;
        ... // stuff
        function () { ... blah /* we can fold this to 42 */ }
        ... blah // we can also fold this to 42.
    })();
        
Previously, only the nested use would have been foldable.

* bytecode/BytecodeLivenessAnalysis.cpp:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/Opcode.h:
(JSC::padOpcodeName):
* bytecode/Watchpoint.h:
(JSC::WatchpointSet::touch):
(JSC::InlineWatchpointSet::touch):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasSymbolTable):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_touch_entry):
* llint/LowLevelInterpreter.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* runtime/JSActivation.h:
(JSC::JSActivation::create):
* runtime/SymbolTable.cpp:
(JSC::SymbolTable::SymbolTable):
* runtime/SymbolTable.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@159942 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index ce3136a..db1c3ef 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,78 @@
+2013-12-02  Filip Pizlo  <fpizlo@apple.com>
+
+        Instead of watchpointing activation allocation, we should watchpoint entry into functions that have captured variables
+        https://bugs.webkit.org/show_bug.cgi?id=125052
+
+        Reviewed by Mark Hahnenberg.
+        
+        This makes us watch function entry rather than activation creation. We only incur the
+        costs of doing so for functions that have captured variables, and only on the first two
+        entries into the function. This means that closure variable constant inference will
+        naturally work even for local uses of the captured variable, like:
+        
+            (function(){
+                var blah = 42;
+                ... // stuff
+                function () { ... blah /* we can fold this to 42 */ }
+                ... blah // we can also fold this to 42.
+            })();
+        
+        Previously, only the nested use would have been foldable.
+
+        * bytecode/BytecodeLivenessAnalysis.cpp:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecode/Opcode.h:
+        (JSC::padOpcodeName):
+        * bytecode/Watchpoint.h:
+        (JSC::WatchpointSet::touch):
+        (JSC::InlineWatchpointSet::touch):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasSymbolTable):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGWatchpointCollectionPhase.cpp:
+        (JSC::DFG::WatchpointCollectionPhase::handle):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_touch_entry):
+        * llint/LowLevelInterpreter.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+        * runtime/JSActivation.h:
+        (JSC::JSActivation::create):
+        * runtime/SymbolTable.cpp:
+        (JSC::SymbolTable::SymbolTable):
+        * runtime/SymbolTable.h:
+
 2013-12-02  Nick Diego Yamane  <nick.yamane@openbossa.org>
 
         [JSC] Get rid of some unused parameters in LLIntSlowPaths.cpp macros
diff --git a/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp b/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
index a119de0..28190ce 100644
--- a/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
+++ b/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp
@@ -89,6 +89,7 @@
     case op_init_lazy_reg:
     case op_get_callee:
     case op_enter:
+    case op_touch_entry:
     case op_catch:
         return;
     // First argument.
@@ -383,6 +384,7 @@
     case op_put_by_index:
     case op_del_by_id:
     case op_del_by_val:
+    case op_touch_entry:
 #define LLINT_HELPER_OPCODES(opcode, length) case opcode:
         FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
 #undef LLINT_HELPER_OPCODES
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index a0cb5b5..eceff1d 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -671,6 +671,10 @@
             printLocationAndOp(out, exec, location, it, "enter");
             break;
         }
+        case op_touch_entry: {
+            printLocationAndOp(out, exec, location, it, "touch_entry");
+            break;
+        }
         case op_create_activation: {
             int r0 = (++it)->u.operand;
             printLocationOpAndRegisterOperand(out, exec, location, it, "create_activation", r0);
diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h
index 3fb2142..97af6bd 100644
--- a/Source/JavaScriptCore/bytecode/Opcode.h
+++ b/Source/JavaScriptCore/bytecode/Opcode.h
@@ -42,6 +42,7 @@
 #define FOR_EACH_CORE_OPCODE_ID_WITH_EXTENSION(macro, extension__) \
     macro(op_enter, 1) \
     macro(op_create_activation, 2) \
+    macro(op_touch_entry, 1) \
     macro(op_init_lazy_reg, 2) \
     macro(op_create_arguments, 2) \
     macro(op_create_this, 4) \
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h
index c029d3c..37b72a7 100644
--- a/Source/JavaScriptCore/bytecode/Watchpoint.h
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.h
@@ -108,7 +108,7 @@
         fireAllSlow();
     }
     
-    void notifyWrite()
+    void touch()
     {
         if (state() == ClearWatchpoint)
             startWatching();
@@ -209,10 +209,10 @@
         WTF::storeStoreFence();
     }
     
-    void notifyWrite()
+    void touch()
     {
         if (isFat()) {
-            fat()->notifyWrite();
+            fat()->touch();
             return;
         }
         if (decodeState(m_data) == ClearWatchpoint)
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
index eebfad0..07a6e49 100644
--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
@@ -352,6 +352,9 @@
     if (shouldCaptureAllTheThings)
         m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
 
+    if (m_symbolTable->captureCount())
+        emitOpcode(op_touch_entry);
+    
     m_parameters.grow(parameters.size() + 1); // reserve space for "this"
 
     // Add "this" as a parameter
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
index 873e1f1..982142f 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
@@ -1146,7 +1146,7 @@
         m_state.setHaveStructures(true);
         break;
         
-    case ActivationAllocationWatchpoint:
+    case FunctionReentryWatchpoint:
         break;
     
     case CreateArguments:
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 7013da7..7807686 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -1881,7 +1881,12 @@
             for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i)
                 set(virtualRegisterForLocal(i), constantUndefined(), SetOnEntry);
             NEXT_OPCODE(op_enter);
-
+            
+        case op_touch_entry:
+            if (m_inlineStackTop->m_codeBlock->symbolTable()->m_functionEnteredOnce.isStillValid())
+                addToGraph(ForceOSRExit);
+            NEXT_OPCODE(op_touch_entry);
+            
         case op_to_this: {
             Node* op1 = getThis();
             if (op1->op() != ToThis) {
@@ -3003,8 +3008,8 @@
             case ClosureVarWithVarInjectionChecks: {
                 JSActivation* activation = currentInstruction[5].u.activation.get();
                 if (activation
-                    && activation->symbolTable()->m_activationAllocatedOnce.isStillValid()) {
-                    addToGraph(ActivationAllocationWatchpoint, OpInfo(activation->symbolTable()));
+                    && activation->symbolTable()->m_functionEnteredOnce.isStillValid()) {
+                    addToGraph(FunctionReentryWatchpoint, OpInfo(activation->symbolTable()));
                     set(VirtualRegister(dst), cellConstant(activation));
                     break;
                 }
diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
index 6240367..ccc78a8 100644
--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
@@ -81,6 +81,7 @@
 {
     switch (opcodeID) {
     case op_enter:
+    case op_touch_entry:
     case op_to_this:
     case op_create_this:
     case op_get_callee:
diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h
index 5dca256..0ef7c22 100644
--- a/Source/JavaScriptCore/dfg/DFGClobberize.h
+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h
@@ -160,7 +160,7 @@
         write(GCState);
         return;
         
-    case ActivationAllocationWatchpoint:
+    case FunctionReentryWatchpoint:
         read(Watchpoint_fire);
         return;
 
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index 54fa2d3..dfc21da 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -950,7 +950,7 @@
         case Unreachable:
         case ExtractOSREntryLocal:
         case LoopHint:
-        case ActivationAllocationWatchpoint:
+        case FunctionReentryWatchpoint:
             break;
 #else
         default:
diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h
index a3564c0..c40f112 100644
--- a/Source/JavaScriptCore/dfg/DFGNode.h
+++ b/Source/JavaScriptCore/dfg/DFGNode.h
@@ -1063,7 +1063,7 @@
     
     bool hasSymbolTable()
     {
-        return op() == ActivationAllocationWatchpoint;
+        return op() == FunctionReentryWatchpoint;
     }
     
     SymbolTable* symbolTable()
diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h
index 50a2c20..34c6a68 100644
--- a/Source/JavaScriptCore/dfg/DFGNodeType.h
+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h
@@ -187,7 +187,7 @@
     macro(NotifyWrite, NodeMustGenerate) \
     macro(VariableWatchpoint, NodeMustGenerate) \
     macro(VarInjectionWatchpoint, NodeMustGenerate) \
-    macro(ActivationAllocationWatchpoint, NodeMustGenerate) \
+    macro(FunctionReentryWatchpoint, NodeMustGenerate) \
     macro(CheckFunction, NodeMustGenerate) \
     macro(AllocationProfileWatchpoint, NodeMustGenerate) \
     \
diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
index 6eb10fb..862770a 100644
--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
@@ -576,7 +576,7 @@
         case Unreachable:
         case LoopHint:
         case NotifyWrite:
-        case ActivationAllocationWatchpoint:
+        case FunctionReentryWatchpoint:
             break;
             
         // This gets ignored because it already has a prediction.
diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
index 8a46880..1fa3b12 100644
--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
@@ -243,7 +243,7 @@
     case Int52ToValue:
     case InvalidationPoint:
     case NotifyWrite:
-    case ActivationAllocationWatchpoint:
+    case FunctionReentryWatchpoint:
         return true;
         
     case GetByVal:
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
index 519fafa..6d6cbaa 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
@@ -4336,7 +4336,7 @@
         break;
     }
         
-    case ActivationAllocationWatchpoint: {
+    case FunctionReentryWatchpoint: {
         noResult(node);
         break;
     }
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
index 998baa3..40eab9d 100644
--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
@@ -4611,7 +4611,7 @@
         break;
     }
         
-    case ActivationAllocationWatchpoint: {
+    case FunctionReentryWatchpoint: {
         noResult(node);
         break;
     }
diff --git a/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp b/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
index 102bf7a..4d4bf0b 100644
--- a/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
@@ -126,8 +126,8 @@
             addLazily(globalObject()->varInjectionWatchpoint());
             break;
             
-        case ActivationAllocationWatchpoint:
-            addLazily(m_node->symbolTable()->m_activationAllocatedOnce);
+        case FunctionReentryWatchpoint:
+            addLazily(m_node->symbolTable()->m_functionEnteredOnce);
             break;
             
         default:
diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
index 2c497ac..cafe356 100644
--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
@@ -102,7 +102,7 @@
     case CheckFunction:
     case StringCharCodeAt:
     case AllocatePropertyStorage:
-    case ActivationAllocationWatchpoint:
+    case FunctionReentryWatchpoint:
     case VariableWatchpoint:
     case NotifyWrite:
         // These are OK.
diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
index 70c32cb..06aa8b20 100644
--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
@@ -399,7 +399,7 @@
             break;
         case VariableWatchpoint:
             break;
-        case ActivationAllocationWatchpoint:
+        case FunctionReentryWatchpoint:
             break;
         case GetMyScope:
             compileGetMyScope();
diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp
index 997d2f2..e72214c 100644
--- a/Source/JavaScriptCore/jit/JIT.cpp
+++ b/Source/JavaScriptCore/jit/JIT.cpp
@@ -109,38 +109,13 @@
     m_bytecodeOffset += OPCODE_LENGTH(name); \
     break;
 
-#if USE(JSVALUE32_64)
-#define DEFINE_BINARY_OP(name) \
+#define DEFINE_SLOW_OP(name) \
     case op_##name: { \
         JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_##name); \
         slowPathCall.call(); \
         NEXT_OPCODE(op_##name); \
     }
 
-#define DEFINE_UNARY_OP(name) \
-    case op_##name: { \
-        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_##name); \
-        slowPathCall.call(); \
-        NEXT_OPCODE(op_##name); \
-    }
-
-#else // USE(JSVALUE32_64)
-
-#define DEFINE_BINARY_OP(name) \
-    case op_##name: { \
-        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_##name); \
-        slowPathCall.call(); \
-        NEXT_OPCODE(op_##name); \
-    }
-
-#define DEFINE_UNARY_OP(name) \
-    case op_##name: { \
-        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_##name); \
-        slowPathCall.call(); \
-        NEXT_OPCODE(op_##name); \
-    }
-#endif // USE(JSVALUE32_64)
-
 #define DEFINE_OP(name) \
     case name: { \
         emit_##name(currentInstruction); \
@@ -187,16 +162,17 @@
         }
 
         switch (opcodeID) {
-        DEFINE_BINARY_OP(del_by_val)
-        DEFINE_BINARY_OP(in)
-        DEFINE_BINARY_OP(less)
-        DEFINE_BINARY_OP(lesseq)
-        DEFINE_BINARY_OP(greater)
-        DEFINE_BINARY_OP(greatereq)
-        DEFINE_UNARY_OP(is_function)
-        DEFINE_UNARY_OP(is_object)
-        DEFINE_UNARY_OP(typeof)
+        DEFINE_SLOW_OP(del_by_val)
+        DEFINE_SLOW_OP(in)
+        DEFINE_SLOW_OP(less)
+        DEFINE_SLOW_OP(lesseq)
+        DEFINE_SLOW_OP(greater)
+        DEFINE_SLOW_OP(greatereq)
+        DEFINE_SLOW_OP(is_function)
+        DEFINE_SLOW_OP(is_object)
+        DEFINE_SLOW_OP(typeof)
 
+        DEFINE_OP(op_touch_entry)
         DEFINE_OP(op_add)
         DEFINE_OP(op_bitand)
         DEFINE_OP(op_bitor)
diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h
index 7f3f238..9d227c6 100644
--- a/Source/JavaScriptCore/jit/JIT.h
+++ b/Source/JavaScriptCore/jit/JIT.h
@@ -455,6 +455,7 @@
         void emit_compareAndJump(OpcodeID, int op1, int op2, unsigned target, RelationalCondition);
         void emit_compareAndJumpSlow(int op1, int op2, unsigned target, DoubleCondition, size_t (JIT_OPERATION *operation)(ExecState*, EncodedJSValue, EncodedJSValue), bool invert, Vector<SlowCaseEntry>::iterator&);
 
+        void emit_op_touch_entry(Instruction*);
         void emit_op_add(Instruction*);
         void emit_op_bitand(Instruction*);
         void emit_op_bitor(Instruction*);
diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp
index 5110ec0..0d2e802 100644
--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1096,6 +1096,15 @@
 
 #endif // USE(JSVALUE64)
 
+void JIT::emit_op_touch_entry(Instruction* currentInstruction)
+{
+    if (m_codeBlock->symbolTable()->m_functionEnteredOnce.hasBeenInvalidated())
+        return;
+    
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_touch_entry);
+    slowPathCall.call();
+}
+
 void JIT::emit_op_loop_hint(Instruction*)
 {
     // Emit the JIT optimization check: 
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
index 1040186..96a9d0f 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
@@ -476,6 +476,12 @@
 
 
 # Value-representation-agnostic code.
+_llint_op_touch_entry:
+    traceExecution()
+    callSlowPath(_slow_path_touch_entry)
+    dispatch(1)
+
+
 _llint_op_new_array:
     traceExecution()
     callSlowPath(_llint_slow_path_new_array)
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
index be6ac59..8504532 100644
--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
@@ -193,6 +193,13 @@
     RETURN_TWO(0, reinterpret_cast<ExecState*>(SlotsToAdd));
 }
 
+SLOW_PATH_DECL(slow_path_touch_entry)
+{
+    BEGIN();
+    exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch();
+    END();
+}
+
 SLOW_PATH_DECL(slow_path_get_callee)
 {
     BEGIN();
diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
index 0addc96..6747fb0 100644
--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h
+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h
@@ -160,6 +160,7 @@
     
 SLOW_PATH_HIDDEN_DECL(slow_path_call_arityCheck);
 SLOW_PATH_HIDDEN_DECL(slow_path_construct_arityCheck);
+SLOW_PATH_HIDDEN_DECL(slow_path_touch_entry);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
 SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h
index bb21636..96bfd7f 100644
--- a/Source/JavaScriptCore/runtime/JSActivation.h
+++ b/Source/JavaScriptCore/runtime/JSActivation.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -50,7 +50,6 @@
     {
         SymbolTable* symbolTable = codeBlock->symbolTable();
         ASSERT(codeBlock->codeType() == FunctionCode);
-        symbolTable->m_activationAllocatedOnce.notifyWrite();
         JSActivation* activation = new (
             NotNull,
             allocateCell<JSActivation>(
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp
index e9e478e..a2e15a2 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.cpp
+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp
@@ -99,7 +99,7 @@
     , m_usesNonStrictEval(false)
     , m_captureStart(0)
     , m_captureEnd(0)
-    , m_activationAllocatedOnce(ClearWatchpoint)
+    , m_functionEnteredOnce(ClearWatchpoint)
 {
 }
 
diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h
index b5b0683..9a92146 100644
--- a/Source/JavaScriptCore/runtime/SymbolTable.h
+++ b/Source/JavaScriptCore/runtime/SymbolTable.h
@@ -497,7 +497,7 @@
     std::unique_ptr<WatchpointCleanup> m_watchpointCleanup;
 
 public:
-    InlineWatchpointSet m_activationAllocatedOnce;
+    InlineWatchpointSet m_functionEnteredOnce;
     
     mutable ConcurrentJITLock m_lock;
 };