Commit 667fa8a7 authored by eric@webkit.org's avatar eric@webkit.org

2010-08-07 Nathan Lawrence <nlawrence@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
parent 29a10d7c
......@@ -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 \
......
......@@ -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
......
2010-08-07 Nathan Lawrence <nlawrence@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@apple.com>
Reviewed by Geoffrey Garen.
......
......@@ -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 \
......
......@@ -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',
......
......@@ -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 \
......
......@@ -1688,6 +1688,9 @@
RelativePath="..\..\jit\JITInlineMethods.h"
>
</File>
<File
RelativePath="..\..\jit\JITMarkObjects.cpp"
>
<File
RelativePath="..\..\jit\JITOpcodes.cpp"
>
......
......@@ -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;
......
......@@ -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);
......
......@@ -209,6 +209,10 @@ public:
xor32(imm, srcDest);
}
void loadPtrWithPatch(void* address, RegisterID dest)
{
load32WithPatch(address, dest);
}
void loadPtr(ImplicitAddress address, RegisterID dest)
{
......
......@@ -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)
......
......@@ -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);
......
......@@ -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)
......
......@@ -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)
{
......
......@@ -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
......@@ -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;
......
......@@ -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;
......
/*
* 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]));