X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/93a3786624b2768d89bfa27e46598dc64e2fb70a..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/bytecode/CodeOrigin.cpp?ds=sidebyside diff --git a/bytecode/CodeOrigin.cpp b/bytecode/CodeOrigin.cpp index 52bc2bf..15f7591 100644 --- a/bytecode/CodeOrigin.cpp +++ b/bytecode/CodeOrigin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2012-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 @@ -29,7 +29,7 @@ #include "CallFrame.h" #include "CodeBlock.h" #include "Executable.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { @@ -45,7 +45,64 @@ unsigned CodeOrigin::inlineDepth() const { return inlineDepthForCallFrame(inlineCallFrame); } + +bool CodeOrigin::isApproximatelyEqualTo(const CodeOrigin& other) const +{ + CodeOrigin a = *this; + CodeOrigin b = other; + + if (!a.isSet()) + return !b.isSet(); + if (!b.isSet()) + return false; + + if (a.isHashTableDeletedValue()) + return b.isHashTableDeletedValue(); + if (b.isHashTableDeletedValue()) + return false; + + for (;;) { + ASSERT(a.isSet()); + ASSERT(b.isSet()); + + if (a.bytecodeIndex != b.bytecodeIndex) + return false; + + if ((!!a.inlineCallFrame) != (!!b.inlineCallFrame)) + return false; + + if (!a.inlineCallFrame) + return true; + + if (a.inlineCallFrame->executable.get() != b.inlineCallFrame->executable.get()) + return false; + + a = a.inlineCallFrame->caller; + b = b.inlineCallFrame->caller; + } +} + +unsigned CodeOrigin::approximateHash() const +{ + if (!isSet()) + return 0; + if (isHashTableDeletedValue()) + return 1; + unsigned result = 2; + CodeOrigin codeOrigin = *this; + for (;;) { + result += codeOrigin.bytecodeIndex; + + if (!codeOrigin.inlineCallFrame) + return result; + + result += WTF::PtrHash::hash(codeOrigin.inlineCallFrame->executable.get()); + + codeOrigin = codeOrigin.inlineCallFrame->caller; + } +} + Vector CodeOrigin::inlineStack() const { Vector result(inlineDepth()); @@ -59,6 +116,11 @@ Vector CodeOrigin::inlineStack() const void CodeOrigin::dump(PrintStream& out) const { + if (!isSet()) { + out.print(""); + return; + } + Vector stack = inlineStack(); for (unsigned i = 0; i < stack.size(); ++i) { if (i) @@ -66,7 +128,7 @@ void CodeOrigin::dump(PrintStream& out) const if (InlineCallFrame* frame = stack[i].inlineCallFrame) { out.print(frame->briefFunctionInformation(), ":<", RawPointer(frame->executable.get()), "> "); - if (frame->isClosureCall()) + if (frame->isClosureCall) out.print("(closure) "); } @@ -74,22 +136,52 @@ void CodeOrigin::dump(PrintStream& out) const } } +void CodeOrigin::dumpInContext(PrintStream& out, DumpContext*) const +{ + dump(out); +} + +JSFunction* InlineCallFrame::calleeConstant() const +{ + if (calleeRecovery.isConstant()) + return jsCast(calleeRecovery.constant()); + return nullptr; +} + +void InlineCallFrame::visitAggregate(SlotVisitor& visitor) +{ + // FIXME: This is an antipattern for two reasons. References introduced by the DFG + // that aren't in the original CodeBlock being compiled should be weakly referenced. + // Inline call frames aren't in the original CodeBlock, so they qualify as weak. Also, + // those weak references should already be tracked in the DFG as weak FrozenValues. So, + // there is probably no need for this. We already have assertions that this should be + // unnecessary. Finally, just marking the executable and not anything else in the inline + // call frame is almost certainly insufficient for what this method thought it was going + // to accomplish. + // https://bugs.webkit.org/show_bug.cgi?id=146613 + visitor.append(&executable); +} + JSFunction* InlineCallFrame::calleeForCallFrame(ExecState* exec) const { - if (!isClosureCall()) - return callee.get(); - - return jsCast((exec + stackOffset)->callee()); + return jsCast(calleeRecovery.recover(exec)); } CodeBlockHash InlineCallFrame::hash() const { - return executable->hashFor(specializationKind()); + return jsCast(executable.get())->codeBlockFor( + specializationKind())->hash(); +} + +CString InlineCallFrame::hashAsStringIfPossible() const +{ + return jsCast(executable.get())->codeBlockFor( + specializationKind())->hashAsStringIfPossible(); } -String InlineCallFrame::inferredName() const +CString InlineCallFrame::inferredName() const { - return jsCast(executable.get())->inferredName().string(); + return jsCast(executable.get())->inferredName().utf8(); } CodeBlock* InlineCallFrame::baselineCodeBlock() const @@ -99,20 +191,57 @@ CodeBlock* InlineCallFrame::baselineCodeBlock() const void InlineCallFrame::dumpBriefFunctionInformation(PrintStream& out) const { - out.print(inferredName(), "#", hash()); + out.print(inferredName(), "#", hashAsStringIfPossible()); } -void InlineCallFrame::dump(PrintStream& out) const +void InlineCallFrame::dumpInContext(PrintStream& out, DumpContext* context) const { - out.print(briefFunctionInformation(), ":<", RawPointer(executable.get()), ", bc#", caller.bytecodeIndex, ", ", specializationKind()); - if (callee) - out.print(", known callee: ", JSValue(callee.get())); - else + out.print(briefFunctionInformation(), ":<", RawPointer(executable.get())); + if (executable->isStrictMode()) + out.print(" (StrictMode)"); + out.print(", bc#", caller.bytecodeIndex, ", ", kind); + if (isClosureCall) out.print(", closure call"); + else + out.print(", known callee: ", inContext(calleeRecovery.constant(), context)); out.print(", numArgs+this = ", arguments.size()); - out.print(", stack >= r", stackOffset); - out.print(">"); + out.print(", stackOffset = ", stackOffset); + out.print(" (", virtualRegisterForLocal(0), " maps to ", virtualRegisterForLocal(0) + stackOffset, ")>"); +} + +void InlineCallFrame::dump(PrintStream& out) const +{ + dumpInContext(out, 0); } } // namespace JSC +namespace WTF { + +void printInternal(PrintStream& out, JSC::InlineCallFrame::Kind kind) +{ + switch (kind) { + case JSC::InlineCallFrame::Call: + out.print("Call"); + return; + case JSC::InlineCallFrame::Construct: + out.print("Construct"); + return; + case JSC::InlineCallFrame::CallVarargs: + out.print("CallVarargs"); + return; + case JSC::InlineCallFrame::ConstructVarargs: + out.print("ConstructVarargs"); + return; + case JSC::InlineCallFrame::GetterCall: + out.print("GetterCall"); + return; + case JSC::InlineCallFrame::SetterCall: + out.print("SetterCall"); + return; + } + RELEASE_ASSERT_NOT_REACHED(); +} + +} // namespace WTF +