Title: [208377] trunk
Revision
208377
Author
[email protected]
Date
2016-11-03 23:18:01 -0700 (Thu, 03 Nov 2016)

Log Message

ClonedArguments need to also support haveABadTime mode.
https://bugs.webkit.org/show_bug.cgi?id=164200
<rdar://problem/27211336>

Reviewed by Geoffrey Garen.

JSTests:

* stress/have-a-bad-time-with-arguments.js: Added.

Source/_javascript_Core:

For those who are not familiar with the parlance, "have a bad time" in the VM
means that Object.prototype has been modified in such a way that we can no longer
trivially do indexed property accesses without consulting the Object.prototype.
This defeats JIT indexed put optimizations, and hence, makes the VM "have a
bad time".

Once the VM enters haveABadTime mode, all existing objects are converted to use
slow put storage.  Thereafter, JSArrays are always created with slow put storage.
JSObjects are always created with a blank indexing type.  When a new indexed
property is put into the new object, its indexing type will be converted to the
slow put array indexing type just before we perform the put operation.  This is
how we ensure that the objects will also use slow put storage.

However, ClonedArguments is an object which was previously created unconditionally
to use contiguous storage.  Subsequently, if we try to call Object.preventExtensions()
on that ClonedArguments object, Object.preventExtensions() will:
1. make the ClonedArguments enter dictionary indexing mode, which means it will
2. first ensure that the ClonedArguments is using slow put array storage via
   JSObject::ensureArrayStorageSlow().

However, JSObject::ensureArrayStorageSlow() expects that we never see an object
with contiguous storage once we're in haveABadTime mode.  Our ClonedArguments
object did not obey this invariant.

The fix is to make the ClonedArguments factories create objects that use slow put
array storage when in haveABadTime mode.  This means:

1. JSGlobalObject::haveABadTime() now changes m_clonedArgumentsStructure to use
   its slow put version.

   Also the caching of the slow put version of m_regExpMatchesArrayStructure,
   because we only need to create it when we are having a bad time. 

2. The ClonedArguments factories now allocates a butterfly with slow put array
   storage if we're in haveABadTime mode.

   Also added some assertions in ClonedArguments' factory methods to ensure that
   the created object has the slow put indexing type when it needsSlowPutIndexing().

3. DFGFixupPhase now watches the havingABadTimeWatchpoint because ClonedArguments'
   structure will change when having a bad time.

4. DFGArgumentEliminationPhase and DFGVarargsForwardingPhase need not be changed
   because it is still valid to eliminate the creation of the arguments object
   even having a bad time, as long as the arguments object does not escape.

5. The DFGAbstractInterpreterInlines now checks for haveABadTime, and sets the
   predicted type to be SpecObject.

Note: this issue does not apply to DirectArguments and ScopedArguments because
they use a blank indexing type (just like JSObject).

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::dump):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* runtime/ClonedArguments.cpp:
(JSC::ClonedArguments::createEmpty):
(JSC::ClonedArguments::createWithInlineFrame):
(JSC::ClonedArguments::createWithMachineFrame):
(JSC::ClonedArguments::createByCopyingFrom):
(JSC::ClonedArguments::createStructure):
(JSC::ClonedArguments::createSlowPutStructure):
* runtime/ClonedArguments.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::haveABadTime):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (208376 => 208377)


--- trunk/JSTests/ChangeLog	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/JSTests/ChangeLog	2016-11-04 06:18:01 UTC (rev 208377)
@@ -1,3 +1,13 @@
+2016-11-03  Mark Lam  <[email protected]>
+
+        ClonedArguments need to also support haveABadTime mode.
+        https://bugs.webkit.org/show_bug.cgi?id=164200
+        <rdar://problem/27211336>
+
+        Reviewed by Geoffrey Garen.
+
+        * stress/have-a-bad-time-with-arguments.js: Added.
+
 2016-11-03  Filip Pizlo  <[email protected]>
 
         DFG plays fast and loose with the shadow values of a Phi

Added: trunk/JSTests/stress/have-a-bad-time-with-arguments.js (0 => 208377)


--- trunk/JSTests/stress/have-a-bad-time-with-arguments.js	                        (rev 0)
+++ trunk/JSTests/stress/have-a-bad-time-with-arguments.js	2016-11-04 06:18:01 UTC (rev 208377)
@@ -0,0 +1,140 @@
+//@ runFTLNoCJIT
+
+// Tests accessing an element in arguments before and after having a bad time.
+// This test should not crash.
+
+let verbose = false;
+
+var utilities =                 'function shouldEqual(testId, actual, expected) {' + '\n' +
+                                '    if (actual != expected)' + '\n' +
+                                '        throw testId + ": ERROR: expect " + expected + ", actual " + actual;' + '\n' +
+                                '}' + '\n';
+
+var haveABadTime =              'Object.defineProperty(Object.prototype, 20, { get() { return 20; } });' + '\n';
+
+var directArgumentsDecl =       '    var args = arguments;' + '\n';
+
+var scopedArgumentsDecl =       '    var args = arguments;' + '\n' +
+                                '    function closure() { return x; }' + '\n';
+
+var clonedArgumentsDecl =       '    "use strict";' + '\n' +
+                                '    var args = arguments;' + '\n';
+
+function testFunction(argsDecl, insertElementAction, indexToReturn) {
+    var script =                'function test(x) {' + '\n' +
+                                     argsDecl +
+                                     insertElementAction +
+                                '    return args[' + indexToReturn + '];' + '\n' +
+                                '}' + '\n' +
+                                'noInline(test);' + '\n';
+    return script;
+}
+
+function warmupFunction(tierWarmupCount, testArgs) {
+    var script =                'function warmup() {' + '\n' +
+                                '    for (var i = 0; i < ' + tierWarmupCount + '; i++) {' + '\n' +
+                                '        test(' + testArgs + ');' + '\n' +
+                                '    }' + '\n' +
+                                '}' + '\n';
+    return script;
+}
+
+let argumentsDecls = {
+    direct: directArgumentsDecl,
+    scoped: scopedArgumentsDecl,
+    cloned: clonedArgumentsDecl
+};
+
+let indicesToReturn = {
+    inBounds: 0,
+    outOfBoundsInsertedElement: 10,
+    outOfBoundsInPrototype: 20
+};
+
+let tierWarmupCounts = {
+    llint: 1,
+    baseline: 50,
+    dfg: 1000,
+    ftl: 10000
+};
+
+let testArgsList = {
+    noArgs:   {
+        args: '',
+        result: {
+            inBounds: { beforeBadTime: 'undefined', afterBadTime: 'undefined', },
+            outOfBoundsInsertedElement: { beforeBadTime: '10', afterBadTime: '10', },
+            outOfBoundsInPrototype: { beforeBadTime: 'undefined', afterBadTime: '20', },
+        }
+    },
+    someArgs: {
+        args: '1, 2, 3',
+        result: {
+            inBounds: { beforeBadTime: '1', afterBadTime: '1', },
+            outOfBoundsInsertedElement: { beforeBadTime: '10', afterBadTime: '10', },
+            outOfBoundsInPrototype: { beforeBadTime: 'undefined', afterBadTime: '20', },
+        }
+    }
+};
+
+let insertElementActions = {
+    insertElement:      '    args[10] = 10;' + '\n',
+    dontInsertElement:  ''
+};
+
+for (let argsDeclIndex in argumentsDecls) {
+    let argsDecl = argumentsDecls[argsDeclIndex];
+
+    for (let indexToReturnIndex in indicesToReturn) {
+        let indexToReturn = indicesToReturn[indexToReturnIndex];
+
+        for (let insertElementActionIndex in insertElementActions) {
+            let insertElementAction = insertElementActions[insertElementActionIndex];
+
+            for (let tierWarmupCountIndex in tierWarmupCounts) {
+                let tierWarmupCount = tierWarmupCounts[tierWarmupCountIndex];
+
+                for (let testArgsIndex in testArgsList) {
+                    let testArgs = testArgsList[testArgsIndex].args;
+                    let expectedResult = testArgsList[testArgsIndex].result[indexToReturnIndex];
+
+                    if (indexToReturnIndex == 'outOfBoundsInsertedElement'
+                        && insertElementActionIndex == 'dontInsertElement')
+                        expectedResult = 'undefined';
+
+                    let testName =
+                        argsDeclIndex + '-' +
+                        indexToReturnIndex + '-' +
+                        insertElementActionIndex + '-' +
+                        tierWarmupCountIndex + '-' +
+                        testArgsIndex;
+
+
+                    let script = utilities +
+                                 testFunction(argsDecl, insertElementAction, indexToReturn) +
+                                 warmupFunction(tierWarmupCount, testArgs) +
+                                 'warmup()' + '\n' +
+                                 'shouldEqual(10000, test(' + testArgs + '), ' + expectedResult['beforeBadTime'] + ');' + '\n';
+                                 haveABadTime +
+                                 'shouldEqual(20000, test(' + testArgs + '), ' + expectedResult['afterBadTime'] + ');' + '\n';
+
+                    if (verbose) {
+                        print('Running test configuration: ' + testName);
+                        print(
+                            'Test script: ====================================================\n' +
+                            script +
+                            '=== END script ==================================================');
+                    }
+
+                    try {
+                        runString(script);
+                    } catch (e) {
+                        print('FAILED test configuration: ' + testName);
+                        print('FAILED test script:\n' + script);
+                        throw e;
+                    }
+                }
+            }
+        }
+    }
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (208376 => 208377)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-04 06:18:01 UTC (rev 208377)
@@ -1,3 +1,83 @@
+2016-11-03  Mark Lam  <[email protected]>
+
+        ClonedArguments need to also support haveABadTime mode.
+        https://bugs.webkit.org/show_bug.cgi?id=164200
+        <rdar://problem/27211336>
+
+        Reviewed by Geoffrey Garen.
+
+        For those who are not familiar with the parlance, "have a bad time" in the VM
+        means that Object.prototype has been modified in such a way that we can no longer
+        trivially do indexed property accesses without consulting the Object.prototype.
+        This defeats JIT indexed put optimizations, and hence, makes the VM "have a
+        bad time".
+
+        Once the VM enters haveABadTime mode, all existing objects are converted to use
+        slow put storage.  Thereafter, JSArrays are always created with slow put storage.
+        JSObjects are always created with a blank indexing type.  When a new indexed
+        property is put into the new object, its indexing type will be converted to the
+        slow put array indexing type just before we perform the put operation.  This is
+        how we ensure that the objects will also use slow put storage.
+
+        However, ClonedArguments is an object which was previously created unconditionally
+        to use contiguous storage.  Subsequently, if we try to call Object.preventExtensions()
+        on that ClonedArguments object, Object.preventExtensions() will:
+        1. make the ClonedArguments enter dictionary indexing mode, which means it will
+        2. first ensure that the ClonedArguments is using slow put array storage via
+           JSObject::ensureArrayStorageSlow().
+
+        However, JSObject::ensureArrayStorageSlow() expects that we never see an object
+        with contiguous storage once we're in haveABadTime mode.  Our ClonedArguments
+        object did not obey this invariant.
+
+        The fix is to make the ClonedArguments factories create objects that use slow put
+        array storage when in haveABadTime mode.  This means:
+
+        1. JSGlobalObject::haveABadTime() now changes m_clonedArgumentsStructure to use
+           its slow put version.
+
+           Also the caching of the slow put version of m_regExpMatchesArrayStructure,
+           because we only need to create it when we are having a bad time. 
+
+        2. The ClonedArguments factories now allocates a butterfly with slow put array
+           storage if we're in haveABadTime mode.
+
+           Also added some assertions in ClonedArguments' factory methods to ensure that
+           the created object has the slow put indexing type when it needsSlowPutIndexing().
+
+        3. DFGFixupPhase now watches the havingABadTimeWatchpoint because ClonedArguments'
+           structure will change when having a bad time.
+
+        4. DFGArgumentEliminationPhase and DFGVarargsForwardingPhase need not be changed
+           because it is still valid to eliminate the creation of the arguments object
+           even having a bad time, as long as the arguments object does not escape.
+
+        5. The DFGAbstractInterpreterInlines now checks for haveABadTime, and sets the
+           predicted type to be SpecObject.
+
+        Note: this issue does not apply to DirectArguments and ScopedArguments because
+        they use a blank indexing type (just like JSObject).
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::dump):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * runtime/ClonedArguments.cpp:
+        (JSC::ClonedArguments::createEmpty):
+        (JSC::ClonedArguments::createWithInlineFrame):
+        (JSC::ClonedArguments::createWithMachineFrame):
+        (JSC::ClonedArguments::createByCopyingFrom):
+        (JSC::ClonedArguments::createStructure):
+        (JSC::ClonedArguments::createSlowPutStructure):
+        * runtime/ClonedArguments.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::haveABadTime):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+
 2016-11-03  Filip Pizlo  <[email protected]>
 
         DFG plays fast and loose with the shadow values of a Phi

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (208376 => 208377)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2016-11-04 06:18:01 UTC (rev 208377)
@@ -1981,6 +1981,10 @@
         break;
         
     case CreateClonedArguments:
+        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
+            forNode(node).setType(m_graph, SpecObject);
+            break;
+        }
         forNode(node).set(m_graph, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
         break;
 

Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp (208376 => 208377)


--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp	2016-11-04 06:18:01 UTC (rev 208377)
@@ -734,7 +734,7 @@
 
 void ArrayMode::dump(PrintStream& out) const
 {
-    out.print(type(), arrayClass(), speculation(), conversion());
+    out.print(type(), "+", arrayClass(), "+", speculation(), "+", conversion());
 }
 
 } } // namespace JSC::DFG

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (208376 => 208377)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2016-11-04 06:18:01 UTC (rev 208377)
@@ -1550,6 +1550,11 @@
             break;
         }
 
+        case CreateClonedArguments: {
+            watchHavingABadTime(node);
+            break;
+        }
+
         case CreateScopedArguments:
         case CreateActivation:
         case NewFunction:
@@ -1776,7 +1781,6 @@
         case IsObjectOrNull:
         case IsFunction:
         case CreateDirectArguments:
-        case CreateClonedArguments:
         case Jump:
         case Return:
         case TailCall:

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (208376 => 208377)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2016-11-04 06:18:01 UTC (rev 208377)
@@ -32,7 +32,6 @@
 
 #include "BatchedTransitionOptimizer.h"
 #include "CallFrameClosure.h"
-#include "ClonedArguments.h"
 #include "CodeBlock.h"
 #include "DirectArguments.h"
 #include "Heap.h"

Modified: trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp (208376 => 208377)


--- trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/runtime/ClonedArguments.cpp	2016-11-04 06:18:01 UTC (rev 208377)
@@ -48,16 +48,23 @@
     if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
         return 0;
 
-    void* temp = vm.heap.tryAllocateAuxiliary(nullptr, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
-    if (!temp)
-        return 0;
-    Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
-    butterfly->setVectorLength(vectorLength);
-    butterfly->setPublicLength(length);
+    Butterfly* butterfly;
+    if (UNLIKELY(structure->needsSlowPutIndexing())) {
+        butterfly = createArrayStorageButterfly(vm, nullptr, structure, length, vectorLength);
+        butterfly->arrayStorage()->m_numValuesInVector = vectorLength;
+
+    } else {
+        void* temp = vm.heap.tryAllocateAuxiliary(nullptr, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
+        if (!temp)
+            return 0;
+        butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
+        butterfly->setVectorLength(vectorLength);
+        butterfly->setPublicLength(length);
+        
+        for (unsigned i = length; i < vectorLength; ++i)
+            butterfly->contiguous()[i].clear();
+    }
     
-    for (unsigned i = length; i < vectorLength; ++i)
-        butterfly->contiguous()[i].clear();
-
     ClonedArguments* result =
         new (NotNull, allocateCell<ClonedArguments>(vm.heap))
         ClonedArguments(vm, structure, butterfly);
@@ -70,9 +77,12 @@
 
 ClonedArguments* ClonedArguments::createEmpty(ExecState* exec, JSFunction* callee, unsigned length)
 {
+    VM& vm = exec->vm();
     // NB. Some clients might expect that the global object of of this object is the global object
     // of the callee. We don't do this for now, but maybe we should.
-    return createEmpty(exec->vm(), exec->lexicalGlobalObject()->clonedArgumentsStructure(), callee, length);
+    ClonedArguments* result = createEmpty(vm, exec->lexicalGlobalObject()->clonedArgumentsStructure(), callee, length);
+    ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType()));
+    return result;
 }
 
 ClonedArguments* ClonedArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode)
@@ -117,12 +127,15 @@
     } }
 
     ASSERT(myFrame->lexicalGlobalObject()->clonedArgumentsStructure() == result->structure());
+    ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType()));
     return result;
 }
 
 ClonedArguments* ClonedArguments::createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode mode)
 {
-    return createWithInlineFrame(myFrame, targetFrame, nullptr, mode);
+    ClonedArguments* result = createWithInlineFrame(myFrame, targetFrame, nullptr, mode);
+    ASSERT(!result->structure()->needsSlowPutIndexing() || shouldUseSlowPut(result->structure()->indexingType()));
+    return result;
 }
 
 ClonedArguments* ClonedArguments::createByCopyingFrom(
@@ -134,15 +147,13 @@
     
     for (unsigned i = length; i--;)
         result->initializeIndex(vm, i, argumentStart[i].jsValue());
-
+    ASSERT(!result->structure(vm)->needsSlowPutIndexing() || shouldUseSlowPut(result->structure(vm)->indexingType()));
     return result;
 }
 
-Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
 {
-    // We use contiguous storage because optimizations in the FTL assume that cloned arguments creation always produces the same initial structure.
-
-    Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), NonArrayWithContiguous);
+    Structure* structure = Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), indexingType);
     PropertyOffset offset;
     structure = structure->addPropertyTransition(vm, structure, vm.propertyNames->length, DontEnum, offset);
     ASSERT(offset == clonedArgumentsLengthPropertyOffset);
@@ -149,6 +160,17 @@
     return structure;
 }
 
+Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    // We use contiguous storage because optimizations in the FTL assume that cloned arguments creation always produces the same initial structure.
+    return createStructure(vm, globalObject, prototype, NonArrayWithContiguous);
+}
+
+Structure* ClonedArguments::createSlowPutStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return createStructure(vm, globalObject, prototype, NonArrayWithSlowPutArrayStorage);
+}
+
 bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot)
 {
     ClonedArguments* thisObject = jsCast<ClonedArguments*>(object);

Modified: trunk/Source/_javascript_Core/runtime/ClonedArguments.h (208376 => 208377)


--- trunk/Source/_javascript_Core/runtime/ClonedArguments.h	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/runtime/ClonedArguments.h	2016-11-04 06:18:01 UTC (rev 208377)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -53,6 +53,7 @@
     static ClonedArguments* createByCopyingFrom(ExecState*, Structure*, Register* argumentsStart, unsigned length, JSFunction* callee);
     
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
+    static Structure* createSlowPutStructure(VM&, JSGlobalObject*, JSValue prototype);
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
@@ -59,6 +60,8 @@
     DECLARE_INFO;
 
 private:
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype, IndexingType);
+
     static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
     static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
     static bool put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (208376 => 208377)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2016-11-04 06:18:01 UTC (rev 208377)
@@ -537,7 +537,6 @@
     m_regExpPrototype.set(vm, this, RegExpPrototype::create(vm, this, RegExpPrototype::createStructure(vm, this, m_objectPrototype.get())));
     m_regExpStructure.set(vm, this, RegExpObject::createStructure(vm, this, m_regExpPrototype.get()));
     m_regExpMatchesArrayStructure.set(vm, this, createRegExpMatchesArrayStructure(vm, this));
-    m_regExpMatchesArraySlowPutStructure.set(vm, this, createRegExpMatchesArraySlowPutStructure(vm, this));
 
     m_moduleRecordStructure.set(vm, this, JSModuleRecord::createStructure(vm, this, m_objectPrototype.get()));
     m_moduleNamespaceObjectStructure.set(vm, this, JSModuleNamespaceObject::createStructure(vm, this, jsNull()));
@@ -1052,8 +1051,12 @@
         m_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage));
 
     // Same for any special array structures.
-    m_regExpMatchesArrayStructure.set(vm, this, m_regExpMatchesArraySlowPutStructure.get());
-    
+    Structure* slowPutStructure;
+    slowPutStructure = createRegExpMatchesArraySlowPutStructure(vm, this);
+    m_regExpMatchesArrayStructure.set(vm, this, slowPutStructure);
+    slowPutStructure = ClonedArguments::createSlowPutStructure(vm, this, m_objectPrototype.get());
+    m_clonedArgumentsStructure.set(vm, this, slowPutStructure);
+
     // Make sure that all objects that have indexed storage switch to the slow kind of
     // indexed storage.
     MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC.
@@ -1191,7 +1194,6 @@
     visitor.append(&thisObject->m_generatorFunctionStructure);
     visitor.append(&thisObject->m_iteratorResultObjectStructure);
     visitor.append(&thisObject->m_regExpMatchesArrayStructure);
-    visitor.append(&thisObject->m_regExpMatchesArraySlowPutStructure);
     visitor.append(&thisObject->m_moduleRecordStructure);
     visitor.append(&thisObject->m_moduleNamespaceObjectStructure);
     visitor.append(&thisObject->m_dollarVMStructure);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (208376 => 208377)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2016-11-04 06:18:01 UTC (rev 208377)
@@ -320,7 +320,6 @@
     WriteBarrier<Structure> m_dollarVMStructure;
     WriteBarrier<Structure> m_iteratorResultObjectStructure;
     WriteBarrier<Structure> m_regExpMatchesArrayStructure;
-    WriteBarrier<Structure> m_regExpMatchesArraySlowPutStructure;
     WriteBarrier<Structure> m_moduleRecordStructure;
     WriteBarrier<Structure> m_moduleNamespaceObjectStructure;
     WriteBarrier<Structure> m_proxyObjectStructure;

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (208376 => 208377)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2016-11-04 06:18:01 UTC (rev 208377)
@@ -768,14 +768,10 @@
     return newButterfly->contiguous();
 }
 
-ArrayStorage* JSObject::createArrayStorage(VM& vm, unsigned length, unsigned vectorLength)
+Butterfly* JSObject::createArrayStorageButterfly(VM& vm, JSCell* intendedOwner, Structure* structure, unsigned length, unsigned vectorLength, Butterfly* oldButterfly)
 {
-    DeferGC deferGC(vm.heap);
-    Structure* structure = this->structure(vm);
-    IndexingType oldType = indexingType();
-    ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
     Butterfly* newButterfly = Butterfly::createOrGrowArrayRight(
-        m_butterfly.get(), vm, this, structure, structure->outOfLineCapacity(), false, 0,
+        oldButterfly, vm, intendedOwner, structure, structure->outOfLineCapacity(), false, 0,
         ArrayStorage::sizeFor(vectorLength));
     RELEASE_ASSERT(newButterfly);
 
@@ -787,6 +783,19 @@
     result->m_indexBias = 0;
     for (size_t i = vectorLength; i--;)
         result->m_vector[i].setWithoutWriteBarrier(JSValue());
+
+    return newButterfly;
+}
+
+ArrayStorage* JSObject::createArrayStorage(VM& vm, unsigned length, unsigned vectorLength)
+{
+    DeferGC deferGC(vm.heap);
+    Structure* structure = this->structure(vm);
+    IndexingType oldType = indexingType();
+    ASSERT_UNUSED(oldType, !hasIndexedProperties(oldType));
+
+    Butterfly* newButterfly = createArrayStorageButterfly(vm, this, structure, length, vectorLength, m_butterfly.get());
+    ArrayStorage* result = newButterfly->arrayStorage();
     Structure* newStructure = Structure::nonPropertyTransition(vm, structure, structure->suggestedArrayStorageTransition());
     setStructureAndButterfly(vm, newStructure, newButterfly);
     return result;

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (208376 => 208377)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2016-11-04 05:33:49 UTC (rev 208376)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2016-11-04 06:18:01 UTC (rev 208377)
@@ -902,6 +902,7 @@
     void createInitialForValueAndSet(VM&, unsigned index, JSValue);
     void convertInt32ForValue(VM&, JSValue);
         
+    static Butterfly* createArrayStorageButterfly(VM&, JSCell* intendedOwner, Structure*, unsigned length, unsigned vectorLength, Butterfly* oldButterfly = nullptr);
     ArrayStorage* createArrayStorage(VM&, unsigned length, unsigned vectorLength);
     ArrayStorage* createInitialArrayStorage(VM&);
         
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to