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