Changeset 282385 in webkit


Ignore:
Timestamp:
Sep 14, 2021 3:13:23 AM (3 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC] ASSERT failed in stress/for-in-tests.js (32bit)
https://bugs.webkit.org/show_bug.cgi?id=229543

Patch by Xan López <Xan Lopez> on 2021-09-14
Reviewed by Yusuke Suzuki.

Since r280760 DFG::SpeculativeJIT::compileEnumeratorGetByVal uses
too many registers for 32bit. Revert to the slow path as a
temporary measure to avoid crashes, we'll try to reenable the
optimizations later on (see bug #230189).

  • dfg/DFGOperations.cpp:

(JSC::DFG::JSC_DEFINE_JIT_OPERATION): define a generic call
operation for compileEnumeratorGetByVal.

  • dfg/DFGOperations.h:
  • dfg/DFGSpeculativeJIT.cpp: move the current version of

compileEnumeratorGetByVal to 64bit, since it won't work on 32bit.

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): call the generic call op always.

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): use the previous version here.

  • runtime/CommonSlowPaths.cpp:

(JSC::JSC_DEFINE_COMMON_SLOW_PATH): refactor a bit the slow path
for enumeratorGetByVal so it can be called from DFG as a call
operation.

  • runtime/CommonSlowPaths.h:

(JSC::CommonSlowPaths::opEnumeratorGetByVal):

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r282336 r282385  
     12021-09-14  Xan López  <xan@igalia.com>
     2
     3        [JSC] ASSERT failed in stress/for-in-tests.js (32bit)
     4        https://bugs.webkit.org/show_bug.cgi?id=229543
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Since r280760 DFG::SpeculativeJIT::compileEnumeratorGetByVal uses
     9        too many registers for 32bit. Revert to the slow path as a
     10        temporary measure to avoid crashes, we'll try to reenable the
     11        optimizations later on (see bug #230189).
     12
     13        * dfg/DFGOperations.cpp:
     14        (JSC::DFG::JSC_DEFINE_JIT_OPERATION): define a generic call
     15        operation for compileEnumeratorGetByVal.
     16        * dfg/DFGOperations.h:
     17        * dfg/DFGSpeculativeJIT.cpp: move the current version of
     18        compileEnumeratorGetByVal to 64bit, since it won't work on 32bit.
     19        * dfg/DFGSpeculativeJIT32_64.cpp:
     20        (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): call the generic call op always.
     21        * dfg/DFGSpeculativeJIT64.cpp:
     22        (JSC::DFG::SpeculativeJIT::compileEnumeratorGetByVal): use the previous version here.
     23        * runtime/CommonSlowPaths.cpp:
     24        (JSC::JSC_DEFINE_COMMON_SLOW_PATH): refactor a bit the slow path
     25        for enumeratorGetByVal so it can be called from DFG as a call
     26        operation.
     27        * runtime/CommonSlowPaths.h:
     28        (JSC::CommonSlowPaths::opEnumeratorGetByVal):
     29
    1302021-09-13  Xan López  <xan@igalia.com>
    231
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r282014 r282385  
    25392539}
    25402540
     2541JSC_DEFINE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* baseCell, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber, JSPropertyNameEnumerator* enumerator))
     2542{
     2543    VM& vm = globalObject->vm();
     2544    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     2545    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     2546    auto scope = DECLARE_THROW_SCOPE(vm);
     2547
     2548    JSValue property = JSValue::decode(propertyNameValue);
     2549    JSPropertyNameEnumerator::Flag mode = static_cast<JSPropertyNameEnumerator::Flag>(modeNumber);
     2550    RELEASE_AND_RETURN(scope, JSValue::encode(CommonSlowPaths::opEnumeratorGetByVal(globalObject, baseCell, property, index, mode, enumerator)));
     2551}
     2552
    25412553JSC_DEFINE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue baseValue, EncodedJSValue propertyNameValue, uint32_t index, int32_t modeNumber))
    25422554{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r280760 r282385  
    113113JSC_DECLARE_JIT_OPERATION(operationEnumeratorHasOwnProperty, EncodedJSValue, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, uint32_t, int32_t));
    114114JSC_DECLARE_JIT_OPERATION(operationEnumeratorRecoverNameAndGetByVal, EncodedJSValue, (JSGlobalObject*, JSCell*, uint32_t, JSPropertyNameEnumerator*));
     115JSC_DECLARE_JIT_OPERATION(operationEnumeratorGetByValGeneric, EncodedJSValue, (JSGlobalObject*, JSCell*, EncodedJSValue, uint32_t, int32_t, JSPropertyNameEnumerator*));
    115116
    116117JSC_DECLARE_JIT_OPERATION(operationNewRegexpWithLastIndex, JSCell*, (JSGlobalObject*, JSCell*, EncodedJSValue));
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r282336 r282385  
    1368813688}
    1368913689
    13690 void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
    13691 {
    13692     Edge baseEdge = m_graph.varArgChild(node, 0);
    13693     auto generate = [&] (GPRReg baseCellGPR) {
    13694         MacroAssembler::JumpList doneCases;
    13695         JSValueRegsTemporary result;
    13696         JSValueRegs resultRegs;
    13697         GPRReg indexGPR;
    13698         GPRReg enumeratorGPR;
    13699         MacroAssembler::Jump badStructureSlowPath;
    13700 
    13701         compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
    13702             Edge storageEdge = m_graph.varArgChild(node, 2);
    13703             StorageOperand storage;
    13704             if (storageEdge)
    13705                 storage.emplace(this, storageEdge);
    13706             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
    13707             SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
    13708             SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
    13709 
    13710             GPRReg modeGPR = mode.gpr();
    13711             indexGPR = index.gpr();
    13712             enumeratorGPR = enumerator.gpr();
    13713 
    13714             result = JSValueRegsTemporary(this);
    13715             resultRegs = result.regs();
    13716             GPRReg scratchGPR = resultRegs.payloadGPR();
    13717 
    13718             bool haveStorage = !!storageEdge;
    13719             GPRTemporary storageTemporary;
    13720             GPRReg storageGPR;
    13721             if (!haveStorage) {
    13722                 storageTemporary = GPRTemporary(this, Reuse, enumerator);
    13723                 storageGPR = storageTemporary.gpr();
    13724             } else
    13725                 storageGPR = storage.gpr();
    13726 
    13727             MacroAssembler::JumpList notFastNamedCases;
    13728 
    13729             // FIXME: We shouldn't generate this code if we know base is not an object.
    13730             notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
    13731             {
    13732                 if (!m_state.forNode(baseEdge).isType(SpecCell))
    13733                     notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
    13734 
    13735                 // Check the structure
    13736                 // FIXME: If we know there's only one structure for base we can just embed it here.
    13737                 m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
    13738 
    13739                 auto badStructure = m_jit.branch32(
    13740                     MacroAssembler::NotEqual,
    13741                     scratchGPR,
    13742                     MacroAssembler::Address(
    13743                         enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
    13744 
    13745                 // FIXME: Maybe we should have a better way to represent Indexed+Named?
    13746                 if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
    13747                     badStructureSlowPath = badStructure;
    13748                 else
    13749                     notFastNamedCases.append(badStructure);
    13750 
    13751                 // Compute the offset
    13752                 // If index is less than the enumerator's cached inline storage, then it's an inline access
    13753                 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
    13754                     indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
    13755 
    13756                 m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
    13757 
    13758                 doneCases.append(m_jit.jump());
    13759 
    13760                 // Otherwise it's out of line
    13761                 outOfLineAccess.link(&m_jit);
    13762                 m_jit.move(indexGPR, scratchGPR);
    13763                 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
    13764                 m_jit.neg32(scratchGPR);
    13765                 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
    13766                 if (!haveStorage)
    13767                     m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
    13768                 constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
    13769                 m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
    13770                 doneCases.append(m_jit.jump());
    13771             }
    13772 
    13773             notFastNamedCases.link(&m_jit);
    13774             return std::make_pair(resultRegs, DataFormatJS);
    13775         }));
    13776 
    13777         // We rely on compileGetByVal to call jsValueResult for us.
    13778         // FIXME: This is kinda hacky...
    13779         ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
    13780 
    13781         if (badStructureSlowPath.isSet())
    13782             addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
    13783 
    13784         doneCases.link(&m_jit);
    13785     };
    13786 
    13787     if (isCell(baseEdge.useKind())) {
    13788         // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
    13789         speculate(node, baseEdge);
    13790         SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
    13791         generate(baseOperand.gpr());
    13792     } else {
    13793         JSValueOperand baseOperand(this, baseEdge);
    13794         generate(baseOperand.gpr());
    13795     }
    13796 }
    13797 
    1379813690template<typename SlowPathFunctionType>
    1379913691void SpeculativeJIT::compileEnumeratorHasProperty(Node* node, SlowPathFunctionType slowPathFunction)
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r281684 r282385  
    44814481}
    44824482
     4483// FIXME: we are always taking the slow path here, we should be able to do the equivalent to the 64bit version if we add more available (callee-save registers) to ARMv7 and/or if we reduce the number of registers compileEnumeratorGetByVal uses. See bug #230189.
     4484void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
     4485{
     4486    SpeculateCellOperand baseOperand(this, m_graph.varArgChild(node, 0));
     4487    JSValueOperand property(this, m_graph.varArgChild(node, 1));
     4488    SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
     4489    SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
     4490    SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
     4491    GPRReg baseOperandGPR = baseOperand.gpr();
     4492    JSValueRegs propertyRegs = property.jsValueRegs();
     4493    GPRReg indexGPR = index.gpr();
     4494    GPRReg modeGPR = mode.gpr();
     4495    GPRReg enumeratorGPR = enumerator.gpr();
     4496
     4497    flushRegisters();
     4498
     4499    JSValueRegsFlushedCallResult result(this);
     4500    JSValueRegs resultRegs = result.regs();
     4501
     4502    callOperation(operationEnumeratorGetByValGeneric, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseOperandGPR, propertyRegs, indexGPR, modeGPR, enumeratorGPR);
     4503    m_jit.exceptionCheck();
     4504    jsValueResult(resultRegs, node);
     4505}
    44834506#endif
    44844507
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r282200 r282385  
    63536353}
    63546354
     6355void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
     6356{
     6357    Edge baseEdge = m_graph.varArgChild(node, 0);
     6358    auto generate = [&] (GPRReg baseCellGPR) {
     6359        MacroAssembler::JumpList doneCases;
     6360        JSValueRegsTemporary result;
     6361        JSValueRegs resultRegs;
     6362        GPRReg indexGPR;
     6363        GPRReg enumeratorGPR;
     6364        MacroAssembler::Jump badStructureSlowPath;
     6365
     6366        compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
     6367            Edge storageEdge = m_graph.varArgChild(node, 2);
     6368            StorageOperand storage;
     6369            if (storageEdge)
     6370                storage.emplace(this, storageEdge);
     6371            SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
     6372            SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
     6373            SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
     6374
     6375            GPRReg modeGPR = mode.gpr();
     6376            indexGPR = index.gpr();
     6377            enumeratorGPR = enumerator.gpr();
     6378
     6379            result = JSValueRegsTemporary(this);
     6380            resultRegs = result.regs();
     6381            GPRReg scratchGPR = resultRegs.payloadGPR();
     6382
     6383            bool haveStorage = !!storageEdge;
     6384            GPRTemporary storageTemporary;
     6385            GPRReg storageGPR;
     6386            if (!haveStorage) {
     6387                storageTemporary = GPRTemporary(this, Reuse, enumerator);
     6388                storageGPR = storageTemporary.gpr();
     6389            } else
     6390                storageGPR = storage.gpr();
     6391
     6392            MacroAssembler::JumpList notFastNamedCases;
     6393
     6394            // FIXME: We shouldn't generate this code if we know base is not an object.
     6395            notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
     6396            {
     6397                if (!m_state.forNode(baseEdge).isType(SpecCell))
     6398                    notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
     6399
     6400                // Check the structure
     6401                // FIXME: If we know there's only one structure for base we can just embed it here.
     6402                m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
     6403
     6404                auto badStructure = m_jit.branch32(
     6405                    MacroAssembler::NotEqual,
     6406                    scratchGPR,
     6407                    MacroAssembler::Address(
     6408                        enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
     6409
     6410                // FIXME: Maybe we should have a better way to represent Indexed+Named?
     6411                if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
     6412                    badStructureSlowPath = badStructure;
     6413                else
     6414                    notFastNamedCases.append(badStructure);
     6415
     6416                // Compute the offset
     6417                // If index is less than the enumerator's cached inline storage, then it's an inline access
     6418                MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
     6419                    indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     6420
     6421                m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
     6422
     6423                doneCases.append(m_jit.jump());
     6424
     6425                // Otherwise it's out of line
     6426                outOfLineAccess.link(&m_jit);
     6427                m_jit.move(indexGPR, scratchGPR);
     6428                m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
     6429                m_jit.neg32(scratchGPR);
     6430                m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
     6431                if (!haveStorage)
     6432                    m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
     6433                constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
     6434                m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
     6435                doneCases.append(m_jit.jump());
     6436            }
     6437
     6438            notFastNamedCases.link(&m_jit);
     6439            return std::make_pair(resultRegs, DataFormatJS);
     6440        }));
     6441
     6442        // We rely on compileGetByVal to call jsValueResult for us.
     6443        // FIXME: This is kinda hacky...
     6444        ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
     6445
     6446        if (badStructureSlowPath.isSet())
     6447            addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
     6448
     6449        doneCases.link(&m_jit);
     6450    };
     6451
     6452    if (isCell(baseEdge.useKind())) {
     6453        // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
     6454        speculate(node, baseEdge);
     6455        SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
     6456        generate(baseOperand.gpr());
     6457    } else {
     6458        JSValueOperand baseOperand(this, baseEdge);
     6459        generate(baseOperand.gpr());
     6460    }
     6461}
     6462
    63556463#endif
    63566464
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r282014 r282385  
    10111011    auto bytecode = pc->as<OpEnumeratorGetByVal>();
    10121012    JSValue baseValue = GET_C(bytecode.m_base).jsValue();
     1013    JSValue propertyName = GET(bytecode.m_propertyName).jsValue();
    10131014    auto& metadata = bytecode.metadata(codeBlock);
    10141015    auto mode = static_cast<JSPropertyNameEnumerator::Flag>(GET(bytecode.m_mode).jsValue().asUInt32());
    10151016    metadata.m_enumeratorMetadata |= static_cast<uint8_t>(mode);
    1016 
    10171017    JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.m_enumerator).jsValue());
    10181018    unsigned index = GET(bytecode.m_index).jsValue().asInt32();
    1019     switch (mode) {
    1020     case JSPropertyNameEnumerator::IndexedMode: {
    1021         if (LIKELY(baseValue.isCell()))
    1022             metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID());
    1023         RETURN_PROFILED(baseValue.get(globalObject, static_cast<unsigned>(index)));
    1024     }
    1025     case JSPropertyNameEnumerator::OwnStructureMode: {
    1026         if (LIKELY(baseValue.isCell()) && baseValue.asCell()->structureID() == enumerator->cachedStructureID()) {
    1027             // We'll only match the structure ID if the base is an object.
    1028             ASSERT(index < enumerator->endStructurePropertyIndex());
    1029             RETURN_PROFILED(baseValue.getObject()->getDirect(index < enumerator->cachedInlineCapacity() ? index : index - enumerator->cachedInlineCapacity() + firstOutOfLineOffset));
    1030         } else
    1031             metadata.m_enumeratorMetadata |= static_cast<uint8_t>(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch);
    1032         FALLTHROUGH;
    1033     }
    1034 
    1035     case JSPropertyNameEnumerator::GenericMode: {
    1036         if (baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
    1037             metadata.m_arrayProfile.observeStructureID(baseValue.asCell()->structureID());
    1038         JSString* string = asString(GET(bytecode.m_propertyName).jsValue());
    1039         auto propertyName = string->toIdentifier(globalObject);
    1040         CHECK_EXCEPTION();
    1041         RETURN_PROFILED(baseValue.get(globalObject, propertyName));
    1042     }
    1043 
    1044     default:
    1045         RELEASE_ASSERT_NOT_REACHED();
    1046         break;
    1047     };
    1048     RELEASE_ASSERT_NOT_REACHED();
     1019
     1020    RETURN_PROFILED(CommonSlowPaths::opEnumeratorGetByVal(globalObject, baseValue, propertyName, index, mode, enumerator, &metadata.m_arrayProfile, &metadata.m_enumeratorMetadata));
    10491021}
    10501022
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r281910 r282385  
    3232#include "FunctionCodeBlock.h"
    3333#include "JSImmutableButterfly.h"
     34#include "JSPropertyNameEnumerator.h"
    3435#include "ScopedArguments.h"
    3536#include "SlowPathFunction.h"
     
    9091        return -1;
    9192    return padding;
     93}
     94
     95inline JSValue opEnumeratorGetByVal(JSGlobalObject* globalObject, JSValue baseValue, JSValue propertyNameValue, unsigned index, JSPropertyNameEnumerator::Flag mode, JSPropertyNameEnumerator* enumerator, ArrayProfile* arrayProfile = nullptr, uint8_t* enumeratorMetadata = nullptr)
     96{
     97    VM& vm = getVM(globalObject);
     98    auto scope = DECLARE_THROW_SCOPE(vm);
     99
     100    switch (mode) {
     101    case JSPropertyNameEnumerator::IndexedMode: {
     102        if (arrayProfile && LIKELY(baseValue.isCell()))
     103            arrayProfile->observeStructureID(baseValue.asCell()->structureID());
     104        RELEASE_AND_RETURN(scope, baseValue.get(globalObject, static_cast<unsigned>(index)));
     105    }
     106    case JSPropertyNameEnumerator::OwnStructureMode: {
     107        if (LIKELY(baseValue.isCell()) && baseValue.asCell()->structureID() == enumerator->cachedStructureID()) {
     108            // We'll only match the structure ID if the base is an object.
     109            ASSERT(index < enumerator->endStructurePropertyIndex());
     110            RELEASE_AND_RETURN(scope, baseValue.getObject()->getDirect(index < enumerator->cachedInlineCapacity() ? index : index - enumerator->cachedInlineCapacity() + firstOutOfLineOffset));
     111        } else {
     112            if (enumeratorMetadata)
     113                *enumeratorMetadata |= static_cast<uint8_t>(JSPropertyNameEnumerator::HasSeenOwnStructureModeStructureMismatch);
     114        }
     115        FALLTHROUGH;
     116    }
     117
     118    case JSPropertyNameEnumerator::GenericMode: {
     119        if (arrayProfile && baseValue.isCell() && mode != JSPropertyNameEnumerator::OwnStructureMode)
     120            arrayProfile->observeStructureID(baseValue.asCell()->structureID());
     121#if USE(JSVALUE32_64)
     122        if (!propertyNameValue.isCell()) {
     123            // This branch is only needed because we use this method
     124            // both as a slow_path and as a DFG call op. We'll end up
     125            // here if propertyName is not a cell then we are in
     126            // index+named mode, so do what RecoverNameAndGetVal
     127            // does. This can probably be removed if we re-enable the
     128            // optimizations for enumeratorGetByVal in DFG, see bug
     129            // #230189.
     130            JSString* string = enumerator->propertyNameAtIndex(index);
     131            auto propertyName = string->toIdentifier(globalObject);
     132            RETURN_IF_EXCEPTION(scope, { });
     133            RELEASE_AND_RETURN(scope, baseValue.get(globalObject, propertyName));
     134        }
     135#endif
     136        JSString* string = asString(propertyNameValue);
     137        auto propertyName = string->toIdentifier(globalObject);
     138        RETURN_IF_EXCEPTION(scope, { });
     139        RELEASE_AND_RETURN(scope, baseValue.get(globalObject, propertyName));
     140    }
     141
     142    default:
     143        RELEASE_ASSERT_NOT_REACHED();
     144        break;
     145    };
     146    RELEASE_ASSERT_NOT_REACHED();
    92147}
    93148
Note: See TracChangeset for help on using the changeset viewer.