API/OpaqueJSString.cpp
bytecode/CallLinkInfo.cpp
+ bytecode/CallLinkStatus.cpp
bytecode/CodeBlock.cpp
bytecode/DFGExitProfile.cpp
+ bytecode/GetByIdStatus.cpp
bytecode/JumpTable.cpp
bytecode/MethodCallLinkInfo.cpp
+ bytecode/MethodCallLinkStatus.cpp
bytecode/Opcode.cpp
bytecode/PredictedType.cpp
+ bytecode/PutByIdStatus.cpp
bytecode/SamplingTool.cpp
bytecode/StructureStubInfo.cpp
bytecode/ValueProfile.cpp
2012-01-20 Filip Pizlo <fpizlo@apple.com>
+ DFG should not have code that directly decodes the states of old JIT inline
+ cache data structures
+ https://bugs.webkit.org/show_bug.cgi?id=76768
+
+ Reviewed by Sam Weinig.
+
+ Introduced new classes (like GetByIdStatus) that encapsulate the set of things
+ that the DFG would like to know about property accesses and calls. Whereas it
+ previously got this information by directly decoding the data structures used
+ by the old JIT for inline caching, it now uses these classes, which do the work
+ for it. This should make it somewhat more straight forward to introduce new
+ ways of profiling the same information.
+
+ Also hoisted StructureSet into bytecode/ from dfg/, because it's now used by
+ code in bytecode/.
+
+ Making this work right involved carefully ensuring that the heuristics for
+ choosing how to handle property accesses was at least as good as what we had
+ before, since I completely restructured that code. Currently the performance
+ looks neutral. Since I rewrote the code I did change some things that I never
+ liked before, like previously if a put_bu_id had executed exactly once then
+ we'd compile it as if it had taken slow-path. Executing once is special because
+ then the inline cache is not baked in, so there is no information about how the
+ DFG should optimize the code. Now this is rationalized: if the put_by_id does
+ not offer enough information to be optimized (i.e. had executed 0 or 1 times)
+ then we turn it into a forced OSR exit (i.e. a patch point). However, get_by_id
+ still has the old behavior; I left it that way because I didn't want to make
+ too many changes at once.
+
+ * CMakeLists.txt:
+ * GNUmakefile.list.am:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * Target.pri:
+ * bytecode/CallLinkStatus.cpp: Added.
+ (JSC::CallLinkStatus::computeFor):
+ * bytecode/CallLinkStatus.h: Added.
+ (JSC::CallLinkStatus::CallLinkStatus):
+ (JSC::CallLinkStatus::isSet):
+ (JSC::CallLinkStatus::operator!):
+ (JSC::CallLinkStatus::couldTakeSlowPath):
+ (JSC::CallLinkStatus::callTarget):
+ * bytecode/GetByIdStatus.cpp: Added.
+ (JSC::GetByIdStatus::computeFor):
+ * bytecode/GetByIdStatus.h: Added.
+ (JSC::GetByIdStatus::GetByIdStatus):
+ (JSC::GetByIdStatus::state):
+ (JSC::GetByIdStatus::isSet):
+ (JSC::GetByIdStatus::operator!):
+ (JSC::GetByIdStatus::isSimpleDirect):
+ (JSC::GetByIdStatus::takesSlowPath):
+ (JSC::GetByIdStatus::makesCalls):
+ (JSC::GetByIdStatus::structureSet):
+ (JSC::GetByIdStatus::offset):
+ * bytecode/MethodCallLinkStatus.cpp: Added.
+ (JSC::MethodCallLinkStatus::computeFor):
+ * bytecode/MethodCallLinkStatus.h: Added.
+ (JSC::MethodCallLinkStatus::MethodCallLinkStatus):
+ (JSC::MethodCallLinkStatus::isSet):
+ (JSC::MethodCallLinkStatus::operator!):
+ (JSC::MethodCallLinkStatus::needsPrototypeCheck):
+ (JSC::MethodCallLinkStatus::structure):
+ (JSC::MethodCallLinkStatus::prototypeStructure):
+ (JSC::MethodCallLinkStatus::function):
+ (JSC::MethodCallLinkStatus::prototype):
+ * bytecode/PutByIdStatus.cpp: Added.
+ (JSC::PutByIdStatus::computeFor):
+ * bytecode/PutByIdStatus.h: Added.
+ (JSC::PutByIdStatus::PutByIdStatus):
+ (JSC::PutByIdStatus::state):
+ (JSC::PutByIdStatus::isSet):
+ (JSC::PutByIdStatus::operator!):
+ (JSC::PutByIdStatus::isSimpleReplace):
+ (JSC::PutByIdStatus::isSimpleTransition):
+ (JSC::PutByIdStatus::takesSlowPath):
+ (JSC::PutByIdStatus::oldStructure):
+ (JSC::PutByIdStatus::newStructure):
+ (JSC::PutByIdStatus::structureChain):
+ (JSC::PutByIdStatus::offset):
+ * bytecode/StructureSet.h: Added.
+ (JSC::StructureSet::StructureSet):
+ (JSC::StructureSet::clear):
+ (JSC::StructureSet::add):
+ (JSC::StructureSet::addAll):
+ (JSC::StructureSet::remove):
+ (JSC::StructureSet::contains):
+ (JSC::StructureSet::isSubsetOf):
+ (JSC::StructureSet::isSupersetOf):
+ (JSC::StructureSet::size):
+ (JSC::StructureSet::at):
+ (JSC::StructureSet::operator[]):
+ (JSC::StructureSet::last):
+ (JSC::StructureSet::predictionFromStructures):
+ (JSC::StructureSet::operator==):
+ (JSC::StructureSet::dump):
+ * dfg/DFGAbstractValue.h:
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleCall):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGStructureSet.h: Removed.
+
+2012-01-20 Filip Pizlo <fpizlo@apple.com>
+
JIT compilation should not require ExecState
https://bugs.webkit.org/show_bug.cgi?id=76729
<rdar://problem/10731545>
Source/JavaScriptCore/assembler/X86Assembler.h \
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/CallLinkInfo.h \
+ Source/JavaScriptCore/bytecode/CallLinkStatus.cpp \
+ Source/JavaScriptCore/bytecode/CallLinkStatus.h \
Source/JavaScriptCore/bytecode/CallReturnOffsetToBytecodeOffset.h \
Source/JavaScriptCore/bytecode/CodeType.h \
Source/JavaScriptCore/bytecode/CodeBlock.cpp \
Source/JavaScriptCore/bytecode/DFGExitProfile.h \
Source/JavaScriptCore/bytecode/EvalCodeCache.h \
Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \
+ Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \
+ Source/JavaScriptCore/bytecode/GetByIdStatus.h \
Source/JavaScriptCore/bytecode/GlobalResolveInfo.h \
Source/JavaScriptCore/bytecode/HandlerInfo.h \
Source/JavaScriptCore/bytecode/Instruction.h \
Source/JavaScriptCore/bytecode/LineInfo.h \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.cpp \
Source/JavaScriptCore/bytecode/MethodCallLinkInfo.h \
+ Source/JavaScriptCore/bytecode/MethodCallLinkStatus.cpp \
+ Source/JavaScriptCore/bytecode/MethodCallLinkStatus.h \
Source/JavaScriptCore/bytecode/Opcode.cpp \
Source/JavaScriptCore/bytecode/Opcode.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/SamplingTool.cpp \
Source/JavaScriptCore/bytecode/SamplingTool.h \
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp \
Name="bytecode"
>
<File
+ RelativePath="..\..\bytecode\GetByIdStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\PutByIdStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\CallLinkStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\MethodCallLinkStatus.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\GetByIdStatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\PutByIdStatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\CallLinkStatus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\bytecode\MethodCallLinkStatus.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\bytecode\HandlerInfo.h"
>
</File>
0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294C14C3CD43007C3DB1 /* DFGByteCodeCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */; };
+ 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */; };
+ 0F9332A014CA7DCD0085F3C6 /* GetByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9332A114CA7DD10085F3C6 /* MethodCallLinkStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329714CA7DC10085F3C6 /* MethodCallLinkStatus.cpp */; };
+ 0F9332A214CA7DD30085F3C6 /* MethodCallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */; };
+ 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2613F753990002D9B2 /* RedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F963B2C13F853EC0002D9B2 /* MetaAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; };
0F963B2D13F854020002D9B2 /* MetaAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD82F4B142806A100179C94 /* BitVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82F491428069200179C94 /* BitVector.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; };
- 0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; };
140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; };
0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; };
+ 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallLinkStatus.cpp; sourceTree = "<group>"; };
+ 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallLinkStatus.h; sourceTree = "<group>"; };
+ 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdStatus.cpp; sourceTree = "<group>"; };
+ 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdStatus.h; sourceTree = "<group>"; };
+ 0F93329714CA7DC10085F3C6 /* MethodCallLinkStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MethodCallLinkStatus.cpp; sourceTree = "<group>"; };
+ 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodCallLinkStatus.h; sourceTree = "<group>"; };
+ 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdStatus.cpp; sourceTree = "<group>"; };
+ 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdStatus.h; sourceTree = "<group>"; };
+ 0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
0F963B2613F753990002D9B2 /* RedBlackTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RedBlackTree.h; sourceTree = "<group>"; };
0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetaAllocator.h; sourceTree = "<group>"; };
0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAllocator.cpp; sourceTree = "<group>"; };
0FD82F491428069200179C94 /* BitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitVector.h; sourceTree = "<group>"; };
0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; };
0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; };
- 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureSet.h; path = dfg/DFGStructureSet.h; sourceTree = "<group>"; };
1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; };
140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; };
86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */,
86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */,
86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */,
- 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */,
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */,
0FC097A0146B28C700CF2442 /* DFGThunks.h */,
0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */,
969A078F0ED1D3AE00F1F681 /* bytecode */ = {
isa = PBXGroup;
children = (
+ 0F93329314CA7DC10085F3C6 /* CallLinkStatus.cpp */,
+ 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */,
+ 0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,
+ 0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */,
+ 0F93329714CA7DC10085F3C6 /* MethodCallLinkStatus.cpp */,
+ 0F93329814CA7DC10085F3C6 /* MethodCallLinkStatus.h */,
+ 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
+ 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
+ 0F93329B14CA7DC10085F3C6 /* StructureSet.h */,
0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */,
0F0B83B614BCF8DF00885B4F /* GlobalResolveInfo.h */,
0F0B83B214BCF85E00885B4F /* MethodCallLinkInfo.cpp */,
86BB09C1138E381B0056702F /* DFGRepatch.h in Headers */,
86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */,
86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */,
- 0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */,
0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */,
0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */,
BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */,
0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */,
91A3905614C0F47200F67901 /* Uint8ClampedArray.h in Headers */,
F69E86C414C6E551002C2C62 /* NumberOfCores.h in Headers */,
+ 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
+ 0F9332A014CA7DCD0085F3C6 /* GetByIdStatus.h in Headers */,
+ 0F9332A214CA7DD30085F3C6 /* MethodCallLinkStatus.h in Headers */,
+ 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */,
+ 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */,
0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */,
F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */,
+ 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */,
+ 0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */,
+ 0F9332A114CA7DD10085F3C6 /* MethodCallLinkStatus.cpp in Sources */,
+ 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
assembler/MacroAssemblerARM.cpp \
assembler/MacroAssemblerSH4.cpp \
bytecode/CallLinkInfo.cpp \
+ bytecode/CallLinkStatus.cpp \
bytecode/CodeBlock.cpp \
bytecode/DFGExitProfile.cpp \
+ bytecode/GetByIdStatus.cpp \
bytecode/JumpTable.cpp \
bytecode/MethodCallLinkInfo.cpp \
+ bytecode/MethodCallLinkStatus.cpp \
bytecode/Opcode.cpp \
bytecode/PredictedType.cpp \
+ bytecode/PutByIdStatus.cpp \
bytecode/SamplingTool.cpp \
bytecode/StructureStubInfo.cpp \
bytecode/ValueProfile.cpp \
--- /dev/null
+/*
+ * 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 "CallLinkStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+CallLinkStatus CallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+#if ENABLE(JIT)
+ return CallLinkStatus(
+ profiledBlock->getCallLinkInfo(bytecodeIndex).lastSeenCallee.get(),
+ profiledBlock->couldTakeSlowCase(bytecodeIndex));
+#else
+ return CallLinkStatus(0, false);
+#endif
+}
+
+} // namespace JSC
+
--- /dev/null
+/*
+ * 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 CallLinkStatus_h
+#define CallLinkStatus_h
+
+namespace JSC {
+
+class JSFunction;
+class CodeBlock;
+
+class CallLinkStatus {
+public:
+ CallLinkStatus()
+ : m_callTarget(0)
+ , m_couldTakeSlowPath(false)
+ {
+ }
+
+ CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath)
+ : m_callTarget(callTarget)
+ , m_couldTakeSlowPath(couldTakeSlowPath)
+ {
+ }
+
+ static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
+
+ bool isSet() const { return !!m_callTarget; }
+
+ bool operator!() const { return !m_callTarget; }
+
+ bool couldTakeSlowPath() const { return m_couldTakeSlowPath; }
+
+ JSFunction* callTarget() const { return m_callTarget; }
+
+private:
+ JSFunction* m_callTarget;
+ bool m_couldTakeSlowPath;
+};
+
+} // namespace JSC
+
+#endif // CallLinkStatus_h
+
--- /dev/null
+/*
+ * 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 "GetByIdStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+#if ENABLE(JIT)
+ // First check if it makes either calls, in which case we want to be super careful, or
+ // if it's not set at all, in which case we punt.
+ StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
+ if (!stubInfo.seen)
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
+
+ PolymorphicAccessStructureList* list;
+ int listSize;
+ switch (stubInfo.accessType) {
+ case access_get_by_id_self_list:
+ list = stubInfo.u.getByIdSelfList.structureList;
+ listSize = stubInfo.u.getByIdSelfList.listSize;
+ break;
+ case access_get_by_id_proto_list:
+ list = stubInfo.u.getByIdProtoList.structureList;
+ listSize = stubInfo.u.getByIdProtoList.listSize;
+ break;
+ default:
+ list = 0;
+ listSize = 0;
+ break;
+ }
+ for (int i = 0; i < listSize; ++i) {
+ if (!list->list[i].isDirect)
+ return GetByIdStatus(MakesCalls, StructureSet(), notFound);
+ }
+
+ // Next check if it takes slow case, in which case we want to be kind of careful.
+ if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
+ return GetByIdStatus(TakesSlowPath, StructureSet(), notFound);
+
+ // Finally figure out if we can derive an access strategy.
+ GetByIdStatus result;
+ switch (stubInfo.accessType) {
+ case access_unset:
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
+
+ case access_get_by_id_self: {
+ Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
+ result.m_offset = structure->get(*profiledBlock->globalData(), ident);
+
+ if (result.m_offset != notFound)
+ result.m_structureSet.add(structure);
+
+ if (result.m_offset != notFound)
+ ASSERT(result.m_structureSet.size());
+ break;
+ }
+
+ case access_get_by_id_self_list: {
+ PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
+ unsigned size = stubInfo.u.getByIdProtoList.listSize;
+ for (unsigned i = 0; i < size; ++i) {
+ ASSERT(list->list[i].isDirect);
+
+ Structure* structure = list->list[i].base.get();
+ if (result.m_structureSet.contains(structure))
+ continue;
+
+ size_t myOffset = structure->get(*profiledBlock->globalData(), ident);
+
+ if (myOffset == notFound) {
+ result.m_offset = notFound;
+ break;
+ }
+
+ if (!i)
+ result.m_offset = myOffset;
+ else if (result.m_offset != myOffset) {
+ result.m_offset = notFound;
+ break;
+ }
+
+ result.m_structureSet.add(structure);
+ }
+
+ if (result.m_offset != notFound)
+ ASSERT(result.m_structureSet.size());
+ break;
+ }
+
+ default:
+ ASSERT(result.m_offset == notFound);
+ break;
+ }
+
+ if (result.m_offset == notFound) {
+ result.m_state = TakesSlowPath;
+ result.m_structureSet.clear();
+ } else
+ result.m_state = SimpleDirect;
+
+ return result;
+#else // ENABLE(JIT)
+ return GetByIdStatus(NoInformation, StructureSet(), notFound);
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
+
--- /dev/null
+/*
+ * 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 GetByIdStatus_h
+#define GetByIdStatus_h
+
+#include "StructureSet.h"
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+
+class GetByIdStatus {
+public:
+ enum State {
+ NoInformation, // It's uncached so we have no information.
+ SimpleDirect, // It's cached for a direct access to a known object property.
+ TakesSlowPath, // It's known to often take slow path.
+ MakesCalls // It's known to take paths that make calls.
+ };
+
+ GetByIdStatus()
+ : m_state(NoInformation)
+ , m_offset(notFound)
+ {
+ }
+
+ GetByIdStatus(State state, const StructureSet& structureSet, size_t offset)
+ : m_state(state)
+ , m_structureSet(structureSet)
+ , m_offset(offset)
+ {
+ ASSERT((state == SimpleDirect) == (offset != notFound));
+ }
+
+ static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+
+ State state() const { return m_state; }
+
+ bool isSet() const { return m_state != NoInformation; }
+ bool operator!() const { return !isSet(); }
+ bool isSimpleDirect() const { return m_state == SimpleDirect; }
+ bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
+ bool makesCalls() const { return m_state == MakesCalls; }
+
+ const StructureSet& structureSet() const { return m_structureSet; }
+ size_t offset() const { return m_offset; }
+
+private:
+ State m_state;
+ StructureSet m_structureSet;
+ size_t m_offset;
+};
+
+} // namespace JSC
+
+#endif // PropertyAccessStatus_h
+
--- /dev/null
+/*
+ * 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 "MethodCallLinkStatus.h"
+
+#include "CodeBlock.h"
+
+namespace JSC {
+
+MethodCallLinkStatus MethodCallLinkStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex)
+{
+#if ENABLE(JIT)
+ MethodCallLinkInfo& methodCall = profiledBlock->getMethodCallLinkInfo(bytecodeIndex);
+
+ if (!methodCall.seen || !methodCall.cachedStructure)
+ return MethodCallLinkStatus();
+
+ if (methodCall.cachedPrototype.get() == profiledBlock->globalObject()->methodCallDummy()) {
+ return MethodCallLinkStatus(
+ methodCall.cachedStructure.get(),
+ 0,
+ methodCall.cachedFunction.get(),
+ 0);
+ }
+
+ return MethodCallLinkStatus(
+ methodCall.cachedStructure.get(),
+ methodCall.cachedPrototypeStructure.get(),
+ methodCall.cachedFunction.get(),
+ methodCall.cachedPrototype.get());
+#else // ENABLE(JIT)
+ return MethodCallLinkStatus();
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
--- /dev/null
+/*
+ * 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 MethodCallLinkStatus_h
+#define MethodCallLinkStatus_h
+
+namespace JSC {
+
+class CodeBlock;
+class JSObject;
+class Structure;
+
+class MethodCallLinkStatus {
+public:
+ MethodCallLinkStatus()
+ : m_structure(0)
+ , m_prototypeStructure(0)
+ , m_function(0)
+ , m_prototype(0)
+ {
+ }
+
+ MethodCallLinkStatus(
+ Structure* structure,
+ Structure* prototypeStructure,
+ JSObject* function,
+ JSObject* prototype)
+ : m_structure(structure)
+ , m_prototypeStructure(prototypeStructure)
+ , m_function(function)
+ , m_prototype(prototype)
+ {
+ if (!m_function) {
+ ASSERT(!m_structure);
+ ASSERT(!m_prototypeStructure);
+ ASSERT(!m_prototype);
+ } else
+ ASSERT(m_structure);
+
+ ASSERT(!m_prototype == !m_prototypeStructure);
+ }
+
+ static MethodCallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex);
+
+ bool isSet() const { return !!m_function; }
+ bool operator!() const { return !m_function; }
+
+ bool needsPrototypeCheck() const { return !!m_prototype; }
+
+ Structure* structure() { return m_structure; }
+ Structure* prototypeStructure() { return m_prototypeStructure; }
+ JSObject* function() const { return m_function; }
+ JSObject* prototype() const { return m_prototype; }
+
+private:
+ Structure* m_structure;
+ Structure* m_prototypeStructure;
+ JSObject* m_function;
+ JSObject* m_prototype;
+};
+
+} // namespace JSC
+
+#endif // MethodCallLinkStatus_h
+
--- /dev/null
+/*
+ * 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 "PutByIdStatus.h"
+
+#include "CodeBlock.h"
+#include "Structure.h"
+#include "StructureChain.h"
+
+namespace JSC {
+
+PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
+{
+#if ENABLE(JIT)
+ if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+
+ StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
+ if (!stubInfo.seen)
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+
+ switch (stubInfo.accessType) {
+ case access_unset:
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+
+ case access_put_by_id_replace: {
+ size_t offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
+ *profiledBlock->globalData(), ident);
+ if (offset != notFound) {
+ return PutByIdStatus(
+ SimpleReplace,
+ stubInfo.u.putByIdReplace.baseObjectStructure.get(),
+ 0, 0,
+ offset);
+ }
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+ }
+
+ case access_put_by_id_transition_normal:
+ case access_put_by_id_transition_direct: {
+ size_t offset = stubInfo.u.putByIdTransition.structure->get(
+ *profiledBlock->globalData(), ident);
+ if (offset != notFound) {
+ return PutByIdStatus(
+ SimpleTransition,
+ stubInfo.u.putByIdTransition.previousStructure.get(),
+ stubInfo.u.putByIdTransition.structure.get(),
+ stubInfo.u.putByIdTransition.chain.get(),
+ offset);
+ }
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+ }
+
+ default:
+ return PutByIdStatus(TakesSlowPath, 0, 0, 0, notFound);
+ }
+#else // ENABLE(JIT)
+ return PutByIdStatus(NoInformation, 0, 0, 0, notFound);
+#endif // ENABLE(JIT)
+}
+
+} // namespace JSC
+
--- /dev/null
+/*
+ * 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 PutByIdStatus_h
+#define PutByIdStatus_h
+
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+class CodeBlock;
+class Identifier;
+class Structure;
+class StructureChain;
+
+class PutByIdStatus {
+public:
+ enum State {
+ // It's uncached so we have no information.
+ NoInformation,
+ // It's cached as a direct store into an object property for cases where the object
+ // already has the property.
+ SimpleReplace,
+ // It's cached as a transition from one structure that lacks the property to one that
+ // includes the property, and a direct store to this new property.
+ SimpleTransition,
+ // It's known to often take slow path.
+ TakesSlowPath
+ };
+
+ PutByIdStatus()
+ : m_state(NoInformation)
+ , m_oldStructure(0)
+ , m_newStructure(0)
+ , m_structureChain(0)
+ , m_offset(notFound)
+ {
+ }
+
+ PutByIdStatus(
+ State state,
+ Structure* oldStructure,
+ Structure* newStructure,
+ StructureChain* structureChain,
+ size_t offset)
+ : m_state(state)
+ , m_oldStructure(oldStructure)
+ , m_newStructure(newStructure)
+ , m_structureChain(structureChain)
+ , m_offset(offset)
+ {
+ ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure);
+ ASSERT((m_state != SimpleTransition) == !m_newStructure);
+ ASSERT((m_state != SimpleTransition) == !m_structureChain);
+ ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == notFound));
+ }
+
+ static PutByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&);
+
+ State state() const { return m_state; }
+
+ bool isSet() const { return m_state != NoInformation; }
+ bool operator!() const { return m_state == NoInformation; }
+ bool isSimpleReplace() const { return m_state == SimpleReplace; }
+ bool isSimpleTransition() const { return m_state == SimpleTransition; }
+ bool takesSlowPath() const { return m_state == TakesSlowPath; }
+
+ Structure* oldStructure() const { return m_oldStructure; }
+ Structure* newStructure() const { return m_newStructure; }
+ StructureChain* structureChain() const { return m_structureChain; }
+ size_t offset() const { return m_offset; }
+
+private:
+ State m_state;
+ Structure* m_oldStructure;
+ Structure* m_newStructure;
+ StructureChain* m_structureChain;
+ size_t m_offset;
+};
+
+} // namespace JSC
+
+#endif // PutByIdStatus_h
+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DFGStructureSet_h
-#define DFGStructureSet_h
-
-#include <wtf/Platform.h>
-
-#if ENABLE(DFG_JIT)
+#ifndef StructureSet_h
+#define StructureSet_h
#include "PredictedType.h"
#include <stdio.h>
class Structure;
namespace DFG {
-
class StructureAbstractValue;
+}
class StructureSet {
public:
return true;
}
-#ifndef NDEBUG
void dump(FILE* out)
{
fprintf(out, "[");
}
fprintf(out, "]");
}
-#endif
private:
- friend class StructureAbstractValue;
+ friend class DFG::StructureAbstractValue;
Vector<Structure*, 2> m_structures;
};
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
+} // namespace JSC
-#endif // DFGStructureSet_h
+#endif // StructureSet_h
#if ENABLE(DFG_JIT)
-#include "DFGStructureSet.h"
#include "JSCell.h"
#include "PredictedType.h"
+#include "StructureSet.h"
namespace JSC { namespace DFG {
#if ENABLE(DFG_JIT)
+#include "CallLinkStatus.h"
+#include "CodeBlock.h"
#include "DFGByteCodeCache.h"
#include "DFGCapabilities.h"
-#include "CodeBlock.h"
+#include "GetByIdStatus.h"
+#include "MethodCallLinkStatus.h"
+#include "PutByIdStatus.h"
#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
return nodeIndex;
}
- bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)
- {
- if (direct)
- return true;
-
- if (!previousStructure->storedPrototype().isNull() && previousStructure->storedPrototype().asCell()->structure() != chain->head()->get())
- return false;
-
- for (WriteBarrier<Structure>* it = chain->head(); *it; ++it) {
- if (!(*it)->storedPrototype().isNull() && (*it)->storedPrototype().asCell()->structure() != it[1].get())
- return false;
- }
-
- return true;
- }
-
bool willNeedFlush(StructureStubInfo& stubInfo)
{
PolymorphicAccessStructureList* list;
return false;
}
+ bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)
+ {
+ if (direct)
+ return true;
+
+ if (!previousStructure->storedPrototype().isNull() && previousStructure->storedPrototype().asCell()->structure() != chain->head()->get())
+ return false;
+
+ for (WriteBarrier<Structure>* it = chain->head(); *it; ++it) {
+ if (!(*it)->storedPrototype().isNull() && (*it)->storedPrototype().asCell()->structure() != it[1].get())
+ return false;
+ }
+
+ return true;
+ }
+
void buildOperandMapsIfNecessary();
JSGlobalData* m_globalData;
m_currentIndex += OPCODE_LENGTH(name); \
return shouldContinueParsing
+
void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op, CodeSpecializationKind kind)
{
ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
#if DFG_ENABLE(DEBUG_VERBOSE)
printf("Slow case count for call at @%zu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
-
+
+ CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex);
+
if (m_graph.isFunctionConstant(m_codeBlock, callTarget))
callType = ConstantFunction;
- else if (!!m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee
- && !m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
+ else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
callType = LinkedFunction;
else
certainAboutExpectedFunction = true;
} else {
ASSERT(callType == LinkedFunction);
- expectedFunction = m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee.get();
+ expectedFunction = callLinkStatus.callTarget();
intrinsic = expectedFunction->executable()->intrinsicFor(kind);
certainAboutExpectedFunction = false;
}
// Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
// node, which is a lot more efficient.
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
- MethodCallLinkInfo& methodCall = m_inlineStackTop->m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
+ GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock,
+ m_currentIndex,
+ m_codeBlock->identifier(identifier));
+ MethodCallLinkStatus methodCallStatus = MethodCallLinkStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex);
- if (methodCall.seen
- && !!methodCall.cachedStructure
- && !stubInfo.seen
+ if (methodCallStatus.isSet()
+ && !getByIdStatus.isSet()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
// It's monomorphic as far as we can tell, since the method_check was linked
// but the slow path (i.e. the normal get_by_id) never fired.
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedStructure.get())), base);
- if (methodCall.cachedPrototype.get() != m_inlineStackTop->m_profiledBlock->globalObject()->methodCallDummy())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedPrototypeStructure.get())), cellConstant(methodCall.cachedPrototype.get()));
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.structure())), base);
+ if (methodCallStatus.needsPrototypeCheck())
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.prototypeStructure())), cellConstant(methodCallStatus.prototype()));
- set(getInstruction[1].u.operand, cellConstant(methodCall.cachedFunction.get()));
+ set(getInstruction[1].u.operand, cellConstant(methodCallStatus.function()));
} else
- set(getInstruction[1].u.operand, addToGraph(willNeedFlush(stubInfo) ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
+ set(getInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
continue;
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
Identifier identifier = m_codeBlock->identifier(identifierNumber);
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
+ GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier);
#if DFG_ENABLE(DEBUG_VERBOSE)
printf("Slow case count for GetById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
- size_t offset = notFound;
- StructureSet structureSet;
- if (stubInfo.seen
- && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
+ if (getByIdStatus.isSimpleDirect()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- switch (stubInfo.accessType) {
- case access_get_by_id_self: {
- Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
- offset = structure->get(*m_globalData, identifier);
-
- if (offset != notFound)
- structureSet.add(structure);
-
- if (offset != notFound)
- ASSERT(structureSet.size());
- break;
- }
-
- case access_get_by_id_self_list: {
- PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
- unsigned size = stubInfo.u.getByIdProtoList.listSize;
- for (unsigned i = 0; i < size; ++i) {
- if (!list->list[i].isDirect) {
- offset = notFound;
- break;
- }
-
- Structure* structure = list->list[i].base.get();
- if (structureSet.contains(structure))
- continue;
-
- size_t myOffset = structure->get(*m_globalData, identifier);
-
- if (myOffset == notFound) {
- offset = notFound;
- break;
- }
-
- if (!i)
- offset = myOffset;
- else if (offset != myOffset) {
- offset = notFound;
- break;
- }
-
- structureSet.add(structure);
- }
-
- if (offset != notFound)
- ASSERT(structureSet.size());
- break;
- }
-
- default:
- ASSERT(offset == notFound);
- break;
- }
- }
-
- if (offset != notFound) {
- ASSERT(structureSet.size());
+ ASSERT(getByIdStatus.structureSet().size());
// The implementation of GetByOffset does not know to terminate speculative
// execution if it doesn't have a prediction, so we do it manually.
if (prediction == PredictNone)
addToGraph(ForceOSRExit);
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), base);
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base)));
StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
+ storageAccessData.offset = getByIdStatus.offset();
storageAccessData.identifierNumber = identifierNumber;
m_graph.m_storageAccessData.append(storageAccessData);
} else
- set(currentInstruction[1].u.operand, addToGraph(willNeedFlush(stubInfo) ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
+ set(currentInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
NEXT_OPCODE(op_get_by_id);
}
-
case op_put_by_id: {
NodeIndex value = get(currentInstruction[3].u.operand);
NodeIndex base = get(currentInstruction[1].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
bool direct = currentInstruction[8].u.operand;
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
- if (!stubInfo.seen)
+ PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock,
+ m_currentIndex,
+ m_codeBlock->identifier(identifierNumber));
+ if (!putByIdStatus.isSet())
addToGraph(ForceOSRExit);
- bool alreadyGenerated = false;
+ bool hasExitSite = m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache);
#if DFG_ENABLE(DEBUG_VERBOSE)
printf("Slow case count for PutById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
- if (stubInfo.seen
- && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- switch (stubInfo.accessType) {
- case access_put_by_id_replace: {
- Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
- Identifier identifier = m_codeBlock->identifier(identifierNumber);
- size_t offset = structure->get(*m_globalData, identifier);
-
- if (offset != notFound) {
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), base);
- addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
-
- alreadyGenerated = true;
- }
- break;
- }
-
- case access_put_by_id_transition_normal:
- case access_put_by_id_transition_direct: {
- Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
- Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
-
- if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
- break;
-
- StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
-
- Identifier identifier = m_codeBlock->identifier(identifierNumber);
- size_t offset = newStructure->get(*m_globalData, identifier);
+ if (!hasExitSite && putByIdStatus.isSimpleReplace()) {
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+ addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = putByIdStatus.offset();
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+ } else if (!hasExitSite
+ && putByIdStatus.isSimpleTransition()
+ && putByIdStatus.oldStructure()->propertyStorageCapacity() == putByIdStatus.newStructure()->propertyStorageCapacity()
+ && structureChainIsStillValid(
+ direct,
+ putByIdStatus.oldStructure(),
+ putByIdStatus.structureChain())) {
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+ if (!direct) {
+ if (!putByIdStatus.oldStructure()->storedPrototype().isNull())
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure()->storedPrototype().asCell()->structure())),
+ cellConstant(putByIdStatus.oldStructure()->storedPrototype().asCell()));
- if (offset != notFound && structureChainIsStillValid(direct, previousStructure, structureChain)) {
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure)), base);
- if (!direct) {
- if (!previousStructure->storedPrototype().isNull())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure->storedPrototype().asCell()->structure())), cellConstant(previousStructure->storedPrototype().asCell()));
-
- for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
- JSValue prototype = (*it)->storedPrototype();
- if (prototype.isNull())
- continue;
- ASSERT(prototype.isCell());
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())), cellConstant(prototype.asCell()));
- }
- }
- addToGraph(PutStructure, OpInfo(m_graph.addStructureTransitionData(StructureTransitionData(previousStructure, newStructure))), base);
-
- addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
-
- alreadyGenerated = true;
+ for (WriteBarrier<Structure>* it = putByIdStatus.structureChain()->head(); *it; ++it) {
+ JSValue prototype = (*it)->storedPrototype();
+ if (prototype.isNull())
+ continue;
+ ASSERT(prototype.isCell());
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())),
+ cellConstant(prototype.asCell()));
}
- break;
}
-
- default:
- break;
- }
- }
-
- if (!alreadyGenerated) {
+ addToGraph(
+ PutStructure,
+ OpInfo(
+ m_graph.addStructureTransitionData(
+ StructureTransitionData(
+ putByIdStatus.oldStructure(),
+ putByIdStatus.newStructure()))),
+ base);
+
+ addToGraph(
+ PutByOffset,
+ OpInfo(m_graph.m_storageAccessData.size()),
+ base,
+ addToGraph(GetPropertyStorage, base),
+ value);
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = putByIdStatus.offset();
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+ } else {
if (direct)
addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
else