diff options
author | Konstantin Tokarev <annulen@yandex.ru> | 2016-08-25 19:20:41 +0300 |
---|---|---|
committer | Konstantin Tokarev <annulen@yandex.ru> | 2017-02-02 12:30:55 +0000 |
commit | 6882a04fb36642862b11efe514251d32070c3d65 (patch) | |
tree | b7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/bytecode/StructureStubInfo.cpp | |
parent | ab6df191029eeeb0b0f16f127d553265659f739e (diff) | |
download | qtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz |
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f
Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/bytecode/StructureStubInfo.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecode/StructureStubInfo.cpp | 208 |
1 files changed, 141 insertions, 67 deletions
diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp index 70cf2fccb..5ffd743a6 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2014, 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,97 +26,171 @@ #include "config.h" #include "StructureStubInfo.h" +#include "JSCellInlines.h" #include "JSObject.h" -#include "PolymorphicPutByIdList.h" - +#include "PolymorphicAccess.h" +#include "Repatch.h" namespace JSC { #if ENABLE(JIT) +StructureStubInfo::StructureStubInfo(AccessType accessType) + : callSiteIndex(UINT_MAX) + , accessType(accessType) + , cacheType(CacheType::Unset) + , countdown(1) // For a totally clear stub, we'll patch it after the first execution. + , repatchCount(0) + , numberOfCoolDowns(0) + , resetByGC(false) + , tookSlowPath(false) + , everConsidered(false) +{ +} + +StructureStubInfo::~StructureStubInfo() +{ +} + +void StructureStubInfo::initGetByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset) +{ + cacheType = CacheType::GetByIdSelf; + + u.byIdSelf.baseObjectStructure.set( + *codeBlock->vm(), codeBlock, baseObjectStructure); + u.byIdSelf.offset = offset; +} + +void StructureStubInfo::initPutByIdReplace(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset) +{ + cacheType = CacheType::PutByIdReplace; + + u.byIdSelf.baseObjectStructure.set( + *codeBlock->vm(), codeBlock, baseObjectStructure); + u.byIdSelf.offset = offset; +} + +void StructureStubInfo::initStub(CodeBlock*, std::unique_ptr<PolymorphicAccess> stub) +{ + cacheType = CacheType::Stub; + u.stub = stub.release(); +} + void StructureStubInfo::deref() { - switch (accessType) { - case access_get_by_id_self_list: { - PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList; - delete polymorphicStructures; + switch (cacheType) { + case CacheType::Stub: + delete u.stub; return; - } - case access_get_by_id_proto_list: { - PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; - delete polymorphicStructures; + case CacheType::Unset: + case CacheType::GetByIdSelf: + case CacheType::PutByIdReplace: return; } - case access_put_by_id_list: - delete u.putByIdList.list; + + RELEASE_ASSERT_NOT_REACHED(); +} + +void StructureStubInfo::aboutToDie() +{ + switch (cacheType) { + case CacheType::Stub: + u.stub->aboutToDie(); return; - case access_get_by_id_self: - case access_get_by_id_proto: - case access_get_by_id_chain: - case access_put_by_id_transition_normal: - case access_put_by_id_transition_direct: - case access_put_by_id_replace: - case access_unset: - case access_get_by_id_generic: - case access_put_by_id_generic: - case access_get_array_length: - case access_get_string_length: - // These instructions don't have to release any allocated memory + case CacheType::Unset: + case CacheType::GetByIdSelf: + case CacheType::PutByIdReplace: return; - default: - RELEASE_ASSERT_NOT_REACHED(); } + + RELEASE_ASSERT_NOT_REACHED(); } -bool StructureStubInfo::visitWeakReferences() +MacroAssemblerCodePtr StructureStubInfo::addAccessCase( + CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase) { + VM& vm = *codeBlock->vm(); + + if (!accessCase) + return MacroAssemblerCodePtr(); + + if (cacheType == CacheType::Stub) + return u.stub->regenerateWithCase(vm, codeBlock, *this, ident, WTFMove(accessCase)); + + std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>(); + + Vector<std::unique_ptr<AccessCase>> accessCases; + + std::unique_ptr<AccessCase> previousCase = + AccessCase::fromStructureStubInfo(vm, codeBlock, *this); + if (previousCase) + accessCases.append(WTFMove(previousCase)); + + accessCases.append(WTFMove(accessCase)); + + MacroAssemblerCodePtr result = + access->regenerateWithCases(vm, codeBlock, *this, ident, WTFMove(accessCases)); + + if (!result) + return MacroAssemblerCodePtr(); + + initStub(codeBlock, WTFMove(access)); + return result; +} + +void StructureStubInfo::reset(CodeBlock* codeBlock) +{ + if (cacheType == CacheType::Unset) + return; + + if (Options::verboseOSR()) { + // This can be called from GC destructor calls, so we don't try to do a full dump + // of the CodeBlock. + dataLog("Clearing structure cache (kind ", static_cast<int>(accessType), ") in ", RawPointer(codeBlock), ".\n"); + } + switch (accessType) { - case access_get_by_id_self: - if (!Heap::isMarked(u.getByIdSelf.baseObjectStructure.get())) - return false; - break; - case access_get_by_id_proto: - if (!Heap::isMarked(u.getByIdProto.baseObjectStructure.get()) - || !Heap::isMarked(u.getByIdProto.prototypeStructure.get())) - return false; - break; - case access_get_by_id_chain: - if (!Heap::isMarked(u.getByIdChain.baseObjectStructure.get()) - || !Heap::isMarked(u.getByIdChain.chain.get())) - return false; + case AccessType::Get: + resetGetByID(codeBlock, *this); break; - case access_get_by_id_self_list: { - PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList; - if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize)) - return false; + case AccessType::Put: + resetPutByID(codeBlock, *this); break; - } - case access_get_by_id_proto_list: { - PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; - if (!polymorphicStructures->visitWeak(u.getByIdProtoList.listSize)) - return false; + case AccessType::In: + resetIn(codeBlock, *this); break; } - case access_put_by_id_transition_normal: - case access_put_by_id_transition_direct: - if (!Heap::isMarked(u.putByIdTransition.previousStructure.get()) - || !Heap::isMarked(u.putByIdTransition.structure.get()) - || !Heap::isMarked(u.putByIdTransition.chain.get())) - return false; - break; - case access_put_by_id_replace: - if (!Heap::isMarked(u.putByIdReplace.baseObjectStructure.get())) - return false; + + deref(); + cacheType = CacheType::Unset; +} + +void StructureStubInfo::visitWeakReferences(CodeBlock* codeBlock) +{ + VM& vm = *codeBlock->vm(); + + switch (cacheType) { + case CacheType::GetByIdSelf: + case CacheType::PutByIdReplace: + if (Heap::isMarked(u.byIdSelf.baseObjectStructure.get())) + return; break; - case access_put_by_id_list: - if (!u.putByIdList.list->visitWeak()) - return false; + case CacheType::Stub: + if (u.stub->visitWeak(vm)) + return; break; default: - // The rest of the instructions don't require references, so there is no need to - // do anything. - break; + return; } - return true; + + reset(codeBlock); + resetByGC = true; +} + +bool StructureStubInfo::containsPC(void* pc) const +{ + if (cacheType != CacheType::Stub) + return false; + return u.stub->containsPC(pc); } #endif |