Changeset 64938 in webkit


Ignore:
Timestamp:
Aug 7, 2010 11:04:59 PM (14 years ago)
Author:
eric@webkit.org
Message:

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

Location:
trunk/JavaScriptCore
Files:
1 added
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/Android.mk

    r64849 r64938  
    5353        jit/JITCall.cpp \
    5454        jit/JITCall32_64.cpp \
     55        jit/JITMarkObjects.cpp \
    5556        jit/JITOpcodes.cpp \
    5657        jit/JITPropertyAccess.cpp \
  • trunk/JavaScriptCore/CMakeLists.txt

    r64866 r64938  
    5656    jit/JITCall.cpp
    5757    jit/JIT.cpp
     58    jit/JITMarkObjects.cpp
    5859    jit/JITOpcodes32_64.cpp
    5960    jit/JITOpcodes.cpp
  • trunk/JavaScriptCore/ChangeLog

    r64937 r64938  
     12010-08-07  Nathan Lawrence  <nlawrence@apple.com>
     2
     3        Reviewed by Geoffrey Garen.
     4
     5        The JIT code contains a number of direct references to GC'd objects.
     6        When we have movable objects, these references will need to be
     7        updated.
     8
     9        * Android.mk:
     10        * CMakeLists.txt:
     11        * GNUmakefile.am:
     12        * JavaScriptCore.gypi:
     13        * JavaScriptCore.pro:
     14        * JavaScriptCore.xcodeproj/project.pbxproj:
     15        * assembler/AbstractMacroAssembler.h:
     16        (JSC::AbstractMacroAssembler::int32AtLocation):
     17        (JSC::AbstractMacroAssembler::pointerAtLocation):
     18        (JSC::AbstractMacroAssembler::jumpTarget):
     19        * assembler/MacroAssembler.h:
     20        (JSC::MacroAssembler::loadPtrWithPatch):
     21            Normally, loadPtr will optimize when the register is eax.  Since
     22            the slightly smaller instruction changes the offsets, it messes up
     23            our ability to repatch the code.  We added this new instruction
     24            that garuntees a constant size.
     25        * assembler/MacroAssemblerX86.h:
     26        (JSC::MacroAssemblerX86::load32WithPatch):
     27            Changed load32 in the same way described above.
     28        (JSC::MacroAssemblerX86::load32):
     29            Moved the logic to optimize laod32 from movl_mr to load32
     30        (JSC::MacroAssemblerX86::store32):
     31            Moved the logic to optimize store32 from movl_rm to store32
     32        * assembler/X86Assembler.h:
     33        (JSC::X86Assembler::movl_rm):
     34        (JSC::X86Assembler::movl_mr):
     35        (JSC::X86Assembler::int32AtLocation):
     36        (JSC::X86Assembler::pointerAtLocation):
     37        (JSC::X86Assembler::jumpTarget):
     38        * bytecode/CodeBlock.cpp:
     39        (JSC::CodeBlock::markAggregate):
     40        * bytecode/Instruction.h:
     41            As described in StructureStubInfo.h, we needed to add additional
     42            fields to both StructureStubInfo and
     43            PolymorphicAccessStructureList so that we can determine the
     44            structure of the JITed code at patch time.
     45        (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
     46        (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
     47        * bytecode/StructureStubInfo.cpp:
     48        (JSC::StructureStubInfo::markAggregate):
     49            Added this function to mark the JITed code that correosponds to
     50            this structure stub info.
     51        * bytecode/StructureStubInfo.h:
     52        (JSC::StructureStubInfo::initGetByIdProto):
     53        (JSC::StructureStubInfo::initGetByIdChain):
     54        (JSC::StructureStubInfo::):
     55        * jit/JIT.h:
     56        * jit/JITMarkObjects.cpp: Added.
     57        (JSC::JIT::patchPrototypeStructureAddress):
     58        (JSC::JIT::patchGetDirectOffset):
     59        (JSC::JIT::markGetByIdProto):
     60        (JSC::JIT::markGetByIdChain):
     61        (JSC::JIT::markGetByIdProtoList):
     62        (JSC::JIT::markPutByIdTransition):
     63        (JSC::JIT::markGlobalObjectReference):
     64        * jit/JITPropertyAccess.cpp:
     65            Added asserts for the patch offsets.
     66        (JSC::JIT::compileGetDirectOffset):
     67        (JSC::JIT::testPrototype):
     68        (JSC::JIT::privateCompilePutByIdTransition):
     69        (JSC::JIT::privateCompileGetByIdProto):
     70        (JSC::JIT::privateCompileGetByIdProtoList):
     71        (JSC::JIT::privateCompileGetByIdChainList):
     72        (JSC::JIT::privateCompileGetByIdChain):
     73        * jit/JITPropertyAccess32_64.cpp:
     74        (JSC::JIT::compileGetDirectOffset):
     75        (JSC::JIT::testPrototype):
     76        (JSC::JIT::privateCompilePutByIdTransition):
     77        (JSC::JIT::privateCompileGetByIdProto):
     78        (JSC::JIT::privateCompileGetByIdProtoList):
     79        (JSC::JIT::privateCompileGetByIdChainList):
     80        (JSC::JIT::privateCompileGetByIdChain):
     81        * jit/JITStubs.cpp:
     82        (JSC::setupPolymorphicProtoList):
     83        * wtf/Platform.h:
     84            Added ENABLE_MOVABLE_GC_OBJECTS flag
     85
    1862010-08-07  Michael Saboff  <msaboff@apple.com>
    287
  • trunk/JavaScriptCore/GNUmakefile.am

    r64849 r64938  
    166166        JavaScriptCore/jit/JIT.h \
    167167        JavaScriptCore/jit/JITInlineMethods.h \
     168        JavaScriptCore/jit/JITMarkObjects.cpp \
    168169        JavaScriptCore/jit/JITOpcodes32_64.cpp \
    169170        JavaScriptCore/jit/JITOpcodes.cpp \
  • trunk/JavaScriptCore/JavaScriptCore.gypi

    r64849 r64938  
    119119            'jit/JITCode.h',
    120120            'jit/JITInlineMethods.h',
     121            'jit/JITMarkObjects.cpp',
    121122            'jit/JITOpcodes.cpp',
    122123            'jit/JITOpcodes32_64.cpp',
  • trunk/JavaScriptCore/JavaScriptCore.pro

    r64849 r64938  
    101101    jit/JITCall32_64.cpp \
    102102    jit/JIT.cpp \
     103    jit/JITMarkObjects.cpp \
    103104    jit/JITOpcodes.cpp \
    104105    jit/JITOpcodes32_64.cpp \
  • trunk/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r64854 r64938  
    16901690                        </File>
    16911691                        <File
     1692                                RelativePath="..\..\jit\JITMarkObjects.cpp"
     1693                                >
     1694                        <File
    16921695                                RelativePath="..\..\jit\JITOpcodes.cpp"
    16931696                                >
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r64861 r64938  
    510510                BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; };
    511511                C0A272630E50A06300E96E15 /* NotFound.h in Headers */ = {isa = PBXBuildFile; fileRef = C0A2723F0E509F1E00E96E15 /* NotFound.h */; settings = {ATTRIBUTES = (Private, ); }; };
     512                DD23669811DBB22D00AF47C8 /* JITMarkObjects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD23669711DBB22D00AF47C8 /* JITMarkObjects.cpp */; };
    512513                DD2724681208D1FF00F9ABE7 /* AlignedMemoryAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2724671208D1FF00F9ABE7 /* AlignedMemoryAllocator.h */; };
    513514                DD2724691208D1FF00F9ABE7 /* AlignedMemoryAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = DD2724671208D1FF00F9ABE7 /* AlignedMemoryAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    10631064                D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; };
    10641065                D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; };
     1066                DD23669711DBB22D00AF47C8 /* JITMarkObjects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITMarkObjects.cpp; sourceTree = "<group>"; };
    10651067                DD2724671208D1FF00F9ABE7 /* AlignedMemoryAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlignedMemoryAllocator.h; sourceTree = "<group>"; };
    10661068                DD377CBB12072C18006A2517 /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = "<group>"; };
     
    12731275                        isa = PBXGroup;
    12741276                        children = (
     1277                                DD23669711DBB22D00AF47C8 /* JITMarkObjects.cpp */,
    12751278                                A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */,
    12761279                                A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */,
     
    26762679                                DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */,
    26772680                                8627E5EB11F1281900A313B5 /* PageAllocation.cpp in Sources */,
     2681                                DD23669811DBB22D00AF47C8 /* JITMarkObjects.cpp in Sources */,
    26782682                                DDE82AD71209D955005C1756 /* GCHandle.cpp in Sources */,
    26792683                        );
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r62306 r64938  
    522522    }
    523523
     524    static int32_t int32AtLocation(CodeLocationDataLabel32 dataLabel32)
     525    {
     526        return AssemblerType::int32AtLocation(dataLabel32.dataLocation());
     527    }
     528
     529    static void* pointerAtLocation(CodeLocationDataLabelPtr dataLabelPtr)
     530    {
     531        return AssemblerType::pointerAtLocation(dataLabelPtr.dataLocation());
     532    }
     533
     534    static void* jumpTarget(CodeLocationJump jump)
     535    {
     536        return AssemblerType::jumpTarget(jump.dataLocation());
     537    }
     538
    524539    static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
    525540    {
  • trunk/JavaScriptCore/assembler/MacroAssembler.h

    r57925 r64938  
    210210    }
    211211
     212    void loadPtrWithPatch(void* address, RegisterID dest)
     213    {
     214        load32WithPatch(address, dest);
     215    }
    212216
    213217    void loadPtr(ImplicitAddress address, RegisterID dest)
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86.h

    r58469 r64938  
    8383    }
    8484
     85    void load32WithPatch(void* address, RegisterID dest)
     86    {
     87        m_assembler.movl_mr(address, dest);
     88    }
     89
    8590    void load32(void* address, RegisterID dest)
    8691    {
    87         m_assembler.movl_mr(address, dest);
     92        if (dest == X86Registers::eax)
     93            m_assembler.movl_mEAX(address);
     94        else
     95            m_assembler.movl_mr(address, dest);
    8896    }
    8997
     
    106114    void store32(RegisterID src, void* address)
    107115    {
    108         m_assembler.movl_rm(src, address);
     116        if (src == X86Registers::eax)
     117            m_assembler.movl_EAXm(address);
     118        else
     119            m_assembler.movl_rm(src, address);
    109120    }
    110121
  • trunk/JavaScriptCore/assembler/X86Assembler.h

    r64608 r64938  
    11551155    void movl_rm(RegisterID src, void* addr)
    11561156    {
    1157         if (src == X86Registers::eax)
    1158             movl_EAXm(addr);
    1159         else
    1160             m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
     1157        m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
    11611158    }
    11621159   
    11631160    void movl_mr(void* addr, RegisterID dst)
    11641161    {
    1165         if (dst == X86Registers::eax)
    1166             movl_mEAX(addr);
    1167         else
    1168             m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
     1162        m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
    11691163    }
    11701164
     
    15581552
    15591553        setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
     1554    }
     1555
     1556    static int32_t int32AtLocation(void* where)
     1557    {
     1558        return static_cast<int32_t*>(where)[-1];
     1559    }
     1560
     1561    static void* pointerAtLocation(void* where)
     1562    {
     1563        return static_cast<void**>(where)[-1];
     1564    }
     1565
     1566    static void* jumpTarget(void* jump)
     1567    {
     1568        intptr_t src = reinterpret_cast<intptr_t>(jump);
     1569        int32_t offset = static_cast<int32_t*>(jump)[-1];
     1570        return reinterpret_cast<void*>(src + offset);
    15601571    }
    15611572
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r64790 r64938  
    15211521        m_functionDecls[i]->markAggregate(markStack);
    15221522    markStack.append(m_globalObject);
     1523#if ENABLE(MOVABLE_GC_OBJECTS)
     1524    // This is the code that is responsible for marking the actual pointers
     1525    // to JSCell*s in the JIT'ed code.  Normally, these pointers are marked
     1526    // elsewhere, however when we have movable objects, we will need to update
     1527    // all of the references.
     1528    for (size_t i = 0; i < m_structureStubInfos.size(); ++i)
     1529        m_structureStubInfos[i].markAggregate(markStack, this);
     1530#endif
    15231531}
    15241532
  • trunk/JavaScriptCore/bytecode/Instruction.h

    r63056 r64938  
    6464                StructureChain* chain;
    6565            } u;
     66#if ENABLE(MOVABLE_GC_OBJECTS)
     67            int count;
     68            PropertySlot::CachedPropertyType propertyType;
     69#endif
    6670
    6771            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
     
    7377            }
    7478           
     79#if ENABLE(MOVABLE_GC_OBJECTS)
     80            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto, PropertySlot::CachedPropertyType _propertyType)
     81#else
    7582            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
     83#endif
    7684            {
    7785                stubRoutine = _stubRoutine;
     
    7987                u.proto = _proto;
    8088                isChain = false;
     89#if ENABLE(MOVABLE_GC_OBJECTS)
     90                propertyType = _propertyType;
     91#endif
    8192            }
    8293           
     94#if ENABLE(MOVABLE_GC_OBJECTS)
     95            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain, int _count, PropertySlot::CachedPropertyType _propertyType)
     96#else
    8397            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
     98#endif
    8499            {
    85100                stubRoutine = _stubRoutine;
     
    87102                u.chain = _chain;
    88103                isChain = true;
     104#if ENABLE(MOVABLE_GC_OBJECTS)
     105                count = _count;
     106                propertyType = _propertyType;
     107#endif
    89108            }
    90109        } list[POLYMORPHIC_LIST_CACHE_SIZE];
     
    95114        }
    96115
     116#if ENABLE(MOVABLE_GC_OBJECTS)
     117        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto, PropertySlot::CachedPropertyType propertyType)
     118        {
     119            list[0].set(stubRoutine, firstBase, firstProto, propertyType);
     120        }
     121#else
    97122        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
    98123        {
    99124            list[0].set(stubRoutine, firstBase, firstProto);
    100125        }
    101 
     126#endif
     127
     128#if ENABLE(MOVABLE_GC_OBJECTS)
     129        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain, int count, PropertySlot::CachedPropertyType propertyType)
     130        {
     131            list[0].set(stubRoutine, firstBase, firstChain, count, propertyType);
     132        }
     133#else
    102134        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
    103135        {
    104136            list[0].set(stubRoutine, firstBase, firstChain);
    105137        }
     138#endif
    106139
    107140        void derefStructures(int count)
  • trunk/JavaScriptCore/bytecode/StructureStubInfo.cpp

    r46879 r64938  
    2626#include "config.h"
    2727#include "StructureStubInfo.h"
     28
     29#include "JIT.h"
    2830
    2931namespace JSC {
     
    7678    }
    7779}
     80
     81#if ENABLE(MOVABLE_GC_OBJECTS)
     82void StructureStubInfo::markAggregate(MarkStack& markStack, CodeBlock* codeBlock)
     83{
     84    switch (accessType) {
     85    case access_get_by_id_proto:
     86        JIT::markGetByIdProto(markStack, codeBlock, this);
     87        return;
     88    case access_get_by_id_chain:
     89        JIT::markGetByIdChain(markStack, codeBlock, this);
     90        return;
     91    case access_get_by_id_proto_list:
     92        JIT::markGetByIdProtoList(markStack, codeBlock, this);
     93        return;
     94    case access_put_by_id_transition:
     95        JIT::markPutByIdTransition(markStack, codeBlock, this);
     96        return;
     97    case access_get_by_id_self:
     98    case access_get_by_id_self_list:
     99    case access_put_by_id_replace:
     100    case access_get_by_id:
     101    case access_put_by_id:
     102    case access_get_by_id_generic:
     103    case access_put_by_id_generic:
     104    case access_get_array_length:
     105    case access_get_string_length:
     106        return;
     107    default:
     108        ASSERT_NOT_REACHED();
     109    }
     110}
     111#endif
     112
    78113#endif
    79114
  • trunk/JavaScriptCore/bytecode/StructureStubInfo.h

    r64608 r64938  
    3131#include "Instruction.h"
    3232#include "MacroAssembler.h"
     33#include "PropertySlot.h"
    3334#include "Opcode.h"
    3435#include "Structure.h"
     
    6768        }
    6869
     70#if ENABLE(MOVABLE_GC_OBJECTS)
     71        void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure, CodeLocationLabel routine, PropertySlot::CachedPropertyType propertyType)
     72#else
    6973        void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure, CodeLocationLabel routine)
     74#endif
    7075        {
    7176            accessType = access_get_by_id_proto;
     
    7883
    7984            stubRoutine = routine;
    80         }
    81 
     85
     86#if ENABLE(MOVABLE_GC_OBJECTS)
     87            u.getByIdProto.propertyType = propertyType;
     88#endif
     89        }
     90
     91#if ENABLE(MOVABLE_GC_OBJECTS)
     92        void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain, CodeLocationLabel routine, int count, PropertySlot::CachedPropertyType propertyType)
     93#else
    8294        void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain, CodeLocationLabel routine)
     95#endif
    8396        {
    8497            accessType = access_get_by_id_chain;
     
    91104
    92105            stubRoutine = routine;
     106
     107#if ENABLE(MOVABLE_GC_OBJECTS)
     108            u.getByIdChain.count = count;
     109            u.getByIdChain.propertyType = propertyType;
     110#endif
    93111        }
    94112
     
    140158
    141159        void deref();
     160#if ENABLE(MOVABLE_GC_OBJECTS)
     161        void markAggregate(MarkStack&, CodeBlock*);
     162#endif
    142163
    143164        bool seenOnce()
     
    161182                Structure* baseObjectStructure;
    162183                Structure* prototypeStructure;
     184#if ENABLE(MOVABLE_GC_OBJECTS)
     185                // The propertyType is required to properly determine the
     186                // structure of the underlying code so that we may patch it
     187                // correctly.  Different code is generated for different
     188                // property types, and therefore, the offsets that we need to
     189                // patch at will change.
     190                PropertySlot::CachedPropertyType propertyType;
     191#endif
    163192            } getByIdProto;
    164193            struct {
    165194                Structure* baseObjectStructure;
    166195                StructureChain* chain;
     196#if ENABLE(MOVABLE_GC_OBJECTS)
     197                // We need the count so that we can iterate over the prototype
     198                // chain, marking all of the references to objects.
     199                int count;
     200                PropertySlot::CachedPropertyType propertyType;
     201#endif
    167202            } getByIdChain;
    168203            struct {
  • trunk/JavaScriptCore/jit/JIT.h

    r64649 r64938  
    238238        static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
    239239
     240#if ENABLE(MOVABLE_GC_OBJECTS)
     241        static void patchPrototypeStructureAddress(CodeLocationDataLabelPtr, MarkStack&, RepatchBuffer&);
     242        static void patchGetDirectOffset(CodeLocationLabel, MarkStack&, RepatchBuffer&, PropertySlot::CachedPropertyType);
     243        static void markGetByIdChainInternal(CodeLocationLabel, MarkStack&, RepatchBuffer&, PropertySlot::CachedPropertyType);
     244
     245        static void markGetByIdProto(MarkStack&, CodeBlock*, StructureStubInfo*);
     246        static void markGetByIdChain(MarkStack&, CodeBlock*, StructureStubInfo*);
     247        static void markGetByIdProtoList(MarkStack&, CodeBlock*, StructureStubInfo*);
     248        static void markPutByIdTransition(MarkStack&, CodeBlock*, StructureStubInfo*);
     249        static void markGlobalObjectReference(MarkStack&, CodeBlock*, CodeLocationDataLabelPtr);
     250#endif
     251
    240252        static bool compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, ReturnAddressPtr returnAddress)
    241253        {
     
    296308        void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
    297309
    298         void testPrototype(JSValue, JumpList& failureCases);
     310        unsigned testPrototype(JSValue, JumpList& failureCases);
    299311
    300312#if USE(JSVALUE32_64)
     
    367379        static const int patchOffsetMethodCheckProtoStruct = 18;
    368380        static const int patchOffsetMethodCheckPutFunction = 29;
     381
     382        static const int patchOffsetGetByIdProtoStruct = 19;
     383        static const int patchOffsetPutByIdProtoStruct = 12;
     384        static const int patchLengthTestPrototype = 16;
     385        static const int patchLengthBranchPtr = 10;
     386        static const int patchLengthMove = 6;
     387        static const int patchLengthStore = 10;
    369388#elif CPU(ARM_TRADITIONAL)
    370389        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
     
    537556        static const int patchOffsetMethodCheckProtoStruct = 30;
    538557        static const int patchOffsetMethodCheckPutFunction = 50;
     558
     559        static const int patchOffsetGetByIdProtoStruct = 40;
     560        static const int patchOffsetPutByIdProtoStruct = 20;
     561        static const int patchLengthTestPrototype = 29;
     562        static const int patchLengthBranchPtr = 9;
     563        static const int patchLengthMove = 10;
     564        static const int patchLengthStore = 13;
    539565#elif CPU(X86)
    540566        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r64937 r64938  
    574574}
    575575
    576 void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
     576void JIT::compileGetDirectOffset(JSObject* base, RegisterID, RegisterID result, size_t cachedOffset)
    577577{
    578578    if (base->isUsingInlineStorage())
     
    580580    else {
    581581        PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
    582         loadPtr(static_cast<void*>(protoPropertyStorage), temp);
    583         loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
     582        loadPtr(static_cast<void*>(protoPropertyStorage), result);
     583        loadPtr(Address(result, cachedOffset * sizeof(JSValue)), result);
    584584    }
    585585}
    586586
    587 void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
     587unsigned JIT::testPrototype(JSValue prototype, JumpList& failureCases)
    588588{
    589589    if (prototype.isNull())
    590         return;
    591 
     590        return 0;
     591
     592    Label testPrototypeBegin(this);
    592593    // We have a special case for X86_64 here because X86 instructions that take immediate values
    593594    // only take 32 bit immediate values, wheras the pointer constants we are using here are 64 bit
     
    600601    failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(prototype)->m_structure), ImmPtr(asCell(prototype)->structure())));
    601602#endif
     603    ASSERT_JIT_OFFSET(differenceBetween(testPrototypeBegin, Label(this)), patchLengthTestPrototype);
     604
     605    return patchLengthTestPrototype;
    602606}
    603607
    604608bool JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
    605609{
     610    Label putByIdTransitionBegin(this);
    606611    JumpList failureCases;
    607612    // Check eax is an object of the right Structure.
    608613    failureCases.append(emitJumpIfNotJSCell(regT0));
    609614    failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
    610     testPrototype(oldStructure->storedPrototype(), failureCases);
     615
     616    unsigned offset = patchOffsetPutByIdProtoStruct + patchLengthBranchPtr;
     617    ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
     618
     619    offset += testPrototype(oldStructure->storedPrototype(), failureCases);
     620    ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
    611621
    612622    // ecx = baseObject->m_structure
    613623    if (!direct) {
    614         for (RefPtr<Structure>* it = chain->head(); *it; ++it)
    615             testPrototype((*it)->storedPrototype(), failureCases);
     624        for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
     625            offset += testPrototype((*it)->storedPrototype(), failureCases);
     626            ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
     627        }
    616628    }
    617629
     
    772784bool JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    773785{
     786    Label getByIdProtoBegin(this);
    774787    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
    775788    // referencing the prototype object - let's speculatively load it's table nice and early!)
     
    788801#endif
    789802
     803    ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
    790804    bool needsStubLink = false;
    791805   
     
    838852    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
    839853    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
     854#if ENABLE(MOVABLE_GC_OBJECTS)
     855    stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel, slot.cachedPropertyType());
     856#else
    840857    stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel);
     858#endif
    841859    return true;
    842860}
     
    909927bool JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
    910928{
     929    Label getByIdProtoListBegin(this);
    911930    PolymorphicAccessStructureList* prototypeStructures = stubInfo->u.getByIdProtoList.structureList;
    912931    int currentIndex = stubInfo->u.getByIdProtoList.listSize;
     
    927946    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
    928947#endif
     948
     949    ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoListBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
    929950
    930951    // Checks out okay!
     
    974995    structure->ref();
    975996    prototypeStructure->ref();
     997#if ENABLE(MOVABLE_GC_OBJECTS)
     998    prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure, slot.cachedPropertyType());
     999#else
    9761000    prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
     1001#endif
    9771002
    9781003    // Finally patch the jump to slow case back in the hot path to jump here instead.
     
    9901015
    9911016    ASSERT(count);
     1017
     1018    Label getByIdChainListBegin(this);
    9921019    JumpList bucketsOfFail;
    9931020
     
    10031030        currStructure = it->get();
    10041031        testPrototype(protoObject, bucketsOfFail);
     1032        ASSERT_JIT_OFFSET(differenceBetween(getByIdChainListBegin, Label(this)),
     1033            patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + i * patchLengthTestPrototype);
    10051034    }
    10061035    ASSERT(protoObject);
     
    10511080    structure->ref();
    10521081    chain->ref();
     1082#if ENABLE(MOVABLE_GC_OBJECTS)
     1083    prototypeStructures->list[currentIndex].set(entryLabel, structure, chain, count, slot.cachedPropertyType());
     1084#else
    10531085    prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
     1086#endif
    10541087
    10551088    // Finally patch the jump to slow case back in the hot path to jump here instead.
     
    10651098    ASSERT(count);
    10661099
     1100    Label getByIdChainBegin(this);
    10671101    JumpList bucketsOfFail;
    10681102
     
    10771111        currStructure = it->get();
    10781112        testPrototype(protoObject, bucketsOfFail);
     1113        ASSERT_JIT_OFFSET(differenceBetween(getByIdChainBegin, Label(this)),
     1114            patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + i * patchLengthTestPrototype);
    10791115    }
    10801116    ASSERT(protoObject);
     
    11281164    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
    11291165    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
     1166#if ENABLE(MOVABLE_GC_OBJECTS)
     1167    stubInfo->initGetByIdChain(structure, chain, entryLabel, count, slot.cachedPropertyType());
     1168#else
    11301169    stubInfo->initGetByIdChain(structure, chain, entryLabel);
     1170#endif
     1171
    11311172    return true;
    11321173}
  • trunk/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r64937 r64938  
    575575void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
    576576{
     577    Label directOffsetBegin(this);
    577578    if (base->isUsingInlineStorage()) {
    578         load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
     579        // On X86, load32 will optimize for a slightly smaller instruction in the case that resultPayoad is regT0
     580        // Since we want this instruction to always be the same length, we use load32WithPatch to avoid this problem
     581        load32WithPatch(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
     582        ASSERT_JIT_OFFSET(differenceBetween(directOffsetBegin, Label(this)), patchLengthMove);
    579583        load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
    580584        return;
     
    584588   
    585589    PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
    586     loadPtr(static_cast<void*>(protoPropertyStorage), temp);
     590    loadPtrWithPatch(static_cast<void*>(protoPropertyStorage), temp);
     591    ASSERT_JIT_OFFSET(differenceBetween(directOffsetBegin, Label(this)), patchLengthMove);
    587592    load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
    588593    load32(Address(temp, offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
    589594}
    590595
    591 void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
     596unsigned JIT::testPrototype(JSValue prototype, JumpList& failureCases)
    592597{
    593598    if (prototype.isNull())
    594         return;
    595    
     599        return 0;
     600   
     601    Label testPrototypeBegin(this);
    596602    // We have a special case for X86_64 here because X86 instructions that take immediate values
    597603    // only take 32 bit immediate values, wheras the pointer constants we are using here are 64 bit
     
    604610    failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(prototype)->m_structure), ImmPtr(asCell(prototype)->structure())));
    605611#endif
     612    ASSERT_JIT_OFFSET(differenceBetween(testPrototypeBegin, Label(this)), patchLengthTestPrototype);
     613
     614    return patchLengthTestPrototype;
    606615}
    607616
     
    610619    // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag.  The value can be found on the stack.
    611620   
     621    Label putByIdTransitionBegin(this);
    612622    JumpList failureCases;
    613623    failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
    614624    failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
    615     testPrototype(oldStructure->storedPrototype(), failureCases);
     625
     626    int offset = patchOffsetPutByIdProtoStruct + patchLengthBranchPtr;
     627    ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
     628
     629    offset += testPrototype(oldStructure->storedPrototype(), failureCases);
     630    ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
    616631   
    617632    if (!direct) {
    618633        // Verify that nothing in the prototype chain has a setter for this property.
    619         for (RefPtr<Structure>* it = chain->head(); *it; ++it)
    620             testPrototype((*it)->storedPrototype(), failureCases);
     634        for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
     635            offset += testPrototype((*it)->storedPrototype(), failureCases);
     636            ASSERT_JIT_OFFSET(differenceBetween(putByIdTransitionBegin, Label(this)), offset);
     637        }
    621638    }
    622 
     639   
    623640    // Reallocate property storage if needed.
    624641    Call callTarget;
     
    783800    // regT0 holds a JSCell*
    784801   
     802    Label getByIdProtoBegin(this);
    785803    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
    786804    // referencing the prototype object - let's speculatively load it's table nice and early!)
     
    797815    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
    798816#endif
     817    ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
     818
    799819    bool needsStubLink = false;
    800820    // Checks out okay!
     
    849869    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
    850870    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
     871#if ENABLE(MOVABLE_GC_OBJECTS)
     872    stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel, slot.cachedPropertyType());
     873#else
    851874    stubInfo->initGetByIdProto(structure, prototypeStructure, entryLabel);
     875#endif
    852876    return true;
    853877}
     
    927951    // regT0 holds a JSCell*
    928952   
     953    Label getByIdProtoListBegin(this);
    929954    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
    930955    // referencing the prototype object - let's speculatively load it's table nice and early!)
     
    942967    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
    943968#endif
     969    ASSERT_JIT_OFFSET(differenceBetween(getByIdProtoListBegin, Label(this)), patchOffsetGetByIdProtoStruct + patchLengthBranchPtr);
    944970   
    945971    bool needsStubLink = false;
     
    962988    } else
    963989        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
    964    
     990
    965991    Jump success = jump();
    966992   
     
    9871013    structure->ref();
    9881014    prototypeStructure->ref();
     1015#if ENABLE(MOVABLE_GC_OBJECTS)
     1016    prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure, slot.cachedPropertyType());
     1017#else
    9891018    prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
    990    
     1019#endif
     1020
    9911021    // Finally patch the jump to slow case back in the hot path to jump here instead.
    9921022    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
     
    10051035    ASSERT(count);
    10061036   
     1037    Label getByIdChainListBegin(this);
    10071038    JumpList bucketsOfFail;
    10081039   
     
    10171048        currStructure = it->get();
    10181049        testPrototype(protoObject, bucketsOfFail);
     1050
     1051        ASSERT_JIT_OFFSET(differenceBetween(getByIdChainListBegin, Label(this)),
     1052            patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + static_cast<int>(i) * patchLengthTestPrototype);
    10191053    }
    10201054    ASSERT(protoObject);
     
    10391073    } else
    10401074        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
    1041 
     1075   
    10421076    Jump success = jump();
    10431077   
     
    10651099    structure->ref();
    10661100    chain->ref();
     1101#if ENABLE(MOVABLE_GC_OBJECTS)
     1102    prototypeStructures->list[currentIndex].set(entryLabel, structure, chain, count, slot.cachedPropertyType());
     1103#else
    10671104    prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
    1068    
     1105#endif
     1106
    10691107    // Finally patch the jump to slow case back in the hot path to jump here instead.
    10701108    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
     
    10801118    ASSERT(count);
    10811119   
     1120    Label getByIdChainBegin(this);
    10821121    JumpList bucketsOfFail;
    10831122   
     
    10921131        currStructure = it->get();
    10931132        testPrototype(protoObject, bucketsOfFail);
     1133
     1134        ASSERT_JIT_OFFSET(differenceBetween(getByIdChainBegin, Label(this)),
     1135            patchOffsetGetByIdProtoStruct + patchLengthBranchPtr + static_cast<int>(i) * patchLengthTestPrototype);
    10941136    }
    10951137    ASSERT(protoObject);
     
    11421184    // We don't want to patch more than once - in future go to cti_op_put_by_id_generic.
    11431185    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list));
     1186#if ENABLE(MOVABLE_GC_OBJECTS)
     1187    stubInfo->initGetByIdChain(structure, chain, entryLabel, count, slot.cachedPropertyType());
     1188#else
    11441189    stubInfo->initGetByIdChain(structure, chain, entryLabel);
     1190#endif
    11451191    return true;
    11461192}
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r64818 r64938  
    15981598{
    15991599    if (stubInfo->accessType == access_get_by_id_proto)
     1600#if ENABLE(MOVABLE_GC_OBJECTS)
     1601        stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure, stubInfo->u.getByIdProto.propertyType));
     1602#else
    16001603        stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure));
     1604#endif
    16011605    else if (stubInfo->accessType == access_get_by_id_chain)
     1606#if ENABLE(MOVABLE_GC_OBJECTS)
     1607        stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain, stubInfo->u.getByIdChain.count, stubInfo->u.getByIdChain.propertyType));
     1608#else
    16021609        stubInfo->initGetByIdProtoList(new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain));
     1610#endif
    16031611    ASSERT(stubInfo->accessType == access_get_by_id_proto_list);
    16041612}
  • trunk/JavaScriptCore/wtf/Platform.h

    r64915 r64938  
    10831083#define ENABLE_JSC_ZOMBIES 0
    10841084
     1085#define ENABLE_MOVABLE_GC_OBJECTS 0
     1086
    10851087/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */
    10861088#if PLATFORM(MAC) || PLATFORM(WIN)
Note: See TracChangeset for help on using the changeset viewer.