[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc
eric at webkit.org
eric at webkit.org
Wed Dec 22 11:49:13 UTC 2010
The following commit has been merged in the debian/experimental branch:
commit 667fa8a739ce49bed14dca1f518351e87a51151a
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Sun Aug 8 06:04:59 2010 +0000
2010-08-07 Nathan Lawrence <nlawrence at apple.com>
Reviewed by Geoffrey Garen.
The JIT code contains a number of direct references to GC'd objects.
When we have movable objects, these references will need to be
updated.
* Android.mk:
* CMakeLists.txt:
* GNUmakefile.am:
* JavaScriptCore.gypi:
* JavaScriptCore.pro:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::int32AtLocation):
(JSC::AbstractMacroAssembler::pointerAtLocation):
(JSC::AbstractMacroAssembler::jumpTarget):
* assembler/MacroAssembler.h:
(JSC::MacroAssembler::loadPtrWithPatch):
Normally, loadPtr will optimize when the register is eax. Since
the slightly smaller instruction changes the offsets, it messes up
our ability to repatch the code. We added this new instruction
that garuntees a constant size.
* assembler/MacroAssemblerX86.h:
(JSC::MacroAssemblerX86::load32WithPatch):
Changed load32 in the same way described above.
(JSC::MacroAssemblerX86::load32):
Moved the logic to optimize laod32 from movl_mr to load32
(JSC::MacroAssemblerX86::store32):
Moved the logic to optimize store32 from movl_rm to store32
* assembler/X86Assembler.h:
(JSC::X86Assembler::movl_rm):
(JSC::X86Assembler::movl_mr):
(JSC::X86Assembler::int32AtLocation):
(JSC::X86Assembler::pointerAtLocation):
(JSC::X86Assembler::jumpTarget):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::markAggregate):
* bytecode/Instruction.h:
As described in StructureStubInfo.h, we needed to add additional
fields to both StructureStubInfo and
PolymorphicAccessStructureList so that we can determine the
structure of the JITed code at patch time.
(JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
(JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::markAggregate):
Added this function to mark the JITed code that correosponds to
this structure stub info.
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::initGetByIdProto):
(JSC::StructureStubInfo::initGetByIdChain):
(JSC::StructureStubInfo::):
* jit/JIT.h:
* jit/JITMarkObjects.cpp: Added.
(JSC::JIT::patchPrototypeStructureAddress):
(JSC::JIT::patchGetDirectOffset):
(JSC::JIT::markGetByIdProto):
(JSC::JIT::markGetByIdChain):
(JSC::JIT::markGetByIdProtoList):
(JSC::JIT::markPutByIdTransition):
(JSC::JIT::markGlobalObjectReference):
* jit/JITPropertyAccess.cpp:
Added asserts for the patch offsets.
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::testPrototype):
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::compileGetDirectOffset):
(JSC::JIT::testPrototype):
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):
* jit/JITStubs.cpp:
(JSC::setupPolymorphicProtoList):
* wtf/Platform.h:
Added ENABLE_MOVABLE_GC_OBJECTS flag
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@64938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/Android.mk b/JavaScriptCore/Android.mk
index 8dd53c1..0cc11bf 100644
--- a/JavaScriptCore/Android.mk
+++ b/JavaScriptCore/Android.mk
@@ -52,6 +52,7 @@ LOCAL_SRC_FILES := \
jit/JITArithmetic.cpp \
jit/JITCall.cpp \
jit/JITCall32_64.cpp \
+ jit/JITMarkObjects.cpp \
jit/JITOpcodes.cpp \
jit/JITPropertyAccess.cpp \
jit/JITStubs.cpp \
diff --git a/JavaScriptCore/CMakeLists.txt b/JavaScriptCore/CMakeLists.txt
index a944363..fe726d2 100644
--- a/JavaScriptCore/CMakeLists.txt
+++ b/JavaScriptCore/CMakeLists.txt
@@ -55,6 +55,7 @@ SET(JavaScriptCore_SOURCES
jit/JITCall32_64.cpp
jit/JITCall.cpp
jit/JIT.cpp
+ jit/JITMarkObjects.cpp
jit/JITOpcodes32_64.cpp
jit/JITOpcodes.cpp
jit/JITPropertyAccess32_64.cpp
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 321a2f1..b2563c8 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,88 @@
+2010-08-07 Nathan Lawrence <nlawrence at apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ The JIT code contains a number of direct references to GC'd objects.
+ When we have movable objects, these references will need to be
+ updated.
+
+ * Android.mk:
+ * CMakeLists.txt:
+ * GNUmakefile.am:
+ * JavaScriptCore.gypi:
+ * JavaScriptCore.pro:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * assembler/AbstractMacroAssembler.h:
+ (JSC::AbstractMacroAssembler::int32AtLocation):
+ (JSC::AbstractMacroAssembler::pointerAtLocation):
+ (JSC::AbstractMacroAssembler::jumpTarget):
+ * assembler/MacroAssembler.h:
+ (JSC::MacroAssembler::loadPtrWithPatch):
+ Normally, loadPtr will optimize when the register is eax. Since
+ the slightly smaller instruction changes the offsets, it messes up
+ our ability to repatch the code. We added this new instruction
+ that garuntees a constant size.
+ * assembler/MacroAssemblerX86.h:
+ (JSC::MacroAssemblerX86::load32WithPatch):
+ Changed load32 in the same way described above.
+ (JSC::MacroAssemblerX86::load32):
+ Moved the logic to optimize laod32 from movl_mr to load32
+ (JSC::MacroAssemblerX86::store32):
+ Moved the logic to optimize store32 from movl_rm to store32
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::movl_rm):
+ (JSC::X86Assembler::movl_mr):
+ (JSC::X86Assembler::int32AtLocation):
+ (JSC::X86Assembler::pointerAtLocation):
+ (JSC::X86Assembler::jumpTarget):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::markAggregate):
+ * bytecode/Instruction.h:
+ As described in StructureStubInfo.h, we needed to add additional
+ fields to both StructureStubInfo and
+ PolymorphicAccessStructureList so that we can determine the
+ structure of the JITed code at patch time.
+ (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
+ (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
+ * bytecode/StructureStubInfo.cpp:
+ (JSC::StructureStubInfo::markAggregate):
+ Added this function to mark the JITed code that correosponds to
+ this structure stub info.
+ * bytecode/StructureStubInfo.h:
+ (JSC::StructureStubInfo::initGetByIdProto):
+ (JSC::StructureStubInfo::initGetByIdChain):
+ (JSC::StructureStubInfo::):
+ * jit/JIT.h:
+ * jit/JITMarkObjects.cpp: Added.
+ (JSC::JIT::patchPrototypeStructureAddress):
+ (JSC::JIT::patchGetDirectOffset):
+ (JSC::JIT::markGetByIdProto):
+ (JSC::JIT::markGetByIdChain):
+ (JSC::JIT::markGetByIdProtoList):
+ (JSC::JIT::markPutByIdTransition):
+ (JSC::JIT::markGlobalObjectReference):
+ * jit/JITPropertyAccess.cpp:
+ Added asserts for the patch offsets.
+ (JSC::JIT::compileGetDirectOffset):
+ (JSC::JIT::testPrototype):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::privateCompileGetByIdProto):
+ (JSC::JIT::privateCompileGetByIdProtoList):
+ (JSC::JIT::privateCompileGetByIdChainList):
+ (JSC::JIT::privateCompileGetByIdChain):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::compileGetDirectOffset):
+ (JSC::JIT::testPrototype):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::privateCompileGetByIdProto):
+ (JSC::JIT::privateCompileGetByIdProtoList):
+ (JSC::JIT::privateCompileGetByIdChainList):
+ (JSC::JIT::privateCompileGetByIdChain):
+ * jit/JITStubs.cpp:
+ (JSC::setupPolymorphicProtoList):
+ * wtf/Platform.h:
+ Added ENABLE_MOVABLE_GC_OBJECTS flag
+
2010-08-07 Michael Saboff <msaboff at apple.com>
Reviewed by Geoffrey Garen.
diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am
index 2ead8e0..82bcb59 100644
--- a/JavaScriptCore/GNUmakefile.am
+++ b/JavaScriptCore/GNUmakefile.am
@@ -165,6 +165,7 @@ javascriptcore_sources += \
JavaScriptCore/jit/JIT.cpp \
JavaScriptCore/jit/JIT.h \
JavaScriptCore/jit/JITInlineMethods.h \
+ JavaScriptCore/jit/JITMarkObjects.cpp \
JavaScriptCore/jit/JITOpcodes32_64.cpp \
JavaScriptCore/jit/JITOpcodes.cpp \
JavaScriptCore/jit/JITPropertyAccess32_64.cpp \
diff --git a/JavaScriptCore/JavaScriptCore.gypi b/JavaScriptCore/JavaScriptCore.gypi
index a85d11c..b845c59 100644
--- a/JavaScriptCore/JavaScriptCore.gypi
+++ b/JavaScriptCore/JavaScriptCore.gypi
@@ -118,6 +118,7 @@
'jit/JITCall32_64.cpp',
'jit/JITCode.h',
'jit/JITInlineMethods.h',
+ 'jit/JITMarkObjects.cpp',
'jit/JITOpcodes.cpp',
'jit/JITOpcodes32_64.cpp',
'jit/JITPropertyAccess.cpp',
diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro
index d6c4420..2826c6b 100644
--- a/JavaScriptCore/JavaScriptCore.pro
+++ b/JavaScriptCore/JavaScriptCore.pro
@@ -100,6 +100,7 @@ SOURCES += \
jit/JITCall.cpp \
jit/JITCall32_64.cpp \
jit/JIT.cpp \
+ jit/JITMarkObjects.cpp \
jit/JITOpcodes.cpp \
jit/JITOpcodes32_64.cpp \
jit/JITPropertyAccess.cpp \
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
index 83d34e3..5efa58c 100644
--- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
+++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj
@@ -1689,6 +1689,9 @@
>
</File>
<File
+ RelativePath="..\..\jit\JITMarkObjects.cpp"
+ >
+ <File
RelativePath="..\..\jit\JITOpcodes.cpp"
>
</File>
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 4809218..6edc0c8 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -509,6 +509,7 @@
BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; };
BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; };
C0A272630E50A06300E96E15 /* NotFound.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A2723F0E509F1E00E96E15 /* NotFound.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ DD23669811DBB22D00AF47C8 /* JITMarkObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD23669711DBB22D00AF47C8 /* JITMarkObjects.cpp */; };
DD2724681208D1FF00F9ABE7 /* AlignedMemoryAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2724671208D1FF00F9ABE7 /* AlignedMemoryAllocator.h */; };
DD2724691208D1FF00F9ABE7 /* AlignedMemoryAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2724671208D1FF00F9ABE7 /* AlignedMemoryAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
DD377CBC12072C18006A2517 /* Bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = DD377CBB12072C18006A2517 /* Bitmap.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1062,6 +1063,7 @@
C0A2723F0E509F1E00E96E15 /* NotFound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotFound.h; sourceTree = "<group>"; };
D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; };
+ DD23669711DBB22D00AF47C8 /* JITMarkObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITMarkObjects.cpp; sourceTree = "<group>"; };
DD2724671208D1FF00F9ABE7 /* AlignedMemoryAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlignedMemoryAllocator.h; sourceTree = "<group>"; };
DD377CBB12072C18006A2517 /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = "<group>"; };
DDE82AD11209D955005C1756 /* GCHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCHandle.cpp; sourceTree = "<group>"; };
@@ -1272,6 +1274,7 @@
1429D92C0ED22D7000B89619 /* jit */ = {
isa = PBXGroup;
children = (
+ DD23669711DBB22D00AF47C8 /* JITMarkObjects.cpp */,
A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */,
@@ -2675,6 +2678,7 @@
86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */,
DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */,
8627E5EB11F1281900A313B5 /* PageAllocation.cpp in Sources */,
+ DD23669811DBB22D00AF47C8 /* JITMarkObjects.cpp in Sources */,
DDE82AD71209D955005C1756 /* GCHandle.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
diff --git a/JavaScriptCore/assembler/AbstractMacroAssembler.h b/JavaScriptCore/assembler/AbstractMacroAssembler.h
index aab9089..50997ac 100644
--- a/JavaScriptCore/assembler/AbstractMacroAssembler.h
+++ b/JavaScriptCore/assembler/AbstractMacroAssembler.h
@@ -521,6 +521,21 @@ protected:
AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
}
+ static int32_t int32AtLocation(CodeLocationDataLabel32 dataLabel32)
+ {
+ return AssemblerType::int32AtLocation(dataLabel32.dataLocation());
+ }
+
+ static void* pointerAtLocation(CodeLocationDataLabelPtr dataLabelPtr)
+ {
+ return AssemblerType::pointerAtLocation(dataLabelPtr.dataLocation());
+ }
+
+ static void* jumpTarget(CodeLocationJump jump)
+ {
+ return AssemblerType::jumpTarget(jump.dataLocation());
+ }
+
static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
{
AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
diff --git a/JavaScriptCore/assembler/MacroAssembler.h b/JavaScriptCore/assembler/MacroAssembler.h
index ce1be78..1632764 100644
--- a/JavaScriptCore/assembler/MacroAssembler.h
+++ b/JavaScriptCore/assembler/MacroAssembler.h
@@ -209,6 +209,10 @@ public:
xor32(imm, srcDest);
}
+ void loadPtrWithPatch(void* address, RegisterID dest)
+ {
+ load32WithPatch(address, dest);
+ }
void loadPtr(ImplicitAddress address, RegisterID dest)
{
diff --git a/JavaScriptCore/assembler/MacroAssemblerX86.h b/JavaScriptCore/assembler/MacroAssemblerX86.h
index 0918996..d2a794d 100644
--- a/JavaScriptCore/assembler/MacroAssemblerX86.h
+++ b/JavaScriptCore/assembler/MacroAssemblerX86.h
@@ -82,11 +82,19 @@ public:
m_assembler.subl_im(imm.m_value, address.m_ptr);
}
- void load32(void* address, RegisterID dest)
+ void load32WithPatch(void* address, RegisterID dest)
{
m_assembler.movl_mr(address, dest);
}
+ void load32(void* address, RegisterID dest)
+ {
+ if (dest == X86Registers::eax)
+ m_assembler.movl_mEAX(address);
+ else
+ m_assembler.movl_mr(address, dest);
+ }
+
void loadDouble(const void* address, FPRegisterID dest)
{
ASSERT(isSSE2Present());
@@ -105,7 +113,10 @@ public:
void store32(RegisterID src, void* address)
{
- m_assembler.movl_rm(src, address);
+ if (src == X86Registers::eax)
+ m_assembler.movl_EAXm(address);
+ else
+ m_assembler.movl_rm(src, address);
}
Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
diff --git a/JavaScriptCore/assembler/X86Assembler.h b/JavaScriptCore/assembler/X86Assembler.h
index a1fae0c..822f27c 100644
--- a/JavaScriptCore/assembler/X86Assembler.h
+++ b/JavaScriptCore/assembler/X86Assembler.h
@@ -1154,18 +1154,12 @@ public:
#else
void movl_rm(RegisterID src, void* addr)
{
- if (src == X86Registers::eax)
- movl_EAXm(addr);
- else
- m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
+ m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
}
void movl_mr(void* addr, RegisterID dst)
{
- if (dst == X86Registers::eax)
- movl_mEAX(addr);
- else
- m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
+ m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
}
void movl_i32m(int imm, void* addr)
@@ -1559,6 +1553,23 @@ public:
setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
}
+ static int32_t int32AtLocation(void* where)
+ {
+ return static_cast<int32_t*>(where)[-1];
+ }
+
+ static void* pointerAtLocation(void* where)
+ {
+ return static_cast<void**>(where)[-1];
+ }
+
+ static void* jumpTarget(void* jump)
+ {
+ intptr_t src = reinterpret_cast<intptr_t>(jump);
+ int32_t offset = static_cast<int32_t*>(jump)[-1];
+ return reinterpret_cast<void*>(src + offset);
+ }
+
static void relinkJump(void* from, void* to)
{
setRel32(from, to);
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 9a8c332..d9a84d9 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -1520,6 +1520,14 @@ void CodeBlock::markAggregate(MarkStack& markStack)
for (size_t i = 0; i < m_functionDecls.size(); ++i)
m_functionDecls[i]->markAggregate(markStack);
markStack.append(m_globalObject);
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ // This is the code that is responsible for marking the actual pointers
+ // to JSCell*s in the JIT'ed code. Normally, these pointers are marked
+ // elsewhere, however when we have movable objects, we will need to update
+ // all of the references.
+ for (size_t i = 0; i < m_structureStubInfos.size(); ++i)
+ m_structureStubInfos[i].markAggregate(markStack, this);
+#endif
}
bool CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
diff --git a/JavaScriptCore/bytecode/Instruction.h b/JavaScriptCore/bytecode/Instruction.h
index c6468a5..96bf604 100644
--- a/JavaScriptCore/bytecode/Instruction.h
+++ b/JavaScriptCore/bytecode/Instruction.h
@@ -63,6 +63,10 @@ namespace JSC {
Structure* proto;
StructureChain* chain;
} u;
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ int count;
+ PropertySlot::CachedPropertyType propertyType;
+#endif
void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
{
@@ -72,20 +76,35 @@ namespace JSC {
isChain = false;
}
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto, PropertySlot::CachedPropertyType _propertyType)
+#else
void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
+#endif
{
stubRoutine = _stubRoutine;
base = _base;
u.proto = _proto;
isChain = false;
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ propertyType = _propertyType;
+#endif
}
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain, int _count, PropertySlot::CachedPropertyType _propertyType)
+#else
void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
+#endif
{
stubRoutine = _stubRoutine;
base = _base;
u.chain = _chain;
isChain = true;
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ count = _count;
+ propertyType = _propertyType;
+#endif
}
} list[POLYMORPHIC_LIST_CACHE_SIZE];
@@ -94,15 +113,29 @@ namespace JSC {
list[0].set(stubRoutine, firstBase);
}
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto, PropertySlot::CachedPropertyType propertyType)
+ {
+ list[0].set(stubRoutine, firstBase, firstProto, propertyType);
+ }
+#else
PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
{
list[0].set(stubRoutine, firstBase, firstProto);
}
+#endif
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain, int count, PropertySlot::CachedPropertyType propertyType)
+ {
+ list[0].set(stubRoutine, firstBase, firstChain, count, propertyType);
+ }
+#else
PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
{
list[0].set(stubRoutine, firstBase, firstChain);
}
+#endif
void derefStructures(int count)
{
diff --git a/JavaScriptCore/bytecode/StructureStubInfo.cpp b/JavaScriptCore/bytecode/StructureStubInfo.cpp
index 018d832..1f36de2 100644
--- a/JavaScriptCore/bytecode/StructureStubInfo.cpp
+++ b/JavaScriptCore/bytecode/StructureStubInfo.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "StructureStubInfo.h"
+#include "JIT.h"
+
namespace JSC {
#if ENABLE(JIT)
@@ -75,6 +77,39 @@ void StructureStubInfo::deref()
ASSERT_NOT_REACHED();
}
}
+
+#if ENABLE(MOVABLE_GC_OBJECTS)
+void StructureStubInfo::markAggregate(MarkStack& markStack, CodeBlock* codeBlock)
+{
+ switch (accessType) {
+ case access_get_by_id_proto:
+ JIT::markGetByIdProto(markStack, codeBlock, this);
+ return;
+ case access_get_by_id_chain:
+ JIT::markGetByIdChain(markStack, codeBlock, this);
+ return;
+ case access_get_by_id_proto_list:
+ JIT::markGetByIdProtoList(markStack, codeBlock, this);
+ return;
+ case access_put_by_id_transition:
+ JIT::markPutByIdTransition(markStack, codeBlock, this);
+ return;
+ case access_get_by_id_self:
+ case access_get_by_id_self_list:
+ case access_put_by_id_replace:
+ case access_get_by_id:
+ case access_put_by_id:
+ case access_get_by_id_generic:
+ case access_put_by_id_generic:
+ case access_get_array_length:
+ case access_get_string_length:
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+#endif
+
#endif
} // namespace JSC
diff --git a/JavaScriptCore/bytecode/StructureStubInfo.h b/JavaScriptCore/bytecode/StructureStubInfo.h
index 8578171..271ee01 100644
--- a/JavaScriptCore/bytecode/StructureStubInfo.h
+++ b/JavaScriptCore/bytecode/StructureStubInfo.h
@@ -30,6 +30,7 @@
#include "Instruction.h"
#include "MacroAssembler.h"
+#include "PropertySlot.h"
#include "Opcode.h"
#include "Structure.h"
@@ -66,7 +67,11 @@ namespace JSC {
baseObjectStructure->ref();
}
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure, CodeLocationLabel routine, PropertySlot::CachedPropertyType propertyType)
+#else
void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure, CodeLocationLabel routine)
+#endif
{
accessType = access_get_by_id_proto;
@@ -77,9 +82,17 @@ namespace JSC {
prototypeStructure->ref();
stubRoutine = routine;
+
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ u.getByIdProto.propertyType = propertyType;
+#endif
}
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain, CodeLocationLabel routine, int count, PropertySlot::CachedPropertyType propertyType)
+#else
void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain, CodeLocationLabel routine)
+#endif
{
accessType = access_get_by_id_chain;
@@ -90,6 +103,11 @@ namespace JSC {
chain->ref();
stubRoutine = routine;
+
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ u.getByIdChain.count = count;
+ u.getByIdChain.propertyType = propertyType;
+#endif
}
void initGetByIdSelfList(PolymorphicAccessStructureList* structureList)
@@ -139,6 +157,9 @@ namespace JSC {
}
void deref();
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ void markAggregate(MarkStack&, CodeBlock*);
+#endif
bool seenOnce()
{
@@ -160,10 +181,24 @@ namespace JSC {
struct {
Structure* baseObjectStructure;
Structure* prototypeStructure;
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ // The propertyType is required to properly determine the
+ // structure of the underlying code so that we may patch it
+ // correctly. Different code is generated for different
+ // property types, and therefore, the offsets that we need to
+ // patch at will change.
+ PropertySlot::CachedPropertyType propertyType;
+#endif
} getByIdProto;
struct {
Structure* baseObjectStructure;
StructureChain* chain;
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ // We need the count so that we can iterate over the prototype
+ // chain, marking all of the references to objects.
+ int count;
+ PropertySlot::CachedPropertyType propertyType;
+#endif
} getByIdChain;
struct {
PolymorphicAccessStructureList* structureList;
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index f3c4b6a..5dd9f71 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -237,6 +237,18 @@ namespace JSC {
static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct);
static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ static void patchPrototypeStructureAddress(CodeLocationDataLabelPtr, MarkStack&, RepatchBuffer&);
+ static void patchGetDirectOffset(CodeLocationLabel, MarkStack&, RepatchBuffer&, PropertySlot::CachedPropertyType);
+ static void markGetByIdChainInternal(CodeLocationLabel, MarkStack&, RepatchBuffer&, PropertySlot::CachedPropertyType);
+
+ static void markGetByIdProto(MarkStack&, CodeBlock*, StructureStubInfo*);
+ static void markGetByIdChain(MarkStack&, CodeBlock*, StructureStubInfo*);
+ static void markGetByIdProtoList(MarkStack&, CodeBlock*, StructureStubInfo*);
+ static void markPutByIdTransition(MarkStack&, CodeBlock*, StructureStubInfo*);
+ static void markGlobalObjectReference(MarkStack&, CodeBlock*, CodeLocationDataLabelPtr);
+#endif
+
static bool compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, ReturnAddressPtr returnAddress)
{
JIT jit(globalData, codeBlock);
@@ -295,7 +307,7 @@ namespace JSC {
void emitLoadDouble(unsigned index, FPRegisterID value);
void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
- void testPrototype(JSValue, JumpList& failureCases);
+ unsigned testPrototype(JSValue, JumpList& failureCases);
#if USE(JSVALUE32_64)
bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
@@ -366,6 +378,13 @@ namespace JSC {
static const int patchOffsetMethodCheckProtoObj = 11;
static const int patchOffsetMethodCheckProtoStruct = 18;
static const int patchOffsetMethodCheckPutFunction = 29;
+
+ static const int patchOffsetGetByIdProtoStruct = 19;
+ static const int patchOffsetPutByIdProtoStruct = 12;
+ static const int patchLengthTestPrototype = 16;
+ static const int patchLengthBranchPtr = 10;
+ static const int patchLengthMove = 6;
+ static const int patchLengthStore = 10;
#elif CPU(ARM_TRADITIONAL)
// These architecture specific value are used to enable patching - see comment on op_put_by_id.
static const int patchOffsetPutByIdStructure = 4;
@@ -536,6 +555,13 @@ namespace JSC {
static const int patchOffsetMethodCheckProtoObj = 20;
static const int patchOffsetMethodCheckProtoStruct = 30;
static const int patchOffsetMethodCheckPutFunction = 50;
+
+ static const int patchOffsetGetByIdProtoStruct = 40;
+ static const int patchOffsetPutByIdProtoStruct = 20;
+ static const int patchLengthTestPrototype = 29;
+ static const int patchLengthBranchPtr = 9;
+ static const int patchLengthMove = 10;
+ static const int patchLengthStore = 13;
#elif CPU(X86)
// These architecture specific value are used to enable patching - see comment on op_put_by_id.
static const int patchOffsetPutByIdStructure = 7;
diff --git a/JavaScriptCore/jit/JITMarkObjects.cpp b/JavaScriptCore/jit/JITMarkObjects.cpp
new file mode 100644
index 0000000..7eb3788
--- /dev/null
+++ b/JavaScriptCore/jit/JITMarkObjects.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2010 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. ``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
+ * 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(JIT)
+#if ENABLE(MOVABLE_GC_OBJECTS)
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+#include "JIT.h"
+
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "JITInlineMethods.h"
+#include "JITStubCall.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "JSObject.h"
+#include "JSPropertyNameIterator.h"
+#include "LinkBuffer.h"
+#include "PropertySlot.h"
+#include "RepatchBuffer.h"
+#include "ResultType.h"
+#include "SamplingTool.h"
+
+using namespace std;
+
+namespace JSC {
+
+typedef PropertySlot::CachedPropertyType PropertyType;
+
+void JIT::patchPrototypeStructureAddress(CodeLocationDataLabelPtr where, MarkStack& markStack, RepatchBuffer& repatchBuffer)
+{
+ uintptr_t prototypeStructureAddress = reinterpret_cast<uintptr_t>(pointerAtLocation(where));
+ JSCell* cell = reinterpret_cast<JSCell*>(prototypeStructureAddress & CELL_ALIGN_MASK);
+
+ ASSERT(&(cell->m_structure) == pointerAtLocation(where));
+ markStack.append(cell);
+ repatchBuffer.repatch(where, &(cell->m_structure));
+}
+
+void JIT::patchGetDirectOffset(CodeLocationLabel patchStart, MarkStack& markStack, RepatchBuffer& repatchBuffer, PropertyType propertyType)
+{
+ CodeLocationDataLabelPtr where;
+ switch (propertyType) {
+ case PropertySlot::Getter:
+ where = patchStart.dataLabelPtrAtOffset(patchLengthStore);
+ break;
+ case PropertySlot::Custom:
+ where = patchStart.dataLabelPtrAtOffset(patchLengthMove);
+ break;
+ default:
+ where = patchStart.dataLabelPtrAtOffset(patchLengthMove);
+ break;
+ }
+
+ uintptr_t propertyAddress;
+ uintptr_t newPropertyAddress;
+ ptrdiff_t offset;
+ JSObject* object;
+
+#if USE(JSVALUE32_64)
+ // JSVALUE32_64 will need to repatch two pointers for 32 bit code
+ propertyAddress = reinterpret_cast<uintptr_t>(pointerAtLocation(where));
+ object = reinterpret_cast<JSObject*>(propertyAddress & CELL_ALIGN_MASK);
+ offset = propertyAddress & CELL_MASK;
+ markStack.append(object);
+ newPropertyAddress = reinterpret_cast<uintptr_t>(object) + offset;
+ repatchBuffer.repatch(where, reinterpret_cast<void*>(newPropertyAddress));
+
+ if (offset == OBJECT_OFFSETOF(JSObject, m_externalStorage))
+ return;
+
+ ASSERT(object->isUsingInlineStorage());
+ ASSERT(offset >= OBJECT_OFFSETOF(JSObject, m_inlineStorage));
+ ASSERT(offset < OBJECT_OFFSETOF(JSObject, m_inlineStorage[JSObject::inlineStorageCapacity]));
+
+ where = where.dataLabelPtrAtOffset(patchLengthMove);
+#endif
+
+ propertyAddress = reinterpret_cast<uintptr_t>(pointerAtLocation(where));
+ object = reinterpret_cast<JSObject*>(propertyAddress & CELL_ALIGN_MASK);
+ offset = propertyAddress & CELL_MASK;
+ markStack.append(object);
+ newPropertyAddress = reinterpret_cast<uintptr_t>(object) + offset;
+ repatchBuffer.repatch(where, reinterpret_cast<void*>(newPropertyAddress));
+}
+
+void JIT::markGetByIdProto(MarkStack& markStack, CodeBlock* codeBlock, StructureStubInfo* stubInfo)
+{
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ CodeLocationLabel patchStart(jumpTarget(jumpLocation));
+
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ CodeLocationDataLabelPtr where = patchStart.dataLabelPtrAtOffset(patchOffsetGetByIdProtoStruct);
+ patchPrototypeStructureAddress(patchStart.dataLabelPtrAtOffset(patchOffsetGetByIdProtoStruct), markStack, repatchBuffer);
+
+ patchGetDirectOffset(where.labelAtOffset(patchLengthBranchPtr), markStack, repatchBuffer, stubInfo->u.getByIdProto.propertyType);
+}
+
+void JIT::markGetByIdChain(MarkStack& markStack, CodeBlock* codeBlock, StructureStubInfo* stubInfo)
+{
+ CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
+ CodeLocationLabel patchStart(jumpTarget(jumpLocation));
+
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ int count = stubInfo->u.getByIdChain.count;
+ for (int i = 0; i < count; ++i) {
+ CodeLocationDataLabelPtr where = patchStart.dataLabelPtrAtOffset(patchOffsetGetByIdProtoStruct + patchLengthTestPrototype * i);
+ patchPrototypeStructureAddress(where, markStack, repatchBuffer);
+ }
+ CodeLocationLabel where =
+ patchStart.labelAtOffset(patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + patchLengthTestPrototype * (count - 1));
+ patchGetDirectOffset(where, markStack, repatchBuffer, stubInfo->u.getByIdChain.propertyType);
+}
+
+void JIT::markGetByIdProtoList(MarkStack& markStack, CodeBlock* codeBlock, StructureStubInfo* stubInfo)
+{
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ for (int i = 0; i < stubInfo->u.getByIdSelfList.listSize; ++i) {
+ CodeLocationLabel patchStart = stubInfo->u.getByIdProtoList.structureList->list[i].stubRoutine;
+
+ PolymorphicAccessStructureList::PolymorphicStubInfo info =
+ stubInfo->u.getByIdProtoList.structureList->list[i];
+
+ if (!info.u.proto)
+ continue;
+
+ if (info.isChain) {
+ int count = info.count;
+ for (int j = 0; j < count; ++j) {
+ CodeLocationDataLabelPtr where = patchStart.dataLabelPtrAtOffset(patchOffsetGetByIdProtoStruct + patchLengthTestPrototype * j);
+ patchPrototypeStructureAddress(where, markStack, repatchBuffer);
+ }
+ CodeLocationLabel where =
+ patchStart.labelAtOffset(patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + patchLengthTestPrototype * (count - 1));
+ patchGetDirectOffset(where, markStack, repatchBuffer, info.propertyType);
+ } else {
+ CodeLocationDataLabelPtr where = patchStart.dataLabelPtrAtOffset(patchOffsetGetByIdProtoStruct);
+ patchPrototypeStructureAddress(where, markStack, repatchBuffer);
+
+ patchGetDirectOffset(where.labelAtOffset(patchLengthBranchPtr), markStack, repatchBuffer, info.propertyType);
+ }
+ }
+}
+
+void JIT::markPutByIdTransition(MarkStack& markStack, CodeBlock* codeBlock, StructureStubInfo* stubInfo)
+{
+ CodeLocationLabel patchStart = stubInfo->stubRoutine;
+
+ RepatchBuffer repatchBuffer(codeBlock);
+
+ RefPtr<Structure>* it = stubInfo->u.putByIdTransition.chain->head();
+ JSValue protoObject = stubInfo->u.putByIdTransition.structure->storedPrototype();
+
+ do {
+ if (protoObject.isNull())
+ continue;
+
+ CodeLocationDataLabelPtr where = patchStart.dataLabelPtrAtOffset(patchOffsetPutByIdProtoStruct + patchLengthTestPrototype);
+ patchPrototypeStructureAddress(where, markStack, repatchBuffer);
+
+ protoObject = it->get()->storedPrototype();
+ patchStart = patchStart.labelAtOffset(patchLengthTestPrototype);
+ } while (*it++);
+}
+
+void JIT::markGlobalObjectReference(MarkStack& markStack, CodeBlock* codeBlock, CodeLocationDataLabelPtr ref)
+{
+ RepatchBuffer repatchBuffer(codeBlock);
+ JSCell* globalObject = reinterpret_cast<JSCell*>(pointerAtLocation(ref));
+
+ ASSERT(!(reinterpret_cast<uintptr_t>(globalObject) & CELL_MASK));
+
+ markStack.append(globalObject);
+ repatchBuffer.repatch(ref, globalObject);
+}
+
+} // namespace JSC
+
+#endif
+
+#endif // ENABLE(MOVABLE_GC_OBJECTS)
+#endif // ENABLE(JIT)
diff --git a/JavaScriptCore/jit/JITPropertyAccess.cpp b/JavaScriptCore/jit/JITPropertyAccess.cpp
index 540e079..e1130e6 100644
--- a/JavaScriptCore/jit/JITPropertyAccess.cpp
+++ b/JavaScriptCore/jit/JITPropertyAccess.cpp
@@ -573,22 +573,23 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure*
loadPtr(Address(base, offset), result);
}
-void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID, RegisterID result, size_t cachedOffset)
{
if (base->isUsingInlineStorage())
loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result);
else {
PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
- loadPtr(static_cast<void*>(protoPropertyStorage), temp);
- loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
+ loadPtr(static_cast<void*>(protoPropertyStorage), result);
+ loadPtr(Address(result, cachedOffset * sizeof(JSValue)), result);
}
}
-void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
+unsigned JIT::testPrototype(JSValue prototype, JumpList& failureCases)
{
if (prototype.isNull())
- return;
+ return 0;
+ Label testPrototypeBegin(this);
// We have a special case for X86_64 here because X86 instructions that take immediate values
// only take 32 bit immediate values, wheras the pointer constants we are using here are 64 bit
// values. In the non X86_64 case, the generated code is slightly more efficient because it uses
@@ -599,20 +600,31 @@ void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
#else
failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(prototype)->m_structure), ImmPtr(asCell(prototype)->structure())));
#endif
+ ASSERT_JIT_OFFSET(differenceBetween(testPrototypeBegin, Label(this)), patchLengthTestPrototype);
+
+ return patchLengthTestPrototype;
}
bool JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
{
+ Label putByIdTransitionBegin(this);
JumpList failureCases;
// Check eax is an object of the right Structure.
failureCases.append(emitJumpIfNotJSCell(regT0));
failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
- testPrototype(oldStructure->storedPrototype(), failureCases);
+
+ unsigned offset = patchOffsetPutByIdProtoStruct + patchLengthBranchPtr;
+ ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
+
+ offset += testPrototype(oldStructure->storedPrototype(), failureCases);
+ ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
// ecx = baseObject->m_structure
if (!direct) {
- for (RefPtr<Structure>* it = chain->head(); *it; ++it)
- testPrototype((*it)->storedPrototype(), failureCases);
+ for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
+ offset += testPrototype((*it)->storedPrototype(), failureCases);
+ ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
+ }
}
Call callTarget;
@@ -771,6 +783,7 @@ bool JIT::privateCompilePatchGetArrayLength(StructureStubInfo* stubInfo, ReturnA
bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
{
+ Label getByIdProtoBegin(this);
// The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
// referencing the prototype object - let's speculatively load it's table nice and early!)
JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
@@ -787,6 +800,7 @@ bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
bool needsStubLink = false;
// Checks out okay!
@@ -837,7 +851,11 @@ bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
// We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel, slot.cachedPropertyType());
+#else
stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel);
+#endif
return true;
}
@@ -908,6 +926,7 @@ bool JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Structure*
bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
{
+ Label getByIdProtoListBegin(this);
PolymorphicAccessStructureList* prototypeStructures = stubInfo->u.getByIdProtoList.structureList;
int currentIndex = stubInfo->u.getByIdProtoList.listSize;
@@ -927,6 +946,8 @@ bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure*
Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoListBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
+
// Checks out okay!
bool needsStubLink = false;
if (slot.cachedPropertyType() == PropertySlot::Getter) {
@@ -973,7 +994,11 @@ bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure*
structure->ref();
prototypeStructure->ref();
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure, slot.cachedPropertyType());
+#else
prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
+#endif
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -989,6 +1014,8 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
int currentIndex = stubInfo->u.getByIdProtoList.listSize;
ASSERT(count);
+
+ Label getByIdChainListBegin(this);
JumpList bucketsOfFail;
// Check eax is an object of the right Structure.
@@ -1002,6 +1029,8 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = it->get();
testPrototype(protoObject, bucketsOfFail);
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdChainListBegin, Label(this)),
+ patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + i * patchLengthTestPrototype);
}
ASSERT(protoObject);
@@ -1050,7 +1079,11 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
// Track the stub we have created so that it will be deleted later.
structure->ref();
chain->ref();
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ prototypeStructures->list[currentIndex].set(entryLabel, structure, chain, count, slot.cachedPropertyType());
+#else
prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
+#endif
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -1064,6 +1097,7 @@ bool JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
{
ASSERT(count);
+ Label getByIdChainBegin(this);
JumpList bucketsOfFail;
// Check eax is an object of the right Structure.
@@ -1076,6 +1110,8 @@ bool JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = it->get();
testPrototype(protoObject, bucketsOfFail);
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdChainBegin, Label(this)),
+ patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + i * patchLengthTestPrototype);
}
ASSERT(protoObject);
@@ -1127,7 +1163,12 @@ bool JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
// We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ stubInfo->initGetByIdChain(structure, chain, entryLabel, count, slot.cachedPropertyType());
+#else
stubInfo->initGetByIdChain(structure, chain, entryLabel);
+#endif
+
return true;
}
diff --git a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
index bbffd7d..5127e85 100644
--- a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
+++ b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
@@ -574,8 +574,12 @@ void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, Register
void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
{
+ Label directOffsetBegin(this);
if (base->isUsingInlineStorage()) {
- load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
+ // On X86, load32 will optimize for a slightly smaller instruction in the case that resultPayoad is regT0
+ // Since we want this instruction to always be the same length, we use load32WithPatch to avoid this problem
+ load32WithPatch(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
+ ASSERT_JIT_OFFSET(differenceBetween(directOffsetBegin, Label(this)), patchLengthMove);
load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
return;
}
@@ -583,16 +587,18 @@ void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID res
size_t offset = cachedOffset * sizeof(JSValue);
PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
- loadPtr(static_cast<void*>(protoPropertyStorage), temp);
+ loadPtrWithPatch(static_cast<void*>(protoPropertyStorage), temp);
+ ASSERT_JIT_OFFSET(differenceBetween(directOffsetBegin, Label(this)), patchLengthMove);
load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
}
-void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
+unsigned JIT::testPrototype(JSValue prototype, JumpList& failureCases)
{
if (prototype.isNull())
- return;
+ return 0;
+ Label testPrototypeBegin(this);
// We have a special case for X86_64 here because X86 instructions that take immediate values
// only take 32 bit immediate values, wheras the pointer constants we are using here are 64 bit
// values. In the non X86_64 case, the generated code is slightly more efficient because it uses
@@ -603,23 +609,34 @@ void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
#else
failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(prototype)->m_structure), ImmPtr(asCell(prototype)->structure())));
#endif
+ ASSERT_JIT_OFFSET(differenceBetween(testPrototypeBegin, Label(this)), patchLengthTestPrototype);
+
+ return patchLengthTestPrototype;
}
bool JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
{
// It is assumed that regT0 contains the basePayload and regT1 contains the baseTag. The value can be found on the stack.
+ Label putByIdTransitionBegin(this);
JumpList failureCases;
failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
- testPrototype(oldStructure->storedPrototype(), failureCases);
+
+ int offset = patchOffsetPutByIdProtoStruct + patchLengthBranchPtr;
+ ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
+
+ offset += testPrototype(oldStructure->storedPrototype(), failureCases);
+ ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
if (!direct) {
// Verify that nothing in the prototype chain has a setter for this property.
- for (RefPtr<Structure>* it = chain->head(); *it; ++it)
- testPrototype((*it)->storedPrototype(), failureCases);
+ for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
+ offset += testPrototype((*it)->storedPrototype(), failureCases);
+ ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
+ }
}
-
+
// Reallocate property storage if needed.
Call callTarget;
bool willNeedStorageRealloc = oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
@@ -782,6 +799,7 @@ bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
{
// regT0 holds a JSCell*
+ Label getByIdProtoBegin(this);
// The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
// referencing the prototype object - let's speculatively load it's table nice and early!)
JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
@@ -796,6 +814,8 @@ bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
#else
Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
+
bool needsStubLink = false;
// Checks out okay!
if (slot.cachedPropertyType() == PropertySlot::Getter) {
@@ -848,7 +868,11 @@ bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
// We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel, slot.cachedPropertyType());
+#else
stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel);
+#endif
return true;
}
@@ -926,6 +950,7 @@ bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure*
// regT0 holds a JSCell*
+ Label getByIdProtoListBegin(this);
// The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
// referencing the prototype object - let's speculatively load it's table nice and early!)
JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
@@ -941,6 +966,7 @@ bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure*
#else
Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
#endif
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoListBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
bool needsStubLink = false;
if (slot.cachedPropertyType() == PropertySlot::Getter) {
@@ -961,7 +987,7 @@ bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure*
stubCall.call();
} else
compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
-
+
Jump success = jump();
LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
@@ -986,8 +1012,12 @@ bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure*
structure->ref();
prototypeStructure->ref();
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure, slot.cachedPropertyType());
+#else
prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
-
+#endif
+
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
RepatchBuffer repatchBuffer(m_codeBlock);
@@ -1004,6 +1034,7 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
// regT0 holds a JSCell*
ASSERT(count);
+ Label getByIdChainListBegin(this);
JumpList bucketsOfFail;
// Check eax is an object of the right Structure.
@@ -1016,6 +1047,9 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = it->get();
testPrototype(protoObject, bucketsOfFail);
+
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdChainListBegin, Label(this)),
+ patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + static_cast<int>(i) * patchLengthTestPrototype);
}
ASSERT(protoObject);
@@ -1038,7 +1072,7 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
stubCall.call();
} else
compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
-
+
Jump success = jump();
LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
@@ -1064,8 +1098,12 @@ bool JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Structure*
// Track the stub we have created so that it will be deleted later.
structure->ref();
chain->ref();
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ prototypeStructures->list[currentIndex].set(entryLabel, structure, chain, count, slot.cachedPropertyType());
+#else
prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
-
+#endif
+
// Finally patch the jump to slow case back in the hot path to jump here instead.
CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
RepatchBuffer repatchBuffer(m_codeBlock);
@@ -1079,6 +1117,7 @@ bool JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
// regT0 holds a JSCell*
ASSERT(count);
+ Label getByIdChainBegin(this);
JumpList bucketsOfFail;
// Check eax is an object of the right Structure.
@@ -1091,6 +1130,9 @@ bool JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
protoObject = asObject(currStructure->prototypeForLookup(callFrame));
currStructure = it->get();
testPrototype(protoObject, bucketsOfFail);
+
+ ASSERT_JIT_OFFSET(differenceBetween(getByIdChainBegin, Label(this)),
+ patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + static_cast<int>(i) * patchLengthTestPrototype);
}
ASSERT(protoObject);
@@ -1141,7 +1183,11 @@ bool JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
// We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ stubInfo->initGetByIdChain(structure, chain, entryLabel, count, slot.cachedPropertyType());
+#else
stubInfo->initGetByIdChain(structure, chain, entryLabel);
+#endif
return true;
}
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index c4ff0ca..7d94e76 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -1597,9 +1597,17 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
static void setupPolymorphicProtoList(StructureStubInfo* stubInfo)
{
if (stubInfo->accessType == access_get_by_id_proto)
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure, stubInfo->u.getByIdProto.propertyType));
+#else
stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure));
+#endif
else if (stubInfo->accessType == access_get_by_id_chain)
+#if ENABLE(MOVABLE_GC_OBJECTS)
+ stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain, stubInfo->u.getByIdChain.count, stubInfo->u.getByIdChain.propertyType));
+#else
stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain));
+#endif
ASSERT(stubInfo->accessType == access_get_by_id_proto_list);
}
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index f40f834..d00c557 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -1082,6 +1082,8 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
#define ENABLE_JSC_ZOMBIES 0
+#define ENABLE_MOVABLE_GC_OBJECTS 0
+
/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */
#if PLATFORM(MAC) || PLATFORM(WIN)
#define WTF_USE_PLATFORM_STRATEGIES 1
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list