Diff
Modified: trunk/JSTests/ChangeLog (207426 => 207427)
--- trunk/JSTests/ChangeLog 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/JSTests/ChangeLog 2016-10-17 20:43:43 UTC (rev 207427)
@@ -1,3 +1,28 @@
+2016-10-17 Yusuke Suzuki <utatane....@gmail.com>
+
+ [DOMJIT] Use DOMJIT::Patchpoint in IC
+ https://bugs.webkit.org/show_bug.cgi?id=163223
+
+ Reviewed by Saam Barati.
+
+ * stress/domjit-exception-ic.js: Added.
+ (shouldBe):
+ (access):
+ * stress/domjit-exception.js: Added.
+ (shouldBe):
+ (access):
+ * stress/domjit-getter-complex-with-incorrect-object.js: Added.
+ (shouldThrow):
+ (access):
+ (i.shouldThrow):
+ * stress/domjit-getter-complex.js: Added.
+ (shouldBe):
+ (access):
+ * stress/domjit-getter-try-catch-getter-as-get-by-id-register-restoration.js: Added.
+ (assert):
+ (bar):
+ (foo):
+
2016-10-15 Saam Barati <sbar...@apple.com>
Assertion failed under operationToLowerCase with a rope with zero length
Added: trunk/JSTests/stress/domjit-exception-ic.js (0 => 207427)
--- trunk/JSTests/stress/domjit-exception-ic.js (rev 0)
+++ trunk/JSTests/stress/domjit-exception-ic.js 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,37 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error(`bad value: ${String(actual)}`);
+}
+
+function shouldThrow(func, errorMessage) {
+ var errorThrown = false;
+ var error = null;
+ try {
+ func();
+ } catch (e) {
+ errorThrown = true;
+ error = e;
+ }
+ if (!errorThrown)
+ throw new Error('not thrown');
+ if (String(error) !== errorMessage)
+ throw new Error(`bad error: ${String(error)}`);
+}
+
+(function () {
+ let domjit = createDOMJITGetterComplexObject();
+ function access(object)
+ {
+ return object.customGetter;
+ }
+ noInline(access);
+ let normal = {
+ customGetter: 42
+ };
+ for (let i = 0; i < 1e4; ++i) {
+ shouldBe(access(domjit), 42);
+ shouldBe(access(normal), 42);
+ }
+ domjit.enableException();
+ shouldThrow(() => access(domjit), `Error: DOMJITGetterComplex slow call exception`);
+}());
Added: trunk/JSTests/stress/domjit-exception.js (0 => 207427)
--- trunk/JSTests/stress/domjit-exception.js (rev 0)
+++ trunk/JSTests/stress/domjit-exception.js 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,67 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error(`bad value: ${String(actual)}`);
+}
+
+function shouldThrow(func, errorMessage) {
+ var errorThrown = false;
+ var error = null;
+ try {
+ func();
+ } catch (e) {
+ errorThrown = true;
+ error = e;
+ }
+ if (!errorThrown)
+ throw new Error('not thrown');
+ if (String(error) !== errorMessage)
+ throw new Error(`bad error: ${String(error)}`);
+}
+(function () {
+ let domjit = createDOMJITGetterComplexObject();
+ function access(object)
+ {
+ return object.customGetter;
+ }
+ noInline(access);
+ for (var i = 0; i < 1e4; ++i)
+ shouldBe(access(domjit), 42);
+ domjit.enableException();
+ shouldThrow(() => access(domjit), `Error: DOMJITGetterComplex slow call exception`);
+}());
+(function () {
+ let domjit = createDOMJITGetterComplexObject();
+ function access(object)
+ {
+ return object.customGetter;
+ }
+ noInline(access);
+ for (let i = 0; i < 1e2; ++i)
+ shouldBe(access(domjit), 42);
+ domjit.enableException();
+ shouldThrow(() => access(domjit), `Error: DOMJITGetterComplex slow call exception`);
+}());
+(function () {
+ let domjit = createDOMJITGetterComplexObject();
+ function access(object)
+ {
+ return object.customGetter;
+ }
+ noInline(access);
+ for (let i = 0; i < 50; ++i)
+ shouldBe(access(domjit), 42);
+ domjit.enableException();
+ shouldThrow(() => access(domjit), `Error: DOMJITGetterComplex slow call exception`);
+}());
+(function () {
+ let domjit = createDOMJITGetterComplexObject();
+ function access(object)
+ {
+ return object.customGetter;
+ }
+ noInline(access);
+ for (let i = 0; i < 10; ++i)
+ shouldBe(access(domjit), 42);
+ domjit.enableException();
+ shouldThrow(() => access(domjit), `Error: DOMJITGetterComplex slow call exception`);
+}());
Added: trunk/JSTests/stress/domjit-getter-complex-with-incorrect-object.js (0 => 207427)
--- trunk/JSTests/stress/domjit-getter-complex-with-incorrect-object.js (rev 0)
+++ trunk/JSTests/stress/domjit-getter-complex-with-incorrect-object.js 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,28 @@
+function shouldThrow(func, errorMessage) {
+ var errorThrown = false;
+ var error = null;
+ try {
+ func();
+ } catch (e) {
+ errorThrown = true;
+ error = e;
+ }
+ if (!errorThrown)
+ throw new Error('not thrown');
+ if (String(error) !== errorMessage)
+ throw new Error(`bad error: ${String(error)}`);
+}
+
+var complex = createDOMJITGetterComplexObject();
+var object = {};
+object.__proto__ = complex;
+function access(object)
+{
+ return object.customGetter;
+}
+noInline(access);
+for (var i = 0; i < 1e4; ++i) {
+ shouldThrow(() => {
+ access(object);
+ }, `TypeError: Type error`);
+}
Added: trunk/JSTests/stress/domjit-getter-complex.js (0 => 207427)
--- trunk/JSTests/stress/domjit-getter-complex.js (rev 0)
+++ trunk/JSTests/stress/domjit-getter-complex.js 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,14 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error(`bad value: ${String(actual)}`);
+}
+
+var complex = createDOMJITGetterComplexObject();
+function access(complex)
+{
+ return complex.customGetter;
+}
+noInline(access);
+for (var i = 0; i < 1e4; ++i) {
+ shouldBe(access(complex), 42);
+}
Added: trunk/JSTests/stress/domjit-getter-try-catch-getter-as-get-by-id-register-restoration.js (0 => 207427)
--- trunk/JSTests/stress/domjit-getter-try-catch-getter-as-get-by-id-register-restoration.js (rev 0)
+++ trunk/JSTests/stress/domjit-getter-try-catch-getter-as-get-by-id-register-restoration.js 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,52 @@
+function assert(b) {
+ if (!b) throw new Error("bad value");
+}
+noInline(assert);
+
+let i;
+var o1 = createDOMJITGetterComplexObject();
+o1.x = "x";
+
+var o2 = {
+ customGetter: 40
+}
+
+var o3 = {
+ x: 100,
+ customGetter: "f"
+}
+
+function bar(i) {
+ if (i === -1000)
+ return o1;
+
+ if (i % 2)
+ return o3;
+ else
+ return o2;
+}
+noInline(bar);
+
+function foo(i) {
+ var o = bar(i);
+ let v;
+ let v2;
+ let v3;
+ try {
+ v2 = o.x;
+ v = o.customGetter + v2;
+ } catch(e) {
+ assert(v2 === "x");
+ assert(o === o1);
+ }
+}
+noInline(foo);
+
+foo(i);
+for (i = 0; i < 1000; i++)
+ foo(i);
+
+o1.enableException();
+i = -1000;
+for (let j = 0; j < 1000; j++)
+ foo(i);
Modified: trunk/Source/_javascript_Core/CMakeLists.txt (207426 => 207427)
--- trunk/Source/_javascript_Core/CMakeLists.txt 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/CMakeLists.txt 2016-10-17 20:43:43 UTC (rev 207427)
@@ -204,6 +204,7 @@
bytecode/ComplexGetStatus.cpp
bytecode/DataFormat.cpp
bytecode/DFGExitProfile.cpp
+ bytecode/DOMJITAccessCasePatchpointParams.cpp
bytecode/DeferredCompilationCallback.cpp
bytecode/DeferredSourceDump.cpp
bytecode/ExecutionCounter.cpp
Modified: trunk/Source/_javascript_Core/ChangeLog (207426 => 207427)
--- trunk/Source/_javascript_Core/ChangeLog 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-10-17 20:43:43 UTC (rev 207427)
@@ -1,3 +1,74 @@
+2016-10-17 Yusuke Suzuki <utatane....@gmail.com>
+
+ [DOMJIT] Use DOMJIT::Patchpoint in IC
+ https://bugs.webkit.org/show_bug.cgi?id=163223
+
+ Reviewed by Saam Barati.
+
+ This patch uses DOMJIT::Patchpoint to inline DOM accesses even in IC!
+ It is useful for Baseline JIT cases and GetById cases in DFG and FTL.
+ In AccessCase, we construct the environment that allows DOMJIT::Patchpoint
+ to emit code and make DOMJIT accessors inlined in IC.
+
+ To allow DOMJIT::Patchpoint to emit code, we create a mechanism to emit calls
+ required in DOMJIT::Patchpoint. This system is useful when we create the super-
+ polymorphic support[1] later. And inlining mechanism is useful even after
+ introducing super-polymorphic support since it can work even after we fire the
+ watchpoint for super-polymorphic handling.
+
+ This patch improves Dromaeo dom-traverse 8% (263.95 runs/s v.s. 244.07 runs/s).
+
+ [1]: https://bugs.webkit.org/show_bug.cgi?id=163226
+
+ * CMakeLists.txt:
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * bytecode/DOMJITAccessCasePatchpointParams.cpp: Added.
+ (JSC::SlowPathCallGeneratorWithArguments::SlowPathCallGeneratorWithArguments):
+ (JSC::SlowPathCallGeneratorWithArguments::generateImpl):
+ (JSC::DOMJITAccessCasePatchpointParams::emitSlowPathCalls):
+ * bytecode/DOMJITAccessCasePatchpointParams.h: Copied from Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.h.
+ (JSC::DOMJITAccessCasePatchpointParams::DOMJITAccessCasePatchpointParams):
+ (JSC::DOMJITAccessCasePatchpointParams::SlowPathCallGenerator::~SlowPathCallGenerator):
+ * bytecode/PolymorphicAccess.cpp:
+ (JSC::AccessGenerationState::liveRegistersForCall):
+ (JSC::AccessGenerationState::liveRegistersToPreserveAtExceptionHandlingCallSite):
+ (JSC::calleeSaveRegisters):
+ (JSC::AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling):
+ (JSC::AccessGenerationState::restoreLiveRegistersFromStackForCallWithThrownException):
+ (JSC::AccessGenerationState::restoreLiveRegistersFromStackForCall):
+ (JSC::AccessGenerationState::callSiteIndexForExceptionHandlingOrOriginal):
+ (JSC::AccessGenerationState::originalExceptionHandler):
+ (JSC::AccessCase::generateImpl):
+ (JSC::AccessCase::emitDOMJITGetter):
+ (JSC::PolymorphicAccess::regenerate):
+ (JSC::AccessGenerationState::preserveLiveRegistersToStackForCall): Deleted.
+ * bytecode/PolymorphicAccess.h:
+ (JSC::AccessGenerationState::SpillState::isEmpty):
+ (JSC::AccessGenerationState::setSpillStateForJSGetterSetter):
+ (JSC::AccessGenerationState::spillStateForJSGetterSetter):
+ (JSC::AccessGenerationState::liveRegistersForCall): Deleted.
+ (JSC::AccessGenerationState::numberOfStackBytesUsedForRegisterPreservation): Deleted.
+ (JSC::AccessGenerationState::liveRegistersToPreserveAtExceptionHandlingCallSite): Deleted.
+ * dfg/DFGDOMJITPatchpointParams.cpp:
+ * dfg/DFGDOMJITPatchpointParams.h:
+ * domjit/DOMJITPatchpoint.h:
+ * domjit/DOMJITPatchpointParams.h:
+ (JSC::DOMJIT::PatchpointParams::addSlowPathCall):
+ * ftl/FTLDOMJITPatchpointParams.cpp:
+ * ftl/FTLDOMJITPatchpointParams.h:
+ * jsc.cpp:
+ (WTF::DOMJITNode::checkDOMJITNode):
+ (WTF::DOMJITGetterComplex::DOMJITGetterComplex):
+ (WTF::DOMJITGetterComplex::createStructure):
+ (WTF::DOMJITGetterComplex::create):
+ (WTF::DOMJITGetterComplex::DOMJITNodeDOMJIT::DOMJITNodeDOMJIT):
+ (WTF::DOMJITGetterComplex::domJITNodeGetterSetter):
+ (WTF::DOMJITGetterComplex::finishCreation):
+ (WTF::DOMJITGetterComplex::functionEnableException):
+ (WTF::DOMJITGetterComplex::customGetter):
+ (GlobalObject::finishCreation):
+ (functionCreateDOMJITGetterComplexObject):
+
2016-10-17 Saam Barati <sbar...@apple.com>
Build fix for HasOwnPropertyCache::Entry caused slowdown by introducing a constructor that doesn't use move semantics for the RefPtr<UniquedStringImpl> parameter
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (207426 => 207427)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2016-10-17 20:43:43 UTC (rev 207427)
@@ -2114,6 +2114,8 @@
E39DA4A61B7E8B7C0084F33A /* JSModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */; };
E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3A421431D6F58930007C617 /* PreciseJumpTargetsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ E3BFD0BB1DAF80870065DEA2 /* DOMJITAccessCasePatchpointParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3BFD0B91DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.cpp */; };
+ E3BFD0BC1DAF808E0065DEA2 /* DOMJITAccessCasePatchpointParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BFD0BA1DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.h */; };
E3C08E3C1DA41B810039478F /* DOMJITPatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3D239C81B829C1C00BBEF67 /* JSModuleEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */; };
E3D239C91B829C1C00BBEF67 /* JSModuleEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4423,6 +4425,8 @@
E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; };
E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleRecord.h; sourceTree = "<group>"; };
E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreciseJumpTargetsInlines.h; sourceTree = "<group>"; };
+ E3BFD0B91DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMJITAccessCasePatchpointParams.cpp; sourceTree = "<group>"; };
+ E3BFD0BA1DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITAccessCasePatchpointParams.h; sourceTree = "<group>"; };
E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITPatchpoint.h; sourceTree = "<group>"; };
E3CB1E241DA7540A00FA1E56 /* DOMJITSlowPathCalls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITSlowPathCalls.h; sourceTree = "<group>"; };
E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleEnvironment.cpp; sourceTree = "<group>"; };
@@ -6824,6 +6828,8 @@
0F0B83A514BCF50400885B4F /* CodeType.h */,
0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */,
0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */,
+ E3BFD0B91DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.cpp */,
+ E3BFD0BA1DAF807C0065DEA2 /* DOMJITAccessCasePatchpointParams.h */,
62E3D5EF1B8D0B7300B868BB /* DataFormat.cpp */,
0F426A4A1460CD6B00131F8F /* DataFormat.h */,
0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */,
@@ -7526,6 +7532,7 @@
0F8364B7164B0C110053329A /* DFGBranchDirection.h in Headers */,
86EC9DC51328DF82002B2AD7 /* DFGByteCodeParser.h in Headers */,
0F256C361627B0AD007F2783 /* DFGCallArrayAllocatorSlowPathGenerator.h in Headers */,
+ E3BFD0BC1DAF808E0065DEA2 /* DOMJITAccessCasePatchpointParams.h in Headers */,
0FBDB9AD1AB0FBC6000B57E5 /* DFGCallCreateDirectArgumentsSlowPathGenerator.h in Headers */,
0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */,
0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */,
@@ -9422,6 +9429,7 @@
E35E035F1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp in Sources */,
A532438B18568335002ED692 /* InspectorProtocolObjects.cpp in Sources */,
A50E4B6118809DD50068A46D /* InspectorRuntimeAgent.cpp in Sources */,
+ E3BFD0BB1DAF80870065DEA2 /* DOMJITAccessCasePatchpointParams.cpp in Sources */,
A593CF821840377100BFCE27 /* InspectorValues.cpp in Sources */,
147F39CF107EC37600427A48 /* InternalFunction.cpp in Sources */,
1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */,
Added: trunk/Source/_javascript_Core/bytecode/DOMJITAccessCasePatchpointParams.cpp (0 => 207427)
--- trunk/Source/_javascript_Core/bytecode/DOMJITAccessCasePatchpointParams.cpp (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/DOMJITAccessCasePatchpointParams.cpp 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "DOMJITAccessCasePatchpointParams.h"
+
+#include "LinkBuffer.h"
+#include "PolymorphicAccess.h"
+#include "StructureStubInfo.h"
+
+#if ENABLE(JIT)
+
+namespace JSC {
+
+template<typename JumpType, typename FunctionType, typename ResultType, typename... Arguments>
+class SlowPathCallGeneratorWithArguments : public DOMJITAccessCasePatchpointParams::SlowPathCallGenerator {
+public:
+ SlowPathCallGeneratorWithArguments(JumpType from, CCallHelpers::Label to, FunctionType function, ResultType result, std::tuple<Arguments...> arguments)
+ : m_from(from)
+ , m_to(to)
+ , m_function(function)
+ , m_result(result)
+ , m_arguments(arguments)
+ {
+ }
+
+ template<size_t... ArgumentsIndex>
+ CCallHelpers::JumpList generateImpl(VM& vm, AccessGenerationState& state, const RegisterSet& usedRegistersByPatchpoint, CCallHelpers& jit, std::index_sequence<ArgumentsIndex...>)
+ {
+ CCallHelpers::JumpList exceptions;
+ // We spill (1) the used registers by IC and (2) the used registers by DOMJIT::Patchpoint.
+ AccessGenerationState::SpillState spillState = state.preserveLiveRegistersToStackForCall(usedRegistersByPatchpoint);
+
+ jit.store32(
+ CCallHelpers::TrustedImm32(state.callSiteIndexForExceptionHandlingOrOriginal().bits()),
+ CCallHelpers::tagFor(static_cast<VirtualRegister>(CallFrameSlot::argumentCount)));
+
+ jit.makeSpaceOnStackForCCall();
+
+ jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame);
+
+ // FIXME: Currently, we do not check any ARM EABI / SH4 things here.
+ // But it is OK because a compile error happens when you pass JSValueRegs as an argument.
+ // https://bugs.webkit.org/show_bug.cgi?id=163099
+ jit.setupArgumentsWithExecState(std::get<ArgumentsIndex>(m_arguments)...);
+
+ CCallHelpers::Call operationCall = jit.call();
+ auto function = m_function;
+ jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
+ linkBuffer.link(operationCall, FunctionPtr(function));
+ });
+
+ jit.setupResults(m_result);
+ jit.reclaimSpaceOnStackForCCall();
+
+ CCallHelpers::Jump noException = jit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
+
+ state.restoreLiveRegistersFromStackForCallWithThrownException(spillState);
+ exceptions.append(jit.jump());
+
+ noException.link(&jit);
+ RegisterSet dontRestore;
+ dontRestore.set(m_result);
+ state.restoreLiveRegistersFromStackForCall(spillState, dontRestore);
+
+ return exceptions;
+ }
+
+ CCallHelpers::JumpList generate(VM& vm, AccessGenerationState& state, const RegisterSet& usedRegistersByPatchpoint, CCallHelpers& jit) override
+ {
+ m_from.link(&jit);
+ CCallHelpers::JumpList exceptions = generateImpl(vm, state, usedRegistersByPatchpoint, jit, std::make_index_sequence<std::tuple_size<std::tuple<Arguments...>>::value>());
+ jit.jump().linkTo(m_to, &jit);
+ return exceptions;
+ }
+
+protected:
+ JumpType m_from;
+ CCallHelpers::Label m_to;
+ FunctionType m_function;
+ ResultType m_result;
+ std::tuple<Arguments...> m_arguments;
+};
+
+#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) \
+ void DOMJITAccessCasePatchpointParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers& jit, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) \
+ { \
+ CCallHelpers::Label to = jit.label(); \
+ m_generators.append(std::make_unique<SlowPathCallGeneratorWithArguments<CCallHelpers::JumpList, OperationType, ResultType, __VA_ARGS__>>(from, to, operation, result, args)); \
+ } \
+
+DOMJIT_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS)
+#undef JSC_DEFINE_CALL_OPERATIONS
+
+CCallHelpers::JumpList DOMJITAccessCasePatchpointParams::emitSlowPathCalls(VM& vm, AccessGenerationState& state, const RegisterSet& usedRegistersByPatchpoint, CCallHelpers& jit)
+{
+ CCallHelpers::JumpList exceptions;
+ for (auto& generator : m_generators)
+ exceptions.append(generator->generate(vm, state, usedRegistersByPatchpoint, jit));
+ return exceptions;
+}
+
+}
+
+#endif
Copied: trunk/Source/_javascript_Core/bytecode/DOMJITAccessCasePatchpointParams.h (from rev 207426, trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.h) (0 => 207427)
--- trunk/Source/_javascript_Core/bytecode/DOMJITAccessCasePatchpointParams.h (rev 0)
+++ trunk/Source/_javascript_Core/bytecode/DOMJITAccessCasePatchpointParams.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -0,0 +1,60 @@
+/*
+ * 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
+
+#if ENABLE(JIT)
+
+#include "DOMJITPatchpointParams.h"
+
+namespace JSC {
+
+struct AccessGenerationState;
+
+class DOMJITAccessCasePatchpointParams : public DOMJIT::PatchpointParams {
+public:
+ DOMJITAccessCasePatchpointParams(Vector<DOMJIT::Value>&& regs, Vector<GPRReg>&& gpScratch, Vector<FPRReg>&& fpScratch)
+ : DOMJIT::PatchpointParams(WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch))
+ {
+ }
+
+ class SlowPathCallGenerator {
+ public:
+ virtual ~SlowPathCallGenerator() { }
+ virtual CCallHelpers::JumpList generate(VM&, AccessGenerationState&, const RegisterSet& usedRegistersByPatchpoint, CCallHelpers&) = 0;
+ };
+
+ CCallHelpers::JumpList emitSlowPathCalls(VM&, AccessGenerationState&, const RegisterSet& usedRegistersByPatchpoint, CCallHelpers&);
+
+private:
+#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) override;
+ DOMJIT_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS)
+#undef JSC_DEFINE_CALL_OPERATIONS
+ Vector<std::unique_ptr<SlowPathCallGenerator>> m_generators;
+};
+
+}
+
+#endif
Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp (207426 => 207427)
--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.cpp 2016-10-17 20:43:43 UTC (rev 207427)
@@ -31,6 +31,8 @@
#include "BinarySwitch.h"
#include "CCallHelpers.h"
#include "CodeBlock.h"
+#include "DOMJITAccessCasePatchpointParams.h"
+#include "DOMJITCallDOMPatchpoint.h"
#include "DirectArguments.h"
#include "GetterSetter.h"
#include "Heap.h"
@@ -72,8 +74,29 @@
success.append(jit->jump());
}
-void AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling(const RegisterSet& extra)
+const RegisterSet& AccessGenerationState::liveRegistersForCall()
{
+ if (!m_calculatedRegistersForCallAndExceptionHandling)
+ calculateLiveRegistersForCallAndExceptionHandling();
+ return m_liveRegistersForCall;
+}
+
+const RegisterSet& AccessGenerationState::liveRegistersToPreserveAtExceptionHandlingCallSite()
+{
+ if (!m_calculatedRegistersForCallAndExceptionHandling)
+ calculateLiveRegistersForCallAndExceptionHandling();
+ return m_liveRegistersToPreserveAtExceptionHandlingCallSite;
+}
+
+static RegisterSet calleeSaveRegisters()
+{
+ RegisterSet result = RegisterSet::registersToNotSaveForJSCall();
+ result.filter(RegisterSet::registersToNotSaveForCCall());
+ return result;
+}
+
+const RegisterSet& AccessGenerationState::calculateLiveRegistersForCallAndExceptionHandling()
+{
if (!m_calculatedRegistersForCallAndExceptionHandling) {
m_calculatedRegistersForCallAndExceptionHandling = true;
@@ -83,36 +106,26 @@
RELEASE_ASSERT(JITCode::isOptimizingJIT(jit->codeBlock()->jitType()));
m_liveRegistersForCall = RegisterSet(m_liveRegistersToPreserveAtExceptionHandlingCallSite, allocator->usedRegisters());
- m_liveRegistersForCall.merge(extra);
- m_liveRegistersForCall.exclude(RegisterSet::registersToNotSaveForJSCall());
- m_liveRegistersForCall.merge(extra);
+ m_liveRegistersForCall.exclude(calleeSaveRegisters());
}
+ return m_liveRegistersForCall;
}
-void AccessGenerationState::preserveLiveRegistersToStackForCall(const RegisterSet& extra)
+auto AccessGenerationState::preserveLiveRegistersToStackForCall(const RegisterSet& extra) -> SpillState
{
- calculateLiveRegistersForCallAndExceptionHandling(extra);
+ RegisterSet liveRegisters = liveRegistersForCall();
+ liveRegisters.merge(extra);
unsigned extraStackPadding = 0;
- unsigned numberOfStackBytesUsedForRegisterPreservation = ScratchRegisterAllocator::preserveRegistersToStackForCall(*jit, liveRegistersForCall(), extraStackPadding);
- if (m_numberOfStackBytesUsedForRegisterPreservation != std::numeric_limits<unsigned>::max())
- RELEASE_ASSERT(numberOfStackBytesUsedForRegisterPreservation == m_numberOfStackBytesUsedForRegisterPreservation);
- m_numberOfStackBytesUsedForRegisterPreservation = numberOfStackBytesUsedForRegisterPreservation;
+ unsigned numberOfStackBytesUsedForRegisterPreservation = ScratchRegisterAllocator::preserveRegistersToStackForCall(*jit, liveRegisters, extraStackPadding);
+ return SpillState {
+ liveRegisters,
+ numberOfStackBytesUsedForRegisterPreservation
+ };
}
-void AccessGenerationState::restoreLiveRegistersFromStackForCall(bool isGetter)
+void AccessGenerationState::restoreLiveRegistersFromStackForCallWithThrownException(const SpillState& spillState)
{
- RegisterSet dontRestore;
- if (isGetter) {
- // This is the result value. We don't want to overwrite the result with what we stored to the stack.
- // We sometimes have to store it to the stack just in case we throw an exception and need the original value.
- dontRestore.set(valueRegs);
- }
- restoreLiveRegistersFromStackForCall(dontRestore);
-}
-
-void AccessGenerationState::restoreLiveRegistersFromStackForCallWithThrownException()
-{
// Even if we're a getter, we don't want to ignore the result value like we normally do
// because the getter threw, and therefore, didn't return a value that means anything.
// Instead, we want to restore that register to what it was upon entering the getter
@@ -119,7 +132,7 @@
// inline cache. The subtlety here is if the base and the result are the same register,
// and the getter threw, we want OSR exit to see the original base value, not the result
// of the getter call.
- RegisterSet dontRestore = liveRegistersForCall();
+ RegisterSet dontRestore = spillState.spilledRegisters;
// As an optimization here, we only need to restore what is live for exception handling.
// We can construct the dontRestore set to accomplish this goal by having it contain only
// what is live for call but not live for exception handling. By ignoring things that are
@@ -126,18 +139,19 @@
// only live at the call but not the exception handler, we will only restore things live
// at the exception handler.
dontRestore.exclude(liveRegistersToPreserveAtExceptionHandlingCallSite());
- restoreLiveRegistersFromStackForCall(dontRestore);
+ restoreLiveRegistersFromStackForCall(spillState, dontRestore);
}
-void AccessGenerationState::restoreLiveRegistersFromStackForCall(const RegisterSet& dontRestore)
+void AccessGenerationState::restoreLiveRegistersFromStackForCall(const SpillState& spillState, const RegisterSet& dontRestore)
{
unsigned extraStackPadding = 0;
- ScratchRegisterAllocator::restoreRegistersFromStackForCall(*jit, liveRegistersForCall(), dontRestore, m_numberOfStackBytesUsedForRegisterPreservation, extraStackPadding);
+ ScratchRegisterAllocator::restoreRegistersFromStackForCall(*jit, spillState.spilledRegisters, dontRestore, spillState.numberOfStackBytesUsedForRegisterPreservation, extraStackPadding);
}
CallSiteIndex AccessGenerationState::callSiteIndexForExceptionHandlingOrOriginal()
{
- RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling);
+ if (!m_calculatedRegistersForCallAndExceptionHandling)
+ calculateLiveRegistersForCallAndExceptionHandling();
if (!m_calculatedCallSiteIndex) {
m_calculatedCallSiteIndex = true;
@@ -151,8 +165,11 @@
return m_callSiteIndex;
}
-const HandlerInfo& AccessGenerationState::originalExceptionHandler() const
+const HandlerInfo& AccessGenerationState::originalExceptionHandler()
{
+ if (!m_calculatedRegistersForCallAndExceptionHandling)
+ calculateLiveRegistersForCallAndExceptionHandling();
+
RELEASE_ASSERT(m_needsToRestoreRegistersIfException);
HandlerInfo* exceptionHandler = jit->codeBlock()->handlerForIndex(stubInfo->callSiteIndex.bits());
RELEASE_ASSERT(exceptionHandler);
@@ -932,6 +949,16 @@
return;
}
+ if (m_type == CustomAccessorGetter && m_rareData->domJIT) {
+ // We do not need to emit CheckDOM operation since structure check ensures
+ // that the structure of the given base value is structure()! So all we should
+ // do is performing the CheckDOM thingy in IC compiling time here.
+ if (structure()->classInfo()->isSubClassOf(m_rareData->domJIT->thisClassInfo())) {
+ emitDOMJITGetter(state, baseForGetGPR);
+ return;
+ }
+ }
+
// Stuff for custom getters/setters.
CCallHelpers::Call operationCall;
@@ -940,13 +967,20 @@
CCallHelpers::Call fastPathCall;
CCallHelpers::Call slowPathCall;
- CCallHelpers::Jump success;
- CCallHelpers::Jump fail;
-
// This also does the necessary calculations of whether or not we're an
// exception handling call site.
- state.preserveLiveRegistersToStackForCall();
+ AccessGenerationState::SpillState spillState = state.preserveLiveRegistersToStackForCall();
+ auto restoreLiveRegistersFromStackForCall = [&](AccessGenerationState::SpillState& spillState, bool callHasReturnValue) {
+ RegisterSet dontRestore;
+ if (callHasReturnValue) {
+ // This is the result value. We don't want to overwrite the result with what we stored to the stack.
+ // We sometimes have to store it to the stack just in case we throw an exception and need the original value.
+ dontRestore.set(valueRegs);
+ }
+ state.restoreLiveRegistersFromStackForCall(spillState, dontRestore);
+ };
+
jit.store32(
CCallHelpers::TrustedImm32(state.callSiteIndexForExceptionHandlingOrOriginal().bits()),
CCallHelpers::tagFor(static_cast<VirtualRegister>(CallFrameSlot::argumentCount)));
@@ -966,6 +1000,8 @@
// Therefore, we temporarily grow the stack for the purpose of the call and then
// shrink it after.
+ state.setSpillStateForJSGetterSetter(spillState);
+
RELEASE_ASSERT(!m_rareData->callLinkInfo);
m_rareData->callLinkInfo = std::make_unique<CallLinkInfo>();
@@ -1065,9 +1101,10 @@
done.link(&jit);
- jit.addPtr(CCallHelpers::TrustedImm32((codeBlock->stackPointerOffset() * sizeof(Register)) - state.preservedReusedRegisterState.numberOfBytesPreserved - state.numberOfStackBytesUsedForRegisterPreservation()),
+ jit.addPtr(CCallHelpers::TrustedImm32((codeBlock->stackPointerOffset() * sizeof(Register)) - state.preservedReusedRegisterState.numberOfBytesPreserved - spillState.numberOfStackBytesUsedForRegisterPreservation),
GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
- state.restoreLiveRegistersFromStackForCall(isGetter());
+ bool callHasReturnValue = isGetter();
+ restoreLiveRegistersFromStackForCall(spillState, callHasReturnValue);
jit.addLinkTask(
[=, &vm] (LinkBuffer& linkBuffer) {
@@ -1127,11 +1164,12 @@
CCallHelpers::Jump noException =
jit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
- state.restoreLiveRegistersFromStackForCallWithThrownException();
+ state.restoreLiveRegistersFromStackForCallWithThrownException(spillState);
state.emitExplicitExceptionHandler();
noException.link(&jit);
- state.restoreLiveRegistersFromStackForCall(isGetter());
+ bool callHasReturnValue = isGetter();
+ restoreLiveRegistersFromStackForCall(spillState, callHasReturnValue);
}
state.succeed();
return;
@@ -1248,7 +1286,7 @@
RegisterSet extraRegistersToPreserve;
extraRegistersToPreserve.set(baseGPR);
extraRegistersToPreserve.set(valueRegs);
- state.preserveLiveRegistersToStackForCall(extraRegistersToPreserve);
+ AccessGenerationState::SpillState spillState = state.preserveLiveRegistersToStackForCall(extraRegistersToPreserve);
jit.store32(
CCallHelpers::TrustedImm32(
@@ -1288,11 +1326,11 @@
CCallHelpers::Jump noException =
jit.emitExceptionCheck(CCallHelpers::InvertedExceptionCheck);
- state.restoreLiveRegistersFromStackForCallWithThrownException();
+ state.restoreLiveRegistersFromStackForCallWithThrownException(spillState);
state.emitExplicitExceptionHandler();
noException.link(&jit);
- state.restoreLiveRegistersFromStackForCall();
+ state.restoreLiveRegistersFromStackForCall(spillState);
}
}
@@ -1385,6 +1423,124 @@
RELEASE_ASSERT_NOT_REACHED();
}
+void AccessCase::emitDOMJITGetter(AccessGenerationState& state, GPRReg baseForGetGPR)
+{
+ CCallHelpers& jit = *state.jit;
+ VM& vm = *jit.vm();
+ StructureStubInfo& stubInfo = *state.stubInfo;
+ JSValueRegs valueRegs = state.valueRegs;
+ GPRReg baseGPR = state.baseGPR;
+ GPRReg scratchGPR = state.scratchGPR;
+
+ // We construct the environment that can execute the DOMJIT::Patchpoint here.
+ Ref<DOMJIT::CallDOMPatchpoint> patchpoint = m_rareData->domJIT->callDOM();
+
+ Vector<GPRReg> gpScratch;
+ Vector<FPRReg> fpScratch;
+ Vector<DOMJIT::Value> regs;
+
+ ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
+ allocator.lock(baseGPR);
+#if USE(JSVALUE32_64)
+ allocator.lock(static_cast<GPRReg>(stubInfo.patch.baseTagGPR));
+#endif
+ allocator.lock(valueRegs);
+ allocator.lock(scratchGPR);
+
+ GPRReg paramBaseGPR = InvalidGPRReg;
+ GPRReg paramGlobalObjectGPR = InvalidGPRReg;
+ JSValueRegs paramValueRegs = valueRegs;
+ GPRReg remainingScratchGPR = InvalidGPRReg;
+
+ // valueRegs and baseForGetGPR may be the same. For example, in Baseline JIT, we pass the same regT0 for baseGPR and valueRegs.
+ // In FTL, there is no constraint that the baseForGetGPR interferes with the result. To make implementation simple in
+ // DOMJIT::Patchpoint, DOMJIT::Patchpoint assumes that result registers always early interfere with input registers, in this case,
+ // baseForGetGPR. So we move baseForGetGPR to the other register if baseForGetGPR == valueRegs.
+ if (baseForGetGPR != valueRegs.payloadGPR()) {
+ paramBaseGPR = baseForGetGPR;
+ if (!patchpoint->requireGlobalObject)
+ remainingScratchGPR = scratchGPR;
+ else
+ paramGlobalObjectGPR = scratchGPR;
+ } else {
+ jit.move(valueRegs.payloadGPR(), scratchGPR);
+ paramBaseGPR = scratchGPR;
+ if (patchpoint->requireGlobalObject)
+ paramGlobalObjectGPR = allocator.allocateScratchGPR();
+ }
+
+ JSGlobalObject* globalObjectForDOMJIT = structure()->globalObject();
+
+ regs.append(paramValueRegs);
+ if (patchpoint->requireGlobalObject) {
+ ASSERT(paramGlobalObjectGPR != InvalidGPRReg);
+ regs.append(DOMJIT::Value(paramGlobalObjectGPR, globalObjectForDOMJIT));
+ }
+ regs.append(paramBaseGPR);
+
+ if (patchpoint->numGPScratchRegisters) {
+ unsigned i = 0;
+ if (remainingScratchGPR != InvalidGPRReg) {
+ gpScratch.append(remainingScratchGPR);
+ ++i;
+ }
+ for (; i < patchpoint->numGPScratchRegisters; ++i)
+ gpScratch.append(allocator.allocateScratchGPR());
+ }
+
+ for (unsigned i = 0; i < patchpoint->numFPScratchRegisters; ++i)
+ fpScratch.append(allocator.allocateScratchFPR());
+
+ // Let's store the reused registers to the stack. After that, we can use allocated scratch registers.
+ ScratchRegisterAllocator::PreservedState preservedState =
+ allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
+
+ if (verbose) {
+ dataLog("baseGPR = ", baseGPR, "\n");
+ dataLog("valueRegs = ", valueRegs, "\n");
+ dataLog("scratchGPR = ", scratchGPR, "\n");
+ dataLog("paramBaseGPR = ", paramBaseGPR, "\n");
+ if (paramGlobalObjectGPR != InvalidGPRReg)
+ dataLog("paramGlobalObjectGPR = ", paramGlobalObjectGPR, "\n");
+ dataLog("paramValueRegs = ", paramValueRegs, "\n");
+ for (unsigned i = 0; i < patchpoint->numGPScratchRegisters; ++i)
+ dataLog("gpScratch[", i, "] = ", gpScratch[i], "\n");
+ }
+
+ if (patchpoint->requireGlobalObject)
+ jit.move(CCallHelpers::TrustedImmPtr(globalObjectForDOMJIT), paramGlobalObjectGPR);
+
+ // We just spill the registers used in DOMJIT::Patchpoint here. For not spilled registers here explicitly,
+ // they must be in the used register set passed by the callers (Baseline, DFG, and FTL) if they need to be kept.
+ // Some registers can be locked, but not in the used register set. For example, the caller could make baseGPR
+ // same to valueRegs, and not include it in the used registers since it will be changed.
+ RegisterSet registersToSpillForCCall;
+ for (auto& value : regs) {
+ DOMJIT::Reg reg = value.reg();
+ if (reg.isJSValueRegs())
+ registersToSpillForCCall.set(reg.jsValueRegs());
+ else if (reg.isGPR())
+ registersToSpillForCCall.set(reg.gpr());
+ else
+ registersToSpillForCCall.set(reg.fpr());
+ }
+ for (GPRReg reg : gpScratch)
+ registersToSpillForCCall.set(reg);
+ for (FPRReg reg : fpScratch)
+ registersToSpillForCCall.set(reg);
+ registersToSpillForCCall.exclude(RegisterSet::registersToNotSaveForCCall());
+
+ DOMJITAccessCasePatchpointParams params(WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
+ patchpoint->generator()->run(jit, params);
+ allocator.restoreReusedRegistersByPopping(jit, preservedState);
+ state.succeed();
+
+ CCallHelpers::JumpList exceptions = params.emitSlowPathCalls(vm, state, registersToSpillForCCall, jit);
+ exceptions.link(&jit);
+ allocator.restoreReusedRegistersByPopping(jit, preservedState);
+ state.emitExplicitExceptionHandler();
+}
+
PolymorphicAccess::PolymorphicAccess() { }
PolymorphicAccess::~PolymorphicAccess() { }
@@ -1684,13 +1840,15 @@
MacroAssembler::Label makeshiftCatchHandler = jit.label();
int stackPointerOffset = codeBlock->stackPointerOffset() * sizeof(EncodedJSValue);
+ AccessGenerationState::SpillState spillStateForJSGetterSetter = state.spillStateForJSGetterSetter();
+ ASSERT(!spillStateForJSGetterSetter.isEmpty());
stackPointerOffset -= state.preservedReusedRegisterState.numberOfBytesPreserved;
- stackPointerOffset -= state.numberOfStackBytesUsedForRegisterPreservation();
+ stackPointerOffset -= spillStateForJSGetterSetter.numberOfStackBytesUsedForRegisterPreservation;
jit.loadPtr(vm.addressOfCallFrameForCatch(), GPRInfo::callFrameRegister);
jit.addPtr(CCallHelpers::TrustedImm32(stackPointerOffset), GPRInfo::callFrameRegister, CCallHelpers::stackPointerRegister);
- state.restoreLiveRegistersFromStackForCallWithThrownException();
+ state.restoreLiveRegistersFromStackForCallWithThrownException(spillStateForJSGetterSetter);
state.restoreScratch();
CCallHelpers::Jump jumpToOSRExitExceptionHandler = jit.jump();
Modified: trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h (207426 => 207427)
--- trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/bytecode/PolymorphicAccess.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -277,6 +277,7 @@
void generateImpl(AccessGenerationState&);
void emitIntrinsicGetter(AccessGenerationState&);
+ void emitDOMJITGetter(AccessGenerationState&, GPRReg baseForGetGPR);
AccessType m_type { Load };
State m_state { Primordial };
@@ -472,20 +473,22 @@
void restoreScratch();
void succeed();
- void calculateLiveRegistersForCallAndExceptionHandling(const RegisterSet& extra = RegisterSet());
+ struct SpillState {
+ RegisterSet spilledRegisters { };
+ unsigned numberOfStackBytesUsedForRegisterPreservation { std::numeric_limits<unsigned>::max() };
- void preserveLiveRegistersToStackForCall(const RegisterSet& extra = RegisterSet());
+ bool isEmpty() const { return numberOfStackBytesUsedForRegisterPreservation == std::numeric_limits<unsigned>::max(); }
+ };
- void restoreLiveRegistersFromStackForCall(bool isGetter = false);
- void restoreLiveRegistersFromStackForCallWithThrownException();
- void restoreLiveRegistersFromStackForCall(const RegisterSet& dontRestore);
+ const RegisterSet& calculateLiveRegistersForCallAndExceptionHandling();
- const RegisterSet& liveRegistersForCall()
- {
- RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling);
- return m_liveRegistersForCall;
- }
+ SpillState preserveLiveRegistersToStackForCall(const RegisterSet& extra = RegisterSet());
+ void restoreLiveRegistersFromStackForCallWithThrownException(const SpillState&);
+ void restoreLiveRegistersFromStackForCall(const SpillState&, const RegisterSet& dontRestore = RegisterSet());
+
+ const RegisterSet& liveRegistersForCall();
+
CallSiteIndex callSiteIndexForExceptionHandlingOrOriginal();
CallSiteIndex callSiteIndexForExceptionHandling()
{
@@ -495,29 +498,30 @@
return m_callSiteIndex;
}
- const HandlerInfo& originalExceptionHandler() const;
- unsigned numberOfStackBytesUsedForRegisterPreservation() const
- {
- RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling);
- return m_numberOfStackBytesUsedForRegisterPreservation;
- }
+ const HandlerInfo& originalExceptionHandler();
bool needsToRestoreRegistersIfException() const { return m_needsToRestoreRegistersIfException; }
CallSiteIndex originalCallSiteIndex() const;
void emitExplicitExceptionHandler();
-
-private:
- const RegisterSet& liveRegistersToPreserveAtExceptionHandlingCallSite()
+
+ void setSpillStateForJSGetterSetter(SpillState& spillState)
{
- RELEASE_ASSERT(m_calculatedRegistersForCallAndExceptionHandling);
- return m_liveRegistersToPreserveAtExceptionHandlingCallSite;
+ if (!m_spillStateForJSGetterSetter.isEmpty()) {
+ ASSERT(m_spillStateForJSGetterSetter.numberOfStackBytesUsedForRegisterPreservation == spillState.numberOfStackBytesUsedForRegisterPreservation);
+ ASSERT(m_spillStateForJSGetterSetter.spilledRegisters == spillState.spilledRegisters);
+ }
+ m_spillStateForJSGetterSetter = spillState;
}
+ SpillState spillStateForJSGetterSetter() const { return m_spillStateForJSGetterSetter; }
+private:
+ const RegisterSet& liveRegistersToPreserveAtExceptionHandlingCallSite();
+
RegisterSet m_liveRegistersToPreserveAtExceptionHandlingCallSite;
RegisterSet m_liveRegistersForCall;
CallSiteIndex m_callSiteIndex { CallSiteIndex(std::numeric_limits<unsigned>::max()) };
- unsigned m_numberOfStackBytesUsedForRegisterPreservation { std::numeric_limits<unsigned>::max() };
+ SpillState m_spillStateForJSGetterSetter;
bool m_calculatedRegistersForCallAndExceptionHandling : 1;
bool m_needsToRestoreRegistersIfException : 1;
bool m_calculatedCallSiteIndex : 1;
Modified: trunk/Source/_javascript_Core/dfg/DFGDOMJITPatchpointParams.cpp (207426 => 207427)
--- trunk/Source/_javascript_Core/dfg/DFGDOMJITPatchpointParams.cpp 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/dfg/DFGDOMJITPatchpointParams.cpp 2016-10-17 20:43:43 UTC (rev 207427)
@@ -40,7 +40,7 @@
}
#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) \
- void DOMJITPatchpointParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers&, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) const \
+ void DOMJITPatchpointParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers&, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) \
{ \
dispatch(m_jit, from, operation, result, args, std::make_index_sequence<std::tuple_size<decltype(args)>::value>()); \
} \
Modified: trunk/Source/_javascript_Core/dfg/DFGDOMJITPatchpointParams.h (207426 => 207427)
--- trunk/Source/_javascript_Core/dfg/DFGDOMJITPatchpointParams.h 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/dfg/DFGDOMJITPatchpointParams.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -42,7 +42,7 @@
}
private:
-#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) const override;
+#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) override;
DOMJIT_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS)
#undef JSC_DEFINE_CALL_OPERATIONS
Modified: trunk/Source/_javascript_Core/domjit/DOMJITPatchpoint.h (207426 => 207427)
--- trunk/Source/_javascript_Core/domjit/DOMJITPatchpoint.h 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/domjit/DOMJITPatchpoint.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -34,7 +34,7 @@
class PatchpointParams;
-typedef CCallHelpers::JumpList PatchpointGeneratorFunction(CCallHelpers&, const PatchpointParams&);
+typedef CCallHelpers::JumpList PatchpointGeneratorFunction(CCallHelpers&, PatchpointParams&);
typedef SharedTask<PatchpointGeneratorFunction> PatchpointGenerator;
// DOMJIT patchpoint is the way to inject an opaque code generator into DFG and FTL.
Modified: trunk/Source/_javascript_Core/domjit/DOMJITPatchpointParams.h (207426 => 207427)
--- trunk/Source/_javascript_Core/domjit/DOMJITPatchpointParams.h 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/domjit/DOMJITPatchpointParams.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -55,13 +55,13 @@
}
template<typename FunctionType, typename ResultType, typename... Arguments>
- void addSlowPathCall(CCallHelpers::JumpList from, CCallHelpers& jit, FunctionType function, ResultType result, Arguments... arguments) const
+ void addSlowPathCall(CCallHelpers::JumpList from, CCallHelpers& jit, FunctionType function, ResultType result, Arguments... arguments)
{
addSlowPathCallImpl(from, jit, function, result, std::make_tuple(arguments...));
}
private:
-#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) JS_EXPORT_PRIVATE virtual void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) const = 0;
+#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) JS_EXPORT_PRIVATE virtual void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) = 0;
DOMJIT_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS)
#undef JSC_DEFINE_CALL_OPERATIONS
Modified: trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.cpp (207426 => 207427)
--- trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.cpp 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.cpp 2016-10-17 20:43:43 UTC (rev 207427)
@@ -50,7 +50,7 @@
}
#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) \
- void DOMJITPatchpointParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers& jit, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) const \
+ void DOMJITPatchpointParams::addSlowPathCallImpl(CCallHelpers::JumpList from, CCallHelpers& jit, OperationType operation, ResultType result, std::tuple<__VA_ARGS__> args) \
{ \
dispatch(jit, &m_state, m_params, m_node, m_exceptions, from, operation, result, args, std::make_index_sequence<std::tuple_size<decltype(args)>::value>()); \
} \
Modified: trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.h (207426 => 207427)
--- trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.h 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/ftl/FTLDOMJITPatchpointParams.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -46,7 +46,7 @@
}
private:
-#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) const override;
+#define JSC_DEFINE_CALL_OPERATIONS(OperationType, ResultType, ...) void addSlowPathCallImpl(CCallHelpers::JumpList, CCallHelpers&, OperationType, ResultType, std::tuple<__VA_ARGS__> args) override;
DOMJIT_SLOW_PATH_CALLS(JSC_DEFINE_CALL_OPERATIONS)
#undef JSC_DEFINE_CALL_OPERATIONS
Modified: trunk/Source/_javascript_Core/jsc.cpp (207426 => 207427)
--- trunk/Source/_javascript_Core/jsc.cpp 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/_javascript_Core/jsc.cpp 2016-10-17 20:43:43 UTC (rev 207427)
@@ -557,6 +557,22 @@
return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
}
+#if ENABLE(JIT)
+ static Ref<DOMJIT::Patchpoint> checkDOMJITNode()
+ {
+ Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
+ patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
+ CCallHelpers::JumpList failureCases;
+ failureCases.append(jit.branch8(
+ CCallHelpers::NotEqual,
+ CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()),
+ CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
+ return failureCases;
+ });
+ return patchpoint;
+ }
+#endif
+
static DOMJITNode* create(VM& vm, Structure* structure)
{
DOMJITNode* getter = new (NotNull, allocateCell<DOMJITNode>(vm.heap, sizeof(DOMJITNode))) DOMJITNode(vm, structure);
@@ -608,16 +624,7 @@
#if ENABLE(JIT)
Ref<DOMJIT::Patchpoint> checkDOM() override
{
- Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
- patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
- CCallHelpers::JumpList failureCases;
- failureCases.append(jit.branch8(
- CCallHelpers::NotEqual,
- CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()),
- CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1))));
- return failureCases;
- });
- return patchpoint;
+ return DOMJITNode::checkDOMJITNode();
}
Ref<DOMJIT::CallDOMPatchpoint> callDOM() override
@@ -624,7 +631,7 @@
{
Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
patchpoint->requireGlobalObject = false;
- patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
JSValueRegs results = params[0].jsValueRegs();
GPRReg dom = params[1].gpr();
@@ -666,6 +673,115 @@
}
};
+class DOMJITGetterComplex : public DOMJITNode {
+public:
+ DOMJITGetterComplex(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ DECLARE_INFO;
+ typedef DOMJITNode Base;
+ static const unsigned StructureFlags = Base::StructureFlags;
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info());
+ }
+
+ static DOMJITGetterComplex* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+ {
+ DOMJITGetterComplex* getter = new (NotNull, allocateCell<DOMJITGetterComplex>(vm.heap, sizeof(DOMJITGetterComplex))) DOMJITGetterComplex(vm, structure);
+ getter->finishCreation(vm, globalObject);
+ return getter;
+ }
+
+ class DOMJITNodeDOMJIT : public DOMJIT::GetterSetter {
+ public:
+ DOMJITNodeDOMJIT()
+ : DOMJIT::GetterSetter(DOMJITGetterComplex::customGetter, nullptr, DOMJITNode::info())
+ {
+ }
+
+#if ENABLE(JIT)
+ Ref<DOMJIT::Patchpoint> checkDOM() override
+ {
+ return DOMJITNode::checkDOMJITNode();
+ }
+
+ Ref<DOMJIT::CallDOMPatchpoint> callDOM() override
+ {
+ RefPtr<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
+ static_assert(GPRInfo::numberOfRegisters >= 4, "Number of registers should be larger or equal to 4.");
+ patchpoint->numGPScratchRegisters = GPRInfo::numberOfRegisters - 4;
+ patchpoint->numFPScratchRegisters = 3;
+ patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
+ JSValueRegs results = params[0].jsValueRegs();
+ GPRReg domGPR = params[2].gpr();
+ for (unsigned i = 0; i < patchpoint->numGPScratchRegisters; ++i)
+ jit.move(CCallHelpers::TrustedImm32(42), params.gpScratch(i));
+
+ params.addSlowPathCall(jit.jump(), jit, static_cast<EncodedJSValue(*)(ExecState*, void*)>([](ExecState* exec, void* pointer) {
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ auto* object = static_cast<DOMJITNode*>(pointer);
+ auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(object);
+ if (domjitGetterComplex) {
+ if (domjitGetterComplex->m_enableException)
+ return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
+ }
+ return JSValue::encode(jsNumber(object->value()));
+ }), results, domGPR);
+ return CCallHelpers::JumpList();
+
+ });
+ return *patchpoint.get();
+ }
+#endif
+ };
+
+ static DOMJIT::GetterSetter* domJITNodeGetterSetter()
+ {
+ static NeverDestroyed<DOMJITNodeDOMJIT> graph;
+ return &graph.get();
+ }
+
+private:
+ void finishCreation(VM& vm, JSGlobalObject* globalObject)
+ {
+ Base::finishCreation(vm);
+ DOMJIT::GetterSetter* domJIT = domJITNodeGetterSetter();
+ CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, domJIT->getter(), domJIT->setter(), domJIT);
+ putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, ReadOnly | CustomAccessor);
+ putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "enableException"), 0, functionEnableException, NoIntrinsic, 0);
+ }
+
+ static EncodedJSValue JSC_HOST_CALL functionEnableException(ExecState* exec)
+ {
+ auto* object = jsDynamicCast<DOMJITGetterComplex*>(exec->thisValue());
+ if (object)
+ object->m_enableException = true;
+ return JSValue::encode(jsUndefined());
+ }
+
+ static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
+ {
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto* thisObject = jsDynamicCast<DOMJITNode*>(JSValue::decode(thisValue));
+ if (!thisObject)
+ return throwVMTypeError(exec, scope);
+ if (auto* domjitGetterComplex = jsDynamicCast<DOMJITGetterComplex*>(JSValue::decode(thisValue))) {
+ if (domjitGetterComplex->m_enableException)
+ return JSValue::encode(throwException(exec, scope, createError(exec, ASCIILiteral("DOMJITGetterComplex slow call exception"))));
+ }
+ return JSValue::encode(jsNumber(thisObject->value()));
+ }
+
+ bool m_enableException { false };
+};
+
const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) };
const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, CREATE_METHOD_TABLE(Masquerader) };
const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, CREATE_METHOD_TABLE(Root) };
@@ -673,6 +789,7 @@
const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(CustomGetter) };
const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, 0, CREATE_METHOD_TABLE(DOMJITNode) };
const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(DOMJITGetter) };
+const ClassInfo DOMJITGetterComplex::s_info = { "DOMJITGetterComplex", &Base::s_info, 0, CREATE_METHOD_TABLE(DOMJITGetterComplex) };
const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) };
const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, 0, CREATE_METHOD_TABLE(SimpleObject) };
static bool test262AsyncPassed { false };
@@ -703,6 +820,7 @@
static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
@@ -990,6 +1108,7 @@
addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0);
addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0);
addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0);
+ addFunction(vm, "createDOMJITGetterComplexObject", functionCreateDOMJITGetterComplexObject, 0);
addFunction(vm, "createBuiltin", functionCreateBuiltin, 2);
addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0);
addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
@@ -1511,6 +1630,14 @@
return JSValue::encode(result);
}
+EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterComplexObject(ExecState* exec)
+{
+ JSLockHolder lock(exec);
+ Structure* structure = DOMJITGetterComplex::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull());
+ DOMJITGetterComplex* result = DOMJITGetterComplex::create(exec->vm(), exec->lexicalGlobalObject(), structure);
+ return JSValue::encode(result);
+}
+
EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec)
{
JSLockHolder lock(exec);
Modified: trunk/Source/WebCore/ChangeLog (207426 => 207427)
--- trunk/Source/WebCore/ChangeLog 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/WebCore/ChangeLog 2016-10-17 20:43:43 UTC (rev 207427)
@@ -1,3 +1,19 @@
+2016-10-17 Yusuke Suzuki <utatane....@gmail.com>
+
+ [DOMJIT] Use DOMJIT::Patchpoint in IC
+ https://bugs.webkit.org/show_bug.cgi?id=163223
+
+ Reviewed by Saam Barati.
+
+ Make DOMJITPatchpointParams non-const.
+
+ * domjit/DOMJITHelpers.h:
+ (WebCore::DOMJITHelpers::toWrapper):
+ * domjit/JSNodeDOMJIT.cpp:
+ (WebCore::createCallDOMForOffsetAccess):
+ (WebCore::checkNode):
+ (WebCore::NodeNodeTypeDOMJIT::callDOM):
+
2016-10-17 Chris Dumez <cdu...@apple.com>
Move form.reportValidity() behind InteractiveFormValidation setting
Modified: trunk/Source/WebCore/domjit/DOMJITHelpers.h (207426 => 207427)
--- trunk/Source/WebCore/domjit/DOMJITHelpers.h 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/WebCore/domjit/DOMJITHelpers.h 2016-10-17 20:43:43 UTC (rev 207427)
@@ -59,7 +59,7 @@
}
template<typename WrappedType, typename ToJSFunction>
-void toWrapper(CCallHelpers& jit, const JSC::DOMJIT::PatchpointParams& params, GPRReg wrapped, GPRReg globalObject, JSValueRegs result, ToJSFunction function, JSC::JSValue globalObjectConstant)
+void toWrapper(CCallHelpers& jit, JSC::DOMJIT::PatchpointParams& params, GPRReg wrapped, GPRReg globalObject, JSValueRegs result, ToJSFunction function, JSC::JSValue globalObjectConstant)
{
ASSERT(wrapped != result.payloadGPR());
ASSERT(globalObject != result.payloadGPR());
Modified: trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp (207426 => 207427)
--- trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp 2016-10-17 20:38:46 UTC (rev 207426)
+++ trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp 2016-10-17 20:43:43 UTC (rev 207427)
@@ -54,7 +54,7 @@
{
Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
patchpoint->numGPScratchRegisters = 1;
- patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
JSValueRegs result = params[0].jsValueRegs();
GPRReg globalObject = params[1].gpr();
GPRReg node = params[2].gpr();
@@ -84,7 +84,7 @@
static Ref<DOMJIT::Patchpoint> checkNode()
{
Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
- patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
CCallHelpers::JumpList failureCases;
failureCases.append(DOMJITHelpers::branchIfNotNode(jit, params[0].gpr()));
return failureCases;
@@ -157,7 +157,7 @@
{
Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
patchpoint->requireGlobalObject = false;
- patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
+ patchpoint->setGenerator([=](CCallHelpers& jit, DOMJIT::PatchpointParams& params) {
JSValueRegs result = params[0].jsValueRegs();
GPRReg node = params[1].gpr();
jit.load8(CCallHelpers::Address(node, JSC::JSCell::typeInfoTypeOffset()), result.payloadGPR());