put_to_scope[5] should not point to the structure if it's a variable access, but...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Nov 2013 23:19:53 +0000 (23:19 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 18 Nov 2013 23:19:53 +0000 (23:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=124539

Reviewed by Mark Hahnenberg.

This is in preparation for getting put_to_scope to directly invalidate the watchpoint set
on stores, which will allow us to run constant inference on all globals.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::finalizeUnconditionally):
* bytecode/Instruction.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* runtime/JSScope.cpp:
(JSC::abstractAccess):
(JSC::JSScope::abstractResolve):
* runtime/JSScope.h:
(JSC::ResolveOp::ResolveOp):
* runtime/SymbolTable.h:
(JSC::SymbolTableEntry::watchpointSet):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@159462 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/runtime/JSScope.cpp
Source/JavaScriptCore/runtime/JSScope.h
Source/JavaScriptCore/runtime/SymbolTable.h

index c726ef4..80ba137 100644 (file)
@@ -1,3 +1,27 @@
+2013-11-18  Filip Pizlo  <fpizlo@apple.com>
+
+        put_to_scope[5] should not point to the structure if it's a variable access, but it should point to the WatchpointSet
+        https://bugs.webkit.org/show_bug.cgi?id=124539
+
+        Reviewed by Mark Hahnenberg.
+        
+        This is in preparation for getting put_to_scope to directly invalidate the watchpoint set
+        on stores, which will allow us to run constant inference on all globals.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::finalizeUnconditionally):
+        * bytecode/Instruction.h:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * runtime/JSScope.cpp:
+        (JSC::abstractAccess):
+        (JSC::JSScope::abstractResolve):
+        * runtime/JSScope.h:
+        (JSC::ResolveOp::ResolveOp):
+        * runtime/SymbolTable.h:
+        (JSC::SymbolTableEntry::watchpointSet):
+
 2013-11-18  Mark Hahnenberg  <mhahnenberg@apple.com>
 
         APIEntryShims need some love
index 06750b8..e63b192 100644 (file)
@@ -1882,7 +1882,10 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), scope, ident, Put, modeAndType.type());
 
             instructions[i + 4].u.operand = ResolveModeAndType(modeAndType.mode(), op.type).operand();
-            if (op.structure)
+            if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks) {
+                ASSERT(!op.structure);
+                instructions[i + 5].u.watchpointSet = op.watchpointSet;
+            } else if (op.structure)
                 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
             break;
@@ -2274,6 +2277,10 @@ void CodeBlock::finalizeUnconditionally()
                 break;
             case op_get_from_scope:
             case op_put_to_scope: {
+                ResolveModeAndType modeAndType =
+                    ResolveModeAndType(curInstruction[4].u.operand);
+                if (modeAndType.type() == GlobalVar || modeAndType.type() == GlobalVarWithVarInjectionChecks)
+                    continue;
                 WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
                 if (!structure || Heap::isMarked(structure.get()))
                     break;
index dac59a0..6aee3ba 100644 (file)
@@ -115,6 +115,7 @@ struct Instruction {
         ArrayProfile* arrayProfile;
         ArrayAllocationProfile* arrayAllocationProfile;
         ObjectAllocationProfile* objectAllocationProfile;
+        WatchpointSet* watchpointSet;
         void* pointer;
         bool* predicatePointer;
     } u;
index 224d3d3..c9423c4 100644 (file)
@@ -3127,7 +3127,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             uintptr_t operand;
             {
                 ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
-                structure = currentInstruction[5].u.structure.get();
+                if (resolveType == GlobalVar || resolveType == GlobalVarWithVarInjectionChecks)
+                    structure = 0;
+                else
+                    structure = currentInstruction[5].u.structure.get();
                 operand = reinterpret_cast<uintptr_t>(currentInstruction[6].u.pointer);
             }
 
index 9779c47..244030d 100644 (file)
@@ -53,19 +53,19 @@ static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identif
     if (JSActivation* activation = jsDynamicCast<JSActivation*>(scope)) {
         if (ident == exec->propertyNames().arguments) {
             // We know the property will be at this activation scope, but we don't know how to cache it.
-            op = ResolveOp(Dynamic, 0, 0, 0);
+            op = ResolveOp(Dynamic, 0, 0, 0, 0);
             return true;
         }
 
         SymbolTableEntry entry = activation->symbolTable()->get(ident.impl());
         if (entry.isReadOnly() && getOrPut == Put) {
             // We know the property will be at this activation scope, but we don't know how to cache it.
-            op = ResolveOp(Dynamic, 0, 0, 0);
+            op = ResolveOp(Dynamic, 0, 0, 0, 0);
             return true;
         }
 
         if (!entry.isNull()) {
-            op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, activation->structure(), entry.getIndex());
+            op = ResolveOp(makeType(ClosureVar, needsVarInjectionChecks), depth, activation->structure(), 0, entry.getIndex());
             return true;
         }
 
@@ -80,7 +80,7 @@ static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identif
             if (getOrPut == Put) {
                 if (entry.isReadOnly()) {
                     // We know the property will be at global scope, but we don't know how to cache it.
-                    op = ResolveOp(Dynamic, 0, 0, 0);
+                    op = ResolveOp(Dynamic, 0, 0, 0, 0);
                     return true;
                 }
 
@@ -88,7 +88,8 @@ static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identif
                 entry.notifyWrite();
             }
 
-            op = ResolveOp(makeType(GlobalVar, needsVarInjectionChecks), depth, globalObject->structure(), 
+            op = ResolveOp(
+                makeType(GlobalVar, needsVarInjectionChecks), depth, 0, entry.watchpointSet(),
                 reinterpret_cast<uintptr_t>(globalObject->registerAt(entry.getIndex()).slot()));
             return true;
         }
@@ -100,15 +101,15 @@ static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identif
             || (globalObject->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto() && getOrPut == Put)) {
             // We know the property will be at global scope, but we don't know how to cache it.
             ASSERT(!scope->next());
-            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0);
+            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0);
             return true;
         }
 
-        op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), slot.cachedOffset());
+        op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, slot.cachedOffset());
         return true;
     }
 
-    op = ResolveOp(Dynamic, 0, 0, 0);
+    op = ResolveOp(Dynamic, 0, 0, 0, 0);
     return true;
 }
 
@@ -146,7 +147,7 @@ JSValue JSScope::resolve(ExecState* exec, JSScope* scope, const Identifier& iden
 
 ResolveOp JSScope::abstractResolve(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, ResolveType unlinkedType)
 {
-    ResolveOp op(Dynamic, 0, 0, 0);
+    ResolveOp op(Dynamic, 0, 0, 0, 0);
     if (unlinkedType == Dynamic)
         return op;
 
index db66237..1ac7780 100644 (file)
@@ -31,6 +31,7 @@
 namespace JSC {
 
 class ScopeChainIterator;
+class WatchpointSet;
 
 enum ResolveMode {
     ThrowIfNotFound,
@@ -95,10 +96,11 @@ inline bool needsVarInjectionChecks(ResolveType type)
 }
 
 struct ResolveOp {
-    ResolveOp(ResolveType type, size_t depth, Structure* structure, uintptr_t operand)
+    ResolveOp(ResolveType type, size_t depth, Structure* structure, WatchpointSet* watchpointSet, uintptr_t operand)
         : type(type)
         , depth(depth)
         , structure(structure)
+        , watchpointSet(watchpointSet)
         , operand(operand)
     {
     }
@@ -106,6 +108,7 @@ struct ResolveOp {
     ResolveType type;
     size_t depth;
     Structure* structure;
+    WatchpointSet* watchpointSet;
     uintptr_t operand;
 };
 
index b8e9db7..a924423 100644 (file)
@@ -234,6 +234,8 @@ struct SymbolTableEntry {
     
     WatchpointSet* watchpointSet()
     {
+        if (!isFat())
+            return 0;
         return fatEntry()->m_watchpoints.get();
     }