blob: 4affa460f72041f9680b5111a403dd0ac381d4cf [file] [log] [blame]
/*
* 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
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "StructureStubInfo.h"
#include "JSObject.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 (cacheType) {
case CacheType::Stub:
delete u.stub;
return;
case CacheType::Unset:
case CacheType::GetByIdSelf:
case CacheType::PutByIdReplace:
return;
}
RELEASE_ASSERT_NOT_REACHED();
}
void StructureStubInfo::aboutToDie()
{
switch (cacheType) {
case CacheType::Stub:
u.stub->aboutToDie();
return;
case CacheType::Unset:
case CacheType::GetByIdSelf:
case CacheType::PutByIdReplace:
return;
}
RELEASE_ASSERT_NOT_REACHED();
}
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, WTF::move(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(WTF::move(previousCase));
accessCases.append(WTF::move(accessCase));
MacroAssemblerCodePtr result =
access->regenerateWithCases(vm, codeBlock, *this, ident, WTF::move(accessCases));
if (!result)
return MacroAssemblerCodePtr();
initStub(codeBlock, WTF::move(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 AccessType::Get:
resetGetByID(codeBlock, *this);
break;
case AccessType::Put:
resetPutByID(codeBlock, *this);
break;
case AccessType::In:
resetIn(codeBlock, *this);
break;
}
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 CacheType::Stub:
if (u.stub->visitWeak(vm))
return;
break;
default:
return;
}
reset(codeBlock);
resetByGC = true;
}
#endif
} // namespace JSC