]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - bytecode/StructureStubInfo.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / bytecode / StructureStubInfo.h
index a9e0678daa9ee0922430ab5966d3ca2621e28cbc..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 "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 {
 
 #if ENABLE(JIT)
-    struct StructureStubInfo {
-        StructureStubInfo(OpcodeID opcodeID)
-            : opcodeID(opcodeID)
-            , stubRoutine(0)
-            , callReturnLocation(0)
-            , hotPathBegin(0)
-        {
-        }
 
-        void initGetByIdSelf(Structure* baseObjectStructure)
-        {
-            opcodeID = op_get_by_id_self;
+class PolymorphicGetByIdList;
+class PolymorphicPutByIdList;
 
-            u.getByIdSelf.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
-        }
+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
+};
 
-        void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure)
-        {
-            opcodeID = op_get_by_id_proto;
-
-            u.getByIdProto.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
+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)
+{
+    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;
+    }
+}
 
-            u.getByIdProto.prototypeStructure = prototypeStructure;
-            prototypeStructure->ref();
-        }
+inline bool isInAccess(AccessType accessType)
+{
+    switch (accessType) {
+    case access_in_list:
+        return true;
+    default:
+        return false;
+    }
+}
 
-        void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain)
-        {
-            opcodeID = op_get_by_id_chain;
+struct StructureStubInfo {
+    StructureStubInfo()
+        : accessType(access_unset)
+        , seen(false)
+        , resetByGC(false)
+    {
+    }
 
-            u.getByIdChain.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
+    void initGetByIdSelf(VM& vm, JSCell* owner, Structure* baseObjectStructure)
+    {
+        accessType = access_get_by_id_self;
 
-            u.getByIdChain.chain = chain;
-            chain->ref();
-        }
+        u.getByIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure);
+    }
 
-        void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
-        {
-            opcodeID = op_get_by_id_self_list;
+    void initGetByIdChain(VM& vm, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain, unsigned count, bool isDirect)
+    {
+        accessType = access_get_by_id_chain;
 
-            u.getByIdProtoList.structureList = structureList;
-            u.getByIdProtoList.listSize = listSize;
-        }
+        u.getByIdChain.baseObjectStructure.set(vm, owner, baseObjectStructure);
+        u.getByIdChain.chain.set(vm, owner, chain);
+        u.getByIdChain.count = count;
+        u.getByIdChain.isDirect = isDirect;
+    }
 
-        void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
-        {
-            opcodeID = op_get_by_id_proto_list;
+    void initGetByIdList(PolymorphicGetByIdList* list)
+    {
+        accessType = access_get_by_id_list;
+        u.getByIdList.list = list;
+    }
 
-            u.getByIdProtoList.structureList = structureList;
-            u.getByIdProtoList.listSize = listSize;
-        }
+    // PutById*
 
-        // 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;
 
-        void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain)
-        {
-            opcodeID = op_put_by_id_transition;
+        u.putByIdTransition.previousStructure.set(vm, owner, previousStructure);
+        u.putByIdTransition.structure.set(vm, owner, structure);
+        u.putByIdTransition.chain.set(vm, owner, chain);
+    }
 
-            u.putByIdTransition.previousStructure = previousStructure;
-            previousStructure->ref();
+    void initPutByIdReplace(VM& vm, JSCell* owner, Structure* baseObjectStructure)
+    {
+        accessType = access_put_by_id_replace;
+    
+        u.putByIdReplace.baseObjectStructure.set(vm, owner, baseObjectStructure);
+    }
+        
+    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.clear();
+        watchpoints.clear();
+    }
 
-            u.putByIdTransition.structure = structure;
-            structure->ref();
+    void deref();
 
-            u.putByIdTransition.chain = chain;
-            chain->ref();
-        }
+    // 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&);
+        
+    bool seenOnce()
+    {
+        return seen;
+    }
 
-        void initPutByIdReplace(Structure* baseObjectStructure)
-        {
-            opcodeID = op_put_by_id_replace;
+    void setSeen()
+    {
+        seen = true;
+    }
+        
+    StructureStubClearingWatchpoint* addWatchpoint(CodeBlock* codeBlock)
+    {
+        return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint(
+            watchpoints, codeBlock, this);
+    }
     
-            u.putByIdReplace.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
-        }
-
-        void deref();
-
-        OpcodeID opcodeID;
-        union {
-            struct {
-                Structure* baseObjectStructure;
-            } getByIdSelf;
-            struct {
-                Structure* baseObjectStructure;
-                Structure* prototypeStructure;
-            } getByIdProto;
-            struct {
-                Structure* baseObjectStructure;
-                StructureChain* chain;
-            } getByIdChain;
-            struct {
-                PolymorphicAccessStructureList* structureList;
-                int listSize;
-            } getByIdSelfList;
-            struct {
-                PolymorphicAccessStructureList* structureList;
-                int listSize;
-            } getByIdProtoList;
-            struct {
-                Structure* previousStructure;
-                Structure* structure;
-                StructureChain* chain;
-            } putByIdTransition;
-            struct {
-                Structure* baseObjectStructure;
-            } putByIdReplace;
-        } u;
-
-        void* stubRoutine;
-        void* callReturnLocation;
-        void* hotPathBegin;
-    };
+    int8_t accessType;
+    bool seen : 1;
+    bool resetByGC : 1;
+
+    CodeOrigin codeOrigin;
+
+    struct {
+        unsigned spillMode : 8;
+        int8_t baseGPR;
+#if USE(JSVALUE32_64)
+        int8_t valueTagGPR;
+#endif
+        int8_t valueGPR;
+        RegisterSet usedRegisters;
+        int32_t deltaCallToDone;
+        int32_t deltaCallToStorageLoad;
+        int32_t deltaCallToJump;
+        int32_t deltaCallToSlowCase;
+        int32_t deltaCheckImmToCall;
+#if USE(JSVALUE64)
+        int32_t deltaCallToLoadOrStore;
+#else
+        int32_t deltaCallToTagLoadOrStore;
+        int32_t deltaCallToPayloadLoadOrStore;
 #endif
+    } 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;
+
+#else
+
+typedef HashMap<int, void*> StubInfoMap;
+
+#endif // ENABLE(JIT)
 
 } // namespace JSC