Title: [89630] trunk/Source/_javascript_Core
Revision
89630
Author
[email protected]
Date
2011-06-23 15:47:04 -0700 (Thu, 23 Jun 2011)

Log Message

2011-06-23  Oliver Hunt  <[email protected]>

        Reviewed by Gavin Barraclough.

        Add the ability to dynamically modify linked call sites
        https://bugs.webkit.org/show_bug.cgi?id=63291

        Add JITWriteBarrier as a writebarrier class that allows
        reading and writing directly into the code stream.

        This required adding logic to all the assemblers to allow
        us to read values back out of the instruction stream.

        * _javascript_Core.xcodeproj/project.pbxproj:
        * assembler/ARMAssembler.h:
        (JSC::ARMAssembler::readPointer):
        * assembler/ARMv7Assembler.h:
        (JSC::ARMv7Assembler::readPointer):
        (JSC::ARMv7Assembler::readInt32):
        (JSC::ARMv7Assembler::decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst):
        (JSC::ARMv7Assembler::decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond):
        * assembler/AbstractMacroAssembler.h:
        (JSC::AbstractMacroAssembler::readPointer):
        * assembler/MIPSAssembler.h:
        (JSC::MIPSAssembler::readInt32):
        (JSC::MIPSAssembler::readPointer):
        * assembler/MacroAssemblerCodeRef.h:
        (JSC::MacroAssemblerCodePtr::operator!):
        * assembler/SH4Assembler.h:
        (JSC::SH4Assembler::readPCrelativeAddress):
        (JSC::SH4Assembler::readPointer):
        (JSC::SH4Assembler::readInt32):
        * assembler/X86Assembler.h:
        (JSC::X86Assembler::readPointer):
        * bytecode/CodeBlock.cpp:
        (JSC::CodeBlock::visitAggregate):
        * bytecode/CodeBlock.h:
        (JSC::MethodCallLinkInfo::seenOnce):
        (JSC::MethodCallLinkInfo::setSeen):
        * heap/MarkStack.h:
        * jit/JIT.cpp:
        (JSC::JIT::privateCompile):
        (JSC::JIT::linkCall):
        (JSC::JIT::linkConstruct):
        * jit/JITPropertyAccess.cpp:
        (JSC::JIT::patchMethodCallProto):
        * jit/JITPropertyAccess32_64.cpp:
        * jit/JITWriteBarrier.h: Added.
        (JSC::JITWriteBarrierBase::operator UnspecifiedBoolType*):
        (JSC::JITWriteBarrierBase::operator!):
        (JSC::JITWriteBarrierBase::setFlagOnBarrier):
        (JSC::JITWriteBarrierBase::isFlagged):
        (JSC::JITWriteBarrierBase::setLocation):
        (JSC::JITWriteBarrierBase::location):
        (JSC::JITWriteBarrierBase::JITWriteBarrierBase):
        (JSC::JITWriteBarrierBase::set):
        (JSC::JITWriteBarrierBase::get):
        (JSC::JITWriteBarrier::JITWriteBarrier):
        (JSC::JITWriteBarrier::set):
        (JSC::JITWriteBarrier::get):
        (JSC::MarkStack::append):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (89629 => 89630)


--- trunk/Source/_javascript_Core/ChangeLog	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-06-23 22:47:04 UTC (rev 89630)
@@ -1,3 +1,65 @@
+2011-06-23  Oliver Hunt  <[email protected]>
+
+        Reviewed by Gavin Barraclough.
+
+        Add the ability to dynamically modify linked call sites
+        https://bugs.webkit.org/show_bug.cgi?id=63291
+
+        Add JITWriteBarrier as a writebarrier class that allows
+        reading and writing directly into the code stream.
+
+        This required adding logic to all the assemblers to allow
+        us to read values back out of the instruction stream.
+
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * assembler/ARMAssembler.h:
+        (JSC::ARMAssembler::readPointer):
+        * assembler/ARMv7Assembler.h:
+        (JSC::ARMv7Assembler::readPointer):
+        (JSC::ARMv7Assembler::readInt32):
+        (JSC::ARMv7Assembler::decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst):
+        (JSC::ARMv7Assembler::decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond):
+        * assembler/AbstractMacroAssembler.h:
+        (JSC::AbstractMacroAssembler::readPointer):
+        * assembler/MIPSAssembler.h:
+        (JSC::MIPSAssembler::readInt32):
+        (JSC::MIPSAssembler::readPointer):
+        * assembler/MacroAssemblerCodeRef.h:
+        (JSC::MacroAssemblerCodePtr::operator!):
+        * assembler/SH4Assembler.h:
+        (JSC::SH4Assembler::readPCrelativeAddress):
+        (JSC::SH4Assembler::readPointer):
+        (JSC::SH4Assembler::readInt32):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::readPointer):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::visitAggregate):
+        * bytecode/CodeBlock.h:
+        (JSC::MethodCallLinkInfo::seenOnce):
+        (JSC::MethodCallLinkInfo::setSeen):
+        * heap/MarkStack.h:
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompile):
+        (JSC::JIT::linkCall):
+        (JSC::JIT::linkConstruct):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::patchMethodCallProto):
+        * jit/JITPropertyAccess32_64.cpp:
+        * jit/JITWriteBarrier.h: Added.
+        (JSC::JITWriteBarrierBase::operator UnspecifiedBoolType*):
+        (JSC::JITWriteBarrierBase::operator!):
+        (JSC::JITWriteBarrierBase::setFlagOnBarrier):
+        (JSC::JITWriteBarrierBase::isFlagged):
+        (JSC::JITWriteBarrierBase::setLocation):
+        (JSC::JITWriteBarrierBase::location):
+        (JSC::JITWriteBarrierBase::JITWriteBarrierBase):
+        (JSC::JITWriteBarrierBase::set):
+        (JSC::JITWriteBarrierBase::get):
+        (JSC::JITWriteBarrier::JITWriteBarrier):
+        (JSC::JITWriteBarrier::set):
+        (JSC::JITWriteBarrier::get):
+        (JSC::MarkStack::append):
+
 2011-06-23  Gavin Barraclough  <[email protected]>
 
         Reviewed by Oliver Hunt.

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (89629 => 89630)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2011-06-23 22:47:04 UTC (rev 89630)
@@ -400,6 +400,7 @@
 		A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; };
 		A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; };
+		A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */; };
 		A783A0D111A36DCA00563D20 /* JSObjectWithGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A783A0D011A36DCA00563D20 /* JSObjectWithGlobalObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A783A2AB11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A783A2AA11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp */; };
 		A784A26111D16622005776AC /* ASTBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */; };
@@ -1115,6 +1116,7 @@
 		A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMv7Assembler.cpp; sourceTree = "<group>"; };
 		A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic32_64.cpp; sourceTree = "<group>"; };
 		A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; };
+		A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITWriteBarrier.h; sourceTree = "<group>"; };
 		A783A0D011A36DCA00563D20 /* JSObjectWithGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectWithGlobalObject.h; sourceTree = "<group>"; };
 		A783A2AA11A5BE8400563D20 /* JSObjectWithGlobalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSObjectWithGlobalObject.cpp; sourceTree = "<group>"; };
 		A791EF260F11E07900AE1F68 /* JSByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSByteArray.h; sourceTree = "<group>"; };
@@ -1485,6 +1487,7 @@
 				A7386551118697B400540279 /* SpecializedThunkJIT.h */,
 				A7386552118697B400540279 /* ThunkGenerators.cpp */,
 				A7386553118697B400540279 /* ThunkGenerators.h */,
+				A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */,
 			);
 			path = jit;
 			sourceTree = "<group>";
@@ -2570,6 +2573,7 @@
 				142A1D8413A19C84009DA5FE /* OldSpace.h in Headers */,
 				14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */,
 				14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */,
+				A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: trunk/Source/_javascript_Core/assembler/ARMAssembler.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/ARMAssembler.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/ARMAssembler.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -739,6 +739,14 @@
 
         static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
 
+        // Read pointers
+        static void* readPointer(void* from)
+        {
+            ARMWord* insn = reinterpret_cast<ARMWord*>(from);
+            void* addr = reinterpret_cast<void*>(getLdrImmAddress(insn));
+            return *addr;
+        }
+        
         // Patch pointers
 
         static void linkPointer(void* code, AssemblerLabel from, void* to)

Modified: trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -340,6 +340,8 @@
         return m_type != TypeInvalid;
     }
 
+    uint16_t asUInt16() const { return m_value.asInt; }
+
     // These methods rely on the format of encoded byte values.
     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
@@ -1776,6 +1778,11 @@
         setPointer(where, value);
     }
 
+    static void* readPointer(void* where)
+    {
+        return reinterpret_cast<void*>(readInt32(where));
+    }
+
 private:
     // VFP operations commonly take one or more 5-bit operands, typically representing a
     // floating point register number.  This will commonly be encoded in the instruction
@@ -1856,6 +1863,23 @@
 
         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
     }
+    
+    static int32_t readInt32(void* code)
+    {
+        uint16_t* location = reinterpret_cast<uint16_t*>(code);
+        ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
+        
+        ARMThumbImmediate lo16;
+        ARMThumbImmediate hi16;
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(lo16, location[-4]);
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(lo16, location[-3]);
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(hi16, location[-2]);
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(hi16, location[-1]);
+        uint32_t result = hi16.asUInt16();
+        result <<= 16;
+        result |= lo16.asUInt16();
+        return static_cast<int32_t>(result);
+    }
 
     static void setUInt7ForLoad(void* code, ARMThumbImmediate imm)
     {
@@ -2122,11 +2146,23 @@
         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
     }
 
+    static void decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(ARMThumbImmediate& result, uint16_t value)
+    {
+        result.m_value.i = (value >> 10) & 1;
+        result.m_value.imm4 = value & 15;
+    }
+
     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
     {
         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
     }
 
+    static void decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(ARMThumbImmediate& result, uint16_t value)
+    {
+        result.m_value.imm3 = (value >> 12) & 7;
+        result.m_value.imm8 = value & 255;
+    }
+
     class ARMInstructionFormatter {
     public:
         void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)

Modified: trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/AbstractMacroAssembler.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -41,6 +41,7 @@
 template <class AssemblerType>
 class AbstractMacroAssembler {
 public:
+    friend class JITWriteBarrierBase;
     typedef AssemblerType AssemblerType_T;
 
     typedef MacroAssemblerCodePtr CodePtr;
@@ -573,6 +574,11 @@
     {
         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
     }
+    
+    static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
+    {
+        return AssemblerType::readPointer(dataLabelPtr.dataLocation());
+    }
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/assembler/MIPSAssembler.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/MIPSAssembler.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/MIPSAssembler.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -745,6 +745,16 @@
         insn--;
         ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord));
     }
+
+    static int32_t readInt32(void* from)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+        int32_t result = (*insn & 0x0000ffff) << 16;
+        insn++;
+        ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
+        result |= *insn & 0x0000ffff
+    }
     
     static void repatchCompact(void* where, int32_t value)
     {
@@ -756,6 +766,11 @@
         repatchInt32(from, reinterpret_cast<int32_t>(to));
     }
 
+    static void* readPointer(void* from)
+    {
+        return static_cast<void*>(readInt32(from));
+    }
+
 private:
     /* Update each jump in the buffer of newBase.  */
     void relocateJumps(void* oldBase, void* newBase)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerCodeRef.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerCodeRef.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerCodeRef.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -184,7 +184,7 @@
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
-    bool operator!()
+    bool operator!() const
     {
         return !m_value;
     }

Modified: trunk/Source/_javascript_Core/assembler/SH4Assembler.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/SH4Assembler.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/SH4Assembler.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -1232,6 +1232,12 @@
         uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
         *reinterpret_cast<uint32_t*>(address) = newAddress;
     }
+    
+    static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
+    {
+        uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
+        return *reinterpret_cast<uint32_t*>(address);
+    }
 
     static uint16_t* getInstructionPtr(void* code, int offset)
     {
@@ -1346,6 +1352,11 @@
         patchPointer(where, value);
     }
 
+    static void* readPointer(void* code)
+    {
+        return static_cast<void*>(readInt32(code));
+    }
+
     static void repatchInt32(void* where, int32_t value)
     {
         uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
@@ -1474,6 +1485,11 @@
         changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value);
     }
 
+    static uint32_t readInt32(void* code)
+    {
+        return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
+    }
+
     void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
     {
         return m_buffer.executableCopy(globalData, allocator);

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (89629 => 89630)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -1565,6 +1565,11 @@
     {
         setPointer(where, value);
     }
+    
+    static void* readPointer(void* where)
+    {
+        return reinterpret_cast<void**>(where)[-1];
+    }
 
     static unsigned getCallReturnOffset(AssemblerLabel call)
     {

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (89629 => 89630)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp	2011-06-23 22:47:04 UTC (rev 89630)
@@ -1508,6 +1508,8 @@
             visitor.append(&m_methodCallLinkInfos[i].cachedStructure);
             ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
             visitor.append(&m_methodCallLinkInfos[i].cachedPrototypeStructure);
+            visitor.append(&m_methodCallLinkInfos[i].cachedFunction);
+            visitor.append(&m_methodCallLinkInfos[i].cachedPrototype);
         }
     }
 #endif

Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (89629 => 89630)


--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -33,6 +33,7 @@
 #include "EvalCodeCache.h"
 #include "Instruction.h"
 #include "JITCode.h"
+#include "JITWriteBarrier.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Nodes.h"
@@ -103,10 +104,9 @@
         CodeLocationNearCall callReturnLocation;
         CodeLocationDataLabelPtr hotPathBegin;
         CodeLocationNearCall hotPathOther;
-        WriteBarrier<JSFunction> callee;
+        JITWriteBarrier<JSFunction> callee;
         bool hasSeenShouldRepatch;
-        
-        void setUnlinked() { callee.clear(); }
+
         bool isLinked() { return callee; }
 
         bool seenOnce()
@@ -128,7 +128,7 @@
         bool seenOnce()
         {
             ASSERT(!cachedStructure);
-            return cachedPrototypeStructure;
+            return cachedPrototypeStructure.isFlagged();
         }
 
         void setSeen()
@@ -140,13 +140,14 @@
             //     - Once this transition has been taken once, cachedStructure is
             //       null and cachedPrototypeStructure is set to a nun-null value.
             //     - Once the call is linked both structures are set to non-null values.
-            cachedPrototypeStructure.setWithoutWriteBarrier((Structure*)1);
+            cachedPrototypeStructure.setFlagOnBarrier();
         }
 
         CodeLocationCall callReturnLocation;
-        CodeLocationDataLabelPtr structureLabel;
-        WriteBarrier<Structure> cachedStructure;
-        WriteBarrier<Structure> cachedPrototypeStructure;
+        JITWriteBarrier<Structure> cachedStructure;
+        JITWriteBarrier<Structure> cachedPrototypeStructure;
+        JITWriteBarrier<JSFunction> cachedFunction;
+        JITWriteBarrier<JSObject> cachedPrototype;
     };
 
     struct GlobalResolveInfo {

Modified: trunk/Source/_javascript_Core/heap/MarkStack.h (89629 => 89630)


--- trunk/Source/_javascript_Core/heap/MarkStack.h	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/heap/MarkStack.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -42,6 +42,7 @@
     class MarkStack;
     class Register;
     template<typename T> class WriteBarrierBase;
+    template<typename T> class JITWriteBarrier;
     
     struct MarkSet {
         MarkSet(JSValue* values, JSValue* end);
@@ -85,7 +86,8 @@
         ~MarkStack();
 
         void append(ConservativeRoots&);
-
+        
+        template<typename T> inline void append(JITWriteBarrier<T>*);
         template<typename T> inline void append(WriteBarrierBase<T>*);
         inline void appendValues(WriteBarrierBase<Unknown>*, size_t count);
         

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (89629 => 89630)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2011-06-23 22:47:04 UTC (rev 89630)
@@ -584,7 +584,7 @@
     m_codeBlock->addMethodCallLinkInfos(methodCallCount);
     for (unsigned i = 0; i < methodCallCount; ++i) {
         MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
-        info.structureLabel = patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare);
+        info.cachedStructure.setLocation(patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare));
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
@@ -602,8 +602,7 @@
     // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
     if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) {
         ASSERT(!callLinkInfo->isLinked());
-        callLinkInfo->callee.set(*globalData, callerCodeBlock->ownerExecutable(), callee);
-        repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee);
+        callLinkInfo->callee.set(*globalData, callLinkInfo->hotPathBegin, callerCodeBlock->ownerExecutable(), callee);
         repatchBuffer.relink(callLinkInfo->hotPathOther, code);
     }
 
@@ -619,8 +618,7 @@
     // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
     if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) {
         ASSERT(!callLinkInfo->isLinked());
-        callLinkInfo->callee.set(*globalData, callerCodeBlock->ownerExecutable(), callee);
-        repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee);
+        callLinkInfo->callee.set(*globalData, callLinkInfo->hotPathBegin, callerCodeBlock->ownerExecutable(), callee);
         repatchBuffer.relink(callLinkInfo->hotPathOther, code);
     }
 

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (89629 => 89630)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2011-06-23 22:47:04 UTC (rev 89630)
@@ -577,24 +577,6 @@
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
 }
 
-void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
-{
-    RepatchBuffer repatchBuffer(codeBlock);
-
-    ASSERT(!methodCallLinkInfo.cachedStructure);
-    methodCallLinkInfo.cachedStructure.set(globalData, codeBlock->ownerExecutable(), structure);
-
-    Structure* prototypeStructure = proto->structure();
-    methodCallLinkInfo.cachedPrototypeStructure.set(globalData, codeBlock->ownerExecutable(), prototypeStructure);
-
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
-
-    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
-}
-
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
 {
     RepatchBuffer repatchBuffer(codeBlock);
@@ -1037,6 +1019,21 @@
     failureCases.append(branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototype.asCell()->structure())));
 }
 
+void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
+{
+    RepatchBuffer repatchBuffer(codeBlock);
+    
+    ASSERT(!methodCallLinkInfo.cachedStructure);
+    CodeLocationDataLabelPtr structureLocation = methodCallLinkInfo.cachedStructure.location();
+    methodCallLinkInfo.cachedStructure.set(globalData, structureLocation, codeBlock->ownerExecutable(), structure);
+    
+    Structure* prototypeStructure = proto->structure();
+    methodCallLinkInfo.cachedPrototypeStructure.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), codeBlock->ownerExecutable(), prototypeStructure);
+    methodCallLinkInfo.cachedPrototype.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), codeBlock->ownerExecutable(), proto);
+    methodCallLinkInfo.cachedFunction.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), codeBlock->ownerExecutable(), callee);
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (89629 => 89630)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2011-06-23 22:35:48 UTC (rev 89629)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2011-06-23 22:47:04 UTC (rev 89630)
@@ -551,23 +551,6 @@
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
 }
 
-void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
-{
-    RepatchBuffer repatchBuffer(codeBlock);
-    
-    ASSERT(!methodCallLinkInfo.cachedStructure);
-    methodCallLinkInfo.cachedStructure.set(globalData, codeBlock->ownerExecutable(), structure);
-    Structure* prototypeStructure = proto->structure();
-    methodCallLinkInfo.cachedPrototypeStructure.set(globalData, codeBlock->ownerExecutable(), prototypeStructure);
-    
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
-    
-    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
-}
-
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
 {
     RepatchBuffer repatchBuffer(codeBlock);

Added: trunk/Source/_javascript_Core/jit/JITWriteBarrier.h (0 => 89630)


--- trunk/Source/_javascript_Core/jit/JITWriteBarrier.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/jit/JITWriteBarrier.h	2011-06-23 22:47:04 UTC (rev 89630)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JITWriteBarrier_h
+#define JITWriteBarrier_h
+
+#if ENABLE(JIT)
+
+#include "MacroAssembler.h"
+#include "MarkStack.h"
+#include "WriteBarrier.h"
+
+namespace JSC {
+
+class JSCell;
+class JSGlobalData;
+
+// Needs to be even to appease some of the backends.
+#define JITWriteBarrierFlag ((void*)2)
+class JITWriteBarrierBase {
+public:
+    typedef void* (JITWriteBarrierBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    bool operator!() const { return !get(); }
+
+    void setFlagOnBarrier()
+    {
+        ASSERT(!m_location);
+        m_location = CodeLocationDataLabelPtr(JITWriteBarrierFlag);
+    }
+
+    bool isFlagged() const
+    {
+        return !!m_location;
+    }
+
+    void setLocation(CodeLocationDataLabelPtr location)
+    {
+        ASSERT(!m_location);
+        m_location = location;
+    }
+
+    CodeLocationDataLabelPtr location() const
+    {
+        ASSERT((!!m_location) && m_location.executableAddress() != JITWriteBarrierFlag);
+        return m_location;
+    }
+    
+protected:
+    JITWriteBarrierBase()
+    {
+    }
+
+    void set(JSGlobalData&, CodeLocationDataLabelPtr location, JSCell* owner, JSCell* value)
+    {
+        Heap::writeBarrier(owner, value);
+        m_location = location;
+        ASSERT(((!!m_location) && m_location.executableAddress() != JITWriteBarrierFlag) || (location.executableAddress() == m_location.executableAddress()));
+        MacroAssembler::repatchPointer(m_location, value);
+        ASSERT(get() == value);
+    }
+
+    JSCell* get() const
+    {
+        if (!m_location || m_location.executableAddress() == JITWriteBarrierFlag)
+            return 0;
+        void* result = static_cast<JSCell*>(MacroAssembler::readPointer(m_location));
+        // We use -1 to indicate a "safe" empty value in the instruction stream
+        if (result == (void*)-1)
+            return 0;
+        return static_cast<JSCell*>(result);
+    }
+
+private:
+    CodeLocationDataLabelPtr m_location;
+};
+
+#undef JITWriteBarrierFlag
+
+template <typename T> class JITWriteBarrier : public JITWriteBarrierBase {
+public:
+    JITWriteBarrier()
+    {
+    }
+
+    void set(JSGlobalData& globalData, CodeLocationDataLabelPtr location, JSCell* owner, T* value)
+    {
+        validateCell(owner);
+        validateCell(value);
+        JITWriteBarrierBase::set(globalData, location, owner, value);
+    }
+    T* get() const
+    {
+        T* result = static_cast<T*>(JITWriteBarrierBase::get());
+        if (result)
+            validateCell(result);
+        return result;
+    }
+};
+
+template<typename T> inline void MarkStack::append(JITWriteBarrier<T>* slot)
+{
+    internalAppend(slot->get());
+}
+
+}
+
+#endif // ENABLE(JIT)
+
+#endif
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to