Changeset 282651 in webkit


Ignore:
Timestamp:
Sep 17, 2021 3:33:25 AM (3 years ago)
Author:
Carlos Garcia Campos
Message:

Merge r282385 - [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:
releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/ChangeLog

    r282650 r282651  
     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
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r281799 r282651  
    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::Mode mode = static_cast<JSPropertyNameEnumerator::Mode>(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{
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/dfg/DFGOperations.h

    r280760 r282651  
    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));
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r282650 r282651  
    1362413624}
    1362513625
    13626 void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
    13627 {
    13628     Edge baseEdge = m_graph.varArgChild(node, 0);
    13629     auto generate = [&] (GPRReg baseCellGPR) {
    13630         MacroAssembler::JumpList doneCases;
    13631         JSValueRegsTemporary result;
    13632         JSValueRegs resultRegs;
    13633         GPRReg indexGPR;
    13634         GPRReg enumeratorGPR;
    13635         MacroAssembler::Jump badStructureSlowPath;
    13636 
    13637         compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
    13638             Edge storageEdge = m_graph.varArgChild(node, 2);
    13639             StorageOperand storage;
    13640             if (storageEdge)
    13641                 storage.emplace(this, storageEdge);
    13642             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
    13643             SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
    13644             SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
    13645 
    13646             GPRReg modeGPR = mode.gpr();
    13647             indexGPR = index.gpr();
    13648             enumeratorGPR = enumerator.gpr();
    13649 
    13650             result = JSValueRegsTemporary(this);
    13651             resultRegs = result.regs();
    13652             GPRReg scratchGPR = resultRegs.payloadGPR();
    13653 
    13654             bool haveStorage = !!storageEdge;
    13655             GPRTemporary storageTemporary;
    13656             GPRReg storageGPR;
    13657             if (!haveStorage) {
    13658                 storageTemporary = GPRTemporary(this, Reuse, enumerator);
    13659                 storageGPR = storageTemporary.gpr();
    13660             } else
    13661                 storageGPR = storage.gpr();
    13662 
    13663             MacroAssembler::JumpList notFastNamedCases;
    13664 
    13665             // FIXME: We shouldn't generate this code if we know base is not an object.
    13666             notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
    13667             {
    13668                 if (!m_state.forNode(baseEdge).isType(SpecCell))
    13669                     notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
    13670 
    13671                 // Check the structure
    13672                 // FIXME: If we know there's only one structure for base we can just embed it here.
    13673                 m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
    13674 
    13675                 auto badStructure = m_jit.branch32(
    13676                     MacroAssembler::NotEqual,
    13677                     scratchGPR,
    13678                     MacroAssembler::Address(
    13679                         enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
    13680 
    13681                 // FIXME: Maybe we should have a better way to represent Indexed+Named?
    13682                 if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
    13683                     badStructureSlowPath = badStructure;
    13684                 else
    13685                     notFastNamedCases.append(badStructure);
    13686 
    13687                 // Compute the offset
    13688                 // If index is less than the enumerator's cached inline storage, then it's an inline access
    13689                 MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
    13690                     indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
    13691 
    13692                 m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
    13693 
    13694                 doneCases.append(m_jit.jump());
    13695 
    13696                 // Otherwise it's out of line
    13697                 outOfLineAccess.link(&m_jit);
    13698                 m_jit.move(indexGPR, scratchGPR);
    13699                 m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
    13700                 m_jit.neg32(scratchGPR);
    13701                 m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
    13702                 if (!haveStorage)
    13703                     m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
    13704                 constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
    13705                 m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
    13706                 doneCases.append(m_jit.jump());
    13707             }
    13708 
    13709             notFastNamedCases.link(&m_jit);
    13710             return std::make_pair(resultRegs, DataFormatJS);
    13711         }));
    13712 
    13713         // We rely on compileGetByVal to call jsValueResult for us.
    13714         // FIXME: This is kinda hacky...
    13715         ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
    13716 
    13717         if (badStructureSlowPath.isSet())
    13718             addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
    13719 
    13720         doneCases.link(&m_jit);
    13721     };
    13722 
    13723     if (isCell(baseEdge.useKind())) {
    13724         // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
    13725         speculate(node, baseEdge);
    13726         SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
    13727         generate(baseOperand.gpr());
    13728     } else {
    13729         JSValueOperand baseOperand(this, baseEdge);
    13730         generate(baseOperand.gpr());
    13731     }
    13732 }
    13733 
    1373413626template<typename SlowPathFunctionType>
    1373513627void SpeculativeJIT::compileEnumeratorHasProperty(Node* node, SlowPathFunctionType slowPathFunction)
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r281684 r282651  
    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
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r281684 r282651  
    62646264}
    62656265
     6266void SpeculativeJIT::compileEnumeratorGetByVal(Node* node)
     6267{
     6268    Edge baseEdge = m_graph.varArgChild(node, 0);
     6269    auto generate = [&] (GPRReg baseCellGPR) {
     6270        MacroAssembler::JumpList doneCases;
     6271        JSValueRegsTemporary result;
     6272        JSValueRegs resultRegs;
     6273        GPRReg indexGPR;
     6274        GPRReg enumeratorGPR;
     6275        MacroAssembler::Jump badStructureSlowPath;
     6276
     6277        compileGetByVal(node, scopedLambda<std::tuple<JSValueRegs, DataFormat>(DataFormat)>([&] (DataFormat) {
     6278            Edge storageEdge = m_graph.varArgChild(node, 2);
     6279            StorageOperand storage;
     6280            if (storageEdge)
     6281                storage.emplace(this, storageEdge);
     6282            SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 3));
     6283            SpeculateStrictInt32Operand mode(this, m_graph.varArgChild(node, 4));
     6284            SpeculateCellOperand enumerator(this, m_graph.varArgChild(node, 5));
     6285
     6286            GPRReg modeGPR = mode.gpr();
     6287            indexGPR = index.gpr();
     6288            enumeratorGPR = enumerator.gpr();
     6289
     6290            result = JSValueRegsTemporary(this);
     6291            resultRegs = result.regs();
     6292            GPRReg scratchGPR = resultRegs.payloadGPR();
     6293
     6294            bool haveStorage = !!storageEdge;
     6295            GPRTemporary storageTemporary;
     6296            GPRReg storageGPR;
     6297            if (!haveStorage) {
     6298                storageTemporary = GPRTemporary(this, Reuse, enumerator);
     6299                storageGPR = storageTemporary.gpr();
     6300            } else
     6301                storageGPR = storage.gpr();
     6302
     6303            MacroAssembler::JumpList notFastNamedCases;
     6304
     6305            // FIXME: We shouldn't generate this code if we know base is not an object.
     6306            notFastNamedCases.append(m_jit.branchTest32(MacroAssembler::NonZero, modeGPR, TrustedImm32(JSPropertyNameEnumerator::IndexedMode | JSPropertyNameEnumerator::GenericMode)));
     6307            {
     6308                if (!m_state.forNode(baseEdge).isType(SpecCell))
     6309                    notFastNamedCases.append(m_jit.branchIfNotCell(baseCellGPR));
     6310
     6311                // Check the structure
     6312                // FIXME: If we know there's only one structure for base we can just embed it here.
     6313                m_jit.load32(MacroAssembler::Address(baseCellGPR, JSCell::structureIDOffset()), scratchGPR);
     6314
     6315                auto badStructure = m_jit.branch32(
     6316                    MacroAssembler::NotEqual,
     6317                    scratchGPR,
     6318                    MacroAssembler::Address(
     6319                        enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
     6320
     6321                // FIXME: Maybe we should have a better way to represent Indexed+Named?
     6322                if (m_graph.varArgChild(node, 1).node() == m_graph.varArgChild(node, 3).node())
     6323                    badStructureSlowPath = badStructure;
     6324                else
     6325                    notFastNamedCases.append(badStructure);
     6326
     6327                // Compute the offset
     6328                // If index is less than the enumerator's cached inline storage, then it's an inline access
     6329                MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual,
     6330                    indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
     6331
     6332                m_jit.loadValue(MacroAssembler::BaseIndex(baseCellGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultRegs);
     6333
     6334                doneCases.append(m_jit.jump());
     6335
     6336                // Otherwise it's out of line
     6337                outOfLineAccess.link(&m_jit);
     6338                m_jit.move(indexGPR, scratchGPR);
     6339                m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
     6340                m_jit.neg32(scratchGPR);
     6341                m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
     6342                if (!haveStorage)
     6343                    m_jit.loadPtr(MacroAssembler::Address(baseCellGPR, JSObject::butterflyOffset()), storageGPR);
     6344                constexpr intptr_t offsetOfFirstProperty = offsetInButterfly(firstOutOfLineOffset) * static_cast<intptr_t>(sizeof(EncodedJSValue));
     6345                m_jit.loadValue(MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultRegs);
     6346                doneCases.append(m_jit.jump());
     6347            }
     6348
     6349            notFastNamedCases.link(&m_jit);
     6350            return std::make_pair(resultRegs, DataFormatJS);
     6351        }));
     6352
     6353        // We rely on compileGetByVal to call jsValueResult for us.
     6354        // FIXME: This is kinda hacky...
     6355        ASSERT(generationInfo(node).jsValueRegs() == resultRegs && generationInfo(node).registerFormat() == DataFormatJS);
     6356
     6357        if (badStructureSlowPath.isSet())
     6358            addSlowPathGenerator(slowPathCall(badStructureSlowPath, this, operationEnumeratorRecoverNameAndGetByVal, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseCellGPR, indexGPR, enumeratorGPR));
     6359
     6360        doneCases.link(&m_jit);
     6361    };
     6362
     6363    if (isCell(baseEdge.useKind())) {
     6364        // Use manual operand speculation since Fixup may have picked a UseKind more restrictive than CellUse.
     6365        speculate(node, baseEdge);
     6366        SpeculateCellOperand baseOperand(this, baseEdge, ManualOperandSpeculation);
     6367        generate(baseOperand.gpr());
     6368    } else {
     6369        JSValueOperand baseOperand(this, baseEdge);
     6370        generate(baseOperand.gpr());
     6371    }
     6372}
     6373
    62666374#endif
    62676375
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r281799 r282651  
    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::Mode>(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
  • releases/WebKitGTK/webkit-2.34/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r280760 r282651  
    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::Mode 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.