Changeset 121280 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Jun 26, 2012, 12:42:05 PM (13 years ago)
Author:
[email protected]
Message:

DFG::operationNewArray is unnecessarily slow, and may use the wrong array
prototype when inlined
https://bugs.webkit.org/show_bug.cgi?id=89821

Source/JavaScriptCore:

Reviewed by Geoffrey Garen.

Fixes all array allocations to use the right structure, and hence the right prototype. Adds
inlining of new Array(...) with a non-zero number of arguments. Optimizes allocations of
empty arrays.

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::execute):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):

  • dfg/DFGCCallHelpers.h:

(JSC::DFG::CCallHelpers::setupArgumentsWithExecState):
(CCallHelpers):

  • dfg/DFGNodeType.h:

(DFG):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • runtime/JSArray.h:

(JSC):
(JSC::constructArray):

  • runtime/JSGlobalObject.h:

(JSC):
(JSC::constructArray):

LayoutTests:

Rubber stamped by Geoffrey Garen.

  • fast/js/dfg-cross-global-object-inline-new-array-expected.txt: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-literal-expected.txt: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-literal-with-variables-expected.txt: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-literal-with-variables.html: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-literal.html: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-with-elements-expected.txt: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-with-elements.html: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-with-size-expected.txt: Added.
  • fast/js/dfg-cross-global-object-inline-new-array-with-size.html: Added.
  • fast/js/dfg-cross-global-object-inline-new-array.html: Added.
  • fast/js/script-tests/cross-global-object-inline-global-var.js:

(done):

  • fast/js/script-tests/dfg-cross-global-object-inline-new-array-literal-with-variables.js: Added.

(foo):
(done):
(doit):

  • fast/js/script-tests/dfg-cross-global-object-inline-new-array-literal.js: Added.

(foo):
(done):
(doit):

  • fast/js/script-tests/dfg-cross-global-object-inline-new-array-with-elements.js: Added.

(foo):
(done):
(doit):

  • fast/js/script-tests/dfg-cross-global-object-inline-new-array-with-size.js: Added.

(foo):
(done):
(doit):

  • fast/js/script-tests/dfg-cross-global-object-inline-new-array.js: Added.

(foo):
(done):
(doit):

Location:
trunk/Source/JavaScriptCore
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r121243 r121280  
     12012-06-25  Filip Pizlo  <[email protected]>
     2
     3        DFG::operationNewArray is unnecessarily slow, and may use the wrong array
     4        prototype when inlined
     5        https://bugs.webkit.org/show_bug.cgi?id=89821
     6
     7        Reviewed by Geoffrey Garen.
     8       
     9        Fixes all array allocations to use the right structure, and hence the right prototype. Adds
     10        inlining of new Array(...) with a non-zero number of arguments. Optimizes allocations of
     11        empty arrays.
     12
     13        * dfg/DFGAbstractState.cpp:
     14        (JSC::DFG::AbstractState::execute):
     15        * dfg/DFGByteCodeParser.cpp:
     16        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
     17        * dfg/DFGCCallHelpers.h:
     18        (JSC::DFG::CCallHelpers::setupArgumentsWithExecState):
     19        (CCallHelpers):
     20        * dfg/DFGNodeType.h:
     21        (DFG):
     22        * dfg/DFGOperations.cpp:
     23        * dfg/DFGOperations.h:
     24        * dfg/DFGPredictionPropagationPhase.cpp:
     25        (JSC::DFG::PredictionPropagationPhase::propagate):
     26        * dfg/DFGSpeculativeJIT.h:
     27        (JSC::DFG::SpeculativeJIT::callOperation):
     28        * dfg/DFGSpeculativeJIT32_64.cpp:
     29        (JSC::DFG::SpeculativeJIT::compile):
     30        * dfg/DFGSpeculativeJIT64.cpp:
     31        (JSC::DFG::SpeculativeJIT::compile):
     32        * runtime/JSArray.h:
     33        (JSC):
     34        (JSC::constructArray):
     35        * runtime/JSGlobalObject.h:
     36        (JSC):
     37        (JSC::constructArray):
     38
    1392012-06-26  Filip Pizlo  <[email protected]>
    240
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r121215 r121280  
    11421142    case NewArrayBuffer:
    11431143        node.setCanExit(false);
    1144         forNode(nodeIndex).set(m_codeBlock->globalObject()->arrayStructure());
     1144        forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
    11451145        m_haveStructures = true;
    11461146        break;
     1147       
     1148    case NewArrayWithSize:
     1149        speculateInt32Unary(node);
     1150        forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->arrayStructure());
     1151        m_haveStructures = true;
     1152        break;
    11471153           
    11481154    case NewRegexp:
    11491155        node.setCanExit(false);
    1150         forNode(nodeIndex).set(m_codeBlock->globalObject()->regExpStructure());
     1156        forNode(nodeIndex).set(m_graph.globalObjectFor(node.codeOrigin)->regExpStructure());
    11511157        m_haveStructures = true;
    11521158        break;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r121073 r121280  
    16071607    // is good enough.
    16081608   
    1609     UNUSED_PARAM(registerOffset); // Remove this once we do more things to the arguments.
    16101609    UNUSED_PARAM(prediction); // Remove this once we do more things.
    16111610    UNUSED_PARAM(kind); // Remove this once we do more things.
    16121611   
    16131612    if (function->classInfo() == &ArrayConstructor::s_info) {
    1614         // We could handle this but don't for now.
    1615         if (argumentCountIncludingThis != 1)
    1616             return false;
    1617        
     1613        if (argumentCountIncludingThis == 2) {
     1614            setIntrinsicResult(
     1615                usesResult, resultOperand,
     1616                addToGraph(NewArrayWithSize, get(registerOffset + argumentToOperand(1))));
     1617            return true;
     1618        }
     1619       
     1620        for (int i = 1; i < argumentCountIncludingThis; ++i)
     1621            addVarArgChild(get(registerOffset + argumentToOperand(i)));
    16181622        setIntrinsicResult(
    16191623            usesResult, resultOperand,
  • trunk/Source/JavaScriptCore/dfg/DFGCCallHelpers.h

    r120244 r121280  
    161161    }
    162162
     163    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2)
     164    {
     165        resetCallArguments();
     166        addCallArgument(GPRInfo::callFrameRegister);
     167        addCallArgument(arg1);
     168        addCallArgument(arg2);
     169    }
     170
    163171    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2)
    164172    {
     
    196204
    197205    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3)
     206    {
     207        resetCallArguments();
     208        addCallArgument(GPRInfo::callFrameRegister);
     209        addCallArgument(arg1);
     210        addCallArgument(arg2);
     211        addCallArgument(arg3);
     212    }
     213
     214    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
    198215    {
    199216        resetCallArguments();
     
    598615    }
    599616
     617    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2, TrustedImmPtr arg3)
     618    {
     619        move(arg1, GPRInfo::argumentGPR1);
     620        move(arg2, GPRInfo::argumentGPR2);
     621        move(arg3, GPRInfo::argumentGPR3);
     622        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     623    }
     624
    600625    ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, TrustedImm32 arg3)
    601626    {
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r120499 r121280  
    185185    macro(NewObject, NodeResultJS) \
    186186    macro(NewArray, NodeResultJS | NodeHasVarArgs) \
     187    macro(NewArrayWithSize, NodeResultJS) \
    187188    macro(NewArrayBuffer, NodeResultJS) \
    188189    macro(NewRegexp, NodeResultJS) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r121215 r121280  
    10061006}
    10071007
    1008 EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* buffer, size_t size)
    1009 {
    1010     JSGlobalData* globalData = &exec->globalData();
    1011     NativeCallFrameTracer tracer(globalData, exec);
    1012 
    1013     return JSValue::encode(constructArray(exec, static_cast<JSValue*>(buffer), size));
     1008EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
     1009{
     1010    JSGlobalData* globalData = &exec->globalData();
     1011    NativeCallFrameTracer tracer(globalData, exec);
     1012
     1013    return JSValue::encode(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
     1014}
     1015
     1016EncodedJSValue DFG_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
     1017{
     1018    return JSValue::encode(JSArray::create(exec->globalData(), arrayStructure));
     1019}
     1020
     1021EncodedJSValue DFG_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
     1022{
     1023    return JSValue::encode(JSArray::create(exec->globalData(), arrayStructure, size));
    10141024}
    10151025
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r121073 r121280  
    7777typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
    7878typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
     79typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESt)(ExecState*, Structure*);
     80typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EStI)(ExecState*, Structure*, int32_t);
     81typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EStPS)(ExecState*, Structure*, void*, size_t);
    7982typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZ)(ExecState*, int32_t);
    8083typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZIcfZ)(ExecState*, int32_t, InlineCallFrame*, int32_t);
     
    125128EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue) WTF_INTERNAL;
    126129EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t) WTF_INTERNAL;
    127 EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t) WTF_INTERNAL;
     130EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, Structure*, void*, size_t) WTF_INTERNAL;
    128131EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t) WTF_INTERNAL;
     132EncodedJSValue DFG_OPERATION operationNewEmptyArray(ExecState*, Structure*) WTF_INTERNAL;
     133EncodedJSValue DFG_OPERATION operationNewArrayWithSize(ExecState*, Structure*, int32_t) WTF_INTERNAL;
    129134EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*) WTF_INTERNAL;
    130135void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r120499 r121280  
    536536        }
    537537           
     538        case NewArrayWithSize: {
     539            changed |= setPrediction(SpecArray);
     540            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
     541            break;
     542        }
     543           
    538544        case NewArrayBuffer: {
    539545            changed |= setPrediction(SpecArray);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r120989 r121280  
    12451245        return appendCallWithExceptionCheckSetResult(operation, result);
    12461246    }
     1247    JITCompiler::Call callOperation(J_DFGOperation_ESt operation, GPRReg result, Structure* structure)
     1248    {
     1249        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
     1250        return appendCallWithExceptionCheckSetResult(operation, result);
     1251    }
     1252    JITCompiler::Call callOperation(J_DFGOperation_EStI operation, GPRReg result, Structure* structure, GPRReg arg2)
     1253    {
     1254        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2);
     1255        return appendCallWithExceptionCheckSetResult(operation, result);
     1256    }
     1257    JITCompiler::Call callOperation(J_DFGOperation_EStPS operation, GPRReg result, Structure* structure, void* pointer, size_t size)
     1258    {
     1259        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(pointer), TrustedImmPtr(size));
     1260        return appendCallWithExceptionCheckSetResult(operation, result);
     1261    }
    12471262    JITCompiler::Call callOperation(J_DFGOperation_EPS operation, GPRReg result, void* pointer, size_t size)
    12481263    {
     
    15011516    {
    15021517        m_jit.setupArgumentsWithExecState(arg1);
     1518        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1519    }
     1520    JITCompiler::Call callOperation(J_DFGOperation_ESt operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure)
     1521    {
     1522        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure));
     1523        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1524    }
     1525    JITCompiler::Call callOperation(J_DFGOperation_EStI operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure, GPRReg arg2)
     1526    {
     1527        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2);
     1528        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1529    }
     1530    JITCompiler::Call callOperation(J_DFGOperation_EStPS operation, GPRReg resultTag, GPRReg resultPayload, Structure* structure, void* pointer, size_t size)
     1531    {
     1532        m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), TrustedImmPtr(pointer), TrustedImmPtr(size));
    15031533        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
    15041534    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r121243 r121280  
    29762976    }
    29772977       
    2978     case StrCat:
    2979     case NewArray: {
    2980         // We really don't want to grow the register file just to do a StrCat or NewArray.
    2981         // Say we have 50 functions on the stack that all have a StrCat in them that has
    2982         // upwards of 10 operands. In the DFG this would mean that each one gets
    2983         // some random virtual register, and then to do the StrCat we'd need a second
    2984         // span of 10 operands just to have somewhere to copy the 10 operands to, where
    2985         // they'd be contiguous and we could easily tell the C code how to find them.
    2986         // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
    2987         // way, those 50 functions will share the same scratchBuffer for offloading their
    2988         // StrCat operands. It's about as good as we can do, unless we start doing
    2989         // virtual register coalescing to ensure that operands to StrCat get spilled
    2990         // in exactly the place where StrCat wants them, or else have the StrCat
    2991         // refer to those operands' SetLocal instructions to force them to spill in
    2992         // the right place. Basically, any way you cut it, the current approach
    2993         // probably has the best balance of performance and sensibility in the sense
    2994         // that it does not increase the complexity of the DFG JIT just to make StrCat
    2995         // fast and pretty.
    2996 
     2978    case StrCat: {
    29972979        size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
    29982980        ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
     
    30223004        GPRResult2 resultTag(this);
    30233005       
    3024         callOperation(op == StrCat ? operationStrCat : operationNewArray, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(buffer), node.numChildren());
     3006        callOperation(operationStrCat, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(buffer), node.numChildren());
    30253007
    30263008        if (scratchSize) {
     
    30363018    }
    30373019
     3020    case NewArray: {
     3021        if (!node.numChildren()) {
     3022            flushRegisters();
     3023            GPRResult result(this);
     3024            GPRResult2 resultTagIgnored(this);
     3025            callOperation(
     3026                operationNewEmptyArray, resultTagIgnored.gpr(), result.gpr(),
     3027                m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure());
     3028            cellResult(result.gpr(), m_compileIndex);
     3029            break;
     3030        }
     3031       
     3032        size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
     3033        ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
     3034        EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
     3035       
     3036        for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
     3037            JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
     3038            GPRReg opTagGPR = operand.tagGPR();
     3039            GPRReg opPayloadGPR = operand.payloadGPR();
     3040            operand.use();
     3041           
     3042            m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     3043            m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     3044        }
     3045       
     3046        flushRegisters();
     3047
     3048        if (scratchSize) {
     3049            GPRTemporary scratch(this);
     3050
     3051            // Tell GC mark phase how much of the scratch buffer is active during call.
     3052            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
     3053            m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
     3054        }
     3055
     3056        GPRResult resultPayload(this);
     3057        GPRResult2 resultTag(this);
     3058       
     3059        callOperation(
     3060            operationNewArray, resultTag.gpr(), resultPayload.gpr(),
     3061            m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(),
     3062            static_cast<void *>(buffer), node.numChildren());
     3063
     3064        if (scratchSize) {
     3065            GPRTemporary scratch(this);
     3066
     3067            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
     3068            m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
     3069        }
     3070
     3071        // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
     3072        cellResult(resultPayload.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
     3073        break;
     3074    }
     3075
     3076    case NewArrayWithSize: {
     3077        SpeculateStrictInt32Operand size(this, node.child1());
     3078        GPRReg sizeGPR = size.gpr();
     3079        flushRegisters();
     3080        GPRResult result(this);
     3081        GPRResult2 resultTagIgnored(this);
     3082        callOperation(
     3083            operationNewArrayWithSize, resultTagIgnored.gpr(), result.gpr(),
     3084            m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), sizeGPR);
     3085        cellResult(result.gpr(), m_compileIndex);
     3086        break;
     3087    }
     3088       
    30383089    case NewArrayBuffer: {
    30393090        flushRegisters();
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r120989 r121280  
    30363036    }
    30373037       
    3038     case StrCat:
    30393038    case NewArray: {
    3040         // We really don't want to grow the register file just to do a StrCat or NewArray.
    3041         // Say we have 50 functions on the stack that all have a StrCat in them that has
    3042         // upwards of 10 operands. In the DFG this would mean that each one gets
    3043         // some random virtual register, and then to do the StrCat we'd need a second
    3044         // span of 10 operands just to have somewhere to copy the 10 operands to, where
    3045         // they'd be contiguous and we could easily tell the C code how to find them.
    3046         // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
    3047         // way, those 50 functions will share the same scratchBuffer for offloading their
    3048         // StrCat operands. It's about as good as we can do, unless we start doing
    3049         // virtual register coalescing to ensure that operands to StrCat get spilled
    3050         // in exactly the place where StrCat wants them, or else have the StrCat
    3051         // refer to those operands' SetLocal instructions to force them to spill in
    3052         // the right place. Basically, any way you cut it, the current approach
    3053         // probably has the best balance of performance and sensibility in the sense
    3054         // that it does not increase the complexity of the DFG JIT just to make StrCat
    3055         // fast and pretty.
    3056 
     3039        if (!node.numChildren()) {
     3040            flushRegisters();
     3041            GPRResult result(this);
     3042            callOperation(
     3043                operationNewEmptyArray, result.gpr(),
     3044                m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure());
     3045            cellResult(result.gpr(), m_compileIndex);
     3046            break;
     3047        }
     3048       
    30573049        size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
    30583050        ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
     
    30793071        GPRResult result(this);
    30803072       
    3081         callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), static_cast<void *>(buffer), node.numChildren());
     3073        callOperation(
     3074            operationNewArray, result.gpr(),
     3075            m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(),
     3076            static_cast<void*>(buffer), node.numChildren());
     3077
     3078        if (scratchSize) {
     3079            GPRTemporary scratch(this);
     3080
     3081            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
     3082            m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
     3083        }
     3084
     3085        cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
     3086        break;
     3087    }
     3088       
     3089    case NewArrayWithSize: {
     3090        SpeculateStrictInt32Operand size(this, node.child1());
     3091        GPRReg sizeGPR = size.gpr();
     3092        flushRegisters();
     3093        GPRResult result(this);
     3094        callOperation(operationNewArrayWithSize, result.gpr(), m_jit.graph().globalObjectFor(node.codeOrigin)->arrayStructure(), sizeGPR);
     3095        cellResult(result.gpr(), m_compileIndex);
     3096        break;
     3097    }
     3098       
     3099    case StrCat: {
     3100        size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
     3101        ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
     3102        EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
     3103       
     3104        for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
     3105            JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
     3106            GPRReg opGPR = operand.gpr();
     3107            operand.use();
     3108           
     3109            m_jit.storePtr(opGPR, buffer + operandIdx);
     3110        }
     3111       
     3112        flushRegisters();
     3113
     3114        if (scratchSize) {
     3115            GPRTemporary scratch(this);
     3116
     3117            // Tell GC mark phase how much of the scratch buffer is active during call.
     3118            m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
     3119            m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
     3120        }
     3121
     3122        GPRResult result(this);
     3123       
     3124        callOperation(operationStrCat, result.gpr(), static_cast<void *>(buffer), node.numChildren());
    30823125
    30833126        if (scratchSize) {
  • trunk/Source/JavaScriptCore/runtime/JSArray.h

    r116828 r121280  
    381381        return size;
    382382    }
     383
     384    inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const ArgList& values)
     385    {
     386        JSGlobalData& globalData = exec->globalData();
     387        unsigned length = values.size();
     388        JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
     389
     390        // FIXME: we should probably throw an out of memory error here, but
     391        // when making this change we should check that all clients of this
     392        // function will correctly handle an exception being thrown from here.
     393        if (!array)
     394            CRASH();
     395
     396        for (unsigned i = 0; i < length; ++i)
     397            array->initializeIndex(globalData, i, values.at(i));
     398        array->completeInitialization(length);
     399        return array;
     400    }
    383401   
    384     } // namespace JSC
     402    inline JSArray* constructArray(ExecState* exec, Structure* arrayStructure, const JSValue* values, unsigned length)
     403    {
     404        JSGlobalData& globalData = exec->globalData();
     405        JSArray* array = JSArray::tryCreateUninitialized(globalData, arrayStructure, length);
     406
     407        // FIXME: we should probably throw an out of memory error here, but
     408        // when making this change we should check that all clients of this
     409        // function will correctly handle an exception being thrown from here.
     410        if (!array)
     411            CRASH();
     412
     413        for (unsigned i = 0; i < length; ++i)
     414            array->initializeIndex(globalData, i, values[i]);
     415        array->completeInitialization(length);
     416        return array;
     417    }
     418
     419} // namespace JSC
    385420
    386421#endif // JSArray_h
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r121215 r121280  
    446446        return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength);
    447447    }
    448 
     448 
    449449    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values)
    450450    {
    451         JSGlobalData& globalData = exec->globalData();
    452         unsigned length = values.size();
    453         JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length);
    454 
    455         // FIXME: we should probably throw an out of memory error here, but
    456         // when making this change we should check that all clients of this
    457         // function will correctly handle an exception being thrown from here.
    458         if (!array)
    459             CRASH();
    460 
    461         for (unsigned i = 0; i < length; ++i)
    462             array->initializeIndex(globalData, i, values.at(i));
    463         array->completeInitialization(length);
    464         return array;
     451        return constructArray(exec, globalObject->arrayStructure(), values);
    465452    }
    466453
     
    472459    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const JSValue* values, unsigned length)
    473460    {
    474         JSGlobalData& globalData = exec->globalData();
    475         JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length);
    476 
    477         // FIXME: we should probably throw an out of memory error here, but
    478         // when making this change we should check that all clients of this
    479         // function will correctly handle an exception being thrown from here.
    480         if (!array)
    481             CRASH();
    482 
    483         for (unsigned i = 0; i < length; ++i)
    484             array->initializeIndex(globalData, i, values[i]);
    485         array->completeInitialization(length);
    486         return array;
     461        return constructArray(exec, globalObject->arrayStructure(), values, length);
    487462    }
    488463
Note: See TracChangeset for help on using the changeset viewer.