Diff
Modified: trunk/JSTests/ChangeLog (208116 => 208117)
--- trunk/JSTests/ChangeLog 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/JSTests/ChangeLog 2016-10-30 01:38:22 UTC (rev 208117)
@@ -1,3 +1,21 @@
+2016-10-29 Saam Barati <[email protected]>
+
+ We should have a way of profiling when a get_by_id is pure and to emit a PureGetById in the DFG/FTL
+ https://bugs.webkit.org/show_bug.cgi?id=163305
+
+ Reviewed by Keith Miller.
+
+ * microbenchmarks/pure-get-by-id-cse-2.js: Added.
+ (foo):
+ * microbenchmarks/pure-get-by-id-cse.js: Added.
+ (foo):
+ * stress/pure-get-by-id-cse-correctness.js: Added.
+ (assert):
+ (foo):
+ * stress/pure-get-by-id-on-non-object.js: Added.
+ (assert):
+ (foo):
+
2016-10-28 Csaba Osztrogonác <[email protected]>
Skip JSTests/microbenchmarks/dense-set.js on memory limited devices
Added: trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js (0 => 208117)
--- trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js (rev 0)
+++ trunk/JSTests/microbenchmarks/pure-get-by-id-cse-2.js 2016-10-30 01:38:22 UTC (rev 208117)
@@ -0,0 +1,30 @@
+function foo(o, c) {
+ if (o.f) {
+ let sum = 0;
+ for (let i = 0; i < c; i++)
+ sum += o.f;
+ return sum;
+ }
+}
+noInline(foo);
+
+let start = Date.now();
+let objects = [];
+const objectCount = 20;
+for (let i = 0; i < objectCount; i++) {
+ let obj = {};
+ for (let j = 0; j < i * 2; j++) {
+ obj["j" + j] = j;
+ }
+ obj.f = 20;
+ objects.push(obj);
+}
+
+for (let i = 0; i < 1000000; i++) {
+ let obj = objects[i % objects.length];
+ foo(obj, 150);
+}
+
+const verbose = false;
+if (verbose)
+ print(Date.now() - start);
Added: trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js (0 => 208117)
--- trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js (rev 0)
+++ trunk/JSTests/microbenchmarks/pure-get-by-id-cse.js 2016-10-30 01:38:22 UTC (rev 208117)
@@ -0,0 +1,26 @@
+function foo(o) {
+ if (o.f)
+ return o.f + o.f + o.f + o.f;
+}
+noInline(foo);
+
+let start = Date.now();
+let objects = [];
+const objectCount = 20;
+for (let i = 0; i < objectCount; i++) {
+ let obj = {};
+ for (let j = 0; j < i * 2; j++) {
+ obj["j" + j] = j;
+ }
+ obj.f = 20;
+ objects.push(obj);
+}
+
+for (let i = 0; i < 10000000; i++) {
+ let obj = objects[i % objects.length];
+ foo(obj);
+}
+
+const verbose = false;
+if (verbose)
+ print(Date.now() - start);
Added: trunk/JSTests/stress/pure-get-by-id-cse-correctness.js (0 => 208117)
--- trunk/JSTests/stress/pure-get-by-id-cse-correctness.js (rev 0)
+++ trunk/JSTests/stress/pure-get-by-id-cse-correctness.js 2016-10-30 01:38:22 UTC (rev 208117)
@@ -0,0 +1,39 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion")
+}
+noInline(assert);
+
+function foo(o1, o2) {
+ let a = o1.f1;
+ let b = o2.f2;
+ return a + o1.f1 + b;
+}
+noInline(foo);
+
+let objs = [];
+const count = 80;
+for (let i = 0; i < count; i++) {
+ let o = {};
+ for (let j = 0; j < i; ++j) {
+ o[j + "J"] = j;
+ }
+ o.f1 = 20;
+ o.f2 = 40;
+ objs.push(o);
+}
+
+for (let i = 0; i < 1000; i++) {
+ let o1 = objs[i % objs.length];
+ let o2 = objs[(i + 1) % objs.length];
+ assert(foo(o1, o2) === 80);
+}
+
+let o = objs[count - 1];
+let numCalls = 0;
+Object.defineProperty(o, "f1", {
+ get() { ++numCalls; return 25; }
+});
+
+assert(foo(o, objs[count - 2]) === 90);
+assert(numCalls === 2);
Added: trunk/JSTests/stress/pure-get-by-id-on-non-object.js (0 => 208117)
--- trunk/JSTests/stress/pure-get-by-id-on-non-object.js (rev 0)
+++ trunk/JSTests/stress/pure-get-by-id-on-non-object.js 2016-10-30 01:38:22 UTC (rev 208117)
@@ -0,0 +1,32 @@
+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion.")
+}
+
+function foo(o) {
+ assert(o.length === o.length);
+ return o.length;
+}
+noInline(foo);
+
+let items = [];
+const numItems = 30;
+for (let i = 0; i < numItems; i++) {
+ let o = {};
+ for (let j = 0; j < i; j++) {
+ o[j + "j"] = j;
+ }
+ o.length = 2;
+ items.push(o);
+}
+
+items.push("st");
+
+for (let i = 0; i < 10000; i++)
+ assert(foo(items[i % items.length]) === 2);
+
+Number.prototype.length = 2;
+items.push(42);
+
+for (let i = 0; i < 100000; i++)
+ assert(foo(items[i % items.length]) === 2);
Modified: trunk/Source/_javascript_Core/ChangeLog (208116 => 208117)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-30 01:38:22 UTC (rev 208117)
@@ -1,3 +1,102 @@
+2016-10-29 Saam Barati <[email protected]>
+
+ We should have a way of profiling when a get_by_id is pure and to emit a PureGetById in the DFG/FTL
+ https://bugs.webkit.org/show_bug.cgi?id=163305
+
+ Reviewed by Keith Miller.
+
+ This creates a new GetById node in the DFG called PureGetById. We emit a
+ PureGetById when we profile that a get_by_id in the baseline never does
+ side effects. PureGetById speculates on the fact that it won't do side
+ effects. If it realizes that it must perform side effects, it will perform
+ the side effect, but also invalidate the CodeBlock that compiled it,
+ which will cause us to exit once we return back to the compiled code.
+ This allows us to have stricter clobberize rules for PureGetById which
+ model how getOwnPropertySlot(VMInquiry) behaves. This means that PureGetByIds
+ can be CSEd with each other, and that other things are more likely to
+ be CSEd around a PureGetById. To profile if a get_by_id does side
+ effects, I've added an extra bit into StructureStubInfo that we write
+ to when performing a get_by_id slow path call. If we notice that we
+ never do effects, inside the ByteCodeParser, we will emit a PureGetById
+ instead of a GetById.
+
+ To justify the performance benefit of this patch, I ran the suite of
+ benchmarks with useAccessInlining=false. This meant that we don't compile
+ any (Multi)GetByOffset/(Multi)PutByOffset. This was just to try to see if
+ this patch is worth anything at all in a world where we emit many
+ PureGetByIds. Running the benchmarks under this mode showed a 3.5% octane
+ improvement and a 15% kraken improvement. However, when running benchmarks
+ with useAccessInlining=true (the default JSC state), this patch is neutral.
+ I think the main reason for this is that the DFG is good at knowing when to
+ emit (Multi)GetByOffset, and most benchmarks that would benefit from
+ PureGetById are already emitting (Multi)GetByOffset. However, PureGetById can be
+ profitable when we encounter code that is too polymorphic for (Multi)GetByOffset.
+ It's reasonable to expect that JS code in the wild will fall into this use
+ case even though it might not be represented in some of the major JS benchmarks.
+ I wrote some microbenchmarks to demonstrate the benefits of PureGetById CSE,
+ and they were 30% (eliminating a few PureGetById from an add _expression_)
+ to 10x faster (eliminating a PureGetById in a loop).
+
+ * bytecode/StructureStubInfo.cpp:
+ (JSC::StructureStubInfo::StructureStubInfo):
+ (JSC::StructureStubInfo::reset):
+ * bytecode/StructureStubInfo.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGArrayMode.cpp:
+ (JSC::DFG::canBecomeGetArrayLength):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleGetById):
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::convertToGetByOffset):
+ (JSC::DFG::Node::convertToMultiGetByOffset):
+ (JSC::DFG::Node::hasIdentifier):
+ (JSC::DFG::Node::hasHeapPrediction):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileTryGetById):
+ (JSC::DFG::SpeculativeJIT::compilePureGetById):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::cachedGetById):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::cachedGetById):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetById):
+ (JSC::FTL::DFG::LowerDFGToB3::getById):
+ * jit/JITOperations.cpp:
+ (JSC::pureGetByIdCommon):
+ * jit/JITOperations.h:
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_try_get_by_id):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_try_get_by_id):
+ * jit/Repatch.cpp:
+ (JSC::appropriateOptimizingGetByIdFunction):
+ (JSC::appropriateGenericGetByIdFunction):
+ (JSC::tryCacheGetByID):
+ * jit/Repatch.h:
+ * profiler/ProfilerJettisonReason.cpp:
+ (WTF::printInternal):
+ * profiler/ProfilerJettisonReason.h:
+
2016-10-28 Joseph Pecoraro <[email protected]>
Web Inspector: Breakpoints not working in scripts with unicode characters
Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -48,6 +48,7 @@
, resetByGC(false)
, tookSlowPath(false)
, everConsidered(false)
+ , didSideEffects(false)
{
}
@@ -216,7 +217,10 @@
}
switch (accessType) {
- case AccessType::GetPure:
+ case AccessType::TryGet:
+ resetGetByID(codeBlock, *this, GetByIDKind::Try);
+ break;
+ case AccessType::PureGet:
resetGetByID(codeBlock, *this, GetByIDKind::Pure);
break;
case AccessType::Get:
Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h (208116 => 208117)
--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -46,7 +46,8 @@
enum class AccessType : int8_t {
Get,
- GetPure,
+ TryGet,
+ PureGet,
Put,
In
};
@@ -205,6 +206,7 @@
bool resetByGC : 1;
bool tookSlowPath : 1;
bool everConsidered : 1;
+ bool didSideEffects : 1;
};
inline CodeOrigin getStructureStubInfoCodeOrigin(StructureStubInfo& structureStubInfo)
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -2119,6 +2119,7 @@
forNode(node).makeHeapTop();
break;
+ case PureGetById:
case GetById:
case GetByIdFlush: {
if (!node->prediction()) {
@@ -2150,7 +2151,10 @@
}
}
- clobberWorld(node->origin.semantic, clobberLimit);
+ if (node->op() == PureGetById)
+ clobberStructures(clobberLimit);
+ else
+ clobberWorld(node->origin.semantic, clobberLimit);
forNode(node).makeHeapTop();
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -152,10 +152,11 @@
static bool canBecomeGetArrayLength(Graph& graph, Node* node)
{
- if (node->op() != GetById)
- return false;
- auto uid = graph.identifiers()[node->identifierNumber()];
- return uid == graph.m_vm.propertyNames->length.impl();
+ if (node->op() == GetById || node->op() == PureGetById) {
+ auto uid = graph.identifiers()[node->identifierNumber()];
+ return uid == graph.m_vm.propertyNames->length.impl();
+ }
+ return false;
}
ArrayMode ArrayMode::refine(
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -3307,10 +3307,19 @@
}
NodeType getById;
- if (type == AccessType::Get)
+ switch (type) {
+ case AccessType::Get:
getById = getByIdStatus.makesCalls() ? GetByIdFlush : GetById;
- else
+ break;
+ case AccessType::TryGet:
getById = TryGetById;
+ break;
+ case AccessType::PureGet:
+ getById = PureGetById;
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
// Special path for custom accessors since custom's offset does not have any meanings.
// So, this is completely different from Simple one. But we have a chance to optimize it when we use DOMJIT.
@@ -4198,7 +4207,8 @@
Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
- bool compiledAsGetById = false;
+ bool compileAsGetById = false;
+ bool compileAsPureGetById = false;
GetByIdStatus getByIdStatus;
unsigned identifierNumber = 0;
{
@@ -4207,7 +4217,8 @@
// FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
// At that time, there is no information.
if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent) && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
- compiledAsGetById = true;
+ compileAsGetById = true;
+ compileAsPureGetById = !byValInfo->stubInfo->didSideEffects;
identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl());
UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
@@ -4225,9 +4236,10 @@
}
}
- if (compiledAsGetById)
- handleGetById(currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus, AccessType::Get, OPCODE_LENGTH(op_get_by_val));
- else {
+ if (compileAsGetById) {
+ AccessType type = compileAsPureGetById ? AccessType::PureGet : AccessType::Get;
+ handleGetById(currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus, type, OPCODE_LENGTH(op_get_by_val));
+ } else {
ArrayMode arrayMode = getArrayMode(currentInstruction[4].u.arrayProfile, Array::Read);
Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property);
m_exitOK = false; // GetByVal must be treated as if it clobbers exit state, since FixupPhase may make it generic.
@@ -4363,7 +4375,18 @@
m_inlineStackTop->m_profiledBlock, m_dfgCodeBlock,
m_inlineStackTop->m_stubInfos, m_dfgStubInfos,
currentCodeOrigin(), uid);
- AccessType type = op_try_get_by_id == opcodeID ? AccessType::GetPure : AccessType::Get;
+ AccessType type;
+ if (opcodeID == op_try_get_by_id)
+ type = AccessType::TryGet;
+ else {
+ ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
+ unsigned bytecodeIndex = currentCodeOrigin().bytecodeIndex;
+ StructureStubInfo* info = m_inlineStackTop->m_stubInfos.get(CodeOrigin(bytecodeIndex));
+ if (info && info->everConsidered && !info->didSideEffects)
+ type = AccessType::PureGet;
+ else
+ type = AccessType::Get;
+ }
unsigned opcodeLength = opcodeID == op_try_get_by_id ? OPCODE_LENGTH(op_try_get_by_id) : OPCODE_LENGTH(op_get_by_id);
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -495,6 +495,35 @@
def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), LazyNode(node));
return;
+ case PureGetById: {
+ // We model what is allowed inside a getOwnPropertySlot(VMInquiry) here.
+ // Some getOwnPropertySlot implementations will lazily inject properties, which
+ // may change the object's structure.
+
+ read(JSCell_structureID);
+ read(JSCell_typeInfoFlags);
+ read(JSCell_typeInfoType);
+ read(JSCell_indexingType);
+ read(JSObject_butterfly);
+ read(MiscFields);
+
+ AbstractHeap propertyNameHeap(NamedProperties, node->identifierNumber());
+ read(propertyNameHeap);
+
+ write(JSCell_structureID);
+ write(JSCell_typeInfoFlags);
+
+ write(Watchpoint_fire);
+ write(MiscFields);
+
+ // This can happen if lazily adding fields to an object happens in getOwnPropertySlot
+ // and we need to allocate out of line storage.
+ write(JSObject_butterfly);
+
+ def(HeapLocation(NamedPropertyLoc, propertyNameHeap, node->child1()), LazyNode(node));
+ return;
+ }
+
case GetById:
case GetByIdFlush:
case GetByIdWithThis:
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -448,6 +448,7 @@
break;
}
+ case PureGetById:
case GetById:
case GetByIdFlush: {
Edge childEdge = node->child1();
@@ -459,6 +460,9 @@
m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
alreadyHandled = true; // Don't allow the default constant folder to do things to this.
+ if (!Options::useAccessInlining())
+ break;
+
if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
|| (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
break;
@@ -514,6 +518,9 @@
m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
alreadyHandled = true; // Don't allow the default constant folder to do things to this.
+ if (!Options::useAccessInlining())
+ break;
+
if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -264,6 +264,7 @@
case ResolveScope:
return false;
+ case PureGetById: // We are modeling getOwnPropertySlot here, which may GC because it is allowed to allocate things.
case CreateActivation:
case CreateDirectArguments:
case CreateScopedArguments:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -1167,6 +1167,7 @@
break;
}
+ case PureGetById:
case GetById:
case GetByIdFlush: {
// FIXME: This should be done in the ByteCodeParser based on reading the
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -532,7 +532,7 @@
void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
{
- ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
+ ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == PureGetById || m_op == MultiGetByOffset);
m_opInfo = &data;
children.setChild1(storage);
children.setChild2(base);
@@ -542,7 +542,7 @@
void convertToMultiGetByOffset(MultiGetByOffsetData* data)
{
- ASSERT(m_op == GetById || m_op == GetByIdFlush);
+ ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == PureGetById);
m_opInfo = data;
child1().setUseKind(CellUse);
m_op = MultiGetByOffset;
@@ -918,6 +918,7 @@
switch (op()) {
case TryGetById:
case GetById:
+ case PureGetById:
case GetByIdFlush:
case GetByIdWithThis:
case PutById:
@@ -1428,6 +1429,7 @@
case ArithCeil:
case ArithTrunc:
case GetDirectPname:
+ case PureGetById:
case GetById:
case GetByIdFlush:
case GetByIdWithThis:
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -185,6 +185,7 @@
macro(PutByVal, NodeMustGenerate | NodeHasVarArgs) \
macro(PutByValAlias, NodeMustGenerate | NodeHasVarArgs) \
macro(TryGetById, NodeResultJS) \
+ macro(PureGetById, NodeResultJS | NodeMustGenerate) \
macro(GetById, NodeResultJS | NodeMustGenerate) \
macro(GetByIdFlush, NodeResultJS | NodeMustGenerate) \
macro(GetByIdWithThis, NodeResultJS | NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -682,6 +682,7 @@
case RegExpTest:
case StringReplace:
case StringReplaceRegExp:
+ case PureGetById:
case GetById:
case GetByIdFlush:
case GetByIdWithThis:
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -199,6 +199,7 @@
case TryGetById:
case DeleteById:
case DeleteByVal:
+ case PureGetById:
case GetById:
case GetByIdWithThis:
case GetByValWithThis:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -1003,7 +1003,7 @@
base.use();
- cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::GetPure);
+ cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::TryGet);
jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
break;
@@ -1020,7 +1020,7 @@
JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
- cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, NeedToSpill, AccessType::GetPure);
+ cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, NeedToSpill, AccessType::TryGet);
jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
break;
@@ -1032,6 +1032,42 @@
}
}
+void SpeculativeJIT::compilePureGetById(Node* node)
+{
+ ASSERT(node->op() == PureGetById);
+
+ switch (node->child1().useKind()) {
+ case CellUse: {
+ SpeculateCellOperand base(this, node->child1());
+ JSValueRegsTemporary result(this, Reuse, base);
+
+ JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
+ JSValueRegs resultRegs = result.regs();
+
+ cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::PureGet);
+
+ jsValueResult(resultRegs, node);
+ break;
+ }
+ case UntypedUse: {
+ JSValueOperand base(this, node->child1());
+ JSValueRegsTemporary result(this, Reuse, base);
+
+ JSValueRegs baseRegs = base.jsValueRegs();
+ JSValueRegs resultRegs = result.regs();
+
+ JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
+
+ cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, NeedToSpill, AccessType::PureGet);
+
+ jsValueResult(resultRegs, node);
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+}
+
void SpeculativeJIT::compileIn(Node* node)
{
SpeculateCellOperand base(this, node->child2());
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -721,6 +721,7 @@
void compileDeleteById(Node*);
void compileDeleteByVal(Node*);
void compileTryGetById(Node*);
+ void compilePureGetById(Node*);
void compileIn(Node*);
void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -210,6 +210,8 @@
J_JITOperation_ESsiJI getByIdFunction;
if (type == AccessType::Get)
getByIdFunction = operationGetByIdOptimize;
+ else if (type == AccessType::PureGet)
+ getByIdFunction = operationPureGetByIdOptimize;
else
getByIdFunction = operationTryGetByIdOptimize;
@@ -4269,6 +4271,11 @@
break;
}
+ case PureGetById: {
+ compilePureGetById(node);
+ break;
+ }
+
case GetByIdWithThis: {
JSValueOperand base(this, node->child1());
JSValueRegs baseRegs = base.jsValueRegs();
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -179,8 +179,11 @@
slowCases.append(slowPathTarget);
slowCases.append(gen.slowPathJump());
+ auto slowPathFunction = type == AccessType::Get ? operationGetByIdOptimize :
+ type == AccessType::PureGet ? operationPureGetByIdOptimize : operationTryGetByIdOptimize;
+
auto slowPath = slowPathCall(
- slowCases, this, type == AccessType::Get ? operationGetByIdOptimize : operationTryGetByIdOptimize,
+ slowCases, this, slowPathFunction,
spillMode, ExceptionCheckRequirement::CheckNeeded,
resultGPR, gen.stubInfo(), baseGPR, identifierUID(identifierNumber));
@@ -4235,6 +4238,11 @@
break;
}
+ case PureGetById: {
+ compilePureGetById(node);
+ break;
+ }
+
case GetByIdFlush: {
if (!node->prediction()) {
terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -176,6 +176,7 @@
case NewArrayWithSize:
case TryGetById:
case GetById:
+ case PureGetById:
case GetByIdFlush:
case GetByIdWithThis:
case ToThis:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -623,8 +623,11 @@
compilePutStructure();
break;
case TryGetById:
- compileGetById(AccessType::GetPure);
+ compileGetById(AccessType::TryGet);
break;
+ case PureGetById:
+ compileGetById(AccessType::PureGet);
+ break;
case GetById:
case GetByIdFlush:
compileGetById(AccessType::Get);
@@ -2788,7 +2791,7 @@
void compileGetById(AccessType type)
{
- ASSERT(type == AccessType::Get || type == AccessType::GetPure);
+ ASSERT(type == AccessType::Get || type == AccessType::TryGet || type == AccessType::PureGet);
switch (m_node->child1().useKind()) {
case CellUse: {
setJSValue(getById(lowCell(m_node->child1()), type));
@@ -2815,6 +2818,8 @@
J_JITOperation_EJI getByIdFunction;
if (type == AccessType::Get)
getByIdFunction = operationGetByIdGeneric;
+ else if (type == AccessType::PureGet)
+ getByIdFunction = operationPureGetByIdGeneric;
else
getByIdFunction = operationTryGetByIdGeneric;
@@ -8838,6 +8843,8 @@
J_JITOperation_ESsiJI optimizationFunction;
if (type == AccessType::Get)
optimizationFunction = operationGetByIdOptimize;
+ else if (type == AccessType::PureGet)
+ optimizationFunction = operationPureGetByIdOptimize;
else
optimizationFunction = operationTryGetByIdOptimize;
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -70,6 +70,35 @@
namespace JSC {
+ALWAYS_INLINE static EncodedJSValue pureGetByIdCommon(VM& vm, ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid, const std::function<void (const PropertySlot&, const Identifier&)>& function = [] (const PropertySlot&, const Identifier&) { })
+{
+ Identifier ident = Identifier::fromUid(&vm, uid);
+ JSValue baseValue = JSValue::decode(base);
+
+ ASSERT(JITCode::isOptimizingJIT(exec->codeBlock()->jitType()));
+
+ PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry);
+ return JSValue::encode(baseValue.getPropertySlot(exec, ident, slot, [&] (bool, PropertySlot&) -> JSValue {
+ bool willDoSideEffects = !(slot.isValue() || slot.isUnset()) || slot.isTaintedByOpaqueObject();
+ if (UNLIKELY(willDoSideEffects)) {
+ {
+ CodeOrigin codeOrigin = exec->codeOrigin();
+ CodeBlock* currentBaseline = baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, exec->codeBlock()->alternative());
+ CodeOrigin originBytecodeIndex = CodeOrigin(codeOrigin.bytecodeIndex); // Since we're searching in the baseline, we just care about bytecode index.
+ ConcurrentJITLocker locker(currentBaseline->m_lock);
+ if (StructureStubInfo* stub = currentBaseline->findStubInfo(originBytecodeIndex))
+ stub->didSideEffects = true;
+ }
+
+ exec->codeBlock()->jettison(Profiler::JettisonDueToPureGetByIdEffects);
+ return baseValue.get(exec, uid);
+ }
+
+ function(slot, ident);
+ return slot.isValue() ? slot.getValue(exec, ident) : jsUndefined();
+ }));
+}
+
extern "C" {
#if COMPILER(MSVC)
@@ -165,6 +194,38 @@
return missingArgCount;
}
+EncodedJSValue JIT_OPERATION operationPureGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ return pureGetByIdCommon(*vm, exec, base, uid);
+}
+
+EncodedJSValue JIT_OPERATION operationPureGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ stubInfo->tookSlowPath = true;
+
+ return pureGetByIdCommon(*vm, exec, base, uid);
+}
+
+EncodedJSValue JIT_OPERATION operationPureGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ return pureGetByIdCommon(*vm, exec, base, uid,
+ [&] (const PropertySlot& slot, const Identifier& ident) {
+ ASSERT((slot.isValue() || slot.isUnset()) && !slot.isTaintedByOpaqueObject());
+ JSValue baseValue = JSValue::decode(base);
+ if (stubInfo->considerCaching(baseValue.structureOrNull()))
+ repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
+ });
+}
+
EncodedJSValue JIT_OPERATION operationTryGetById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
@@ -179,7 +240,6 @@
return JSValue::encode(slot.getPureResult());
}
-
EncodedJSValue JIT_OPERATION operationTryGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
{
VM* vm = &exec->vm();
@@ -207,7 +267,7 @@
RETURN_IF_EXCEPTION(scope, encodedJSValue());
if (stubInfo->considerCaching(baseValue.structureOrNull()) && !slot.isTaintedByOpaqueObject() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
- repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Pure);
+ repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Try);
return JSValue::encode(slot.getPureResult());
}
@@ -226,7 +286,10 @@
Identifier ident = Identifier::fromUid(vm, uid);
LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(), ident));
- return JSValue::encode(baseValue.get(exec, ident, slot));
+ JSValue result = baseValue.get(exec, ident, slot);
+ bool willDoSideEffects = !(slot.isValue() || slot.isUnset()) || slot.isTaintedByOpaqueObject();
+ stubInfo->didSideEffects |= willDoSideEffects;
+ return JSValue::encode(result);
}
EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
@@ -255,6 +318,9 @@
LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(), ident));
return JSValue::encode(baseValue.getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
+ bool willDoSideEffects = !(slot.isValue() || slot.isUnset()) || slot.isTaintedByOpaqueObject();
+ stubInfo->didSideEffects |= willDoSideEffects;
+
if (stubInfo->considerCaching(baseValue.structureOrNull()))
repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
return found ? slot.getValue(exec, ident) : jsUndefined();
Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (208116 => 208117)
--- trunk/Source/_javascript_Core/jit/JITOperations.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -330,6 +330,9 @@
EncodedJSValue JIT_OPERATION operationTryGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationTryGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationTryGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationPureGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationPureGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationPureGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationGetById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -579,7 +579,7 @@
JITGetByIdGenerator gen(
m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
- ident->impl(), JSValueRegs(regT0), JSValueRegs(regT0), AccessType::GetPure);
+ ident->impl(), JSValueRegs(regT0), JSValueRegs(regT0), AccessType::TryGet);
gen.generateFastPath(*this);
addSlowCase(gen.slowPathJump());
m_getByIds.append(gen);
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -594,7 +594,7 @@
JITGetByIdGenerator gen(
m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
- ident->impl(), JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::GetPure);
+ ident->impl(), JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), AccessType::TryGet);
gen.generateFastPath(*this);
addSlowCase(gen.slowPathJump());
m_getByIds.append(gen);
Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/jit/Repatch.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -134,16 +134,34 @@
inline J_JITOperation_ESsiJI appropriateOptimizingGetByIdFunction(GetByIDKind kind)
{
- if (kind == GetByIDKind::Normal)
+ switch (kind) {
+ case GetByIDKind::Normal:
return operationGetByIdOptimize;
- return operationTryGetByIdOptimize;
+ case GetByIDKind::Try:
+ return operationTryGetByIdOptimize;
+ case GetByIDKind::Pure:
+ return operationPureGetByIdOptimize;
+ default:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return operationGetByIdOptimize;
}
inline J_JITOperation_ESsiJI appropriateGenericGetByIdFunction(GetByIDKind kind)
{
- if (kind == GetByIDKind::Normal)
+ switch (kind) {
+ case GetByIDKind::Normal:
return operationGetById;
- return operationTryGetById;
+ case GetByIDKind::Try:
+ return operationTryGetById;
+ case GetByIDKind::Pure:
+ return operationPureGetById;
+ default:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return operationGetById;
}
static InlineCacheAction tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo, GetByIDKind kind)
@@ -271,6 +289,16 @@
type = AccessCase::Load;
else if (slot.isUnset())
type = AccessCase::Miss;
+ else
+ RELEASE_ASSERT_NOT_REACHED();
+
+ newCase = AccessCase::tryGet(vm, codeBlock, type, offset, structure, conditionSet, loadTargetFromProxy, slot.watchpointSet());
+ } else if (kind == GetByIDKind::Try) {
+ AccessCase::AccessType type;
+ if (slot.isCacheableValue())
+ type = AccessCase::Load;
+ else if (slot.isUnset())
+ type = AccessCase::Miss;
else if (slot.isCacheableGetter())
type = AccessCase::GetGetter;
else
Modified: trunk/Source/_javascript_Core/jit/Repatch.h (208116 => 208117)
--- trunk/Source/_javascript_Core/jit/Repatch.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/jit/Repatch.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -36,6 +36,7 @@
enum class GetByIDKind {
Normal,
+ Try,
Pure
};
Modified: trunk/Source/_javascript_Core/profiler/ProfilerJettisonReason.cpp (208116 => 208117)
--- trunk/Source/_javascript_Core/profiler/ProfilerJettisonReason.cpp 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/profiler/ProfilerJettisonReason.cpp 2016-10-30 01:38:22 UTC (rev 208117)
@@ -56,6 +56,9 @@
case JettisonDueToOSRExit:
out.print("OSRExit");
return;
+ case JettisonDueToPureGetByIdEffects:
+ out.print("PureGetByIdEffects");
+ return;
case JettisonDueToProfiledWatchpoint:
out.print("ProfiledWatchpoint");
return;
Modified: trunk/Source/_javascript_Core/profiler/ProfilerJettisonReason.h (208116 => 208117)
--- trunk/Source/_javascript_Core/profiler/ProfilerJettisonReason.h 2016-10-29 22:34:43 UTC (rev 208116)
+++ trunk/Source/_javascript_Core/profiler/ProfilerJettisonReason.h 2016-10-30 01:38:22 UTC (rev 208117)
@@ -35,6 +35,7 @@
JettisonDueToBaselineLoopReoptimizationTrigger,
JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail,
JettisonDueToOSRExit,
+ JettisonDueToPureGetByIdEffects,
JettisonDueToProfiledWatchpoint,
JettisonDueToUnprofiledWatchpoint,
JettisonDueToOldAge