WebKit Bugzilla
Attachment 340222 Details for
Bug 185564
: REGRESSION(r231316): Appears to be a Speedometer2/MotionMark regression (Requested by keith_miller on #webkit).
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ROLLOUT of r231316
bug-185564-20180511171334.patch (text/plain), 34.30 KB, created by
WebKit Commit Bot
on 2018-05-11 14:13:35 PDT
(
hide
)
Description:
ROLLOUT of r231316
Filename:
MIME Type:
Creator:
WebKit Commit Bot
Created:
2018-05-11 14:13:35 PDT
Size:
34.30 KB
patch
obsolete
>Subversion Revision: 231718 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 97f3a60a76fa989f8df87edecd71996ac40af840..9455e15dff20834fa5b301dbfe730092b79b88c4 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,20 @@ >+2018-05-11 Commit Queue <commit-queue@webkit.org> >+ >+ Unreviewed, rolling out r231316 and r231332. >+ https://bugs.webkit.org/show_bug.cgi?id=185564 >+ >+ Appears to be a Speedometer2/MotionMark regression (Requested >+ by keith_miller on #webkit). >+ >+ Reverted changesets: >+ >+ "Remove the prototype caching for get_by_id in the LLInt" >+ https://bugs.webkit.org/show_bug.cgi?id=185226 >+ https://trac.webkit.org/changeset/231316 >+ >+ "Unreviewed, fix 32-bit profile offset for change in bytecode" >+ https://trac.webkit.org/changeset/231332 >+ > 2018-05-11 Michael Saboff <msaboff@apple.com> > > [DFG] Compiler uses incorrect output register for NumberIsInteger operation >diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt >index cfcda976b549b31ce8a9e3b018ae5b9e85a1871e..dd9a6f8c86e4d6e87747e408d9936b789652af0e 100644 >--- a/Source/JavaScriptCore/CMakeLists.txt >+++ b/Source/JavaScriptCore/CMakeLists.txt >@@ -454,6 +454,7 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS > bytecode/InternalFunctionAllocationProfile.h > bytecode/JumpTable.h > bytecode/LLIntCallLinkInfo.h >+ bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h > bytecode/LazyOperandValueProfile.h > bytecode/ObjectAllocationProfile.h > bytecode/ObjectPropertyCondition.h >diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >index f1d05381da047c00d96f5b80cc067d8c5d69b24a..f7f1f4433d6218ea422be699bc18a2d9f7c65024 100644 >--- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >+++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj >@@ -1037,6 +1037,7 @@ > 53F40E951D5A7AEF0099A1B6 /* WasmModuleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */; }; > 53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 53F8D2001E8387D400D21116 /* WasmBBQPlanInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F8D1FF1E8387D400D21116 /* WasmBBQPlanInlines.h */; }; >+ 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 53FD04D41D7AB291003287D3 /* WasmCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */; }; > 5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */; }; >@@ -3462,6 +3463,8 @@ > 53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmModuleParser.cpp; sourceTree = "<group>"; }; > 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = "<group>"; }; > 53F8D1FF1E8387D400D21116 /* WasmBBQPlanInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmBBQPlanInlines.h; sourceTree = "<group>"; }; >+ 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; }; >+ 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; }; > 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmCallingConvention.cpp; sourceTree = "<group>"; }; > 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCallingConvention.h; sourceTree = "<group>"; }; > 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmValidate.h; sourceTree = "<group>"; }; >@@ -6658,7 +6661,6 @@ > 865A30F0135007E100CDB49E /* JSCJSValueInlines.h */, > FE2B0B681FD0D2970075DA5F /* JSCPoison.cpp */, > FE2B0B701FD8C4630075DA5F /* JSCPoison.h */, >- FE7497E5209001B00003565B /* JSCPtrTag.h */, > 72AAF7CB1D0D318B005E60BE /* JSCustomGetterSetterFunction.cpp */, > 72AAF7CC1D0D318B005E60BE /* JSCustomGetterSetterFunction.h */, > 0F2B66BD17B6B5AB00A7AE3F /* JSDataView.cpp */, >@@ -6744,6 +6746,7 @@ > 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */, > 862553CE16136AA5009F17D0 /* JSProxy.cpp */, > 862553CF16136AA5009F17D0 /* JSProxy.h */, >+ FE7497E5209001B00003565B /* JSCPtrTag.h */, > 534638721E70D01500F12AC1 /* JSRunLoopTimer.cpp */, > 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */, > 14874AE115EBDE4A002E3587 /* JSScope.cpp */, >@@ -7626,6 +7629,8 @@ > 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */, > 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */, > 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */, >+ 53FA2AE21CF380390022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp */, >+ 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */, > 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */, > 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */, > 20ECB15EFC524624BC2F02D5 /* ModuleNamespaceAccessCase.cpp */, >@@ -8992,7 +8997,6 @@ > A5D2E665195E174000A518E7 /* JSContextRefInternal.h in Headers */, > 148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */, > FE2B0B731FD9EF700075DA5F /* JSCPoison.h in Headers */, >- FE7497E6209001B10003565B /* JSCPtrTag.h in Headers */, > A72028B81797601E0098028C /* JSCTestRunnerUtils.h in Headers */, > 72AAF7CE1D0D31B3005E60BE /* JSCustomGetterSetterFunction.h in Headers */, > 0F2B66EC17B6B5AB00A7AE3F /* JSDataView.h in Headers */, >@@ -9068,6 +9072,7 @@ > 7C008CDB187124BB00955C24 /* JSPromiseDeferred.h in Headers */, > 7C184E1F17BEE22E007CB63A /* JSPromisePrototype.h in Headers */, > 996B731F1BDA08EF00331B84 /* JSPromisePrototype.lut.h in Headers */, >+ FE7497E6209001B10003565B /* JSCPtrTag.h in Headers */, > 2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */, > 862553D216136E1A009F17D0 /* JSProxy.h in Headers */, > A552C3801ADDB8FE00139726 /* JSRemoteInspector.h in Headers */, >@@ -9156,6 +9161,7 @@ > 0F4680CB14BBB17200BFE272 /* LLIntOfflineAsmConfig.h in Headers */, > FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */, > 79CFC6F01C33B10000C768EA /* LLIntPCRanges.h in Headers */, >+ 53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */, > 0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */, > 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */, > 0F75A061200D26180038E2CF /* LocalAllocator.h in Headers */, >diff --git a/Source/JavaScriptCore/Sources.txt b/Source/JavaScriptCore/Sources.txt >index 6c40a945f8e8baa8c4d85d0fb1eef74092b328c5..29f3d763729c1b436e866cec4ae26e1c6b9656dc 100644 >--- a/Source/JavaScriptCore/Sources.txt >+++ b/Source/JavaScriptCore/Sources.txt >@@ -224,6 +224,7 @@ bytecode/InlineCallFrame.cpp > bytecode/InlineCallFrameSet.cpp > bytecode/IntrinsicGetterAccessCase.cpp > bytecode/JumpTable.cpp >+bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp > bytecode/LazyOperandValueProfile.cpp > bytecode/MethodOfGettingAValueProfile.cpp > bytecode/ModuleNamespaceAccessCase.cpp >diff --git a/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp b/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >index 6e534e7ba60c64abd17fd0395fe8eadfcf383ef2..abe9a8a282edf4e78a463830f350b76f98d0f50f 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >+++ b/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp >@@ -377,6 +377,12 @@ void BytecodeDumper<Block>::printGetByIdOp(PrintStream& out, int location, const > case op_get_by_id: > op = "get_by_id"; > break; >+ case op_get_by_id_proto_load: >+ op = "get_by_id_proto_load"; >+ break; >+ case op_get_by_id_unset: >+ op = "get_by_id_unset"; >+ break; > case op_get_array_length: > op = "array_length"; > break; >@@ -391,7 +397,7 @@ void BytecodeDumper<Block>::printGetByIdOp(PrintStream& out, int location, const > int id0 = (++it)->u.operand; > printLocationAndOp(out, location, it, op); > out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data()); >- it += 3; // Increment up to the value profiler. >+ it += 4; // Increment up to the value profiler. > } > > static void dumpStructure(PrintStream& out, const char* name, Structure* structure, const Identifier& ident) >@@ -436,6 +442,8 @@ void BytecodeDumper<Block>::printGetByIdCacheStatus(PrintStream& out, int locati > out.printf(" llint("); > dumpStructure(out, "struct", structure, ident); > out.printf(")"); >+ if (Interpreter::getOpcodeID(instruction[0]) == op_get_by_id_proto_load) >+ out.printf(" proto(%p)", getPointer(instruction[6])); > } > > #if ENABLE(JIT) >@@ -1030,6 +1038,8 @@ void BytecodeDumper<Block>::dumpBytecode(PrintStream& out, const typename Block: > break; > } > case op_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > case op_get_array_length: { > printGetByIdOp(out, location, it); > printGetByIdCacheStatus(out, location, stubInfos); >diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.json b/Source/JavaScriptCore/bytecode/BytecodeList.json >index 0046c6ef97b2ffe3ff7314d675f1e00b249eddd9..5628df5b462163eb296321fe858d03b6d9f76e55 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeList.json >+++ b/Source/JavaScriptCore/bytecode/BytecodeList.json >@@ -81,8 +81,10 @@ > { "name" : "op_is_function", "length" : 3 }, > { "name" : "op_is_cell_with_type", "length" : 4 }, > { "name" : "op_in", "length" : 5 }, >- { "name" : "op_get_array_length", "length" : 8 }, >- { "name" : "op_get_by_id", "length" : 8 }, >+ { "name" : "op_get_array_length", "length" : 9 }, >+ { "name" : "op_get_by_id", "length" : 9 }, >+ { "name" : "op_get_by_id_proto_load", "length" : 9 }, >+ { "name" : "op_get_by_id_unset", "length" : 9 }, > { "name" : "op_get_by_id_with_this", "length" : 6 }, > { "name" : "op_get_by_val_with_this", "length" : 6 }, > { "name" : "op_get_by_id_direct", "length" : 7 }, >diff --git a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >index 15b952abc41661be67a94c7519d6289ccaf6b24c..701d36cfac451b3c88235661a105717203580ddf 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >+++ b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >@@ -182,6 +182,8 @@ void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instructi > case op_to_primitive: > case op_try_get_by_id: > case op_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > case op_get_by_id_direct: > case op_get_array_length: > case op_typeof: >@@ -432,6 +434,8 @@ void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instructi > case op_construct: > case op_try_get_by_id: > case op_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > case op_get_by_id_direct: > case op_get_by_id_with_this: > case op_get_by_val_with_this: >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >index d111de0b6c1d75ce9a46fe900a6f31dd4510b12a..8f1a4bd90e3cab0b5b02cfbf8611ade257933441 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp >@@ -65,6 +65,7 @@ > #include "JSTemplateObjectDescriptor.h" > #include "LLIntData.h" > #include "LLIntEntrypoint.h" >+#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" > #include "LowLevelInterpreter.h" > #include "ModuleProgramCodeBlock.h" > #include "ObjectAllocationProfileInlines.h" >@@ -1250,7 +1251,9 @@ void CodeBlock::finalizeLLIntInlineCaches() > for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { > Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]]; > switch (Interpreter::getOpcodeID(curInstruction[0])) { >- case op_get_by_id: { >+ case op_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: { > StructureID oldStructureID = curInstruction[4].u.structureID; > if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID))) > break; >@@ -1344,6 +1347,12 @@ void CodeBlock::finalizeLLIntInlineCaches() > } > } > >+ // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set >+ // then cleared the cache without GCing in between. >+ m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool { >+ return !Heap::isMarked(pair.key); >+ }); >+ > for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) { > if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) { > if (Options::verboseOSR()) >diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h >index 854f34f0f777a454f6dc0317068d723811debcea..97b8ab943bc33baa6c7400b9184e4d28d9eb4978 100644 >--- a/Source/JavaScriptCore/bytecode/CodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h >@@ -54,6 +54,7 @@ > #include "JSGlobalObject.h" > #include "JumpTable.h" > #include "LLIntCallLinkInfo.h" >+#include "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" > #include "LazyOperandValueProfile.h" > #include "ModuleProgramExecutable.h" > #include "ObjectAllocationProfile.h" >@@ -627,6 +628,9 @@ public: > return m_llintExecuteCounter; > } > >+ typedef HashMap<Structure*, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap; >+ StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; } >+ > // Functions for controlling when tiered compilation kicks in. This > // controls both when the optimizing compiler is invoked and when OSR > // entry happens. Two triggers exist: the loop trigger and the return >@@ -971,6 +975,7 @@ private: > > RefCountedArray<LLIntCallLinkInfo> m_llintCallLinkInfos; > SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo>> m_incomingLLIntCalls; >+ StructureWatchpointMap m_llintGetByIdWatchpointMap; > PoisonedRefPtr<CodeBlockPoison, JITCode> m_jitCode; > #if ENABLE(JIT) > std::unique_ptr<RegisterAtOffsetList> m_calleeSaveRegisters; >diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp >index 9fcde551b1202e8d9a855188fc5628572238a7a2..04a3767d551104642a67b361264abdc46193c193 100644 >--- a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp >+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp >@@ -104,7 +104,11 @@ GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned > } > > case op_get_array_length: >- case op_try_get_by_id: { >+ case op_try_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: { >+ // FIXME: We should not just bail if we see a try_get_by_id or a get_by_id_proto_load. >+ // https://bugs.webkit.org/show_bug.cgi?id=158039 > return GetByIdStatus(NoInformation, false); > } > >diff --git a/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp b/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..d6cc22d5150df8ecdb8bb8a35c5acd2c57f71e50 >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.cpp >@@ -0,0 +1,60 @@ >+/* >+ * Copyright (C) 2016-2017 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 "LLIntPrototypeLoadAdaptiveStructureWatchpoint.h" >+ >+#include "CodeBlock.h" >+#include "Instruction.h" >+#include "JSCInlines.h" >+ >+namespace JSC { >+ >+LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, Instruction* getByIdInstruction) >+ : m_key(key) >+ , m_getByIdInstruction(getByIdInstruction) >+{ >+ RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint()); >+ RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint()); >+} >+ >+void LLIntPrototypeLoadAdaptiveStructureWatchpoint::install() >+{ >+ RELEASE_ASSERT(m_key.isWatchable()); >+ >+ m_key.object()->structure()->addTransitionWatchpoint(this); >+} >+ >+void LLIntPrototypeLoadAdaptiveStructureWatchpoint::fireInternal(const FireDetail&) >+{ >+ if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) { >+ install(); >+ return; >+ } >+ >+ CodeBlock::clearLLIntGetByIdCache(m_getByIdInstruction); >+} >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h b/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h >new file mode 100644 >index 0000000000000000000000000000000000000000..8a73c6c79d7fd354658ec6a39caa40d1a043058e >--- /dev/null >+++ b/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h >@@ -0,0 +1,48 @@ >+/* >+ * Copyright (C) 2016 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 "Instruction.h" >+#include "ObjectPropertyCondition.h" >+#include "Watchpoint.h" >+ >+namespace JSC { >+ >+class LLIntPrototypeLoadAdaptiveStructureWatchpoint : public Watchpoint { >+public: >+ LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, Instruction*); >+ >+ void install(); >+ >+protected: >+ void fireInternal(const FireDetail&) override; >+ >+private: >+ ObjectPropertyCondition m_key; >+ Instruction* m_getByIdInstruction; >+}; >+ >+} // namespace JSC >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 8695ca05bb2ee5a21d5dac91091cb14eb6336999..6d6449b30e278c3efae7082ee9e7005efd0b59b6 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -2703,6 +2703,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co > instructions().append(0); > instructions().append(0); > instructions().append(0); >+ instructions().append(Options::prototypeHitCountForLLIntCaching()); > instructions().append(profile); > return dst; > } >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index 35e35227b2da2a3f462e3e345374c738e984d9c1..4059022f0ceba51d305b5ecdd238fa969f0d5018 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -5153,6 +5153,8 @@ void ByteCodeParser::parseBlock(unsigned limit) > case op_get_by_id_direct: > case op_try_get_by_id: > case op_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > case op_get_array_length: { > SpeculatedType prediction = getPrediction(); > >diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >index db84e96f38d4e1c07a9b805584e4213823a13390..5cee65b6843eca5088ed1a9a91094f34057aaa44 100644 >--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >@@ -164,6 +164,8 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc > case op_put_by_val_direct: > case op_try_get_by_id: > case op_get_by_id: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > case op_get_by_id_with_this: > case op_get_by_id_direct: > case op_get_by_val_with_this: >diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp >index 17466934c9ccbf1ca5f81011fe0656db0cc7a52d..1d3cc911ef477822fbcfdca9f57158493e315bcd 100644 >--- a/Source/JavaScriptCore/jit/JIT.cpp >+++ b/Source/JavaScriptCore/jit/JIT.cpp >@@ -342,6 +342,8 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_beloweq) > DEFINE_OP(op_try_get_by_id) > case op_get_array_length: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > DEFINE_OP(op_get_by_id) > DEFINE_OP(op_get_by_id_with_this) > DEFINE_OP(op_get_by_id_direct) >@@ -519,6 +521,8 @@ void JIT::privateCompileSlowCases() > DEFINE_SLOWCASE_OP(op_eq) > DEFINE_SLOWCASE_OP(op_try_get_by_id) > case op_get_array_length: >+ case op_get_by_id_proto_load: >+ case op_get_by_id_unset: > DEFINE_SLOWCASE_OP(op_get_by_id) > DEFINE_SLOWCASE_OP(op_get_by_id_with_this) > DEFINE_SLOWCASE_OP(op_get_by_id_direct) >diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >index 817e6c930b12ca1f1d4fe6e2424c0e7d1e4001d6..88bcbc98d9fc52df16ff84aabaa4ea2c9e671025 100644 >--- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >+++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp >@@ -641,6 +641,63 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id_direct) > LLINT_RETURN_PROFILED(op_get_by_id_direct, result); > } > >+ >+static void setupGetByIdPrototypeCache(ExecState* exec, VM& vm, Instruction* pc, JSCell* baseCell, PropertySlot& slot, const Identifier& ident) >+{ >+ CodeBlock* codeBlock = exec->codeBlock(); >+ Structure* structure = baseCell->structure(); >+ >+ if (structure->typeInfo().prohibitsPropertyCaching()) >+ return; >+ >+ if (structure->needImpurePropertyWatchpoint()) >+ return; >+ >+ if (structure->isDictionary()) { >+ if (structure->hasBeenFlattenedBefore()) >+ return; >+ structure->flattenDictionaryStructure(vm, jsCast<JSObject*>(baseCell)); >+ } >+ >+ ObjectPropertyConditionSet conditions; >+ if (slot.isUnset()) >+ conditions = generateConditionsForPropertyMiss(vm, codeBlock, exec, structure, ident.impl()); >+ else >+ conditions = generateConditionsForPrototypePropertyHit(vm, codeBlock, exec, structure, slot.slotBase(), ident.impl()); >+ >+ if (!conditions.isValid()) >+ return; >+ >+ PropertyOffset offset = invalidOffset; >+ CodeBlock::StructureWatchpointMap& watchpointMap = codeBlock->llintGetByIdWatchpointMap(); >+ auto result = watchpointMap.add(structure, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>()); >+ for (ObjectPropertyCondition condition : conditions) { >+ if (!condition.isWatchable()) >+ return; >+ if (condition.condition().kind() == PropertyCondition::Presence) >+ offset = condition.condition().offset(); >+ result.iterator->value.add(condition, pc)->install(); >+ } >+ ASSERT((offset == invalidOffset) == slot.isUnset()); >+ >+ ConcurrentJSLocker locker(codeBlock->m_lock); >+ >+ if (slot.isUnset()) { >+ pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_unset); >+ pc[4].u.structureID = structure->id(); >+ return; >+ } >+ ASSERT(slot.isValue()); >+ >+ pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_proto_load); >+ pc[4].u.structureID = structure->id(); >+ pc[5].u.operand = offset; >+ // We know that this pointer will remain valid because it will be cleared by either a watchpoint fire or >+ // during GC when we clear the LLInt caches. >+ pc[6].u.pointer = slot.slotBase(); >+} >+ >+ > LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > { > LLINT_BEGIN(); >@@ -661,7 +718,9 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > StructureID oldStructureID = pc[4].u.structureID; > if (oldStructureID) { > auto opcode = Interpreter::getOpcodeID(pc[0]); >- if (opcode == op_get_by_id) { >+ if (opcode == op_get_by_id >+ || opcode == op_get_by_id_unset >+ || opcode == op_get_by_id_proto_load) { > Structure* a = vm.heap.structureIDTable().get(oldStructureID); > Structure* b = baseValue.asCell()->structure(vm); > >@@ -680,6 +739,9 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > pc[0].u.opcode = LLInt::getOpcode(op_get_by_id); > pc[4].u.pointer = nullptr; // old structure > pc[5].u.pointer = nullptr; // offset >+ >+ // Prevent the prototype cache from ever happening. >+ pc[7].u.operand = 0; > > if (structure->propertyAccessesAreCacheable() > && !structure->needImpurePropertyWatchpoint()) { >@@ -690,6 +752,11 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > pc[4].u.structureID = structure->id(); > pc[5].u.operand = slot.cachedOffset(); > } >+ } else if (UNLIKELY(pc[7].u.operand && (slot.isValue() || slot.isUnset()))) { >+ ASSERT(slot.slotBase() != baseValue); >+ >+ if (!(--pc[7].u.operand)) >+ setupGetByIdPrototypeCache(exec, vm, pc, baseCell, slot, ident); > } > } else if (!LLINT_ALWAYS_ACCESS_SLOW > && isJSArray(baseValue) >@@ -698,6 +765,9 @@ LLINT_SLOW_PATH_DECL(slow_path_get_by_id) > ArrayProfile* arrayProfile = codeBlock->getOrAddArrayProfile(codeBlock->bytecodeOffset(pc)); > arrayProfile->observeStructure(baseValue.asCell()->structure()); > pc[4].u.arrayProfile = arrayProfile; >+ >+ // Prevent the prototype cache from ever happening. >+ pc[7].u.operand = 0; > } > > pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result); >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >index 16d5ab867186de3ce95a8a804ae538cdeb8d5f3e..d51b6d14c00fad68d84770f3c03beb88646f2791 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm >@@ -1420,7 +1420,7 @@ _llint_op_get_by_id: > loadi 4[PC], t2 > storei t0, TagOffset[cfr, t2, 8] > storei t1, PayloadOffset[cfr, t2, 8] >- valueProfile(t0, t1, 28, t2) >+ valueProfile(t0, t1, 32, t2) > dispatch(constexpr op_get_by_id_length) > > .opGetByIdSlow: >@@ -1428,6 +1428,43 @@ _llint_op_get_by_id: > dispatch(constexpr op_get_by_id_length) > > >+_llint_op_get_by_id_proto_load: >+ traceExecution() >+ loadi 8[PC], t0 >+ loadi 16[PC], t1 >+ loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdProtoSlow) >+ loadi 20[PC], t2 >+ bineq JSCell::m_structureID[t3], t1, .opGetByIdProtoSlow >+ loadpFromInstruction(6, t3) >+ loadPropertyAtVariableOffset(t2, t3, t0, t1) >+ loadi 4[PC], t2 >+ storei t0, TagOffset[cfr, t2, 8] >+ storei t1, PayloadOffset[cfr, t2, 8] >+ valueProfile(t0, t1, 32, t2) >+ dispatch(constexpr op_get_by_id_proto_load_length) >+ >+.opGetByIdProtoSlow: >+ callSlowPath(_llint_slow_path_get_by_id) >+ dispatch(constexpr op_get_by_id_proto_load_length) >+ >+ >+_llint_op_get_by_id_unset: >+ traceExecution() >+ loadi 8[PC], t0 >+ loadi 16[PC], t1 >+ loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdUnsetSlow) >+ bineq JSCell::m_structureID[t3], t1, .opGetByIdUnsetSlow >+ loadi 4[PC], t2 >+ storei UndefinedTag, TagOffset[cfr, t2, 8] >+ storei 0, PayloadOffset[cfr, t2, 8] >+ valueProfile(UndefinedTag, 0, 32, t2) >+ dispatch(constexpr op_get_by_id_unset_length) >+ >+.opGetByIdUnsetSlow: >+ callSlowPath(_llint_slow_path_get_by_id) >+ dispatch(constexpr op_get_by_id_unset_length) >+ >+ > _llint_op_get_array_length: > traceExecution() > loadi 8[PC], t0 >@@ -1441,7 +1478,7 @@ _llint_op_get_array_length: > loadp JSObject::m_butterfly[t3], t0 > loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0 > bilt t0, 0, .opGetArrayLengthSlow >- valueProfile(Int32Tag, t0, 28, t2) >+ valueProfile(Int32Tag, t0, 32, t2) > storep t0, PayloadOffset[cfr, t1, 8] > storep Int32Tag, TagOffset[cfr, t1, 8] > dispatch(constexpr op_get_array_length_length) >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >index 7d2a98de1e2c65b66dd4cf791219555ad8eef3b7..626989d526faeb02a85b20e95d6dcb968abb0ad0 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >@@ -1342,7 +1342,7 @@ _llint_op_get_by_id: > loadisFromInstruction(1, t2) > loadPropertyAtVariableOffset(t1, t3, t0) > storeq t0, [cfr, t2, 8] >- valueProfile(t0, constexpr (op_get_by_id_length - 1), t1) >+ valueProfile(t0, 8, t1) > dispatch(constexpr op_get_by_id_length) > > .opGetByIdSlow: >@@ -1350,6 +1350,43 @@ _llint_op_get_by_id: > dispatch(constexpr op_get_by_id_length) > > >+_llint_op_get_by_id_proto_load: >+ traceExecution() >+ loadisFromInstruction(2, t0) >+ loadConstantOrVariableCell(t0, t3, .opGetByIdProtoSlow) >+ loadi JSCell::m_structureID[t3], t1 >+ loadisFromInstruction(4, t2) >+ bineq t2, t1, .opGetByIdProtoSlow >+ loadisFromInstruction(5, t1) >+ loadpFromInstruction(6, t3) >+ loadisFromInstruction(1, t2) >+ loadPropertyAtVariableOffset(t1, t3, t0) >+ storeq t0, [cfr, t2, 8] >+ valueProfile(t0, 8, t1) >+ dispatch(constexpr op_get_by_id_proto_load_length) >+ >+.opGetByIdProtoSlow: >+ callSlowPath(_llint_slow_path_get_by_id) >+ dispatch(constexpr op_get_by_id_proto_load_length) >+ >+ >+_llint_op_get_by_id_unset: >+ traceExecution() >+ loadisFromInstruction(2, t0) >+ loadConstantOrVariableCell(t0, t3, .opGetByIdUnsetSlow) >+ loadi JSCell::m_structureID[t3], t1 >+ loadisFromInstruction(4, t2) >+ bineq t2, t1, .opGetByIdUnsetSlow >+ loadisFromInstruction(1, t2) >+ storeq ValueUndefined, [cfr, t2, 8] >+ valueProfile(ValueUndefined, 8, t1) >+ dispatch(constexpr op_get_by_id_unset_length) >+ >+.opGetByIdUnsetSlow: >+ callSlowPath(_llint_slow_path_get_by_id) >+ dispatch(constexpr op_get_by_id_unset_length) >+ >+ > _llint_op_get_array_length: > traceExecution() > loadisFromInstruction(2, t0) >@@ -1364,7 +1401,7 @@ _llint_op_get_array_length: > loadi -sizeof IndexingHeader + IndexingHeader::u.lengths.publicLength[t0], t0 > bilt t0, 0, .opGetArrayLengthSlow > orq tagTypeNumber, t0 >- valueProfile(t0, constexpr (op_get_array_length_length - 1), t2) >+ valueProfile(t0, 8, t2) > storeq t0, [cfr, t1, 8] > dispatch(constexpr op_get_array_length_length) > >diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h >index ee18e2187baa7622520d2c8904dd903c08a2f2ce..7c1409ad70e56e4c197d0861cec62569b723e151 100644 >--- a/Source/JavaScriptCore/runtime/Options.h >+++ b/Source/JavaScriptCore/runtime/Options.h >@@ -457,6 +457,8 @@ constexpr bool enableWebAssemblyStreamingApi = false; > \ > v(bool, useICStats, false, Normal, nullptr) \ > \ >+ v(unsigned, prototypeHitCountForLLIntCaching, 2, Normal, "Number of prototype property hits before caching a prototype in the LLInt. A count of 0 means never cache.") \ >+ \ > v(bool, dumpCompiledRegExpPatterns, false, Normal, nullptr) \ > \ > v(bool, dumpModuleRecord, false, 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 185564
: 340222