]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - bytecode/StructureStubInfo.h
JavaScriptCore-7600.1.4.13.1.tar.gz
[apple/javascriptcore.git] / bytecode / StructureStubInfo.h
index 03c64bf3975f099ab3aec059f7fe58594661097a..008996663c26784714e8250b224714c2edb3095c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef StructureStubInfo_h
 #define StructureStubInfo_h
 
-#include <wtf/Platform.h>
-
-#if ENABLE(JIT)
-
 #include "CodeOrigin.h"
 #include "Instruction.h"
+#include "JITStubRoutine.h"
 #include "MacroAssembler.h"
 #include "Opcode.h"
+#include "PolymorphicAccessStructureList.h"
+#include "RegisterSet.h"
+#include "SpillRegistersMode.h"
 #include "Structure.h"
+#include "StructureStubClearingWatchpoint.h"
+#include <wtf/OwnPtr.h>
 
 namespace JSC {
 
-    class PolymorphicPutByIdList;
-
-    enum AccessType {
-        access_get_by_id_self,
-        access_get_by_id_proto,
-        access_get_by_id_chain,
-        access_get_by_id_self_list,
-        access_get_by_id_proto_list,
-        access_put_by_id_transition_normal,
-        access_put_by_id_transition_direct,
-        access_put_by_id_replace,
-        access_put_by_id_list,
-        access_unset,
-        access_get_by_id_generic,
-        access_put_by_id_generic,
-        access_get_array_length,
-        access_get_string_length,
-    };
-
-    inline bool isGetByIdAccess(AccessType accessType)
-    {
-        switch (accessType) {
-        case access_get_by_id_self:
-        case access_get_by_id_proto:
-        case access_get_by_id_chain:
-        case access_get_by_id_self_list:
-        case access_get_by_id_proto_list:
-        case access_get_by_id_generic:
-        case access_get_array_length:
-        case access_get_string_length:
-            return true;
-        default:
-            return false;
-        }
+#if ENABLE(JIT)
+
+class PolymorphicGetByIdList;
+class PolymorphicPutByIdList;
+
+enum AccessType {
+    access_get_by_id_self,
+    access_get_by_id_chain,
+    access_get_by_id_list,
+    access_put_by_id_transition_normal,
+    access_put_by_id_transition_direct,
+    access_put_by_id_replace,
+    access_put_by_id_list,
+    access_unset,
+    access_in_list
+};
+
+inline bool isGetByIdAccess(AccessType accessType)
+{
+    switch (accessType) {
+    case access_get_by_id_self:
+    case access_get_by_id_chain:
+    case access_get_by_id_list:
+        return true;
+    default:
+        return false;
     }
+}
     
-    inline bool isPutByIdAccess(AccessType accessType)
+inline bool isPutByIdAccess(AccessType accessType)
+{
+    switch (accessType) {
+    case access_put_by_id_transition_normal:
+    case access_put_by_id_transition_direct:
+    case access_put_by_id_replace:
+    case access_put_by_id_list:
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool isInAccess(AccessType accessType)
+{
+    switch (accessType) {
+    case access_in_list:
+        return true;
+    default:
+        return false;
+    }
+}
+
+struct StructureStubInfo {
+    StructureStubInfo()
+        : accessType(access_unset)
+        , seen(false)
+        , resetByGC(false)
     {
-        switch (accessType) {
-        case access_put_by_id_transition_normal:
-        case access_put_by_id_transition_direct:
-        case access_put_by_id_replace:
-        case access_put_by_id_list:
-        case access_put_by_id_generic:
-            return true;
-        default:
-            return false;
-        }
     }
 
-    struct StructureStubInfo {
-        StructureStubInfo()
-            : accessType(access_unset)
-            , seen(false)
-        {
-        }
-
-        void initGetByIdSelf(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure)
-        {
-            accessType = access_get_by_id_self;
-
-            u.getByIdSelf.baseObjectStructure.set(globalData, owner, baseObjectStructure);
-        }
-
-        void initGetByIdProto(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, Structure* prototypeStructure)
-        {
-            accessType = access_get_by_id_proto;
-
-            u.getByIdProto.baseObjectStructure.set(globalData, owner, baseObjectStructure);
-            u.getByIdProto.prototypeStructure.set(globalData, owner, prototypeStructure);
-        }
-
-        void initGetByIdChain(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain)
-        {
-            accessType = access_get_by_id_chain;
-
-            u.getByIdChain.baseObjectStructure.set(globalData, owner, baseObjectStructure);
-            u.getByIdChain.chain.set(globalData, owner, chain);
-        }
-
-        void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
-        {
-            accessType = access_get_by_id_self_list;
-
-            u.getByIdSelfList.structureList = structureList;
-            u.getByIdSelfList.listSize = listSize;
-        }
-
-        void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
-        {
-            accessType = access_get_by_id_proto_list;
-
-            u.getByIdProtoList.structureList = structureList;
-            u.getByIdProtoList.listSize = listSize;
-        }
-
-        // PutById*
-
-        void initPutByIdTransition(JSGlobalData& globalData, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain, bool isDirect)
-        {
-            if (isDirect)
-                accessType = access_put_by_id_transition_direct;
-            else
-                accessType = access_put_by_id_transition_normal;
-
-            u.putByIdTransition.previousStructure.set(globalData, owner, previousStructure);
-            u.putByIdTransition.structure.set(globalData, owner, structure);
-            u.putByIdTransition.chain.set(globalData, owner, chain);
-        }
-
-        void initPutByIdReplace(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure)
-        {
-            accessType = access_put_by_id_replace;
+    void initGetByIdSelf(VM& vm, JSCell* owner, Structure* baseObjectStructure)
+    {
+        accessType = access_get_by_id_self;
+
+        u.getByIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure);
+    }
+
+    void initGetByIdChain(VM& vm, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain, unsigned count, bool isDirect)
+    {
+        accessType = access_get_by_id_chain;
+
+        u.getByIdChain.baseObjectStructure.set(vm, owner, baseObjectStructure);
+        u.getByIdChain.chain.set(vm, owner, chain);
+        u.getByIdChain.count = count;
+        u.getByIdChain.isDirect = isDirect;
+    }
+
+    void initGetByIdList(PolymorphicGetByIdList* list)
+    {
+        accessType = access_get_by_id_list;
+        u.getByIdList.list = list;
+    }
+
+    // PutById*
+
+    void initPutByIdTransition(VM& vm, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain, bool isDirect)
+    {
+        if (isDirect)
+            accessType = access_put_by_id_transition_direct;
+        else
+            accessType = access_put_by_id_transition_normal;
+
+        u.putByIdTransition.previousStructure.set(vm, owner, previousStructure);
+        u.putByIdTransition.structure.set(vm, owner, structure);
+        u.putByIdTransition.chain.set(vm, owner, chain);
+    }
+
+    void initPutByIdReplace(VM& vm, JSCell* owner, Structure* baseObjectStructure)
+    {
+        accessType = access_put_by_id_replace;
     
-            u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure);
-        }
+        u.putByIdReplace.baseObjectStructure.set(vm, owner, baseObjectStructure);
+    }
         
-        void initPutByIdList(PolymorphicPutByIdList* list)
-        {
-            accessType = access_put_by_id_list;
-            u.putByIdList.list = list;
-        }
+    void initPutByIdList(PolymorphicPutByIdList* list)
+    {
+        accessType = access_put_by_id_list;
+        u.putByIdList.list = list;
+    }
+    
+    void initInList(PolymorphicAccessStructureList* list, int listSize)
+    {
+        accessType = access_in_list;
+        u.inList.structureList = list;
+        u.inList.listSize = listSize;
+    }
         
-        void reset()
-        {
-            deref();
-            accessType = access_unset;
-            stubRoutine = MacroAssemblerCodeRef();
-        }
-
-        void deref();
+    void reset()
+    {
+        deref();
+        accessType = access_unset;
+        stubRoutine.clear();
+        watchpoints.clear();
+    }
 
-        bool visitWeakReferences();
-        
-        bool seenOnce()
-        {
-            return seen;
-        }
-
-        void setSeen()
-        {
-            seen = true;
-        }
+    void deref();
+
+    // Check if the stub has weak references that are dead. If there are dead ones that imply
+    // that the stub should be entirely reset, this should return false. If there are dead ones
+    // that can be handled internally by the stub and don't require a full reset, then this
+    // should reset them and return true. If there are no dead weak references, return true.
+    // If this method returns true it means that it has left the stub in a state where all
+    // outgoing GC pointers are known to point to currently marked objects; this method is
+    // allowed to accomplish this by either clearing those pointers somehow or by proving that
+    // they have already been marked. It is not allowed to mark new objects.
+    bool visitWeakReferences(RepatchBuffer&);
         
-        unsigned bytecodeIndex;
+    bool seenOnce()
+    {
+        return seen;
+    }
 
-        int8_t accessType;
-        int8_t seen;
+    void setSeen()
+    {
+        seen = true;
+    }
+        
+    StructureStubClearingWatchpoint* addWatchpoint(CodeBlock* codeBlock)
+    {
+        return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint(
+            watchpoints, codeBlock, this);
+    }
+    
+    int8_t accessType;
+    bool seen : 1;
+    bool resetByGC : 1;
 
-#if ENABLE(DFG_JIT)
-        CodeOrigin codeOrigin;
-#endif // ENABLE(DFG_JIT)
+    CodeOrigin codeOrigin;
 
-        union {
-            struct {
-                int8_t registersFlushed;
-                int8_t baseGPR;
+    struct {
+        unsigned spillMode : 8;
+        int8_t baseGPR;
 #if USE(JSVALUE32_64)
-                int8_t valueTagGPR;
+        int8_t valueTagGPR;
 #endif
-                int8_t valueGPR;
-                int8_t scratchGPR;
-                int16_t deltaCallToDone;
-                int16_t deltaCallToStructCheck;
-                int16_t deltaCallToSlowCase;
-                int16_t deltaCheckImmToCall;
+        int8_t valueGPR;
+        RegisterSet usedRegisters;
+        int32_t deltaCallToDone;
+        int32_t deltaCallToStorageLoad;
+        int32_t deltaCallToJump;
+        int32_t deltaCallToSlowCase;
+        int32_t deltaCheckImmToCall;
 #if USE(JSVALUE64)
-                int16_t deltaCallToLoadOrStore;
+        int32_t deltaCallToLoadOrStore;
 #else
-                int16_t deltaCallToTagLoadOrStore;
-                int16_t deltaCallToPayloadLoadOrStore;
+        int32_t deltaCallToTagLoadOrStore;
+        int32_t deltaCallToPayloadLoadOrStore;
 #endif
-            } dfg;
-            struct {
-                union {
-                    struct {
-                        int16_t structureToCompare;
-                        int16_t structureCheck;
-#if USE(JSVALUE64)
-                        int16_t displacementLabel;
-#else
-                        int16_t displacementLabel1;
-                        int16_t displacementLabel2;
-#endif
-                        int16_t putResult;
-                        int16_t coldPathBegin;
-                    } get;
-                    struct {
-                        int16_t structureToCompare;
-#if USE(JSVALUE64)
-                        int16_t displacementLabel;
-#else
-                        int16_t displacementLabel1;
-                        int16_t displacementLabel2;
-#endif
-                    } put;
-                } u;
-                int16_t methodCheckProtoObj;
-                int16_t methodCheckProtoStructureToCompare;
-                int16_t methodCheckPutFunction;
-            } baseline;
-        } patch;
-
-        union {
-            struct {
-                // It would be unwise to put anything here, as it will surely be overwritten.
-            } unset;
-            struct {
-                WriteBarrierBase<Structure> baseObjectStructure;
-            } getByIdSelf;
-            struct {
-                WriteBarrierBase<Structure> baseObjectStructure;
-                WriteBarrierBase<Structure> prototypeStructure;
-            } getByIdProto;
-            struct {
-                WriteBarrierBase<Structure> baseObjectStructure;
-                WriteBarrierBase<StructureChain> chain;
-            } getByIdChain;
-            struct {
-                PolymorphicAccessStructureList* structureList;
-                int listSize;
-            } getByIdSelfList;
-            struct {
-                PolymorphicAccessStructureList* structureList;
-                int listSize;
-            } getByIdProtoList;
-            struct {
-                WriteBarrierBase<Structure> previousStructure;
-                WriteBarrierBase<Structure> structure;
-                WriteBarrierBase<StructureChain> chain;
-            } putByIdTransition;
-            struct {
-                WriteBarrierBase<Structure> baseObjectStructure;
-            } putByIdReplace;
-            struct {
-                PolymorphicPutByIdList* list;
-            } putByIdList;
-        } u;
-
-        MacroAssemblerCodeRef stubRoutine;
-        CodeLocationCall callReturnLocation;
-        CodeLocationLabel hotPathBegin;
-    };
-
-    inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
-    {
-        return structureStubInfo->callReturnLocation.executableAddress();
-    }
+    } patch;
+
+    union {
+        struct {
+            // It would be unwise to put anything here, as it will surely be overwritten.
+        } unset;
+        struct {
+            WriteBarrierBase<Structure> baseObjectStructure;
+        } getByIdSelf;
+        struct {
+            WriteBarrierBase<Structure> baseObjectStructure;
+            WriteBarrierBase<Structure> prototypeStructure;
+            bool isDirect;
+        } getByIdProto;
+        struct {
+            WriteBarrierBase<Structure> baseObjectStructure;
+            WriteBarrierBase<StructureChain> chain;
+            unsigned count : 31;
+            bool isDirect : 1;
+        } getByIdChain;
+        struct {
+            PolymorphicGetByIdList* list;
+        } getByIdList;
+        struct {
+            WriteBarrierBase<Structure> previousStructure;
+            WriteBarrierBase<Structure> structure;
+            WriteBarrierBase<StructureChain> chain;
+        } putByIdTransition;
+        struct {
+            WriteBarrierBase<Structure> baseObjectStructure;
+        } putByIdReplace;
+        struct {
+            PolymorphicPutByIdList* list;
+        } putByIdList;
+        struct {
+            PolymorphicAccessStructureList* structureList;
+            int listSize;
+        } inList;
+    } u;
+
+    RefPtr<JITStubRoutine> stubRoutine;
+    CodeLocationCall callReturnLocation;
+    RefPtr<WatchpointsOnStructureStubInfo> watchpoints;
+};
+
+inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo)
+{
+    return structureStubInfo.codeOrigin;
+}
+
+typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
 
-    inline unsigned getStructureStubInfoBytecodeIndex(StructureStubInfo* structureStubInfo)
-    {
-        return structureStubInfo->bytecodeIndex;
-    }
+#else
 
-} // namespace JSC
+typedef HashMap<int, void*> StubInfoMap;
 
 #endif // ENABLE(JIT)
 
+} // namespace JSC
+
 #endif // StructureStubInfo_h