Commit 40cae3a4 authored by fpizlo@apple.com's avatar fpizlo@apple.com

DFG should have polymorphic put_by_id caching

https://bugs.webkit.org/show_bug.cgi?id=78062
<rdar://problem/10326439> <rdar://problem/10824839>

Reviewed by Oliver Hunt.
        
Implemented polymorphic put_by_id caching in the DFG, and added much of the
machinery that would be needed to implement it in the old JIT as well.
        
I decided against using the old PolymorphicAccessStructureList mechanism as
this didn't quite fit with put_by_id. In particular, I wanted the ability to
have one list that captured all relevant cases (including proto put_by_id
if we ever decided to do it). And I wanted the code to have better
encapsulation. And I didn't want to get confused by the fact that the
original (non-list) put_by_id cache may itself consist of a stub routine.
        
This code is still sub-optimal (for example adding a replace to a list whose
previous elements are all transitions should just repatch the original code,
but here it will generate a stub) but it already generates a >20% speed-up
on V8-splay, leading to a 2% win overall in splay. Neutral elsewhere.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/PolymorphicPutByIdList.cpp: Added.
(JSC):
(JSC::PutByIdAccess::fromStructureStubInfo):
(JSC::PutByIdAccess::visitWeak):
(JSC::PolymorphicPutByIdList::PolymorphicPutByIdList):
(JSC::PolymorphicPutByIdList::from):
(JSC::PolymorphicPutByIdList::~PolymorphicPutByIdList):
(JSC::PolymorphicPutByIdList::isFull):
(JSC::PolymorphicPutByIdList::isAlmostFull):
(JSC::PolymorphicPutByIdList::addAccess):
(JSC::PolymorphicPutByIdList::visitWeak):
* bytecode/PolymorphicPutByIdList.h: Added.
(JSC):
(PutByIdAccess):
(JSC::PutByIdAccess::PutByIdAccess):
(JSC::PutByIdAccess::transition):
(JSC::PutByIdAccess::replace):
(JSC::PutByIdAccess::isSet):
(JSC::PutByIdAccess::operator!):
(JSC::PutByIdAccess::type):
(JSC::PutByIdAccess::isTransition):
(JSC::PutByIdAccess::isReplace):
(JSC::PutByIdAccess::oldStructure):
(JSC::PutByIdAccess::structure):
(JSC::PutByIdAccess::newStructure):
(JSC::PutByIdAccess::chain):
(JSC::PutByIdAccess::stubRoutine):
(PolymorphicPutByIdList):
(JSC::PolymorphicPutByIdList::currentSlowPathTarget):
(JSC::PolymorphicPutByIdList::isEmpty):
(JSC::PolymorphicPutByIdList::size):
(JSC::PolymorphicPutByIdList::at):
(JSC::PolymorphicPutByIdList::operator[]):
(JSC::PolymorphicPutByIdList::kind):
* bytecode/PutKind.h: Added.
(JSC):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::deref):
(JSC::StructureStubInfo::visitWeakReferences):
* bytecode/StructureStubInfo.h:
(JSC):
(JSC::isPutByIdAccess):
(JSC::StructureStubInfo::initPutByIdList):
(StructureStubInfo):
(JSC::StructureStubInfo::reset):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
(DFG):
* dfg/DFGRepatch.cpp:
(JSC::DFG::appropriateGenericPutByIdFunction):
(JSC::DFG::appropriateListBuildingPutByIdFunction):
(DFG):
(JSC::DFG::emitPutReplaceStub):
(JSC::DFG::emitPutTransitionStub):
(JSC::DFG::tryCachePutByID):
(JSC::DFG::dfgRepatchPutByID):
(JSC::DFG::tryBuildPutByIdList):
(JSC::DFG::dfgBuildPutByIdList):
(JSC::DFG::dfgResetPutByID):
* dfg/DFGRepatch.h:
(DFG):
* runtime/WriteBarrier.h:
(WriteBarrierBase):
(JSC::WriteBarrierBase::copyFrom):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@107485 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 8b0e843f
......@@ -44,6 +44,7 @@ SET(JavaScriptCore_SOURCES
bytecode/MethodCallLinkInfo.cpp
bytecode/MethodCallLinkStatus.cpp
bytecode/Opcode.cpp
bytecode/PolymorphicPutByIdList.cpp
bytecode/PredictedType.cpp
bytecode/PutByIdStatus.cpp
bytecode/SamplingTool.cpp
......
2012-02-07 Filip Pizlo <fpizlo@apple.com>
DFG should have polymorphic put_by_id caching
https://bugs.webkit.org/show_bug.cgi?id=78062
<rdar://problem/10326439> <rdar://problem/10824839>
Reviewed by Oliver Hunt.
Implemented polymorphic put_by_id caching in the DFG, and added much of the
machinery that would be needed to implement it in the old JIT as well.
I decided against using the old PolymorphicAccessStructureList mechanism as
this didn't quite fit with put_by_id. In particular, I wanted the ability to
have one list that captured all relevant cases (including proto put_by_id
if we ever decided to do it). And I wanted the code to have better
encapsulation. And I didn't want to get confused by the fact that the
original (non-list) put_by_id cache may itself consist of a stub routine.
This code is still sub-optimal (for example adding a replace to a list whose
previous elements are all transitions should just repatch the original code,
but here it will generate a stub) but it already generates a >20% speed-up
on V8-splay, leading to a 2% win overall in splay. Neutral elsewhere.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/PolymorphicPutByIdList.cpp: Added.
(JSC):
(JSC::PutByIdAccess::fromStructureStubInfo):
(JSC::PutByIdAccess::visitWeak):
(JSC::PolymorphicPutByIdList::PolymorphicPutByIdList):
(JSC::PolymorphicPutByIdList::from):
(JSC::PolymorphicPutByIdList::~PolymorphicPutByIdList):
(JSC::PolymorphicPutByIdList::isFull):
(JSC::PolymorphicPutByIdList::isAlmostFull):
(JSC::PolymorphicPutByIdList::addAccess):
(JSC::PolymorphicPutByIdList::visitWeak):
* bytecode/PolymorphicPutByIdList.h: Added.
(JSC):
(PutByIdAccess):
(JSC::PutByIdAccess::PutByIdAccess):
(JSC::PutByIdAccess::transition):
(JSC::PutByIdAccess::replace):
(JSC::PutByIdAccess::isSet):
(JSC::PutByIdAccess::operator!):
(JSC::PutByIdAccess::type):
(JSC::PutByIdAccess::isTransition):
(JSC::PutByIdAccess::isReplace):
(JSC::PutByIdAccess::oldStructure):
(JSC::PutByIdAccess::structure):
(JSC::PutByIdAccess::newStructure):
(JSC::PutByIdAccess::chain):
(JSC::PutByIdAccess::stubRoutine):
(PolymorphicPutByIdList):
(JSC::PolymorphicPutByIdList::currentSlowPathTarget):
(JSC::PolymorphicPutByIdList::isEmpty):
(JSC::PolymorphicPutByIdList::size):
(JSC::PolymorphicPutByIdList::at):
(JSC::PolymorphicPutByIdList::operator[]):
(JSC::PolymorphicPutByIdList::kind):
* bytecode/PutKind.h: Added.
(JSC):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::deref):
(JSC::StructureStubInfo::visitWeakReferences):
* bytecode/StructureStubInfo.h:
(JSC):
(JSC::isPutByIdAccess):
(JSC::StructureStubInfo::initPutByIdList):
(StructureStubInfo):
(JSC::StructureStubInfo::reset):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
(DFG):
* dfg/DFGRepatch.cpp:
(JSC::DFG::appropriateGenericPutByIdFunction):
(JSC::DFG::appropriateListBuildingPutByIdFunction):
(DFG):
(JSC::DFG::emitPutReplaceStub):
(JSC::DFG::emitPutTransitionStub):
(JSC::DFG::tryCachePutByID):
(JSC::DFG::dfgRepatchPutByID):
(JSC::DFG::tryBuildPutByIdList):
(JSC::DFG::dfgBuildPutByIdList):
(JSC::DFG::dfgResetPutByID):
* dfg/DFGRepatch.h:
(DFG):
* runtime/WriteBarrier.h:
(WriteBarrierBase):
(JSC::WriteBarrierBase::copyFrom):
2012-02-10 Vineet Chaudhary <rgf748@motorola.com>
https://bugs.webkit.org/show_bug.cgi?id=72756
......@@ -109,11 +109,14 @@ javascriptcore_sources += \
Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h \
Source/JavaScriptCore/bytecode/Opcode.cpp \
Source/JavaScriptCore/bytecode/Opcode.h \
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp \
Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h \
Source/JavaScriptCore/bytecode/PredictedType.cpp \
Source/JavaScriptCore/bytecode/PredictedType.h \
Source/JavaScriptCore/bytecode/PredictionTracker.h \
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \
Source/JavaScriptCore/bytecode/PutByIdStatus.h \
Source/JavaScriptCore/bytecode/PutKind.h \
Source/JavaScriptCore/bytecode/SamplingTool.cpp \
Source/JavaScriptCore/bytecode/SamplingTool.h \
Source/JavaScriptCore/bytecode/StructureSet.h \
......
......@@ -1585,6 +1585,10 @@
RelativePath="..\..\bytecode\Opcode.h"
>
</File>
<File
RelativePath="..\..\bytecode\PolymorphicPutByIdList.cpp"
>
</File>
<File
RelativePath="..\..\bytecode\PredictedType.cpp"
>
......
......@@ -102,6 +102,9 @@
0F963B2D13F854020002D9B2 /* MetaAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B2F13FC66BB0002D9B2 /* MetaAllocatorHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */; };
0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */; };
0FBC0AE81496C7C700D4FBDD /* DFGExitProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FBD7E691447999600481315 /* CodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBD7E671447998F00481315 /* CodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -896,6 +899,9 @@
0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAllocator.cpp; sourceTree = "<group>"; };
0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetaAllocatorHandle.h; sourceTree = "<group>"; };
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicPutByIdList.cpp; sourceTree = "<group>"; };
0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicPutByIdList.h; sourceTree = "<group>"; };
0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutKind.h; sourceTree = "<group>"; };
0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = "<group>"; };
0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; };
0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; };
......@@ -2553,6 +2559,9 @@
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */,
0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */,
0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,
0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,
......@@ -3128,6 +3137,8 @@
0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */,
0F66E16B14DF3F1600B7B2E4 /* DFGNodeReferenceBlob.h in Headers */,
0F66E16C14DF3F1600B7B2E4 /* DFGNodeUse.h in Headers */,
0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */,
0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -3674,6 +3685,7 @@
86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */,
86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */,
C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */,
0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -58,6 +58,7 @@ SOURCES += \
bytecode/MethodCallLinkInfo.cpp \
bytecode/MethodCallLinkStatus.cpp \
bytecode/Opcode.cpp \
bytecode/PolymorphicPutByIdList.cpp \
bytecode/PredictedType.cpp \
bytecode/PutByIdStatus.cpp \
bytecode/SamplingTool.cpp \
......
/*
* Copyright (C) 2012 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 "PolymorphicPutByIdList.h"
#include "StructureStubInfo.h"
namespace JSC {
PutByIdAccess PutByIdAccess::fromStructureStubInfo(
StructureStubInfo& stubInfo,
MacroAssemblerCodePtr initialSlowPath)
{
PutByIdAccess result;
switch (stubInfo.accessType) {
case access_put_by_id_replace:
result.m_type = Replace;
result.m_oldStructure.copyFrom(stubInfo.u.putByIdReplace.baseObjectStructure);
result.m_stubRoutine = MacroAssemblerCodeRef::createSelfManagedCodeRef(initialSlowPath);
break;
case access_put_by_id_transition_direct:
case access_put_by_id_transition_normal:
result.m_type = Transition;
result.m_oldStructure.copyFrom(stubInfo.u.putByIdTransition.previousStructure);
result.m_newStructure.copyFrom(stubInfo.u.putByIdTransition.structure);
result.m_chain.copyFrom(stubInfo.u.putByIdTransition.chain);
result.m_stubRoutine = stubInfo.stubRoutine;
break;
default:
ASSERT_NOT_REACHED();
}
return result;
}
bool PutByIdAccess::visitWeak() const
{
switch (m_type) {
case Replace:
if (!Heap::isMarked(m_oldStructure.get()))
return false;
break;
case Transition:
if (!Heap::isMarked(m_oldStructure.get()))
return false;
if (!Heap::isMarked(m_newStructure.get()))
return false;
if (!Heap::isMarked(m_chain.get()))
return false;
break;
default:
ASSERT_NOT_REACHED();
return false;
}
return true;
}
PolymorphicPutByIdList::PolymorphicPutByIdList(
PutKind putKind,
StructureStubInfo& stubInfo,
MacroAssemblerCodePtr initialSlowPath)
: m_kind(putKind)
{
m_list.append(PutByIdAccess::fromStructureStubInfo(stubInfo, initialSlowPath));
}
PolymorphicPutByIdList* PolymorphicPutByIdList::from(
PutKind putKind,
StructureStubInfo& stubInfo,
MacroAssemblerCodePtr initialSlowPath)
{
if (stubInfo.accessType == access_put_by_id_list)
return stubInfo.u.putByIdList.list;
ASSERT(stubInfo.accessType == access_put_by_id_replace
|| stubInfo.accessType == access_put_by_id_transition_normal
|| stubInfo.accessType == access_put_by_id_transition_direct);
PolymorphicPutByIdList* result =
new PolymorphicPutByIdList(putKind, stubInfo, initialSlowPath);
stubInfo.initPutByIdList(result);
return result;
}
PolymorphicPutByIdList::~PolymorphicPutByIdList() { }
bool PolymorphicPutByIdList::isFull() const
{
ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE);
return size() == POLYMORPHIC_LIST_CACHE_SIZE;
}
bool PolymorphicPutByIdList::isAlmostFull() const
{
ASSERT(size() <= POLYMORPHIC_LIST_CACHE_SIZE);
return size() >= POLYMORPHIC_LIST_CACHE_SIZE - 1;
}
void PolymorphicPutByIdList::addAccess(const PutByIdAccess& putByIdAccess)
{
ASSERT(!isFull());
// Make sure that the resizing optimizes for space, not time.
m_list.resize(m_list.size() + 1);
m_list.last() = putByIdAccess;
}
bool PolymorphicPutByIdList::visitWeak() const
{
for (unsigned i = 0; i < size(); ++i) {
if (!at(i).visitWeak())
return false;
}
return true;
}
} // namespace JSC
/*
* Copyright (C) 2012 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.
*/
#ifndef PolymorphicPutByIdList_h
#define PolymorphicPutByIdList_h
#include <wtf/Platform.h>
#if ENABLE(JIT)
#include "CodeOrigin.h"
#include "MacroAssembler.h"
#include "Opcode.h"
#include "PutKind.h"
#include "Structure.h"
#include <wtf/Vector.h>
namespace JSC {
struct StructureStubInfo;
class PutByIdAccess {
public:
enum AccessType {
Invalid,
Transition,
Replace
};
PutByIdAccess()
: m_type(Invalid)
{
}
static PutByIdAccess transition(
JSGlobalData& globalData,
JSCell* owner,
Structure* oldStructure,
Structure* newStructure,
StructureChain* chain,
MacroAssemblerCodeRef stubRoutine)
{
PutByIdAccess result;
result.m_type = Transition;
result.m_oldStructure.set(globalData, owner, oldStructure);
result.m_newStructure.set(globalData, owner, newStructure);
result.m_chain.set(globalData, owner, chain);
result.m_stubRoutine = stubRoutine;
return result;
}
static PutByIdAccess replace(
JSGlobalData& globalData,
JSCell* owner,
Structure* structure,
MacroAssemblerCodeRef stubRoutine)
{
PutByIdAccess result;
result.m_type = Replace;
result.m_oldStructure.set(globalData, owner, structure);
result.m_stubRoutine = stubRoutine;
return result;
}
static PutByIdAccess fromStructureStubInfo(
StructureStubInfo&,
MacroAssemblerCodePtr initialSlowPath);
bool isSet() const { return m_type != Invalid; }
bool operator!() const { return !isSet(); }
AccessType type() const { return m_type; }
bool isTransition() const { return m_type == Transition; }
bool isReplace() const { return m_type == Replace; }
Structure* oldStructure() const
{
// Using this instead of isSet() to make this assertion robust against the possibility
// of additional access types being added.
ASSERT(isTransition() || isReplace());
return m_oldStructure.get();
}
Structure* structure() const
{
ASSERT(isReplace());
return m_oldStructure.get();
}
Structure* newStructure() const
{
ASSERT(isTransition());
return m_newStructure.get();
}
StructureChain* chain() const
{
ASSERT(isTransition());
return m_chain.get();
}
MacroAssemblerCodeRef stubRoutine() const
{
ASSERT(isTransition() || isReplace());
return m_stubRoutine;
}
bool visitWeak() const;
private:
AccessType m_type;
WriteBarrier<Structure> m_oldStructure;
WriteBarrier<Structure> m_newStructure;
WriteBarrier<StructureChain> m_chain;
MacroAssemblerCodeRef m_stubRoutine;
};
class PolymorphicPutByIdList {
WTF_MAKE_FAST_ALLOCATED;
public:
// Initialize from a stub info; this will place one element in the list and it will
// be created by converting the stub info's put by id access information into our
// PutByIdAccess.
PolymorphicPutByIdList(
PutKind,
StructureStubInfo&,
MacroAssemblerCodePtr initialSlowPath);
// Either creates a new polymorphic put list, or returns the one that is already
// in place.
static PolymorphicPutByIdList* from(
PutKind,
StructureStubInfo&,
MacroAssemblerCodePtr initialSlowPath);
~PolymorphicPutByIdList();
MacroAssemblerCodePtr currentSlowPathTarget() const
{
return m_list.last().stubRoutine().code();
}
void addAccess(const PutByIdAccess&);
bool isEmpty() const { return m_list.isEmpty(); }
unsigned size() const { return m_list.size(); }
bool isFull() const;
bool isAlmostFull() const; // True if adding an element would make isFull() true.
const PutByIdAccess& at(unsigned i) const { return m_list[i]; }
const PutByIdAccess& operator[](unsigned i) const { return m_list[i]; }
PutKind kind() const { return m_kind; }
bool visitWeak() const;
private:
Vector<PutByIdAccess, 2> m_list;
PutKind m_kind;
};
} // namespace JSC
#endif // ENABLE(JIT)
#endif // PolymorphicPutByIdList_h
/*
* Copyright (C) 2012 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.
*/
#ifndef PutKind_h
#define PutKind_h
namespace JSC {
enum PutKind { Direct, NotDirect };
} // namespace JSC
#endif // PutKind_h
......@@ -27,6 +27,7 @@
#include "StructureStubInfo.h"
#include "JSObject.h"
#include "PolymorphicPutByIdList.h"
#include "ScopeChain.h"
namespace JSC {
......@@ -45,6 +46,9 @@ void StructureStubInfo::deref()
delete polymorphicStructures;
return;
}
case access_put_by_id_list:
delete u.putByIdList.list;
return;
case access_get_by_id_self:
case access_get_by_id_proto:
case access_get_by_id_chain:
......@@ -82,18 +86,14 @@ bool StructureStubInfo::visitWeakReferences()
break;
case access_get_by_id_self_list: {
PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize)) {
delete polymorphicStructures;
if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize))
return false;
}
break;
}
case access_get_by_id_proto_list: {
PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize)) {
delete polymorphicStructures;
if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize))
return false;
}
break;
}
case access_put_by_id_transition_normal:
......@@ -107,6 +107,10 @@ bool StructureStubInfo::visitWeakReferences()
if (!Heap::isMarked(u.putByIdReplace.baseObjectStructure.get()))
return false;
break;
case access_put_by_id_list:
if (!u.putByIdList.list->visitWeak())
return false;
break;
default:
// The rest of the instructions don't require references, so there is no need to
// do anything.
......
......@@ -26,6 +26,8 @@
#ifndef StructureStubInfo_h
#define StructureStubInfo_h
#include <wtf/Platform.h>
#if ENABLE(JIT)
#include "CodeOrigin.h"
......@@ -36,6 +38,8 @@
namespace JSC {
class PolymorphicPutByIdList;
enum AccessType {
access_get_by_id_self,
access_get_by_id_proto,
......@@ -45,6 +49,7 @@ namespace JSC {
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,
......@@ -75,6 +80,7 @@ namespace JSC {
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:
......@@ -149,10 +155,16 @@ namespace JSC {
u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure);
}
void initPutByIdList(PolymorphicPutByIdList* list)
{
accessType = access_put_by_id_list;
u.putByIdList.list = list;
}
void reset()
{
accessType = access_unset;
deref();
stubRoutine = MacroAssemblerCodeRef();
}
......@@ -227,6 +239,9 @@ namespace JSC {
struct {