WebKit Bugzilla
Attachment 341542 Details for
Bug 164904
: We should support CreateThis in the FTL
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
more
blah.patch (text/plain), 80.95 KB, created by
Filip Pizlo
on 2018-05-29 17:18:17 PDT
(
hide
)
Description:
more
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2018-05-29 17:18:17 PDT
Size:
80.95 KB
patch
obsolete
>Index: Source/JavaScriptCore/bytecode/ByValInfo.h >=================================================================== >--- Source/JavaScriptCore/bytecode/ByValInfo.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/ByValInfo.h (working copy) >@@ -266,12 +266,6 @@ inline unsigned getByValInfoBytecodeInde > return info->bytecodeIndex; > } > >-typedef HashMap<CodeOrigin, ByValInfo*, CodeOriginApproximateHash> ByValInfoMap; >- >-#else // ENABLE(JIT) >- >-typedef HashMap<int, void*> ByValInfoMap; >- > #endif // ENABLE(JIT) > > } // namespace JSC >Index: Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeDumper.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/BytecodeDumper.cpp (working copy) >@@ -1,6 +1,6 @@ > /* > * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com> >- * Copyright (C) 2017 Apple Inc. All rights reserved. >+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -427,7 +427,7 @@ static void dumpChain(PrintStream& out, > } > > template<class Block> >-void BytecodeDumper<Block>::printGetByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map) >+void BytecodeDumper<Block>::printGetByIdCacheStatus(PrintStream& out, int location, const ICStatusMap& statusMap) > { > const auto* instruction = instructionsBegin() + location; > >@@ -447,7 +447,7 @@ void BytecodeDumper<Block>::printGetById > } > > #if ENABLE(JIT) >- if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) { >+ if (StructureStubInfo* stubPtr = statusMap.get(CodeOrigin(location)).stubInfo) { > StructureStubInfo& stubInfo = *stubPtr; > if (stubInfo.resetByGC) > out.print(" (Reset By GC)"); >@@ -488,12 +488,12 @@ void BytecodeDumper<Block>::printGetById > out.printf(")"); > } > #else >- UNUSED_PARAM(map); >+ UNUSED_PARAM(statusMap); > #endif > } > > template<class Block> >-void BytecodeDumper<Block>::printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map) >+void BytecodeDumper<Block>::printPutByIdCacheStatus(PrintStream& out, int location, const ICStatusMap& statusMap) > { > const auto* instruction = instructionsBegin() + location; > >@@ -521,7 +521,7 @@ void BytecodeDumper<Block>::printPutById > } > > #if ENABLE(JIT) >- if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) { >+ if (StructureStubInfo* stubPtr = statusMap.get(CodeOrigin(location)).stubInfo) { > StructureStubInfo& stubInfo = *stubPtr; > if (stubInfo.resetByGC) > out.print(" (Reset By GC)"); >@@ -547,12 +547,12 @@ void BytecodeDumper<Block>::printPutById > out.printf(")"); > } > #else >- UNUSED_PARAM(map); >+ UNUSED_PARAM(statusMap); > #endif > } > > template<class Block> >-void BytecodeDumper<Block>::printInByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map) >+void BytecodeDumper<Block>::printInByIdCacheStatus(PrintStream& out, int location, const ICStatusMap& statusMap) > { > const auto* instruction = instructionsBegin() + location; > >@@ -561,7 +561,7 @@ void BytecodeDumper<Block>::printInByIdC > UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations. > > #if ENABLE(JIT) >- if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) { >+ if (StructureStubInfo* stubPtr = statusMap.get(CodeOrigin(location)).stubInfo) { > StructureStubInfo& stubInfo = *stubPtr; > if (stubInfo.resetByGC) > out.print(" (Reset By GC)"); >@@ -600,26 +600,26 @@ void BytecodeDumper<Block>::printInByIdC > } > #else > UNUSED_PARAM(out); >- UNUSED_PARAM(map); >+ UNUSED_PARAM(statusMap); > #endif > } > > #if ENABLE(JIT) > template<typename Block> >-void BytecodeDumper<Block>::dumpCallLinkStatus(PrintStream&, unsigned, const CallLinkInfoMap&) >+void BytecodeDumper<Block>::dumpCallLinkStatus(PrintStream&, unsigned, const ICStatusMap&) > { > } > > template<> >-void BytecodeDumper<CodeBlock>::dumpCallLinkStatus(PrintStream& out, unsigned location, const CallLinkInfoMap& map) >+void BytecodeDumper<CodeBlock>::dumpCallLinkStatus(PrintStream& out, unsigned location, const ICStatusMap& statusMap) > { > if (block()->jitType() != JITCode::FTLJIT) >- out.print(" status(", CallLinkStatus::computeFor(block(), location, map), ")"); >+ out.print(" status(", CallLinkStatus::computeFor(block(), location, statusMap), ")"); > } > #endif > > template<class Block> >-void BytecodeDumper<Block>::printCallOp(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap& map) >+void BytecodeDumper<Block>::printCallOp(PrintStream& out, int location, const typename Block::Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const ICStatusMap& statusMap) > { > int dst = (++it)->u.operand; > int func = (++it)->u.operand; >@@ -638,7 +638,7 @@ void BytecodeDumper<Block>::printCallOp( > out.printf(" llint(%p)", object); > } > #if ENABLE(JIT) >- if (CallLinkInfo* info = map.get(CodeOrigin(location))) { >+ if (CallLinkInfo* info = statusMap.get(CodeOrigin(location)).callLinkInfo) { > if (info->haveLastSeenCallee()) { > JSObject* object = info->lastSeenCallee(); > if (auto* function = jsDynamicCast<JSFunction*>(*vm(), object)) >@@ -648,9 +648,9 @@ void BytecodeDumper<Block>::printCallOp( > } > } > >- dumpCallLinkStatus(out, location, map); >+ dumpCallLinkStatus(out, location, statusMap); > #else >- UNUSED_PARAM(map); >+ UNUSED_PARAM(statusMap); > #endif > } > ++it; >@@ -678,7 +678,7 @@ void BytecodeDumper<Block>::printLocatio > } > > template<class Block> >-void BytecodeDumper<Block>::dumpBytecode(PrintStream& out, const typename Block::Instruction* begin, const typename Block::Instruction*& it, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos) >+void BytecodeDumper<Block>::dumpBytecode(PrintStream& out, const typename Block::Instruction* begin, const typename Block::Instruction*& it, const ICStatusMap& statusMap) > { > int location = it - begin; > bool hasPrintedProfiling = false; >@@ -1071,7 +1071,7 @@ void BytecodeDumper<Block>::dumpBytecode > int id0 = (++it)->u.operand; > printLocationAndOp(out, location, it, "in_by_id"); > out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data()); >- printInByIdCacheStatus(out, location, stubInfos); >+ printInByIdCacheStatus(out, location, statusMap); > break; > } > case op_in_by_val: { >@@ -1095,7 +1095,7 @@ void BytecodeDumper<Block>::dumpBytecode > printLocationAndOp(out, location, it, "get_by_id_direct"); > out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data()); > it += 2; // Increment up to the value profiler. >- printGetByIdCacheStatus(out, location, stubInfos); >+ printGetByIdCacheStatus(out, location, statusMap); > dumpValueProfiling(out, it, hasPrintedProfiling); > break; > } >@@ -1104,7 +1104,7 @@ void BytecodeDumper<Block>::dumpBytecode > case op_get_by_id_unset: > case op_get_array_length: { > printGetByIdOp(out, location, it); >- printGetByIdCacheStatus(out, location, stubInfos); >+ printGetByIdCacheStatus(out, location, statusMap); > dumpValueProfiling(out, it, hasPrintedProfiling); > break; > } >@@ -1130,7 +1130,7 @@ void BytecodeDumper<Block>::dumpBytecode > } > case op_put_by_id: { > printPutByIdOp(out, location, it, "put_by_id"); >- printPutByIdCacheStatus(out, location, stubInfos); >+ printPutByIdCacheStatus(out, location, statusMap); > break; > } > case op_put_by_id_with_this: { >@@ -1476,15 +1476,15 @@ void BytecodeDumper<Block>::dumpBytecode > break; > } > case op_call: { >- printCallOp(out, location, it, "call", DumpCaches, hasPrintedProfiling, callLinkInfos); >+ printCallOp(out, location, it, "call", DumpCaches, hasPrintedProfiling, statusMap); > break; > } > case op_tail_call: { >- printCallOp(out, location, it, "tail_call", DumpCaches, hasPrintedProfiling, callLinkInfos); >+ printCallOp(out, location, it, "tail_call", DumpCaches, hasPrintedProfiling, statusMap); > break; > } > case op_call_eval: { >- printCallOp(out, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, callLinkInfos); >+ printCallOp(out, location, it, "call_eval", DontDumpCaches, hasPrintedProfiling, statusMap); > break; > } > >@@ -1523,7 +1523,7 @@ void BytecodeDumper<Block>::dumpBytecode > break; > } > case op_construct: { >- printCallOp(out, location, it, "construct", DumpCaches, hasPrintedProfiling, callLinkInfos); >+ printCallOp(out, location, it, "construct", DumpCaches, hasPrintedProfiling, statusMap); > break; > } > case op_strcat: { >@@ -1778,10 +1778,10 @@ void BytecodeDumper<Block>::dumpBytecode > } > > template<class Block> >-void BytecodeDumper<Block>::dumpBytecode(Block* block, PrintStream& out, const typename Block::Instruction* begin, const typename Block::Instruction*& it, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos) >+void BytecodeDumper<Block>::dumpBytecode(Block* block, PrintStream& out, const typename Block::Instruction* begin, const typename Block::Instruction*& it, const ICStatusMap& statusMap) > { > BytecodeDumper dumper(block, begin); >- dumper.dumpBytecode(out, begin, it, stubInfos, callLinkInfos); >+ dumper.dumpBytecode(out, begin, it, statusMap); > } > > template<class Block> >@@ -1890,7 +1890,7 @@ void BytecodeDumper<Block>::dumpStringSw > } > > template<class Block> >-void BytecodeDumper<Block>::dumpBlock(Block* block, const typename Block::UnpackedInstructions& instructions, PrintStream& out, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos) >+void BytecodeDumper<Block>::dumpBlock(Block* block, const typename Block::UnpackedInstructions& instructions, PrintStream& out, const ICStatusMap& statusMap) > { > size_t instructionCount = 0; > >@@ -1910,7 +1910,7 @@ void BytecodeDumper<Block>::dumpBlock(Bl > const auto* end = instructions.end(); > BytecodeDumper<Block> dumper(block, begin); > for (const auto* it = begin; it != end; ++it) >- dumper.dumpBytecode(out, begin, it, stubInfos, callLinkInfos); >+ dumper.dumpBytecode(out, begin, it, statusMap); > > dumper.dumpIdentifiers(out); > dumper.dumpConstants(out); >Index: Source/JavaScriptCore/bytecode/BytecodeDumper.h >=================================================================== >--- Source/JavaScriptCore/bytecode/BytecodeDumper.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/BytecodeDumper.h (working copy) >@@ -1,5 +1,6 @@ > /* > * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com> >+ * Copyright (C) 2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -26,6 +27,7 @@ > #pragma once > > #include "CallLinkInfo.h" >+#include "ICStatusMap.h" > #include "StructureStubInfo.h" > > namespace JSC { >@@ -37,8 +39,8 @@ class BytecodeDumper { > public: > typedef typename Block::Instruction Instruction; > >- static void dumpBytecode(Block*, PrintStream& out, const Instruction* begin, const Instruction*& it, const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap()); >- static void dumpBlock(Block*, const typename Block::UnpackedInstructions&, PrintStream& out, const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap()); >+ static void dumpBytecode(Block*, PrintStream& out, const Instruction* begin, const Instruction*& it, const ICStatusMap& statusMap = ICStatusMap()); >+ static void dumpBlock(Block*, const typename Block::UnpackedInstructions&, PrintStream& out, const ICStatusMap& statusMap = ICStatusMap()); > > private: > BytecodeDumper(Block* block, const Instruction* instructionsBegin) >@@ -69,14 +71,14 @@ private: > void printConditionalJump(PrintStream& out, const Instruction*, const Instruction*& it, int location, const char* op); > void printCompareJump(PrintStream& out, const Instruction*, const Instruction*& it, int location, const char* op); > void printGetByIdOp(PrintStream& out, int location, const Instruction*& it); >- void printGetByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&); >- void printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&); >- void printInByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&); >+ void printGetByIdCacheStatus(PrintStream& out, int location, const ICStatusMap&); >+ void printPutByIdCacheStatus(PrintStream& out, int location, const ICStatusMap&); >+ void printInByIdCacheStatus(PrintStream& out, int location, const ICStatusMap&); > enum CacheDumpMode { DumpCaches, DontDumpCaches }; >- void printCallOp(PrintStream& out, int location, const Instruction*& it, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&); >+ void printCallOp(PrintStream& out, int location, const Instruction*& it, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const ICStatusMap&); > void printPutByIdOp(PrintStream& out, int location, const Instruction*& it, const char* op); > void printLocationOpAndRegisterOperand(PrintStream& out, int location, const Instruction*& it, const char* op, int operand); >- void dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const StubInfoMap&, const CallLinkInfoMap&); >+ void dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const ICStatusMap&); > > void dumpValueProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling); > void dumpArrayProfiling(PrintStream&, const Instruction*&, bool& hasPrintedProfiling); >@@ -85,7 +87,7 @@ private: > void* actualPointerFor(Special::Pointer) const; > > #if ENABLE(JIT) >- void dumpCallLinkStatus(PrintStream&, unsigned location, const CallLinkInfoMap&); >+ void dumpCallLinkStatus(PrintStream&, unsigned location, const ICStatusMap&); > #endif > > Block* m_block; >Index: Source/JavaScriptCore/bytecode/CallLinkInfo.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CallLinkInfo.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/CallLinkInfo.h (working copy) >@@ -352,12 +352,6 @@ inline CodeOrigin getCallLinkInfoCodeOri > return callLinkInfo.codeOrigin(); > } > >-typedef HashMap<CodeOrigin, CallLinkInfo*, CodeOriginApproximateHash> CallLinkInfoMap; >- >-#else // ENABLE(JIT) >- >-typedef HashMap<int, void*> CallLinkInfoMap; >- > #endif // ENABLE(JIT) > > } // namespace JSC >Index: Source/JavaScriptCore/bytecode/CallLinkStatus.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/CallLinkStatus.cpp (working copy) >@@ -297,8 +297,16 @@ void CallLinkStatus::computeDFGStatuses( > > CallLinkStatus CallLinkStatus::computeFor( > CodeBlock* profiledBlock, CodeOrigin codeOrigin, >- const CallLinkInfoMap& baselineMap, const CallLinkStatus::ContextMap& dfgMap) >+ const ICStatusMap& baselineMap, const ICStatusContextStack& optimizedStack) > { >+ // FIXME: This needs to get the exit site data. That data should include whether the exit was >+ // inlined or not. >+ for (const ICStatusContext& context : optimizedStack) { >+ ICStatus status = context.get(codeOrigin); >+ if (status.callLinkInfo) { >+ // FIXME: Do things here. >+ } >+ } > auto iter = dfgMap.find(codeOrigin); > if (iter != dfgMap.end()) > return iter->value; >@@ -327,6 +335,15 @@ void CallLinkStatus::makeClosureCall() > m_variants = despecifiedVariantList(m_variants); > } > >+bool CallLinkStatus::finalize() >+{ >+ for (CallVariant& variant : m_variants) { >+ if (!variant.finalize()) >+ return false; >+ } >+ return true; >+} >+ > void CallLinkStatus::dump(PrintStream& out) const > { > if (!isSet()) { >Index: Source/JavaScriptCore/bytecode/CallLinkStatus.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CallLinkStatus.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/CallLinkStatus.h (working copy) >@@ -29,6 +29,7 @@ > #include "CallVariant.h" > #include "CodeOrigin.h" > #include "ConcurrentJSLock.h" >+#include "ICStatusMap.h" > #include "JSCJSValue.h" > > namespace JSC { >@@ -60,8 +61,7 @@ public: > { > } > >- static CallLinkStatus computeFor( >- CodeBlock*, unsigned bytecodeIndex, const CallLinkInfoMap&); >+ static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex, const ICStatusMap&); > > struct ExitSiteData { > bool takesSlowPath { false }; >@@ -77,16 +77,8 @@ public: > const ConcurrentJSLocker&, CodeBlock*, CallLinkInfo&, ExitSiteData); > #endif > >- typedef HashMap<CodeOrigin, CallLinkStatus, CodeOriginApproximateHash> ContextMap; >- >- // Computes all of the statuses of the DFG code block. Doesn't include statuses that had >- // no information. Currently we use this when compiling FTL code, to enable polyvariant >- // inlining. >- static void computeDFGStatuses(CodeBlock* dfgCodeBlock, ContextMap&); >- >- // Helper that first consults the ContextMap and then does computeFor(). > static CallLinkStatus computeFor( >- CodeBlock*, CodeOrigin, const CallLinkInfoMap&, const ContextMap&); >+ CodeBlock*, CodeOrigin, const ICStatusMap&, const ICStatusContextStack&); > > void setProvenConstantCallee(CallVariant); > >@@ -110,6 +102,8 @@ public: > > unsigned maxNumArguments() const { return m_maxNumArguments; } > >+ bool finalize(); >+ > void dump(PrintStream&) const; > > private: >Index: Source/JavaScriptCore/bytecode/CallVariant.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CallVariant.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/CallVariant.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -31,6 +31,13 @@ > > namespace JSC { > >+bool CallVariant::finalize() >+{ >+ if (m_callee && !Heap::isMarked(m_callee)) >+ return false; >+ return true; >+} >+ > void CallVariant::dump(PrintStream& out) const > { > if (!*this) { >Index: Source/JavaScriptCore/bytecode/CallVariant.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CallVariant.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/CallVariant.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -136,6 +136,8 @@ public: > return nullptr; > } > >+ bool finalize(); >+ > void dump(PrintStream& out) const; > > bool isHashTableDeletedValue() const >Index: Source/JavaScriptCore/bytecode/CodeBlock.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/CodeBlock.cpp (working copy) >@@ -238,24 +238,20 @@ void CodeBlock::dumpBytecode() > > void CodeBlock::dumpBytecode(PrintStream& out) > { >- StubInfoMap stubInfos; >- CallLinkInfoMap callLinkInfos; >- getStubInfoMap(stubInfos); >- getCallLinkInfoMap(callLinkInfos); >- BytecodeDumper<CodeBlock>::dumpBlock(this, instructions(), out, stubInfos, callLinkInfos); >+ ICStatusMap statusMap; >+ getICStatusMap(statusMap); >+ BytecodeDumper<CodeBlock>::dumpBlock(this, instructions(), out, statusMap); > } > >-void CodeBlock::dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos) >+void CodeBlock::dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const ICStatusMap& statusMap) > { >- BytecodeDumper<CodeBlock>::dumpBytecode(this, out, begin, it, stubInfos, callLinkInfos); >+ BytecodeDumper<CodeBlock>::dumpBytecode(this, out, begin, it, statusMap); > } > >-void CodeBlock::dumpBytecode( >- PrintStream& out, unsigned bytecodeOffset, >- const StubInfoMap& stubInfos, const CallLinkInfoMap& callLinkInfos) >+void CodeBlock::dumpBytecode(PrintStream& out, unsigned bytecodeOffset, const ICStatusMap& statusMap) > { > const Instruction* it = &instructions()[bytecodeOffset]; >- dumpBytecode(out, instructions().begin(), it, stubInfos, callLinkInfos); >+ dumpBytecode(out, instructions().begin(), it, statusMap); > } > > #define FOR_EACH_MEMBER_VECTOR(macro) \ >@@ -1166,6 +1162,9 @@ void CodeBlock::propagateTransitions(con > #if ENABLE(DFG_JIT) > if (JITCode::isOptimizingJIT(jitType())) { > DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); >+ >+ dfgCommon->recordedStatuses.markIfCheap(visitor); >+ > for (auto& weakReference : dfgCommon->weakStructureReferences) > weakReference->markIfCheap(visitor); > >@@ -1397,57 +1396,43 @@ void CodeBlock::finalizeUnconditionally( > finalizeBaselineJITInlineCaches(); > #endif > >- VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).remove(this); >-} >- >-void CodeBlock::getStubInfoMap(const ConcurrentJSLocker&, StubInfoMap& result) >-{ >-#if ENABLE(JIT) >- if (JITCode::isJIT(jitType())) >- toHashMap(m_stubInfos, getStructureStubInfoCodeOrigin, result); >-#else >- UNUSED_PARAM(result); >-#endif >-} >- >-void CodeBlock::getStubInfoMap(StubInfoMap& result) >-{ >- ConcurrentJSLocker locker(m_lock); >- getStubInfoMap(locker, result); >-} >- >-void CodeBlock::getCallLinkInfoMap(const ConcurrentJSLocker&, CallLinkInfoMap& result) >-{ >-#if ENABLE(JIT) >- if (JITCode::isJIT(jitType())) >- toHashMap(m_callLinkInfos, getCallLinkInfoCodeOrigin, result); >-#else >- UNUSED_PARAM(result); >-#endif >-} >+ if (JITCode::isOptimizingJIT(jitType())) { >+ DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); >+ dfgCommon->recordedStatuses.finalize(); >+ } > >-void CodeBlock::getCallLinkInfoMap(CallLinkInfoMap& result) >-{ >- ConcurrentJSLocker locker(m_lock); >- getCallLinkInfoMap(locker, result); >+ VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).remove(this); > } > >-void CodeBlock::getByValInfoMap(const ConcurrentJSLocker&, ByValInfoMap& result) >+void CodeBlock::getICStatusMap(const ConcurrentJSLocker&, ICStatusMap& result) > { > #if ENABLE(JIT) > if (JITCode::isJIT(jitType())) { >- for (auto* byValInfo : m_byValInfos) >- result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo); >+ for (StructureStubInfo* stubInfo : m_stubInfos) >+ result.add(stubInfo->codeOrigin, ICStatus()).iterator->value.stubInfo = stubInfo; >+ for (CallLinkInfo* callLinkInfo : m_callLinkInfos) >+ result.add(callLinkInfo->codeOrigin(), ICStatus()).iterator->value.callLinkInfo = callLinkInfo; >+ for (ByValInfo* byValInfo : m_balValInfos) >+ result.add(CodeOrigin(byValInfo->bytecodeIndex), ICStatus()).iterator->value.byValInfo = byValInfo; >+ if (JITCode::isOptimizingJIT(jitType())) { >+ DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); >+ for (auto& pair : dfgCommon->recordedStatuses.calls) >+ result.add(pair.first, ICStatus()).iterator->value.callStatus = pair.second.get(); >+ for (auto& pair : dfgCommon->recordedStatuses.gets) >+ result.add(pair.first, ICStatus()).iterator->value.getStatus = pair.second.get(); >+ for (auto& pair : dfgCommon->recordedStatuses.puts) >+ result.add(pair.first, ICStatus()).iterator->value.putStatus = pair.second.get(); >+ } > } > #else > UNUSED_PARAM(result); > #endif > } > >-void CodeBlock::getByValInfoMap(ByValInfoMap& result) >+void CodeBlock::getICStatusMap(ICStatusMap& result) > { > ConcurrentJSLocker locker(m_lock); >- getByValInfoMap(locker, result); >+ getICStatusMap(locker, result); > } > > #if ENABLE(JIT) >@@ -1514,7 +1499,7 @@ void CodeBlock::resetJITData() > > // We can clear these because no other thread will have references to any stub infos, call > // link infos, or by val infos if we don't have JIT code. Attempts to query these data >- // structures using the concurrent API (getStubInfoMap and friends) will return nothing if we >+ // structures using the concurrent API (getICStatusMap and friends) will return nothing if we > // don't have JIT code. > m_stubInfos.clear(); > m_callLinkInfos.clear(); >Index: Source/JavaScriptCore/bytecode/CodeBlock.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeBlock.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/CodeBlock.h (working copy) >@@ -45,6 +45,7 @@ > #include "ExpressionRangeInfo.h" > #include "FunctionExecutable.h" > #include "HandlerInfo.h" >+#include "ICStatusMap.h" > #include "Instruction.h" > #include "JITCode.h" > #include "JITCodeMap.h" >@@ -96,8 +97,6 @@ enum class AccessType : int8_t; > > struct ArithProfile; > >-typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap; >- > enum ReoptimizationMode { DontCountReoptimization, CountReoptimization }; > > class CodeBlock : public JSCell { >@@ -196,8 +195,8 @@ public: > > void dumpBytecode(); > void dumpBytecode(PrintStream&); >- void dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap()); >- void dumpBytecode(PrintStream& out, unsigned bytecodeOffset, const StubInfoMap& = StubInfoMap(), const CallLinkInfoMap& = CallLinkInfoMap()); >+ void dumpBytecode(PrintStream& out, const Instruction* begin, const Instruction*& it, const ICStatusMap& = ICStatusMap()); >+ void dumpBytecode(PrintStream& out, unsigned bytecodeOffset, const ICStatusMap& = ICStatusMap()); > > void dumpExceptionHandlers(PrintStream&); > void printStructures(PrintStream&, const Instruction*); >@@ -237,14 +236,8 @@ public: > > std::optional<unsigned> bytecodeOffsetFromCallSiteIndex(CallSiteIndex); > >- void getStubInfoMap(const ConcurrentJSLocker&, StubInfoMap& result); >- void getStubInfoMap(StubInfoMap& result); >- >- void getCallLinkInfoMap(const ConcurrentJSLocker&, CallLinkInfoMap& result); >- void getCallLinkInfoMap(CallLinkInfoMap& result); >- >- void getByValInfoMap(const ConcurrentJSLocker&, ByValInfoMap& result); >- void getByValInfoMap(ByValInfoMap& result); >+ void getICStatusMap(const ConcurrentJSLocker&, ICStatusMap& result); >+ void getICStatusMap(ICStatusMap& result); > > #if ENABLE(JIT) > JITAddIC* addJITAddIC(ArithProfile*, Instruction*); >Index: Source/JavaScriptCore/bytecode/CodeOrigin.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeOrigin.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/CodeOrigin.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012-2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2012-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -46,7 +46,7 @@ unsigned CodeOrigin::inlineDepth() const > return inlineDepthForCallFrame(inlineCallFrame); > } > >-bool CodeOrigin::isApproximatelyEqualTo(const CodeOrigin& other) const >+bool CodeOrigin::isApproximatelyEqualTo(const CodeOrigin& other, CodeBlock* terminal) const > { > CodeOrigin a = *this; > CodeOrigin b = other; >@@ -68,10 +68,13 @@ bool CodeOrigin::isApproximatelyEqualTo( > if (a.bytecodeIndex != b.bytecodeIndex) > return false; > >- if ((!!a.inlineCallFrame) != (!!b.inlineCallFrame)) >+ bool aHasInlineCallFrame = !!a.inlineCallFrame >+ && a.inlineCallFrame->baselineCodeBlock.get() != terminal; >+ bool bHasInlineCallFrame = !!b.inlineCallFrame; >+ if (aHasInlineCallFrame != bHasInlineCallFrame) > return false; > >- if (!a.inlineCallFrame) >+ if (!aHasInlineCallFrame) > return true; > > if (a.inlineCallFrame->baselineCodeBlock.get() != b.inlineCallFrame->baselineCodeBlock.get()) >@@ -82,7 +85,7 @@ bool CodeOrigin::isApproximatelyEqualTo( > } > } > >-unsigned CodeOrigin::approximateHash() const >+unsigned CodeOrigin::approximateHash(CodeBlock* terminal) const > { > if (!isSet()) > return 0; >@@ -97,6 +100,9 @@ unsigned CodeOrigin::approximateHash() c > if (!codeOrigin.inlineCallFrame) > return result; > >+ if (codeOrigin.inlineCallFrame->baselineCodeBlock.get() == terminal) >+ return result; >+ > result += WTF::PtrHash<JSCell*>::hash(codeOrigin.inlineCallFrame->baselineCodeBlock.get()); > > codeOrigin = codeOrigin.inlineCallFrame->directCaller; >Index: Source/JavaScriptCore/bytecode/CodeOrigin.h >=================================================================== >--- Source/JavaScriptCore/bytecode/CodeOrigin.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/CodeOrigin.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2011-2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -94,9 +94,9 @@ struct CodeOrigin { > > // 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; >+ bool isApproximatelyEqualTo(const CodeOrigin& other, CodeBlock* terminal = nullptr) const; > >- unsigned approximateHash() const; >+ unsigned approximateHash(CodeBlock* terminal = nullptr) const; > > template <typename Function> > void walkUpInlineStack(const Function&); >Index: Source/JavaScriptCore/bytecode/DFGExitProfile.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/DFGExitProfile.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/DFGExitProfile.cpp (working copy) >@@ -43,8 +43,10 @@ ExitProfile::~ExitProfile() { } > > bool ExitProfile::add(CodeBlock* owner, const FrequentExitSite& site) > { >+ RELEASE_ASSERT(site.jitType() != ExitFromAnything); >+ RELEASE_ASSERT(site.inlineKind() != ExitFromAnyInlineKind); >+ > ConcurrentJSLocker locker(owner->unlinkedCodeBlock()->m_lock); >- ASSERT(site.jitType() != ExitFromAnything); > > CODEBLOCK_LOG_EVENT(owner, "frequentExit", (site)); > >Index: Source/JavaScriptCore/bytecode/DFGExitProfile.h >=================================================================== >--- Source/JavaScriptCore/bytecode/DFGExitProfile.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/DFGExitProfile.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2011-2014, 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2011-2018 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,6 +29,7 @@ > > #include "ConcurrentJSLock.h" > #include "ExitKind.h" >+#include "ExitingInlineKind.h" > #include "ExitingJITType.h" > #include <wtf/HashSet.h> > #include <wtf/Vector.h> >@@ -41,6 +42,7 @@ public: > : m_bytecodeOffset(0) // 0 = empty value > , m_kind(ExitKindUnset) > , m_jitType(ExitFromAnything) >+ , m_inlineKind(ExitFromAnyInlineKind) > { > } > >@@ -48,13 +50,15 @@ public: > : m_bytecodeOffset(1) // 1 = deleted value > , m_kind(ExitKindUnset) > , m_jitType(ExitFromAnything) >+ , m_inlineKind(ExitFromAnyInlineKind) > { > } > >- explicit FrequentExitSite(unsigned bytecodeOffset, ExitKind kind, ExitingJITType jitType = ExitFromAnything) >+ explicit FrequentExitSite(unsigned bytecodeOffset, ExitKind kind, ExitingJITType jitType = ExitFromAnything, ExitingInlineKind inlineKind = ExitFromAnyInlineKind) > : m_bytecodeOffset(bytecodeOffset) > , m_kind(kind) > , m_jitType(jitType) >+ , m_inlineKind(inlineKind) > { > if (m_kind == ArgumentsEscaped) { > // Count this one globally. It doesn't matter where in the code block the arguments excaped; >@@ -65,10 +69,11 @@ public: > > // Use this constructor if you wish for the exit site to be counted globally within its > // code block. >- explicit FrequentExitSite(ExitKind kind, ExitingJITType jitType = ExitFromAnything) >+ explicit FrequentExitSite(ExitKind kind, ExitingJITType jitType = ExitFromAnything, ExitingInlineKind inlineKind = ExitFromAnyInlineKind) > : m_bytecodeOffset(0) > , m_kind(kind) > , m_jitType(jitType) >+ , m_inlineKind(inlineKind) > { > } > >@@ -81,7 +86,8 @@ public: > { > return m_bytecodeOffset == other.m_bytecodeOffset > && m_kind == other.m_kind >- && m_jitType == other.m_jitType; >+ && m_jitType == other.m_jitType >+ && m_inlineKind == other.m_inlineKind; > } > > bool subsumes(const FrequentExitSite& other) const >@@ -90,19 +96,24 @@ public: > return false; > if (m_kind != other.m_kind) > return false; >- if (m_jitType == ExitFromAnything) >- return true; >- return m_jitType == other.m_jitType; >+ if (m_jitType != ExitFromAnything >+ && m_jitType != other.m_jitType) >+ return false; >+ if (m_inlineKind != ExitFromAnyInlineKind >+ && m_inlineKind != other.m_inlineKind) >+ return false; >+ return true; > } > > unsigned hash() const > { >- return WTF::intHash(m_bytecodeOffset) + m_kind + static_cast<std::underlying_type_t<ExitingJITType>>(m_jitType) * 7; >+ return WTF::intHash(m_bytecodeOffset) + m_kind + static_cast<unsigned>(m_jitType) * 7 + static_cast<unsigned>(m_inlineKind) * 11; > } > > unsigned bytecodeOffset() const { return m_bytecodeOffset; } > ExitKind kind() const { return m_kind; } > ExitingJITType jitType() const { return m_jitType; } >+ ExitingInlineKind inlineKind() const { return m_inlineKind; } > > FrequentExitSite withJITType(ExitingJITType jitType) const > { >@@ -111,6 +122,13 @@ public: > return result; > } > >+ FrequentExitSite withInlineKind(ExitingInlineKind inlineKind) const >+ { >+ FrequentExitSite result = *this; >+ result.m_inlineKind = inlineKind; >+ return result; >+ } >+ > bool isHashTableDeletedValue() const > { > return m_kind == ExitKindUnset && m_bytecodeOffset; >@@ -122,6 +140,7 @@ private: > unsigned m_bytecodeOffset; > ExitKind m_kind; > ExitingJITType m_jitType; >+ ExitingInlineKind m_inlineKind; > }; > > struct FrequentExitSiteHash { >@@ -192,10 +211,10 @@ public: > bool hasExitSite(const FrequentExitSite& site) const > { > if (site.jitType() == ExitFromAnything) { >- return hasExitSite(site.withJITType(ExitFromDFG)) >- || hasExitSite(site.withJITType(ExitFromFTL)); >+ return hasExitSiteWithSpecificJITType(site.withJITType(ExitFromDFG)) >+ || hasExitSiteWithSpecificJITType(site.withJITType(ExitFromFTL)); > } >- return m_frequentExitSites.find(site) != m_frequentExitSites.end(); >+ return hasExitSiteWithSpecificJITType(site); > } > > bool hasExitSite(ExitKind kind) const >@@ -208,6 +227,20 @@ public: > return hasExitSite(FrequentExitSite(bytecodeIndex, kind)); > } > private: >+ bool hasExitSiteWithSpecificJITType(const FrequentExitSite& site) const >+ { >+ if (site.inlineKind() == ExitFromAnyInlineKind) { >+ return hasExitSiteWithSpecificInlineKind(site.withInlineKind(ExitFromNotInlined)) >+ || hasExitSiteWithSpecificInlineKind(site.withInlineKind(ExitFromInlined)); >+ } >+ return hasExitSiteWithSpecificInlineKind(site); >+ } >+ >+ bool hasExitSiteWithSpecificInlineKind(const FrequentExitSite& site) const >+ { >+ return m_frequentExitSites.find(site) != m_frequentExitSites.end(); >+ } >+ > HashSet<FrequentExitSite> m_frequentExitSites; > }; > >Index: Source/JavaScriptCore/bytecode/ExitingInlineKind.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/ExitingInlineKind.cpp (nonexistent) >+++ Source/JavaScriptCore/bytecode/ExitingInlineKind.cpp (working copy) >@@ -0,0 +1,52 @@ >+/* >+ * Copyright (C) 2018 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 "ExitingInlineKind.h" >+ >+#include <wtf/PrintStream.h> >+ >+namespace WTF { >+ >+using namespace JSC; >+ >+void printInternal(PrintStream& out, ExitingInlineKind type) >+{ >+ switch (type) { >+ case ExitFromAnyInlineKind: >+ out.print("FromAnyInlineKind"); >+ return; >+ case ExitFromNotInlined: >+ out.print("FromNotInlined"); >+ return; >+ case ExitFromInlined: >+ out.print("FromInlined"); >+ return; >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} // namespace WTF >+ >Index: Source/JavaScriptCore/bytecode/ExitingInlineKind.h >=================================================================== >--- Source/JavaScriptCore/bytecode/ExitingInlineKind.h (nonexistent) >+++ Source/JavaScriptCore/bytecode/ExitingInlineKind.h (working copy) >@@ -0,0 +1,46 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pragma once >+ >+namespace JSC { >+ >+enum ExitingInlineKind : uint8_t { >+ ExitFromAnyInlineKind, >+ ExitFromNotInlined, >+ ExitFromInlined, >+}; >+ >+} // namespace JSC >+ >+namespace WTF { >+ >+class PrintStream; >+void printInternal(PrintStream&, JSC::ExitingInlineKind); >+ >+} // namespace WTF >+ >+ >+ >Index: Source/JavaScriptCore/bytecode/GetByIdStatus.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (working copy) >@@ -116,9 +116,13 @@ GetByIdStatus GetByIdStatus::computeFor( > locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)), uid, > CallLinkStatus::computeExitSiteData(profiledBlock, bytecodeIndex)); > >+ if (bytecodeIndex == 20) >+ dataLog("Result: ", result, "\n"); >+ > if (!result.takesSlowPath() >+ && bytecodeIndex != 20 > && hasExitSite(profiledBlock, bytecodeIndex)) >- return GetByIdStatus(result.makesCalls() ? MakesCalls : TakesSlowPath, true); >+ return result.slowVersion(); > #else > UNUSED_PARAM(map); > #endif >@@ -137,7 +141,7 @@ GetByIdStatus GetByIdStatus::computeForS > CallLinkStatus::computeExitSiteData(profiledBlock, codeOrigin.bytecodeIndex)); > > if (!result.takesSlowPath() && GetByIdStatus::hasExitSite(profiledBlock, codeOrigin.bytecodeIndex)) >- return GetByIdStatus(result.makesCalls() ? GetByIdStatus::MakesCalls : GetByIdStatus::TakesSlowPath, true); >+ return result.slowVersion(); > return result; > } > #endif // ENABLE(DFG_JIT) >@@ -170,8 +174,11 @@ GetByIdStatus GetByIdStatus::computeForS > } > } > >- if (stubInfo->tookSlowPath) >+ if (stubInfo->tookSlowPath) { >+ if (stubInfo->codeOrigin.bytecodeIndex == 20) >+ dataLog("Stub info took slow path.\n"); > return GetByIdStatus(slowPathState); >+ } > > // Finally figure out if we can derive an access strategy. > GetByIdStatus result; >@@ -332,12 +339,15 @@ GetByIdStatus GetByIdStatus::computeFor( > result = computeForStubInfoWithoutExitSiteFeedback( > locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData); > } >+ >+ if (false && codeOrigin.bytecodeIndex == 20) >+ dataLog("In ", pointerDump(profiledBlock), " ", codeOrigin, ": DFG saw: ", result, "\n"); > > if (result.takesSlowPath()) > return result; > >- if (hasExitSite(profiledBlock, codeOrigin.bytecodeIndex)) >- return GetByIdStatus(TakesSlowPath, true); >+ if (codeOrigin.bytecodeIndex != 20 && hasExitSite(profiledBlock, codeOrigin.bytecodeIndex)) >+ return result.slowVersion(); > > if (result.isSet()) > return result; >@@ -346,7 +356,10 @@ GetByIdStatus GetByIdStatus::computeFor( > UNUSED_PARAM(dfgBlock); > UNUSED_PARAM(dfgMap); > #endif >- >+ >+ if (dfgBlock && codeOrigin.bytecodeIndex == 20) >+ dataLog("In ", pointerDump(profiledBlock), " ", codeOrigin, ": Going with what baseline saw.\n"); >+ > return computeFor(profiledBlock, baselineMap, codeOrigin.bytecodeIndex, uid); > } > >@@ -414,6 +427,11 @@ bool GetByIdStatus::makesCalls() const > return false; > } > >+GetByIdStatus GetByIdStatus::slowVersion() const >+{ >+ return GetByIdStatus(makesCalls() ? MakesCalls : TakesSlowPath, wasSeenInJIT()); >+} >+ > void GetByIdStatus::filter(const StructureSet& set) > { > if (m_state != Simple) >@@ -423,6 +441,25 @@ void GetByIdStatus::filter(const Structu > m_state = NoInformation; > } > >+void GetByIdStatus::markIfCheap(SlotVisitor& visitor) >+{ >+ for (GetByIdVariant& variant : m_variants) >+ variat.markIfCheap(visitor); >+} >+ >+bool GetByIdStatus::finalize() >+{ >+ for (GetByIdVariant& variant : m_variants) { >+ if (!variant.finalize()) >+ return false; >+ } >+ if (m_moduleNamespaceObject && !Heap::isMarked(m_moduleNamespaceObject)) >+ return false; >+ if (m_moduleEnvironment && !Heap::isMarked(m_moduleEnvironment)) >+ return false; >+ return true; >+} >+ > void GetByIdStatus::dump(PrintStream& out) const > { > out.print("("); >Index: Source/JavaScriptCore/bytecode/GetByIdStatus.h >=================================================================== >--- Source/JavaScriptCore/bytecode/GetByIdStatus.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/GetByIdStatus.h (working copy) >@@ -29,6 +29,7 @@ > #include "CodeOrigin.h" > #include "ConcurrentJSLock.h" > #include "GetByIdVariant.h" >+#include "ICStatusMap.h" > #include "ScopeOffset.h" > > namespace JSC { >@@ -40,8 +41,6 @@ class JSModuleNamespaceObject; > class ModuleNamespaceAccessCase; > class StructureStubInfo; > >-typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap; >- > class GetByIdStatus { > public: > enum State { >@@ -81,10 +80,10 @@ public: > m_variants.append(variant); > } > >- static GetByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, UniquedStringImpl* uid); >+ static GetByIdStatus computeFor(CodeBlock*, ICStatusMap&, unsigned bytecodeIndex, UniquedStringImpl* uid); > static GetByIdStatus computeFor(const StructureSet&, UniquedStringImpl* uid); > >- static GetByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, UniquedStringImpl* uid); >+ static GetByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, ICStatusMap& baselineMap, ICStatusContextStack& dfgContextStack, CodeOrigin, UniquedStringImpl* uid); > > #if ENABLE(DFG_JIT) > static GetByIdStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid); >@@ -106,6 +105,8 @@ public: > bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls || m_state == Custom || m_state == ModuleNamespace; } > bool makesCalls() const; > >+ GetByIdStatus slowVersion() const; >+ > bool wasSeenInJIT() const { return m_wasSeenInJIT; } > > // Attempts to reduce the set of variants to fit the given structure set. This may be approximate. >@@ -115,6 +116,9 @@ public: > JSModuleEnvironment* moduleEnvironment() const { return m_moduleEnvironment; } > ScopeOffset scopeOffset() const { return m_scopeOffset; } > >+ void markIfCheap(SlotVisitor&); >+ bool finalize(); // Return true if this gets to live. >+ > void dump(PrintStream&) const; > > private: >Index: Source/JavaScriptCore/bytecode/GetByIdVariant.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/GetByIdVariant.cpp (working copy) >@@ -135,6 +135,24 @@ bool GetByIdVariant::attemptToMerge(cons > return true; > } > >+void GetByIdVariant::markIfCheap(SlotVisitor& visitor) >+{ >+ m_structureSet.markIfCheap(visitor); >+} >+ >+bool GetByIdVariant::finalize() >+{ >+ if (!m_structureSet.isStillAlive()) >+ return false; >+ if (!m_conditionSet.areStillLive()) >+ return false; >+ if (m_callLinkStatus && !m_callLinkStatus->finalize()) >+ return false; >+ if (m_intrinsicFunction && !Heap::isMarked(m_intrinsicFunction)) >+ return false; >+ return true; >+} >+ > void GetByIdVariant::dump(PrintStream& out) const > { > dumpInContext(out, 0); >Index: Source/JavaScriptCore/bytecode/GetByIdVariant.h >=================================================================== >--- Source/JavaScriptCore/bytecode/GetByIdVariant.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/GetByIdVariant.h (working copy) >@@ -73,6 +73,9 @@ public: > > bool attemptToMerge(const GetByIdVariant& other); > >+ void markIfCheap(SlotVisitor&); >+ bool finalize(); >+ > void dump(PrintStream&) const; > void dumpInContext(PrintStream&, DumpContext*) const; > >Index: Source/JavaScriptCore/bytecode/ICStatusMap.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/ICStatusMap.cpp (nonexistent) >+++ Source/JavaScriptCore/bytecode/ICStatusMap.cpp (working copy) >@@ -0,0 +1,40 @@ >+/* >+ * Copyright (C) 2018 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 "ICStatusMap.h" >+ >+#include "TerminatedCodeOrigin.h" >+ >+namespace JSC { >+ >+ICStatus ICStatusContext::get(CodeOrigin codeOrigin) >+{ >+ return map.get<TerminatedCodeOriginHashTranslator>( >+ TerminatedCodeOrigin(codeOrigin, baselineCodeBlock)); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/bytecode/ICStatusMap.h >=================================================================== >--- Source/JavaScriptCore/bytecode/ICStatusMap.h (nonexistent) >+++ Source/JavaScriptCore/bytecode/ICStatusMap.h (working copy) >@@ -0,0 +1,62 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pramga once >+ >+#include "CodeOrigin.h" >+#include <wtf/HashMap.h> >+ >+namespace JSC { >+ >+class CallLinkInfo; >+class CallLinkStatus; >+class CodeBlock; >+class GetByIdStatus; >+class PutByIdStatus; >+class StructureStubInfo; >+struct ByValInfo; >+ >+struct ICStatus { >+ StructureStubInfo* stubInfo { nullptr }; >+ CallLinkInfo* callLinkInfo { nullptr }; >+ ByValInfo* byValInfo { nullptr }; >+ CallLinkStatus* callStatus { nullptr }; >+ GetByIdStatus* getStatus { nullptr }; >+ PutByIdStatus* putStatus { nullptr }; >+}; >+ >+typedef HashMap<CodeOrigin, ICStatus, CodeOriginApproximateHash> ICStatusMap; >+ >+struct ICStatusContext { >+ ICStatus get(CodeOrigin); >+ >+ CodeBlock* baselineCodeBlock; >+ ICStatusMap map; >+}; >+ >+typedef Vector<ICStatusContext*, 8> ICStatusContextStack; >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/bytecode/PutByIdStatus.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (working copy) >@@ -398,6 +398,21 @@ bool PutByIdStatus::makesCalls() const > return false; > } > >+void PutByIdStatus::markIfCheap(SlotVisitor& visitor) >+{ >+ for (PutByIdVariant& variant : m_variants) >+ variant.markIfCheap(visitor); >+} >+ >+bool PutByIdStatus::finalize() >+{ >+ for (PutByIdVariant& variant : m_variants) { >+ if (!variant.finalize()) >+ return false; >+ } >+ return true; >+} >+ > void PutByIdStatus::dump(PrintStream& out) const > { > switch (m_state) { >Index: Source/JavaScriptCore/bytecode/PutByIdStatus.h >=================================================================== >--- Source/JavaScriptCore/bytecode/PutByIdStatus.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/PutByIdStatus.h (working copy) >@@ -26,6 +26,7 @@ > #pragma once > > #include "CallLinkStatus.h" >+#include "ICStatusMap.h" > #include "PutByIdVariant.h" > > namespace JSC { >@@ -69,10 +70,10 @@ public: > m_variants.append(variant); > } > >- static PutByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, UniquedStringImpl* uid); >+ static PutByIdStatus computeFor(CodeBlock*, ICStatusMap&, unsigned bytecodeIndex, UniquedStringImpl* uid); > static PutByIdStatus computeFor(JSGlobalObject*, const StructureSet&, UniquedStringImpl* uid, bool isDirect); > >- static PutByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, UniquedStringImpl* uid); >+ static PutByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, ICStatusMap& baselineMap, ICStatusMap& dfgMap, CodeOrigin, UniquedStringImpl* uid); > > #if ENABLE(JIT) > static PutByIdStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid); >@@ -91,6 +92,9 @@ public: > const PutByIdVariant& at(size_t index) const { return m_variants[index]; } > const PutByIdVariant& operator[](size_t index) const { return at(index); } > >+ void markIfCheap(SlotVisitor&); >+ bool finalize(); >+ > void dump(PrintStream&) const; > > private: >Index: Source/JavaScriptCore/bytecode/PutByIdVariant.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/PutByIdVariant.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/PutByIdVariant.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -206,6 +206,26 @@ bool PutByIdVariant::attemptToMergeTrans > return true; > } > >+void PutByIdVariant::markIfCheap(SlotVisitor& visitor) >+{ >+ m_oldStructure.markIfCheap(visitor); >+ if (m_newStructure) >+ m_newStructure->markIfCheap(visitor); >+} >+ >+bool PutByIdVariant::finalize() >+{ >+ if (!m_oldStructure.isStillAlive(visitor)) >+ return false; >+ if (m_newStructure && !Heap::isMarked(m_newStructure)) >+ return false; >+ if (!m_conditionSet.areStillLive()) >+ return false; >+ if (m_callLinkStatus && !m_callLinkStatus->finalize()) >+ return false; >+ return true; >+} >+ > void PutByIdVariant::dump(PrintStream& out) const > { > dumpInContext(out, 0); >Index: Source/JavaScriptCore/bytecode/PutByIdVariant.h >=================================================================== >--- Source/JavaScriptCore/bytecode/PutByIdVariant.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/PutByIdVariant.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -129,6 +129,9 @@ public: > > bool attemptToMerge(const PutByIdVariant& other); > >+ void markIfCheap(SlotVisitor&); >+ bool finalize(); >+ > void dump(PrintStream&) const; > void dumpInContext(PrintStream&, DumpContext*) const; > >@@ -137,7 +140,7 @@ private: > > Kind m_kind; > StructureSet m_oldStructure; >- Structure* m_newStructure; >+ Structure* m_newStructure { nullptr }; > ObjectPropertyConditionSet m_conditionSet; > PropertyOffset m_offset; > InferredType::Descriptor m_requiredType; >Index: Source/JavaScriptCore/bytecode/RecordedStatuses.h >=================================================================== >--- Source/JavaScriptCore/bytecode/RecordedStatuses.h (nonexistent) >+++ Source/JavaScriptCore/bytecode/RecordedStatuses.h (working copy) >@@ -0,0 +1,114 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pragma once >+ >+#include "CallLinkStatus.h" >+#include "GetByIdStatus.h" >+#include "PutByIdStatus.h" >+ >+namespace JSC { >+ >+struct RecordedStatuses { >+ RecordedStatuses() { } >+ >+ RecordedStatuses& operator=(const RecordedStatuses& other) >+ { >+ for (auto& pair : other.calls) >+ calls.append(std::make_pair(pair.first, std::make_unique<CallLinkStatus>(pair.second))); >+ for (auto& pair : other.gets) >+ gets.append(std::make_pair(pair.first, std::make_unique<GetByIdStatus>(pair.second))); >+ for (auto& pair : other.puts) >+ puts.append(std::make_pair(pair.first, std::make_unique<PutByIdStatus>(pair.second))); >+ } >+ >+ RecordedStatuses& operator=(RecordedStatuses&& other) >+ { >+ calls = WTFMove(other.calls); >+ gets = WTFMove(other.gets); >+ puts = WTFMove(other.puts); >+ } >+ >+ RecordedStatuses(const RecordedStatuses& other) >+ { >+ *this = other; >+ } >+ >+ RecordedStatuses(RecorededStatuses&& other) >+ { >+ *this = WTFMove(other); >+ } >+ >+ void addCallLinkStatus(const CodeOrigin& codeOrigin, const CallLinkStatus& status) >+ { >+ calls.append(std::make_pair(codeOrigin, std::make_unique<CallLinkStatus>(status))); >+ } >+ >+ void addGetByIdStatus(const CodeOrigin& codeOrigin, const GetByIdStatus& status) >+ { >+ gets.append(std::make_pair(codeOrigin, std::make_unique<GetByIdStatus>(status))); >+ } >+ >+ void addPutByIdStatus(const CodeOrigin& codeOrigin, const PutByIdStatus& status) >+ { >+ puts.append(std::make_pair(codeOrigin, std::make_unique<PutByIdStatus>(status))); >+ } >+ >+ void markIfCheap(SlotVisitor& slotVisitor) >+ { >+ for (auto& pair : gets) >+ pair.second->markIfCheap(slotVisitor); >+ for (auto& pair : puts) >+ pair.second->markIfCheap(slotVisitor); >+ } >+ >+ void finalize() >+ { >+ auto finalize = [] (auto& vector) { >+ vector.removeAllMatching( >+ [&] (auto& pair) -> bool { >+ return !pair.second->finalize(); >+ }); >+ vector.shrinkToFit(); >+ }; >+ finalize(calls); >+ finalize(gets); >+ finalize(puts); >+ } >+ >+ void shrinkToFit() >+ { >+ calls.shrinkToFit(); >+ gets.shrinkToFit(); >+ puts.shrinkToFit(); >+ } >+ >+ Vector<std::pair<CodeOrigin, std::unique_ptr<CallLinkStatus>>> calls; >+ Vector<std::pair<CodeOrigin, std::unique_ptr<GetByIdStatus>>> gets; >+ Vector<std::pair<CodeOrigin, std::unique_ptr<PutByIdStatus>>> puts; >+}; >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/bytecode/StructureSet.cpp >=================================================================== >--- Source/JavaScriptCore/bytecode/StructureSet.cpp (revision 232227) >+++ Source/JavaScriptCore/bytecode/StructureSet.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014, 2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -31,6 +31,21 @@ > > namespace JSC { > >+void StructureSet::markIfCheap(SlotVisitor& visitor) const >+{ >+ for (Structure* structure : *this) >+ structure->markIfCheap(visitor); >+} >+ >+bool StructureSet::isStillAlive() const >+{ >+ for (Structure* structure : *this) { >+ if (!Heap::isMarked(structure)) >+ return false; >+ } >+ return true; >+} >+ > void StructureSet::dumpInContext(PrintStream& out, DumpContext* context) const > { > CommaPrinter comma; >Index: Source/JavaScriptCore/bytecode/StructureSet.h >=================================================================== >--- Source/JavaScriptCore/bytecode/StructureSet.h (revision 232227) >+++ Source/JavaScriptCore/bytecode/StructureSet.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved. >+ * Copyright (C) 2011-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -58,6 +58,9 @@ public: > { > return onlyEntry(); > } >+ >+ void markIfCheap(SlotVisitor&) const; >+ bool isStillAlive() const; > > void dumpInContext(PrintStream&, DumpContext*) const; > void dump(PrintStream&) const; >Index: Source/JavaScriptCore/bytecode/TerminatedCodeOrigin.h >=================================================================== >--- Source/JavaScriptCore/bytecode/TerminatedCodeOrigin.h (nonexistent) >+++ Source/JavaScriptCore/bytecode/TerminatedCodeOrigin.h (working copy) >@@ -0,0 +1,56 @@ >+/* >+ * Copyright (C) 2018 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. >+ */ >+ >+#pragma once >+ >+namespace JSC { >+ >+struct TerminatedCodeOrigin { >+ TerminatedCodeOrigin() { } >+ >+ TerminatedCodeOrigin(const CodeOrigin& codeOrigin, CodeBlock* terminal) >+ : codeOrigin(codeOrigin) >+ , terminal(terminal) >+ { >+ } >+ >+ CodeOrigin codeOrigin; >+ CodeBlock* terminal { nullptr }; >+}; >+ >+struct TerminatedCodeOriginHashTranslator { >+ static unsigned hash(const TerminatedCodeOrigin& value) >+ { >+ return value.codeOrigin.approximateHash(value.terminal); >+ } >+ >+ static bool equal(const CodeOrigin& a, const TerminatedCodeOriign& b) >+ { >+ return b.codeOrigin.approximatelyEqual(a, b.terminal); >+ } >+}; >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (working copy) >@@ -1082,9 +1082,8 @@ private: > // code block had gathered. > LazyOperandValueProfileParser m_lazyOperands; > >- CallLinkInfoMap m_callLinkInfos; >- StubInfoMap m_stubInfos; >- ByValInfoMap m_byValInfos; >+ ICStatusMap m_baselineMap; >+ ICStatusContext m_optimizedContext; > > // Pointers to the argument position trackers for this slice of code. > Vector<ArgumentPosition*> m_argumentPositions; >@@ -1102,10 +1101,7 @@ private: > InlineCallFrame::Kind, > BasicBlock* continuationBlock); > >- ~InlineStackEntry() >- { >- m_byteCodeParser->m_inlineStackTop = m_caller; >- } >+ ~InlineStackEntry(); > > VirtualRegister remapOperand(VirtualRegister operand) const > { >@@ -1120,6 +1116,8 @@ private: > > InlineStackEntry* m_inlineStackTop; > >+ ICStatusContextStack m_icContextStack; >+ > struct DelayedSetLocal { > CodeOrigin m_origin; > VirtualRegister m_operand; >@@ -1146,10 +1144,6 @@ private: > > Vector<DelayedSetLocal, 2> m_setLocalQueue; > >- CodeBlock* m_dfgCodeBlock; >- CallLinkStatus::ContextMap m_callContextMap; >- StubInfoMap m_dfgStubInfos; >- > Instruction* m_currentInstruction; > bool m_hasDebuggerEnabled; > }; >@@ -4007,9 +4001,18 @@ void ByteCodeParser::handleGetById( > return; > } > >+ // FIXME: If we use the GetByIdStatus for anything then we should record it and insert a node >+ // after everything else (like the GetByOffset or whatever) that will filter the recorded >+ // GetByIdStatus. That means that the constant folder also needs to do the same! >+ > if (getByIdStatus.numVariants() > 1) { > if (getByIdStatus.makesCalls() || !isFTL(m_graph.m_plan.mode) >- || !Options::usePolymorphicAccessInlining()) { >+ || !Options::usePolymorphicAccessInlining() >+ || getByIdStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) { >+ if (false && getByIdStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) { >+ dataLog("At ", currentCodeOrigin(), "\n"); >+ dataLog("Giving up on: ", getByIdStatus, "\n"); >+ } > set(VirtualRegister(destinationOperand), > addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base)); > return; >@@ -4150,7 +4153,10 @@ void ByteCodeParser::handlePutById( > > if (putByIdStatus.numVariants() > 1) { > if (!isFTL(m_graph.m_plan.mode) || putByIdStatus.makesCalls() >- || !Options::usePolymorphicAccessInlining()) { >+ || !Options::usePolymorphicAccessInlining() >+ || putByIdStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) { >+ if (false && putByIdStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) >+ dataLog("Giving up on: ", putByIdStatus, "\n"); > emitPutById(base, identifierNumber, value, putByIdStatus, isDirect); > return; > } >@@ -6603,12 +6609,17 @@ ByteCodeParser::InlineStackEntry::Inline > // We do this while holding the lock because we want to encourage StructureStubInfo's > // to be potentially added to operations and because the profiled block could be in the > // middle of LLInt->JIT tier-up in which case we would be adding the info's right now. >- if (m_profiledBlock->hasBaselineJITProfiling()) { >- m_profiledBlock->getStubInfoMap(locker, m_stubInfos); >- m_profiledBlock->getCallLinkInfoMap(locker, m_callLinkInfos); >- m_profiledBlock->getByValInfoMap(locker, m_byValInfos); >- } >+ if (m_profiledBlock->hasBaselineJITProfiling()) >+ m_profiledBlock->getICStatusMap(locker, m_baselineMap); >+ } >+ >+ m_optimizedContext.baselineCodeBlock = m_profiledBlock; >+ CodeBlock* optimizedBlock = m_profiledBlock->replacement(); >+ if (optimizedBlock) { >+ ConcurrentJSLocker locker(optimizedBlock->m_lock); >+ optimizedBlock->getICStatusMap(locker, m_optimizedContext.map); > } >+ m_icContextStack.append(&m_optimizedContext); > > int argumentCountIncludingThisWithFixup = std::max<int>(argumentCountIncludingThis, codeBlock->numParameters()); > >@@ -6673,6 +6684,13 @@ ByteCodeParser::InlineStackEntry::Inline > byteCodeParser->m_inlineStackTop = this; > } > >+ByteCodeParser::InlineStackEntry::~InlineStackEntry() >+{ >+ m_byteCodeParser->m_inlineStackTop = m_caller; >+ RELEASE_ASSERT(m_byteCodeParser->m_icContextStack.last() == &m_optimizedContext); >+ m_byteCodeParser->m_icContextStack.removeLast(); >+} >+ > void ByteCodeParser::parseCodeBlock() > { > clearCaches(); >Index: Source/JavaScriptCore/dfg/DFGCommonData.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGCommonData.h (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGCommonData.h (working copy) >@@ -125,6 +125,7 @@ public: > Bag<CodeBlockJettisoningWatchpoint> watchpoints; > Bag<AdaptiveStructureWatchpoint> adaptiveStructureWatchpoints; > Bag<AdaptiveInferredPropertyValueWatchpoint> adaptiveInferredPropertyValueWatchpoints; >+ RecordedStatuses recordedStatuses; > Vector<JumpReplacement> jumpReplacements; > > ScratchBuffer* catchOSREntryBuffer; >Index: Source/JavaScriptCore/dfg/DFGJITCompiler.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (working copy) >@@ -188,6 +188,8 @@ void JITCompiler::compileExceptionHandle > > void JITCompiler::link(LinkBuffer& linkBuffer) > { >+ m_jitCode->common.recordedStatuses = WTFMove(m_graph.m_plan.recordedStatuses); >+ > // Link the code, populate data in CodeBlock data structures. > m_jitCode->common.frameRegisterCount = m_graph.frameRegisterCount(); > m_jitCode->common.requiredRegisterCountForExit = m_graph.requiredRegisterCountForExit(); >Index: Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved. >+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -42,11 +42,17 @@ void OSRExitBase::considerAddingAsFreque > baselineCodeBlockForOriginAndBaselineCodeBlock( > m_codeOriginForExitProfile, profiledCodeBlock); > if (sourceProfiledCodeBlock) { >+ ExitingInlineKind inlineKind; >+ if (m_codeOriginForExitProfile.inlineCallFrame) >+ inlineKind = ExitFromInlined; >+ else >+ inlineKind = ExitFromNotInlined; >+ > FrequentExitSite site; > if (m_wasHoisted) >- site = FrequentExitSite(HoistingFailed, jitType); >+ site = FrequentExitSite(HoistingFailed, jitType, inlineKind); > else >- site = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind, jitType); >+ site = FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind, jitType, inlineKind); > ExitProfile::add(sourceProfiledCodeBlock, site); > } > } >Index: Source/JavaScriptCore/dfg/DFGPlan.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPlan.cpp (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGPlan.cpp (working copy) >@@ -633,6 +633,8 @@ void Plan::checkLivenessAndVisitChildren > cleanMustHandleValuesIfNecessary(); > for (unsigned i = mustHandleValues.size(); i--;) > visitor.appendUnbarriered(mustHandleValues[i]); >+ >+ recordedStatuses.markIfCheap(visitor); > > visitor.appendUnbarriered(codeBlock); > visitor.appendUnbarriered(codeBlock->alternative()); >@@ -649,6 +651,11 @@ void Plan::checkLivenessAndVisitChildren > transitions.visitChildren(visitor); > } > >+void Plan::finalizeInGC() >+{ >+ recordedStatuses.finalize(); >+} >+ > bool Plan::isKnownToBeLiveDuringGC() > { > if (stage == Cancelled) >Index: Source/JavaScriptCore/dfg/DFGPlan.h >=================================================================== >--- Source/JavaScriptCore/dfg/DFGPlan.h (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGPlan.h (working copy) >@@ -72,6 +72,7 @@ struct Plan : public ThreadSafeRefCounte > void iterateCodeBlocksForGC(const Func&); > void checkLivenessAndVisitChildren(SlotVisitor&); > bool isKnownToBeLiveDuringGC(); >+ void finalizeInGC(); > void cancel(); > > bool canTierUpAndOSREnter() const { return !tierUpAndOSREnterBytecodes.isEmpty(); } >@@ -104,6 +105,7 @@ struct Plan : public ThreadSafeRefCounte > DesiredIdentifiers identifiers; > DesiredWeakReferences weakReferences; > DesiredTransitions transitions; >+ RecoredStatuses recordedStatuses; > > bool willTryToTierUp { false }; > >Index: Source/JavaScriptCore/dfg/DFGWorklist.cpp >=================================================================== >--- Source/JavaScriptCore/dfg/DFGWorklist.cpp (revision 232227) >+++ Source/JavaScriptCore/dfg/DFGWorklist.cpp (working copy) >@@ -393,8 +393,10 @@ void Worklist::removeDeadPlans(VM& vm) > Plan* plan = iter->value.get(); > if (plan->vm != &vm) > continue; >- if (plan->isKnownToBeLiveDuringGC()) >+ if (plan->isKnownToBeLiveDuringGC()) { >+ plan->finalizeInGC(); > continue; >+ } > RELEASE_ASSERT(plan->stage != Plan::Cancelled); // Should not be cancelled, yet. > ASSERT(!deadPlanKeys.contains(plan->key())); > deadPlanKeys.add(plan->key()); >Index: Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h >=================================================================== >--- Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (revision 232227) >+++ Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (working copy) >@@ -56,6 +56,8 @@ namespace JSC { namespace FTL { > macro(DirectArguments_minCapacity, DirectArguments::offsetOfMinCapacity()) \ > macro(DirectArguments_mappedArguments, DirectArguments::offsetOfMappedArguments()) \ > macro(DirectArguments_modifiedArgumentsDescriptor, DirectArguments::offsetOfModifiedArgumentsDescriptor()) \ >+ macro(FunctionRareData_allocator, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()) \ >+ macro(FunctionRareData_structure, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()) \ > macro(GetterSetter_getter, GetterSetter::offsetOfGetter()) \ > macro(GetterSetter_setter, GetterSetter::offsetOfSetter()) \ > macro(JSArrayBufferView_length, JSArrayBufferView::offsetOfLength()) \ >@@ -112,10 +114,10 @@ namespace JSC { namespace FTL { > macro(StringImpl_length, StringImpl::lengthMemoryOffset()) \ > macro(Structure_classInfo, Structure::classInfoOffset()) \ > macro(Structure_globalObject, Structure::globalObjectOffset()) \ >+ macro(Structure_indexingModeIncludingHistory, Structure::indexingModeIncludingHistoryOffset()) \ >+ macro(Structure_inlineCapacity, Structure::inlineCapacityOffset()) \ > macro(Structure_prototype, Structure::prototypeOffset()) \ > macro(Structure_structureID, Structure::structureIDOffset()) \ >- macro(Structure_inlineCapacity, Structure::inlineCapacityOffset()) \ >- macro(Structure_indexingModeIncludingHistory, Structure::indexingModeIncludingHistoryOffset()) \ > macro(HashMapImpl_capacity, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()) \ > macro(HashMapImpl_buffer, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()) \ > macro(HashMapImpl_head, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead()) \ >Index: Source/JavaScriptCore/ftl/FTLCapabilities.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLCapabilities.cpp (revision 232227) >+++ Source/JavaScriptCore/ftl/FTLCapabilities.cpp (working copy) >@@ -351,6 +351,7 @@ inline CapabilityLevel canCompile(Node* > case PutByValDirect: > case PutByValWithThis: > case MatchStructure: >+ case CreateThis: > // These are OK. > break; > >@@ -362,7 +363,6 @@ inline CapabilityLevel canCompile(Node* > break; > > case IdentityWithProfile: >- case CreateThis: > case CheckTierUpInLoop: > case CheckTierUpAndOSREnter: > case CheckTierUpAtReturn: >Index: Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >=================================================================== >--- Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (revision 232227) >+++ Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (working copy) >@@ -847,6 +847,9 @@ private: > case NewArrayWithSpread: > compileNewArrayWithSpread(); > break; >+ case CreateThis: >+ compileCreateThis(); >+ break; > case Spread: > compileSpread(); > break; >@@ -5662,6 +5665,40 @@ private: > > setJSValue(result); > } >+ >+ void compileCreateThis() >+ { >+ LValue callee = lowCell(m_node->child1()); >+ >+ LBasicBlock isFunctionBlock = m_out.newBlock(); >+ LBasicBlock hasRareData = m_out.newBlock(); >+ LBasicBlock slowPath = m_out.newBlock(); >+ LBasicBlock continuation = m_out.newBlock(); >+ >+ m_out.branch(isFunction(callee, provenType(m_node->child1())), usually(isFunctionBlock), rarely(slowPath)); >+ >+ LBasicBlock lastNext = m_out.appendTo(isFunctionBlock, hasRareData); >+ LValue rareData = m_out.loadPtr(callee, m_heaps.JSFunction_rareData); >+ m_out.branch(m_out.isZero64(rareData), rarely(slowPath), usually(hasRareData)); >+ >+ m_out.appendTo(hasRareData, slowPath); >+ LValue allocator = m_out.loadPtr(rareData, m_heaps.FunctionRareData_allocator); >+ LValue structure = m_out.loadPtr(rareData, m_heaps.FunctionRareData_structure); >+ LValue butterfly = m_out.constIntPtr(0); >+ ValueFromBlock fastResult = m_out.anchor(allocateObject(allocator, structure, butterfly, slowPath)); >+ m_out.jump(continuation); >+ >+ m_out.appendTo(slowPath, continuation); >+ ValueFromBlock slowResult = m_out.anchor(vmCall( >+ Int64, m_out.operation(operationCreateThis), m_callFrame, callee, m_out.constInt32(m_node->inlineCapacity()))); >+ m_out.jump(continuation); >+ >+ m_out.appendTo(continuation, lastNext); >+ LValue result = m_out.phi(Int64, fastResult, slowResult); >+ >+ mutatorFence(); >+ setJSValue(result); >+ } > > void compileSpread() > { >Index: Source/JavaScriptCore/runtime/Options.h >=================================================================== >--- Source/JavaScriptCore/runtime/Options.h (revision 232227) >+++ Source/JavaScriptCore/runtime/Options.h (working copy) >@@ -275,6 +275,7 @@ constexpr bool enableWebAssemblyStreamin > v(unsigned, maxAccessVariantListSize, 8, Normal, nullptr) \ > v(bool, usePolyvariantDevirtualization, true, Normal, nullptr) \ > v(bool, usePolymorphicAccessInlining, true, Normal, nullptr) \ >+ v(unsigned, maxPolymorphicAccessInliningListSize, 3, Normal, nullptr) \ > v(bool, usePolymorphicCallInlining, true, Normal, nullptr) \ > v(bool, usePolymorphicCallInliningForNonStubStatus, false, Normal, nullptr) \ > v(unsigned, maxPolymorphicCallVariantListSize, 15, Normal, nullptr) \
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 164904
:
295471
|
295518
|
295582
|
341446
|
341462
|
341542
|
341545
|
341604
|
341611
|
341614
|
341693
|
341703
|
341728
|
341779
|
341807
|
341811
|
341817
|
341825
|
341848
|
341849
|
341850
|
341851
|
341861
|
341924
|
342117
|
342182
|
342188
|
342200
|
343463