Changeset 218836 in webkit


Ignore:
Timestamp:
Jun 27, 2017 10:43:03 AM (7 years ago)
Author:
Joseph Pecoraro
Message:

Web Inspector: Crash generating object preview for ArrayIterator
https://bugs.webkit.org/show_bug.cgi?id=173754
<rdar://problem/32859012>

Reviewed by Saam Barati.

Source/JavaScriptCore:

When Inspector generates an object preview for an ArrayIterator instance it made
a "clone" of the original ArrayIterator instance by constructing a new object with
the instance's structure. However, user code could have modified that instance's
structure, such as adding / removing properties. The return property had special
meaning, and our clone did not fill that slot. This approach is brittle in that
we weren't satisfying the expectations of an object with a particular Structure,
and the original goal of having Web Inspector peek values of built-in Iterators
was to avoid observable behavior.

This tightens Web Inspector's Iterator preview to only peek values if the
Iterators would actually be non-observable. It also builds an ArrayIterator
clone like a regular object construction.

  • inspector/JSInjectedScriptHost.cpp:

(Inspector::cloneArrayIteratorObject):
Build up the Object from scratch with a new ArrayIterator prototype.

(Inspector::JSInjectedScriptHost::iteratorEntries):
Only clone and peek iterators if it would not be observable.
Also update iteration to be more in line with IterationOperations, such as when
we call iteratorClose.

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::JSGlobalObject):
(JSC::JSGlobalObject::init):

  • runtime/JSGlobalObject.h:

(JSC::JSGlobalObject::stringIteratorProtocolWatchpoint):

  • runtime/JSGlobalObjectInlines.h:

(JSC::JSGlobalObject::isStringPrototypeIteratorProtocolFastAndNonObservable):
Add a StringIterator WatchPoint in line with the Array/Map/Set iterator watchpoints.

  • runtime/JSMap.cpp:

(JSC::JSMap::isIteratorProtocolFastAndNonObservable):
(JSC::JSMap::canCloneFastAndNonObservable):

  • runtime/JSMap.h:
  • runtime/JSSet.cpp:

(JSC::JSSet::isIteratorProtocolFastAndNonObservable):
(JSC::JSSet::canCloneFastAndNonObservable):

  • runtime/JSSet.h:

Promote isIteratorProtocolFastAndNonObservable to a method.

  • runtime/JSObject.cpp:

(JSC::canDoFastPutDirectIndex):

  • runtime/JSTypeInfo.h:

(JSC::TypeInfo::isArgumentsType):
Helper to detect if an Object is an Arguments type.

LayoutTests:

  • platform/mac/inspector/model/remote-object-expected.txt:
  • inspector/model/remote-object-expected.txt:
  • inspector/model/remote-object.html:

Test generating a preview for an ArrayIterator that has had a return property added to it.

  • inspector/model/remote-object-mutated-iterators-expected.txt: Added.
  • inspector/model/remote-object-mutated-iterators.html: Added.

Test generating a preview for different iterators after the IteratorPrototypes have been mutated.

  • inspector/model/resources/remote-object-utilities.js: Added.

(runInBrowserTest):
(TestPage.registerInitializer):
(TestPage.registerInitializer.checkComplete):
(TestPage.registerInitializer.window.runSteps):
Share code for remote-object dump tests.

Location:
trunk
Files:
3 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r218835 r218836  
     12017-06-27  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Crash generating object preview for ArrayIterator
     4        https://bugs.webkit.org/show_bug.cgi?id=173754
     5        <rdar://problem/32859012>
     6
     7        Reviewed by Saam Barati.
     8
     9        * platform/mac/inspector/model/remote-object-expected.txt:
     10        * inspector/model/remote-object-expected.txt:
     11        * inspector/model/remote-object.html:
     12        Test generating a preview for an ArrayIterator that has had a `return` property added to it.
     13
     14        * inspector/model/remote-object-mutated-iterators-expected.txt: Added.
     15        * inspector/model/remote-object-mutated-iterators.html: Added.
     16        Test generating a preview for different iterators after the IteratorPrototypes have been mutated.
     17
     18        * inspector/model/resources/remote-object-utilities.js: Added.
     19        (runInBrowserTest):
     20        (TestPage.registerInitializer):
     21        (TestPage.registerInitializer.checkComplete):
     22        (TestPage.registerInitializer.window.runSteps):
     23        Share code for remote-object dump tests.
     24
    1252017-06-27  Frederic Wang  <fwang@igalia.com>
    226
  • trunk/LayoutTests/inspector/model/remote-object-expected.txt

    r218784 r218836  
    39233923
    39243924-----------------------------------------------------
     3925EXPRESSION: iter = [1, 2][Symbol.iterator](); iter['return'] = function(){}; iter
     3926{
     3927  "_type": "object",
     3928  "_subtype": "iterator",
     3929  "_objectId": "<filtered>",
     3930  "_description": "Array Iterator",
     3931  "_preview": {
     3932    "_type": "object",
     3933    "_subtype": "iterator",
     3934    "_description": "Array Iterator",
     3935    "_lossless": true,
     3936    "_overflow": false,
     3937    "_properties": [
     3938      {
     3939        "_name": "array",
     3940        "_type": "object",
     3941        "_subtype": "array",
     3942        "_valuePreview": {
     3943          "_type": "object",
     3944          "_subtype": "array",
     3945          "_description": "Array",
     3946          "_lossless": true,
     3947          "_overflow": false,
     3948          "_size": 2,
     3949          "_properties": [
     3950            {
     3951              "_name": "0",
     3952              "_type": "number",
     3953              "_value": "1"
     3954            },
     3955            {
     3956              "_name": "1",
     3957              "_type": "number",
     3958              "_value": "2"
     3959            }
     3960          ],
     3961          "_entries": null
     3962        },
     3963        "_internal": true
     3964      },
     3965      {
     3966        "_name": "kind",
     3967        "_type": "string",
     3968        "_value": "value",
     3969        "_internal": true
     3970      }
     3971    ],
     3972    "_entries": [
     3973      {
     3974        "_value": {
     3975          "_type": "number",
     3976          "_description": "1",
     3977          "_lossless": true,
     3978          "_overflow": false,
     3979          "_properties": null,
     3980          "_entries": null
     3981        }
     3982      },
     3983      {
     3984        "_value": {
     3985          "_type": "number",
     3986          "_description": "2",
     3987          "_lossless": true,
     3988          "_overflow": false,
     3989          "_properties": null,
     3990          "_entries": null
     3991        }
     3992      }
     3993    ]
     3994  }
     3995}
     3996
     3997-----------------------------------------------------
    39253998EXPRESSION: new Promise(function(){})
    39263999{
  • trunk/LayoutTests/inspector/model/remote-object.html

    r218784 r218836  
    1 <!doctype html>
     1<!DOCTYPE html>
    22<html>
    33<head>
    4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     4<meta charset="utf-8">
    55<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
     6<script src="resources/remote-object-utilities.js"></script>
    67<script>
    78function test()
    89{
    9     var currentStepIndex = 0;
    10     var steps = [
     10    let steps = [
    1111    // Special:
    1212
     
    160160        {expression: "map.entries()"},
    161161        {expression: "x = undefined; (function() { x = arguments; })(1, 'two'); x[Symbol.iterator]()"},
     162        {expression: "iter = [1, 2][Symbol.iterator](); iter['return'] = function(){}; iter"},
    162163
    163164        // Promise
     
    192193    }
    193194
    194     function remoteObjectJSONFilter(key, value)
    195     {
    196         if (key === "_target" || key === "_hasChildren" || key === "_listeners")
    197             return undefined;
    198         if (key === "_objectId" || key === "_stackTrace")
    199             return "<filtered>";
    200         return value;
    201     }
    202 
    203     function runSteps() {
    204 
    205         function afterStep() {
    206             if (++currentStepIndex >= steps.length)
    207                 InspectorTest.completeTest();
    208         }
    209 
    210         function runStep(step) {
    211             if (step.browserOnly) {
    212                 afterStep();
    213                 return;
    214             }
    215 
    216             WebInspector.runtimeManager.evaluateInInspectedWindow(step.expression, {objectGroup: "test", doNotPauseOnExceptionsAndMuteConsole: true, generatePreview: true}, function(remoteObject, wasThrown) {
    217                 InspectorTest.log("");
    218                 InspectorTest.log("-----------------------------------------------------");
    219                 InspectorTest.log("EXPRESSION: " + step.expression);
    220                 InspectorTest.assert(remoteObject instanceof WebInspector.RemoteObject);
    221                 InspectorTest.log(JSON.stringify(remoteObject, remoteObjectJSONFilter, "  "));
    222                 afterStep();
    223             });
    224         }
    225 
    226         for (var step of steps)
    227             runStep(step);
    228     }
    229 
    230     runSteps();
    231 }
    232 
    233 function runInBrowserTest()
    234 {
    235     if (window.testRunner)
    236         return;
    237  
    238     test(); // get steps.
    239 
    240     for (var step of steps) {
    241         console.info("EXPRESSION", step.expression);
    242         try {
    243             console.log(eval(step.expression));
    244         } catch (e) {
    245             console.log("EXCEPTION: " + e);
    246         }
    247     }
     195    runSteps(steps);
    248196}
    249197</script>
  • trunk/LayoutTests/platform/mac/inspector/model/remote-object-expected.txt

    r218784 r218836  
    39263926
    39273927-----------------------------------------------------
     3928EXPRESSION: iter = [1, 2][Symbol.iterator](); iter['return'] = function(){}; iter
     3929{
     3930  "_type": "object",
     3931  "_subtype": "iterator",
     3932  "_objectId": "<filtered>",
     3933  "_description": "Array Iterator",
     3934  "_preview": {
     3935    "_type": "object",
     3936    "_subtype": "iterator",
     3937    "_description": "Array Iterator",
     3938    "_lossless": true,
     3939    "_overflow": false,
     3940    "_properties": [
     3941      {
     3942        "_name": "array",
     3943        "_type": "object",
     3944        "_subtype": "array",
     3945        "_valuePreview": {
     3946          "_type": "object",
     3947          "_subtype": "array",
     3948          "_description": "Array",
     3949          "_lossless": true,
     3950          "_overflow": false,
     3951          "_size": 2,
     3952          "_properties": [
     3953            {
     3954              "_name": "0",
     3955              "_type": "number",
     3956              "_value": "1"
     3957            },
     3958            {
     3959              "_name": "1",
     3960              "_type": "number",
     3961              "_value": "2"
     3962            }
     3963          ],
     3964          "_entries": null
     3965        },
     3966        "_internal": true
     3967      },
     3968      {
     3969        "_name": "kind",
     3970        "_type": "string",
     3971        "_value": "value",
     3972        "_internal": true
     3973      }
     3974    ],
     3975    "_entries": [
     3976      {
     3977        "_value": {
     3978          "_type": "number",
     3979          "_description": "1",
     3980          "_lossless": true,
     3981          "_overflow": false,
     3982          "_properties": null,
     3983          "_entries": null
     3984        }
     3985      },
     3986      {
     3987        "_value": {
     3988          "_type": "number",
     3989          "_description": "2",
     3990          "_lossless": true,
     3991          "_overflow": false,
     3992          "_properties": null,
     3993          "_entries": null
     3994        }
     3995      }
     3996    ]
     3997  }
     3998}
     3999
     4000-----------------------------------------------------
    39284001EXPRESSION: new Promise(function(){})
    39294002{
  • trunk/Source/JavaScriptCore/ChangeLog

    r218828 r218836  
     12017-06-27  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Crash generating object preview for ArrayIterator
     4        https://bugs.webkit.org/show_bug.cgi?id=173754
     5        <rdar://problem/32859012>
     6
     7        Reviewed by Saam Barati.
     8
     9        When Inspector generates an object preview for an ArrayIterator instance it made
     10        a "clone" of the original ArrayIterator instance by constructing a new object with
     11        the instance's structure. However, user code could have modified that instance's
     12        structure, such as adding / removing properties. The `return` property had special
     13        meaning, and our clone did not fill that slot. This approach is brittle in that
     14        we weren't satisfying the expectations of an object with a particular Structure,
     15        and the original goal of having Web Inspector peek values of built-in Iterators
     16        was to avoid observable behavior.
     17
     18        This tightens Web Inspector's Iterator preview to only peek values if the
     19        Iterators would actually be non-observable. It also builds an ArrayIterator
     20        clone like a regular object construction.
     21
     22        * inspector/JSInjectedScriptHost.cpp:
     23        (Inspector::cloneArrayIteratorObject):
     24        Build up the Object from scratch with a new ArrayIterator prototype.
     25
     26        (Inspector::JSInjectedScriptHost::iteratorEntries):
     27        Only clone and peek iterators if it would not be observable.
     28        Also update iteration to be more in line with IterationOperations, such as when
     29        we call iteratorClose.
     30
     31        * runtime/JSGlobalObject.cpp:
     32        (JSC::JSGlobalObject::JSGlobalObject):
     33        (JSC::JSGlobalObject::init):
     34        * runtime/JSGlobalObject.h:
     35        (JSC::JSGlobalObject::stringIteratorProtocolWatchpoint):
     36        * runtime/JSGlobalObjectInlines.h:
     37        (JSC::JSGlobalObject::isStringPrototypeIteratorProtocolFastAndNonObservable):
     38        Add a StringIterator WatchPoint in line with the Array/Map/Set iterator watchpoints.
     39
     40        * runtime/JSMap.cpp:
     41        (JSC::JSMap::isIteratorProtocolFastAndNonObservable):
     42        (JSC::JSMap::canCloneFastAndNonObservable):
     43        * runtime/JSMap.h:
     44        * runtime/JSSet.cpp:
     45        (JSC::JSSet::isIteratorProtocolFastAndNonObservable):
     46        (JSC::JSSet::canCloneFastAndNonObservable):
     47        * runtime/JSSet.h:
     48        Promote isIteratorProtocolFastAndNonObservable to a method.
     49
     50        * runtime/JSObject.cpp:
     51        (JSC::canDoFastPutDirectIndex):
     52        * runtime/JSTypeInfo.h:
     53        (JSC::TypeInfo::isArgumentsType):
     54        Helper to detect if an Object is an Arguments type.
     55
    1562017-06-26  Saam Barati  <sbarati@apple.com>
    257
  • trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp

    r218784 r218836  
    2727#include "JSInjectedScriptHost.h"
    2828
     29#include "ArrayIteratorPrototype.h"
    2930#include "BuiltinNames.h"
    3031#include "Completion.h"
     
    3435#include "InjectedScriptHost.h"
    3536#include "IteratorOperations.h"
     37#include "IteratorPrototype.h"
    3638#include "JSArray.h"
    3739#include "JSBoundFunction.h"
     
    358360        return array;
    359361    }
    360        
     362
    361363    if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value)) {
    362364        String kind;
     
    509511}
    510512
    511 static JSObject* cloneArrayIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSValue nextIndex)
     513static JSObject* cloneArrayIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSGlobalObject* globalObject, JSValue nextIndex, JSValue iteratedObject)
    512514{
    513515    ASSERT(iteratorObject->type() == FinalObjectType);
    514     JSObject* clone = constructEmptyObject(exec, iteratorObject->structure());
     516    JSObject* clone = constructEmptyObject(exec, ArrayIteratorPrototype::create(vm, globalObject, ArrayIteratorPrototype::createStructure(vm, globalObject, globalObject->iteratorPrototype())));
     517    clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratedObject);
     518    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorKindPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorKindPrivateName()));
    515519    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName(), nextIndex);
    516     clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName()));
     520    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName()));
    517521    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorIsDonePrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorIsDonePrivateName()));
    518     clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName()));
    519522    return clone;
    520523}
     
    527530    VM& vm = exec->vm();
    528531    auto scope = DECLARE_THROW_SCOPE(vm);
     532
    529533    JSValue iterator;
    530     JSValue value = exec->uncheckedArgument(0);
    531     if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(vm, value))
    532         iterator = mapIterator->clone(exec);
    533     else if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value))
    534         iterator = setIterator->clone(exec);
    535     else if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(vm, value))
    536         iterator = stringIterator->clone(exec);
    537     else {
    538         if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(vm, value)) {
    539             // Array Iterators are created in JS for performance reasons. Thus the only way to know we have one is to
    540             // look for a property that is unique to them.
    541             if (JSValue nextIndex = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName()))
    542                 iterator = cloneArrayIteratorObject(exec, vm, iteratorObject, nextIndex);
    543         }
    544     }
     534    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     535    JSValue value = exec->uncheckedArgument(0);
     536    if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(vm, value)) {
     537        if (jsCast<JSMap*>(mapIterator->iteratedValue())->isIteratorProtocolFastAndNonObservable())
     538            iterator = mapIterator->clone(exec);
     539    } else if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value)) {
     540        if (jsCast<JSSet*>(setIterator->iteratedValue())->isIteratorProtocolFastAndNonObservable())
     541            iterator = setIterator->clone(exec);
     542    } else if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(vm, value)) {
     543        if (globalObject->isStringPrototypeIteratorProtocolFastAndNonObservable())
     544            iterator = stringIterator->clone(exec);
     545    } else if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(vm, value)) {
     546        // Detect an ArrayIterator by checking for one of its unique private properties.
     547        if (JSValue nextIndex = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) {
     548            JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
     549            if (isJSArray(iteratedObject)) {
     550                JSArray* array = jsCast<JSArray*>(iteratedObject);
     551                if (array->isIteratorProtocolFastAndNonObservable())
     552                    iterator = cloneArrayIteratorObject(exec, vm, iteratorObject, globalObject, nextIndex, iteratedObject);
     553            } else if (iteratedObject.isObject() && TypeInfo::isArgumentsType(asObject(iteratedObject)->type())) {
     554                if (globalObject->isArrayPrototypeIteratorProtocolFastAndNonObservable())
     555                    iterator = cloneArrayIteratorObject(exec, vm, iteratorObject, globalObject, nextIndex, iteratedObject);
     556            }
     557        }
     558    }
     559    RETURN_IF_EXCEPTION(scope, { });
    545560    if (!iterator)
    546561        return jsUndefined();
     
    549564    JSValue numberToFetchArg = exec->argument(1);
    550565    double fetchDouble = numberToFetchArg.toInteger(exec);
     566    RETURN_IF_EXCEPTION(scope, { });
    551567    if (fetchDouble >= 0)
    552568        numberToFetch = static_cast<unsigned>(fetchDouble);
    553569
    554570    JSArray* array = constructEmptyArray(exec, nullptr);
    555     RETURN_IF_EXCEPTION(scope, JSValue());
     571    RETURN_IF_EXCEPTION(scope, { });
    556572
    557573    for (unsigned i = 0; i < numberToFetch; ++i) {
    558574        JSValue next = iteratorStep(exec, iterator);
    559         if (UNLIKELY(scope.exception()))
    560             break;
    561         if (next.isFalse())
     575        if (UNLIKELY(scope.exception()) || next.isFalse())
    562576            break;
    563577
    564578        JSValue nextValue = iteratorValue(exec, next);
    565         if (UNLIKELY(scope.exception()))
    566             break;
     579        RETURN_IF_EXCEPTION(scope, { });
    567580
    568581        JSObject* entry = constructEmptyObject(exec);
    569582        entry->putDirect(exec->vm(), Identifier::fromString(exec, "value"), nextValue);
    570583        array->putDirectIndex(exec, i, entry);
    571         if (UNLIKELY(scope.exception()))
    572             break;
    573     }
    574 
    575     iteratorClose(exec, iterator);
     584        if (UNLIKELY(scope.exception())) {
     585            scope.release();
     586            iteratorClose(exec, iterator);
     587            break;
     588        }
     589    }
    576590
    577591    return array;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r218794 r218836  
    327327    , m_mapIteratorProtocolWatchpoint(IsWatched)
    328328    , m_setIteratorProtocolWatchpoint(IsWatched)
     329    , m_stringIteratorProtocolWatchpoint(IsWatched)
    329330    , m_mapSetWatchpoint(IsWatched)
    330331    , m_setAddWatchpoint(IsWatched)
     
    938939            m_arrayIteratorPrototypeNext->install();
    939940        }
    940 
    941941        {
    942942            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(this->arrayPrototype(), m_vm.propertyNames->iteratorSymbol);
     
    950950            m_mapIteratorPrototypeNextWatchpoint->install();
    951951        }
    952 
    953952        {
    954953            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m_mapPrototype.get(), m_vm.propertyNames->iteratorSymbol);
     
    962961            m_setIteratorPrototypeNextWatchpoint->install();
    963962        }
    964 
    965963        {
    966964            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m_setPrototype.get(), m_vm.propertyNames->iteratorSymbol);
    967965            m_setPrototypeSymbolIteratorWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_setIteratorProtocolWatchpoint);
    968966            m_setPrototypeSymbolIteratorWatchpoint->install();
     967        }
     968
     969        {
     970            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m_stringIteratorPrototype.get(), m_vm.propertyNames->next);
     971            m_stringIteratorPrototypeNextWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_stringIteratorProtocolWatchpoint);
     972            m_stringIteratorPrototypeNextWatchpoint->install();
     973        }
     974        {
     975            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m_stringPrototype.get(), m_vm.propertyNames->iteratorSymbol);
     976            m_stringPrototypeSymbolIteratorWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_stringIteratorProtocolWatchpoint);
     977            m_stringPrototypeSymbolIteratorWatchpoint->install();
    969978        }
    970979
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r218794 r218836  
    409409    InlineWatchpointSet& mapIteratorProtocolWatchpoint() { return m_mapIteratorProtocolWatchpoint; }
    410410    InlineWatchpointSet& setIteratorProtocolWatchpoint() { return m_setIteratorProtocolWatchpoint; }
     411    InlineWatchpointSet& stringIteratorProtocolWatchpoint() { return m_stringIteratorProtocolWatchpoint; }
    411412    InlineWatchpointSet& mapSetWatchpoint() { return m_mapSetWatchpoint; }
    412413    InlineWatchpointSet& setAddWatchpoint() { return m_setAddWatchpoint; }
     
    417418    InlineWatchpointSet m_mapIteratorProtocolWatchpoint;
    418419    InlineWatchpointSet m_setIteratorProtocolWatchpoint;
     420    InlineWatchpointSet m_stringIteratorProtocolWatchpoint;
    419421    InlineWatchpointSet m_mapSetWatchpoint;
    420422    InlineWatchpointSet m_setAddWatchpoint;
     
    426428    std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_setPrototypeSymbolIteratorWatchpoint;
    427429    std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_setIteratorPrototypeNextWatchpoint;
     430    std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_stringPrototypeSymbolIteratorWatchpoint;
     431    std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_stringIteratorPrototypeNextWatchpoint;
    428432    std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_mapPrototypeSetWatchpoint;
    429433    std::unique_ptr<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>> m_setPrototypeAddWatchpoint;
     
    432436    bool isMapPrototypeIteratorProtocolFastAndNonObservable();
    433437    bool isSetPrototypeIteratorProtocolFastAndNonObservable();
     438    bool isStringPrototypeIteratorProtocolFastAndNonObservable();
    434439    bool isMapPrototypeSetFastAndNonObservable();
    435440    bool isSetPrototypeAddFastAndNonObservable();
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h

    r217525 r218836  
    8383}
    8484
     85ALWAYS_INLINE bool JSGlobalObject::isStringPrototypeIteratorProtocolFastAndNonObservable()
     86{
     87    return stringIteratorProtocolWatchpoint().isStillValid();
     88}
     89
    8590ALWAYS_INLINE bool JSGlobalObject::isMapPrototypeSetFastAndNonObservable()
    8691{
  • trunk/Source/JavaScriptCore/runtime/JSMap.cpp

    r217525 r218836  
    4646}
    4747
     48bool JSMap::isIteratorProtocolFastAndNonObservable()
     49{
     50    JSGlobalObject* globalObject = this->globalObject();
     51    if (!globalObject->isMapPrototypeIteratorProtocolFastAndNonObservable())
     52        return false;
     53
     54    Structure* structure = this->structure();
     55    // This is the fast case. Many maps will be an original map.
     56    if (structure == globalObject->mapStructure())
     57        return true;
     58
     59    if (structure->storedPrototype() != globalObject->mapPrototype())
     60        return false;
     61
     62    if (getDirectOffset(globalObject->vm(), globalObject->vm().propertyNames->iteratorSymbol) != invalidOffset)
     63        return false;
     64
     65    return true;
     66}
     67
    4868bool JSMap::canCloneFastAndNonObservable(Structure* structure)
    4969{
    50     auto isIteratorProtocolFastAndNonObservable = [&] () {
    51         JSGlobalObject* globalObject = this->globalObject();
    52         if (!globalObject->isMapPrototypeIteratorProtocolFastAndNonObservable())
    53             return false;
    54 
    55         Structure* structure = this->structure();
    56         // This is the fast case. Many maps will be an original map.
    57         if (structure == globalObject->mapStructure())
    58             return true;
    59 
    60         if (structure->storedPrototype() != globalObject->mapPrototype())
    61             return false;
    62 
    63         if (getDirectOffset(globalObject->vm(), globalObject->vm().propertyNames->iteratorSymbol) != invalidOffset)
    64             return false;
    65 
    66         return true;
    67     };
    68 
    6970    auto setFastAndNonObservable = [&] (Structure* structure) {
    7071        JSGlobalObject* globalObject = structure->globalObject();
  • trunk/Source/JavaScriptCore/runtime/JSMap.h

    r217527 r218836  
    5757    }
    5858
     59    bool isIteratorProtocolFastAndNonObservable();
    5960    bool canCloneFastAndNonObservable(Structure*);
    6061    JSMap* clone(ExecState*, VM&, Structure*);
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r218794 r218836  
    23632363    return isJSArray(object)
    23642364        || isJSFinalObject(object)
    2365         || object->type() == DirectArgumentsType
    2366         || object->type() == ScopedArgumentsType
    2367         || object->type() == ClonedArgumentsType;
     2365        || TypeInfo::isArgumentsType(object->type());
    23682366}
    23692367
  • trunk/Source/JavaScriptCore/runtime/JSSet.cpp

    r217525 r218836  
    4646}
    4747
     48bool JSSet::isIteratorProtocolFastAndNonObservable()
     49{
     50    JSGlobalObject* globalObject = this->globalObject();
     51    if (!globalObject->isSetPrototypeIteratorProtocolFastAndNonObservable())
     52        return false;
     53
     54    Structure* structure = this->structure();
     55    // This is the fast case. Many sets will be an original set.
     56    if (structure == globalObject->setStructure())
     57        return true;
     58
     59    if (structure->storedPrototype() != globalObject->jsSetPrototype())
     60        return false;
     61
     62    if (getDirectOffset(globalObject->vm(), globalObject->vm().propertyNames->iteratorSymbol) != invalidOffset)
     63        return false;
     64
     65    return true;
     66}
     67
    4868bool JSSet::canCloneFastAndNonObservable(Structure* structure)
    4969{
    50     auto isIteratorProtocolFastAndNonObservable = [&] () {
    51         JSGlobalObject* globalObject = this->globalObject();
    52         if (!globalObject->isSetPrototypeIteratorProtocolFastAndNonObservable())
    53             return false;
    54 
    55         Structure* structure = this->structure();
    56         // This is the fast case. Many sets will be an original set.
    57         if (structure == globalObject->setStructure())
    58             return true;
    59 
    60         if (structure->storedPrototype() != globalObject->jsSetPrototype())
    61             return false;
    62 
    63         if (getDirectOffset(globalObject->vm(), globalObject->vm().propertyNames->iteratorSymbol) != invalidOffset)
    64             return false;
    65 
    66         return true;
    67     };
    68 
    6970    auto addFastAndNonObservable = [&] (Structure* structure) {
    7071        JSGlobalObject* globalObject = structure->globalObject();
  • trunk/Source/JavaScriptCore/runtime/JSSet.h

    r217527 r218836  
    5353    }
    5454
     55    bool isIteratorProtocolFastAndNonObservable();
    5556    bool canCloneFastAndNonObservable(Structure*);
    5657    JSSet* clone(ExecState*, VM&, Structure*);
  • trunk/Source/JavaScriptCore/runtime/JSTypeInfo.h

    r209424 r218836  
    9595    bool interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero() const { return isSetOnFlags2(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero); }
    9696
     97    static bool isArgumentsType(JSType type)
     98    {
     99        return type == DirectArgumentsType
     100            || type == ScopedArgumentsType
     101            || type == ClonedArgumentsType;
     102    }
     103
    97104    static ptrdiff_t flagsOffset()
    98105    {
Note: See TracChangeset for help on using the changeset viewer.