Title: [174036] trunk
Revision
174036
Author
[email protected]
Date
2014-09-27 13:27:59 -0700 (Sat, 27 Sep 2014)

Log Message

Disable function.arguments
https://bugs.webkit.org/show_bug.cgi?id=137167

Source/_javascript_Core:

Rubber stamped by Geoffrey Garen.
        
Add an option to disable function.arguments. Add a test for disabling it.
        
Disabling function.arguments means that it returns an Arguments object that claims that
there were zero arguments. All other Arguments functionality still works, so any code
that tries to inspect this object will still think that it is looking at a perfectly
valid Arguments object.
        
This also makes function.arguments disabled by default. Note that the RJST harness will
enable them by default, to continue to get test coverage for the code that implements
the feature.
        
We will rip out that code once we're confident that it's really safe to remove this
feature. Only once we rip out that support will we be able to do optimizations to
leverage the lack of this feature. It's important to keep the support code, and the test
infrastructure, in place before we are confident. The logic to keep this working touches
the entire compiler and a large chunk of the runtime, so reimplementing it - or even
merging it back in - would be a nightmare. That's also basically the reason why we want
to rip it out if at all possible. It's a lot of terrible code.

* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::createArguments):
* runtime/Arguments.h:
(JSC::Arguments::create):
(JSC::Arguments::finishCreation):
* runtime/Options.h:
* tests/stress/disable-function-dot-arguments.js: Added.
(foo):
(bar):

Tools:

Rubber stamped by Geoffrey Garen
        
Enable the feature by default during tests.

* Scripts/run-jsc-stress-tests:

LayoutTests:

Rubber stamped by Geoffrey Garen.
        
Don't remove the tests for this, yet - but mark them as failing. We will rebase these,
or remove them entirely, once we know that it's safe to rip out this feature entirely.

* TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (174035 => 174036)


--- trunk/LayoutTests/ChangeLog	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/LayoutTests/ChangeLog	2014-09-27 20:27:59 UTC (rev 174036)
@@ -1,3 +1,15 @@
+2014-09-26  Filip Pizlo  <[email protected]>
+
+        Disable function.arguments
+        https://bugs.webkit.org/show_bug.cgi?id=137167
+
+        Rubber stamped by Geoffrey Garen.
+        
+        Don't remove the tests for this, yet - but mark them as failing. We will rebase these,
+        or remove them entirely, once we know that it's safe to rip out this feature entirely.
+
+        * TestExpectations:
+
 2014-09-27  Benjamin Poulain  <[email protected]>
 
         Chaining multiple :nth-child() does not work properly

Modified: trunk/LayoutTests/TestExpectations (174035 => 174036)


--- trunk/LayoutTests/TestExpectations	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/LayoutTests/TestExpectations	2014-09-27 20:27:59 UTC (rev 174036)
@@ -199,3 +199,27 @@
 
 # nth-child tests takes long time and Debug build sometimes timeouts because there are many test cases.
 webkit.org/b/137149 fast/selectors/nth-child-of-basics.html [ Slow ]
+
+# Deprecated tests for function.arguments. These tests need to stay in the tree because the RJST
+# harness will run these after forcibly reenabling the function.arguments feature. We want to
+# keep testing the feature for as long as we haven't achieved confidence that it is safe to
+# remove it entirely.
+webkit.org/b/137167 js/dfg-arguments-unexpected-escape.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-become-double.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-become-int32.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-int32.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-osr-exit-and-capture.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-reset-changetype.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-reset.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-simple.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-use-directly-from-inlined-code.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-use-from-all-the-places.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-use-from-getter.html [ Failure ]
+webkit.org/b/137167 js/dfg-inline-arguments-use-from-uninlined-code.html [ Failure ]
+webkit.org/b/137167 js/dfg-tear-off-arguments-not-activation.html [ Failure ]
+webkit.org/b/137167 js/dfg-tear-off-function-dot-arguments.html [ Failure ]
+webkit.org/b/137167 js/dom/exception-thrown-from-function-with-lazy-activation.html [ Failure ]
+webkit.org/b/137167 js/dom/function-dot-arguments2.html [ Failure ]
+webkit.org/b/137167 js/function-dot-arguments.html [ Failure ]
+webkit.org/b/137167 js/kde/function.html [ Failure ]
+webkit.org/b/137167 js/kde/function_arguments.html [ Failure ]

Modified: trunk/Source/_javascript_Core/ChangeLog (174035 => 174036)


--- trunk/Source/_javascript_Core/ChangeLog	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-09-27 20:27:59 UTC (rev 174036)
@@ -1,3 +1,39 @@
+2014-09-26  Filip Pizlo  <[email protected]>
+
+        Disable function.arguments
+        https://bugs.webkit.org/show_bug.cgi?id=137167
+
+        Rubber stamped by Geoffrey Garen.
+        
+        Add an option to disable function.arguments. Add a test for disabling it.
+        
+        Disabling function.arguments means that it returns an Arguments object that claims that
+        there were zero arguments. All other Arguments functionality still works, so any code
+        that tries to inspect this object will still think that it is looking at a perfectly
+        valid Arguments object.
+        
+        This also makes function.arguments disabled by default. Note that the RJST harness will
+        enable them by default, to continue to get test coverage for the code that implements
+        the feature.
+        
+        We will rip out that code once we're confident that it's really safe to remove this
+        feature. Only once we rip out that support will we be able to do optimizations to
+        leverage the lack of this feature. It's important to keep the support code, and the test
+        infrastructure, in place before we are confident. The logic to keep this working touches
+        the entire compiler and a large chunk of the runtime, so reimplementing it - or even
+        merging it back in - would be a nightmare. That's also basically the reason why we want
+        to rip it out if at all possible. It's a lot of terrible code.
+
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::Frame::createArguments):
+        * runtime/Arguments.h:
+        (JSC::Arguments::create):
+        (JSC::Arguments::finishCreation):
+        * runtime/Options.h:
+        * tests/stress/disable-function-dot-arguments.js: Added.
+        (foo):
+        (bar):
+
 2014-09-26  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: Automatic Inspection should continue once all breakpoints are loaded

Modified: trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp (174035 => 174036)


--- trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/Source/_javascript_Core/interpreter/StackVisitor.cpp	2014-09-27 20:27:59 UTC (rev 174036)
@@ -261,15 +261,20 @@
     CallFrame* physicalFrame = m_callFrame;
     VM& vm = physicalFrame->vm();
     Arguments* arguments;
+    ArgumentsMode mode;
+    if (Options::enableFunctionDotArguments())
+        mode = NormalArgumentsCreationMode;
+    else
+        mode = FakeArgumentValuesCreationMode;
 #if ENABLE(DFG_JIT)
     if (isInlinedFrame()) {
         ASSERT(m_inlineCallFrame);
-        arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame);
+        arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame, mode);
         arguments->tearOff(physicalFrame, m_inlineCallFrame);
     } else 
 #endif
     {
-        arguments = Arguments::create(vm, physicalFrame);
+        arguments = Arguments::create(vm, physicalFrame, mode);
         arguments->tearOff(physicalFrame);
     }
     return arguments;

Modified: trunk/Source/_javascript_Core/runtime/Arguments.h (174035 => 174036)


--- trunk/Source/_javascript_Core/runtime/Arguments.h	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/Source/_javascript_Core/runtime/Arguments.h	2014-09-27 20:27:59 UTC (rev 174036)
@@ -35,23 +35,28 @@
 
 namespace JSC {
 
+enum ArgumentsMode {
+    NormalArgumentsCreationMode,
+    FakeArgumentValuesCreationMode
+};
+
 class Arguments : public JSNonFinalObject {
     friend class JIT;
     friend class JSArgumentsIterator;
 public:
     typedef JSNonFinalObject Base;
 
-    static Arguments* create(VM& vm, CallFrame* callFrame)
+    static Arguments* create(VM& vm, CallFrame* callFrame, ArgumentsMode mode = NormalArgumentsCreationMode)
     {
         Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap)) Arguments(callFrame);
-        arguments->finishCreation(callFrame);
+        arguments->finishCreation(callFrame, mode);
         return arguments;
     }
         
-    static Arguments* create(VM& vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame)
+    static Arguments* create(VM& vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode = NormalArgumentsCreationMode)
     {
         Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap)) Arguments(callFrame);
-        arguments->finishCreation(callFrame, inlineCallFrame);
+        arguments->finishCreation(callFrame, inlineCallFrame, mode);
         return arguments;
     }
 
@@ -107,8 +112,8 @@
 protected:
     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSObject::StructureFlags;
 
-    void finishCreation(CallFrame*);
-    void finishCreation(CallFrame*, InlineCallFrame*);
+    void finishCreation(CallFrame*, ArgumentsMode);
+    void finishCreation(CallFrame*, InlineCallFrame*, ArgumentsMode);
 
 private:
     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
@@ -271,62 +276,88 @@
     return m_lexicalEnvironment->registerAt(index - m_slowArgumentData->bytecodeToMachineCaptureOffset());
 }
 
-inline void Arguments::finishCreation(CallFrame* callFrame)
+inline void Arguments::finishCreation(CallFrame* callFrame, ArgumentsMode mode)
 {
     Base::finishCreation(callFrame->vm());
     ASSERT(inherits(info()));
 
     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
-    m_numArguments = callFrame->argumentCount();
-    m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers());
     m_callee.set(callFrame->vm(), this, callee);
     m_overrodeLength = false;
     m_overrodeCallee = false;
     m_overrodeCaller = false;
     m_isStrictMode = callFrame->codeBlock()->isStrictMode();
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    if (codeBlock->hasSlowArguments()) {
-        SymbolTable* symbolTable = codeBlock->symbolTable();
-        const SlowArgument* slowArguments = codeBlock->machineSlowArguments();
-        allocateSlowArguments(callFrame->vm());
-        size_t count = std::min<unsigned>(m_numArguments, symbolTable->parameterCount());
-        for (size_t i = 0; i < count; ++i)
-            m_slowArgumentData->slowArguments()[i] = slowArguments[i];
-        m_slowArgumentData->setBytecodeToMachineCaptureOffset(
-            codeBlock->framePointerOffsetToGetActivationRegisters());
+    switch (mode) {
+    case NormalArgumentsCreationMode: {
+        m_numArguments = callFrame->argumentCount();
+        m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers());
+
+        CodeBlock* codeBlock = callFrame->codeBlock();
+        if (codeBlock->hasSlowArguments()) {
+            SymbolTable* symbolTable = codeBlock->symbolTable();
+            const SlowArgument* slowArguments = codeBlock->machineSlowArguments();
+            allocateSlowArguments(callFrame->vm());
+            size_t count = std::min<unsigned>(m_numArguments, symbolTable->parameterCount());
+            for (size_t i = 0; i < count; ++i)
+                m_slowArgumentData->slowArguments()[i] = slowArguments[i];
+            m_slowArgumentData->setBytecodeToMachineCaptureOffset(
+                codeBlock->framePointerOffsetToGetActivationRegisters());
+        }
+
+        // The bytecode generator omits op_tear_off_lexical_environment in cases of no
+        // declared parameters, so we need to tear off immediately.
+        if (m_isStrictMode || !callee->jsExecutable()->parameterCount())
+            tearOff(callFrame);
+        break;
     }
-
-    // The bytecode generator omits op_tear_off_lexical_environment in cases of no
-    // declared parameters, so we need to tear off immediately.
-    if (m_isStrictMode || !callee->jsExecutable()->parameterCount())
+        
+    case FakeArgumentValuesCreationMode: {
+        m_numArguments = 0;
+        m_registers = nullptr;
         tearOff(callFrame);
+        break;
+    } }
+        
 }
 
-inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame)
+inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode)
 {
     Base::finishCreation(callFrame->vm());
     ASSERT(inherits(info()));
 
     JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame);
-    m_numArguments = inlineCallFrame->arguments.size() - 1;
-    
-    if (m_numArguments) {
-        int offsetForArgumentOne = inlineCallFrame->arguments[1].virtualRegister().offset();
-        m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + offsetForArgumentOne - virtualRegisterForArgument(1).offset();
-    } else
-        m_registers = 0;
     m_callee.set(callFrame->vm(), this, callee);
     m_overrodeLength = false;
     m_overrodeCallee = false;
     m_overrodeCaller = false;
     m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode();
-    ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->specializationKind())->slowArguments());
 
-    // The bytecode generator omits op_tear_off_lexical_environment in cases of no
-    // declared parameters, so we need to tear off immediately.
-    if (m_isStrictMode || !callee->jsExecutable()->parameterCount())
-        tearOff(callFrame, inlineCallFrame);
+    switch (mode) {
+    case NormalArgumentsCreationMode: {
+        m_numArguments = inlineCallFrame->arguments.size() - 1;
+        
+        if (m_numArguments) {
+            int offsetForArgumentOne = inlineCallFrame->arguments[1].virtualRegister().offset();
+            m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + offsetForArgumentOne - virtualRegisterForArgument(1).offset();
+        } else
+            m_registers = 0;
+        
+        ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->specializationKind())->slowArguments());
+        
+        // The bytecode generator omits op_tear_off_lexical_environment in cases of no
+        // declared parameters, so we need to tear off immediately.
+        if (m_isStrictMode || !callee->jsExecutable()->parameterCount())
+            tearOff(callFrame, inlineCallFrame);
+        break;
+    }
+        
+    case FakeArgumentValuesCreationMode: {
+        m_numArguments = 0;
+        m_registers = nullptr;
+        tearOff(callFrame);
+        break;
+    } }
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/Options.h (174035 => 174036)


--- trunk/Source/_javascript_Core/runtime/Options.h	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2014-09-27 20:27:59 UTC (rev 174036)
@@ -112,6 +112,8 @@
     v(bool, forceDebuggerBytecodeGeneration, false) \
     v(bool, forceProfilerBytecodeGeneration, false) \
     \
+    v(bool, enableFunctionDotArguments, false) \
+    \
     /* showDisassembly implies showDFGDisassembly. */ \
     v(bool, showDisassembly, false) \
     v(bool, showDFGDisassembly, false) \

Added: trunk/Source/_javascript_Core/tests/stress/disable-function-dot-arguments.js (0 => 174036)


--- trunk/Source/_javascript_Core/tests/stress/disable-function-dot-arguments.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/disable-function-dot-arguments.js	2014-09-27 20:27:59 UTC (rev 174036)
@@ -0,0 +1,20 @@
+//@ run("function-dot-arguments", "--enableFunctionDotArguments=false")
+
+function foo() {
+    var a = bar.arguments;
+    if (a.length != 0)
+        throw "Error: arguments have non-zero length";
+    for (var i = 0; i < 100; ++i) {
+        if (a[i] !== void 0)
+            throw "Error: argument " + i + " has non-undefined value";
+    }
+}
+
+function bar() {
+    foo();
+}
+
+bar();
+bar(1);
+bar(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+

Modified: trunk/Tools/ChangeLog (174035 => 174036)


--- trunk/Tools/ChangeLog	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/Tools/ChangeLog	2014-09-27 20:27:59 UTC (rev 174036)
@@ -1,3 +1,14 @@
+2014-09-26  Filip Pizlo  <[email protected]>
+
+        Disable function.arguments
+        https://bugs.webkit.org/show_bug.cgi?id=137167
+
+        Rubber stamped by Geoffrey Garen
+        
+        Enable the feature by default during tests.
+
+        * Scripts/run-jsc-stress-tests:
+
 2014-09-26  Beth Dakin  <[email protected]>
 
         Many platform/mac-wk2/tiled-drawing/ tests fail when run on a retina device

Modified: trunk/Tools/Scripts/run-jsc-stress-tests (174035 => 174036)


--- trunk/Tools/Scripts/run-jsc-stress-tests	2014-09-27 18:49:12 UTC (rev 174035)
+++ trunk/Tools/Scripts/run-jsc-stress-tests	2014-09-27 20:27:59 UTC (rev 174036)
@@ -260,9 +260,9 @@
 
 $numFailures = 0
 
+BASE_OPTIONS = ["--useFTLJIT=false", "--enableFunctionDotArguments=true"]
 EAGER_OPTIONS = ["--thresholdForJITAfterWarmUp=10", "--thresholdForJITSoon=10", "--thresholdForOptimizeAfterWarmUp=20", "--thresholdForOptimizeAfterLongWarmUp=20", "--thresholdForOptimizeSoon=20", "--thresholdForFTLOptimizeAfterWarmUp=20", "--thresholdForFTLOptimizeSoon=20"]
 NO_CJIT_OPTIONS = ["--enableConcurrentJIT=false", "--thresholdForJITAfterWarmUp=100"]
-NO_FTL_OPTIONS = ["--useFTLJIT=false"]
 FTL_OPTIONS = ["--useFTLJIT=true", "--enableExperimentalFTLCoverage=true"]
 
 $runlist = []
@@ -569,7 +569,7 @@
 end
 
 def run(kind, *options)
-    addRunCommand(kind, [pathToVM.to_s] + NO_FTL_OPTIONS + options + [$benchmark.to_s], silentOutputHandler, simpleErrorHandler)
+    addRunCommand(kind, [pathToVM.to_s] + BASE_OPTIONS + options + [$benchmark.to_s], silentOutputHandler, simpleErrorHandler)
 end
 
 def runDefault
@@ -728,7 +728,7 @@
     prepareExtraRelativeFiles(["../#{testName}-expected.txt"], $benchmarkDirectory)
     prepareExtraAbsoluteFiles(LAYOUTTESTS_PATH, ["resources/standalone-pre.js", "resources/standalone-post.js"])
 
-    args = [pathToVM.to_s] + NO_FTL_OPTIONS + options +
+    args = [pathToVM.to_s] + BASE_OPTIONS + options +
         [(Pathname.new("resources") + "standalone-pre.js").to_s,
          $benchmark.to_s,
          (Pathname.new("resources") + "standalone-post.js").to_s]
@@ -810,7 +810,7 @@
         kind = "mozilla"
     end
     prepareExtraRelativeFiles(extraFiles.map{|v| (Pathname("..") + v).to_s}, $collection)
-    args = [pathToVM.to_s] + NO_FTL_OPTIONS + options + extraFiles.map{|v| v.to_s} + [$benchmark.to_s]
+    args = [pathToVM.to_s] + BASE_OPTIONS + options + extraFiles.map{|v| v.to_s} + [$benchmark.to_s]
     case mode
     when :normal
         errorHandler = mozillaErrorHandler
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to