X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/bytecode/StructureStubInfo.h diff --git a/bytecode/StructureStubInfo.h b/bytecode/StructureStubInfo.h index 7f11edd..d402ace 100644 --- a/bytecode/StructureStubInfo.h +++ b/bytecode/StructureStubInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2012-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,148 +26,245 @@ #ifndef StructureStubInfo_h #define StructureStubInfo_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" namespace JSC { - 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, - access_put_by_id_replace, - access_get_by_id, - access_put_by_id, - access_get_by_id_generic, - access_put_by_id_generic, - access_get_array_length, - access_get_string_length, - }; - - struct StructureStubInfo { - StructureStubInfo(AccessType accessType) - : accessType(accessType) - , 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.getByIdProtoList.structureList = structureList; - u.getByIdProtoList.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) - { - accessType = access_put_by_id_transition; - - 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; +#if ENABLE(JIT) + +class PolymorphicGetByIdList; +class PolymorphicPutByIdList; + +enum AccessType { + access_get_by_id_self, + 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_list: + return true; + default: + return false; + } +} - u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure); - } - - void deref(); - void visitAggregate(SlotVisitor&); - - bool seenOnce() - { - return seen; - } - - void setSeen() - { - seen = true; - } - - int accessType : 31; - int seen : 1; - - union { - struct { - WriteBarrierBase baseObjectStructure; - } getByIdSelf; - struct { - WriteBarrierBase baseObjectStructure; - WriteBarrierBase prototypeStructure; - } getByIdProto; - struct { - WriteBarrierBase baseObjectStructure; - WriteBarrierBase chain; - } getByIdChain; - struct { - PolymorphicAccessStructureList* structureList; - int listSize; - } getByIdSelfList; - struct { - PolymorphicAccessStructureList* structureList; - int listSize; - } getByIdProtoList; - struct { - WriteBarrierBase previousStructure; - WriteBarrierBase structure; - WriteBarrierBase chain; - } putByIdTransition; - struct { - WriteBarrierBase baseObjectStructure; - } putByIdReplace; - } u; - - CodeLocationLabel stubRoutine; - CodeLocationCall callReturnLocation; - CodeLocationLabel hotPathBegin; - }; +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; + } +} -} // namespace JSC +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) + , tookSlowPath(false) + { + } + + void initGetByIdSelf(VM& vm, JSCell* owner, Structure* baseObjectStructure) + { + accessType = access_get_by_id_self; + + u.getByIdSelf.baseObjectStructure.set(vm, owner, baseObjectStructure); + } + + 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(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 = nullptr; + watchpoints = nullptr; + } + + 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&); + + bool seenOnce() + { + return seen; + } + + void setSeen() + { + seen = true; + } + + StructureStubClearingWatchpoint* addWatchpoint(CodeBlock* codeBlock) + { + return WatchpointsOnStructureStubInfo::ensureReferenceAndAddWatchpoint( + watchpoints, codeBlock, this); + } + + int8_t accessType; + bool seen : 1; + bool resetByGC : 1; + bool tookSlowPath : 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 baseObjectStructure; + } getByIdSelf; + struct { + WriteBarrierBase baseObjectStructure; + WriteBarrierBase prototypeStructure; + bool isDirect; + } getByIdProto; + struct { + WriteBarrierBase baseObjectStructure; + WriteBarrierBase chain; + unsigned count : 31; + bool isDirect : 1; + } getByIdChain; + struct { + PolymorphicGetByIdList* list; + } getByIdList; + struct { + WriteBarrierBase previousStructure; + WriteBarrierBase structure; + WriteBarrierBase chain; + } putByIdTransition; + struct { + WriteBarrierBase baseObjectStructure; + } putByIdReplace; + struct { + PolymorphicPutByIdList* list; + } putByIdList; + struct { + PolymorphicAccessStructureList* structureList; + int listSize; + } inList; + } u; + + RefPtr stubRoutine; + CodeLocationCall callReturnLocation; + RefPtr watchpoints; +}; + +inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo) +{ + return structureStubInfo.codeOrigin; +} + +typedef HashMap StubInfoMap; + +#else + +typedef HashMap StubInfoMap; + +#endif // ENABLE(JIT) + +} // namespace JSC #endif // StructureStubInfo_h