diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
commit | e15dd966d523731101f70ccf768bba12435a0208 (patch) | |
tree | ae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/bytecode/CodeOrigin.h | |
download | WebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz |
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/bytecode/CodeOrigin.h')
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeOrigin.h | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h new file mode 100644 index 000000000..d1879a327 --- /dev/null +++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2011-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. + */ + +#ifndef CodeOrigin_h +#define CodeOrigin_h + +#include "CodeBlockHash.h" +#include "CodeSpecializationKind.h" +#include "ValueRecovery.h" +#include "WriteBarrier.h" +#include <wtf/BitVector.h> +#include <wtf/HashMap.h> +#include <wtf/PrintStream.h> +#include <wtf/StdLibExtras.h> +#include <wtf/Vector.h> + +namespace JSC { + +struct InlineCallFrame; +class ExecState; +class ScriptExecutable; +class JSFunction; + +struct CodeOrigin { + static const unsigned invalidBytecodeIndex = UINT_MAX; + + // Bytecode offset that you'd use to re-execute this instruction, and the + // bytecode index of the bytecode instruction that produces some result that + // you're interested in (used for mapping Nodes whose values you're using + // to bytecode instructions that have the appropriate value profile). + unsigned bytecodeIndex; + + InlineCallFrame* inlineCallFrame; + + CodeOrigin() + : bytecodeIndex(invalidBytecodeIndex) + , inlineCallFrame(0) + { + } + + CodeOrigin(WTF::HashTableDeletedValueType) + : bytecodeIndex(invalidBytecodeIndex) + , inlineCallFrame(deletedMarker()) + { + } + + explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0) + : bytecodeIndex(bytecodeIndex) + , inlineCallFrame(inlineCallFrame) + { + ASSERT(bytecodeIndex < invalidBytecodeIndex); + } + + bool isSet() const { return bytecodeIndex != invalidBytecodeIndex; } + bool operator!() const { return !isSet(); } + + bool isHashTableDeletedValue() const + { + return bytecodeIndex == invalidBytecodeIndex && !!inlineCallFrame; + } + + // The inline depth is the depth of the inline stack, so 1 = not inlined, + // 2 = inlined one deep, etc. + unsigned inlineDepth() const; + + // If the code origin corresponds to inlined code, gives you the heap object that + // would have owned the code if it had not been inlined. Otherwise returns 0. + ScriptExecutable* codeOriginOwner() const; + + int stackOffset() const; + + static unsigned inlineDepthForCallFrame(InlineCallFrame*); + + unsigned hash() const; + bool operator==(const CodeOrigin& other) const; + bool operator!=(const CodeOrigin& other) const { return !(*this == other); } + + // This checks if the two code origins correspond to the same stack trace snippets, + // but ignore whether the InlineCallFrame's are identical. + bool isApproximatelyEqualTo(const CodeOrigin& other) const; + + unsigned approximateHash() const; + + // Get the inline stack. This is slow, and is intended for debugging only. + Vector<CodeOrigin> inlineStack() const; + + void dump(PrintStream&) const; + void dumpInContext(PrintStream&, DumpContext*) const; + +private: + static InlineCallFrame* deletedMarker() + { + return bitwise_cast<InlineCallFrame*>(static_cast<uintptr_t>(1)); + } +}; + +struct InlineCallFrame { + enum Kind { + Call, + Construct, + CallVarargs, + ConstructVarargs, + + // For these, the stackOffset incorporates the argument count plus the true return PC + // slot. + GetterCall, + SetterCall + }; + + static Kind kindFor(CodeSpecializationKind kind) + { + switch (kind) { + case CodeForCall: + return Call; + case CodeForConstruct: + return Construct; + } + RELEASE_ASSERT_NOT_REACHED(); + return Call; + } + + static Kind varargsKindFor(CodeSpecializationKind kind) + { + switch (kind) { + case CodeForCall: + return CallVarargs; + case CodeForConstruct: + return ConstructVarargs; + } + RELEASE_ASSERT_NOT_REACHED(); + return Call; + } + + static CodeSpecializationKind specializationKindFor(Kind kind) + { + switch (kind) { + case Call: + case CallVarargs: + case GetterCall: + case SetterCall: + return CodeForCall; + case Construct: + case ConstructVarargs: + return CodeForConstruct; + } + RELEASE_ASSERT_NOT_REACHED(); + return CodeForCall; + } + + static bool isVarargs(Kind kind) + { + switch (kind) { + case CallVarargs: + case ConstructVarargs: + return true; + default: + return false; + } + } + bool isVarargs() const + { + return isVarargs(static_cast<Kind>(kind)); + } + + Vector<ValueRecovery> arguments; // Includes 'this'. + WriteBarrier<ScriptExecutable> executable; + ValueRecovery calleeRecovery; + CodeOrigin caller; + + signed stackOffset : 28; + unsigned kind : 3; // real type is Kind + bool isClosureCall : 1; // If false then we know that callee/scope are constants and the DFG won't treat them as variables, i.e. they have to be recovered manually. + VirtualRegister argumentCountRegister; // Only set when we inline a varargs call. + + // There is really no good notion of a "default" set of values for + // InlineCallFrame's fields. This constructor is here just to reduce confusion if + // we forgot to initialize explicitly. + InlineCallFrame() + : stackOffset(0) + , kind(Call) + , isClosureCall(false) + { + } + + CodeSpecializationKind specializationKind() const { return specializationKindFor(static_cast<Kind>(kind)); } + + JSFunction* calleeConstant() const; + void visitAggregate(SlotVisitor&); + + // Get the callee given a machine call frame to which this InlineCallFrame belongs. + JSFunction* calleeForCallFrame(ExecState*) const; + + CString inferredName() const; + CodeBlockHash hash() const; + CString hashAsStringIfPossible() const; + + CodeBlock* baselineCodeBlock() const; + + void setStackOffset(signed offset) + { + stackOffset = offset; + RELEASE_ASSERT(static_cast<signed>(stackOffset) == offset); + } + + ptrdiff_t callerFrameOffset() const { return stackOffset * sizeof(Register) + CallFrame::callerFrameOffset(); } + ptrdiff_t returnPCOffset() const { return stackOffset * sizeof(Register) + CallFrame::returnPCOffset(); } + + void dumpBriefFunctionInformation(PrintStream&) const; + void dump(PrintStream&) const; + void dumpInContext(PrintStream&, DumpContext*) const; + + MAKE_PRINT_METHOD(InlineCallFrame, dumpBriefFunctionInformation, briefFunctionInformation); +}; + +inline int CodeOrigin::stackOffset() const +{ + if (!inlineCallFrame) + return 0; + + return inlineCallFrame->stackOffset; +} + +inline unsigned CodeOrigin::hash() const +{ + return WTF::IntHash<unsigned>::hash(bytecodeIndex) + + WTF::PtrHash<InlineCallFrame*>::hash(inlineCallFrame); +} + +inline bool CodeOrigin::operator==(const CodeOrigin& other) const +{ + return bytecodeIndex == other.bytecodeIndex + && inlineCallFrame == other.inlineCallFrame; +} + +inline ScriptExecutable* CodeOrigin::codeOriginOwner() const +{ + if (!inlineCallFrame) + return 0; + return inlineCallFrame->executable.get(); +} + +struct CodeOriginHash { + static unsigned hash(const CodeOrigin& key) { return key.hash(); } + static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +struct CodeOriginApproximateHash { + static unsigned hash(const CodeOrigin& key) { return key.approximateHash(); } + static bool equal(const CodeOrigin& a, const CodeOrigin& b) { return a.isApproximatelyEqualTo(b); } + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} // namespace JSC + +namespace WTF { + +void printInternal(PrintStream&, JSC::InlineCallFrame::Kind); + +template<typename T> struct DefaultHash; +template<> struct DefaultHash<JSC::CodeOrigin> { + typedef JSC::CodeOriginHash Hash; +}; + +template<typename T> struct HashTraits; +template<> struct HashTraits<JSC::CodeOrigin> : SimpleClassHashTraits<JSC::CodeOrigin> { + static const bool emptyValueIsZero = false; +}; + +} // namespace WTF + +#endif // CodeOrigin_h + |