Changeset 222675 in webkit
- Timestamp:
- Sep 29, 2017 6:16:52 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 14 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r222671 r222675 1 2017-09-29 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DFG] Support ArrayPush with multiple args 4 https://bugs.webkit.org/show_bug.cgi?id=175823 5 6 Reviewed by Saam Barati. 7 8 * microbenchmarks/array-push-0.js: Added. 9 (arrayPush0): 10 * microbenchmarks/array-push-1.js: Added. 11 (arrayPush1): 12 * microbenchmarks/array-push-2.js: Added. 13 (arrayPush2): 14 * microbenchmarks/array-push-3.js: Added. 15 (arrayPush3): 16 * stress/array-push-multiple-contiguous.js: Added. 17 (shouldBe): 18 (test): 19 * stress/array-push-multiple-double-nan.js: Added. 20 (shouldBe): 21 (test): 22 * stress/array-push-multiple-double.js: Added. 23 (shouldBe): 24 (test): 25 * stress/array-push-multiple-int32.js: Added. 26 (shouldBe): 27 (test): 28 * stress/array-push-multiple-many-contiguous.js: Added. 29 (shouldBe): 30 (test): 31 * stress/array-push-multiple-many-double.js: Added. 32 (shouldBe): 33 (test): 34 * stress/array-push-multiple-many-int32.js: Added. 35 (shouldBe): 36 (test): 37 * stress/array-push-multiple-many-storage.js: Added. 38 (shouldBe): 39 (test): 40 * stress/array-push-multiple-storage.js: Added. 41 (shouldBe): 42 (test): 43 * stress/array-push-with-force-exit.js: Added. 44 (target.createBuiltin): 45 1 46 2017-09-29 Saam Barati <sbarati@apple.com> 2 47 -
trunk/Source/JavaScriptCore/ChangeLog
r222671 r222675 1 2017-09-29 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DFG] Support ArrayPush with multiple args 4 https://bugs.webkit.org/show_bug.cgi?id=175823 5 6 Reviewed by Saam Barati. 7 8 Reviewed by Saam Barati. 9 10 This patch implements ArrayPush(with multiple arguments) in DFG and FTL. Previously, they are not handled 11 by ArrayPush. Then they go to generic direct call to Array#push and it does in slow path. This patch 12 extends ArrayPush to push multiple arguments in a bulk push manner. 13 14 The problem of ArrayPush is that we need to perform ArrayPush atomically: If OSR exit occurs in the middle 15 of ArrayPush, we incorrectly push pushed elements twice. Once we start pushing values, we should not exit. 16 But we do not want to iterate elements twice, once for type checks and once for actually pushing it. It 17 could move elements between registers and memory back and forth. 18 19 This patch achieves the above goal by separating type checks from ArrayPush. When starting ArrayPush, type 20 checks for elements are already done by separately emitted Check nodes. 21 22 We also add JSArray::pushInline for DFG operations just calling JSArray::push. And we also use it in 23 arrayProtoFuncPush's fast path. 24 25 This patch significantly improves performance of `push(multiple args)`. 26 27 baseline patched 28 Microbenchmarks: 29 array-push-0 461.8455+-28.9995 ^ 151.3438+-6.5653 ^ definitely 3.0516x faster 30 array-push-1 133.8845+-7.0349 ? 136.1775+-5.8327 ? might be 1.0171x slower 31 array-push-2 675.6555+-13.4645 ^ 145.8747+-6.4621 ^ definitely 4.6318x faster 32 array-push-3 849.5284+-15.2540 ^ 253.4421+-9.1249 ^ definitely 3.3520x faster 33 34 baseline patched 35 SixSpeed: 36 spread-literal.es5 90.3482+-6.6514 ^ 24.8123+-2.3304 ^ definitely 3.6413x faster 37 38 * dfg/DFGByteCodeParser.cpp: 39 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 40 * dfg/DFGFixupPhase.cpp: 41 (JSC::DFG::FixupPhase::fixupNode): 42 * dfg/DFGNodeType.h: 43 * dfg/DFGOperations.cpp: 44 * dfg/DFGOperations.h: 45 * dfg/DFGSpeculativeJIT.cpp: 46 (JSC::DFG::SpeculativeJIT::compileArrayPush): 47 * dfg/DFGSpeculativeJIT.h: 48 (JSC::DFG::SpeculativeJIT::callOperation): 49 * dfg/DFGSpeculativeJIT32_64.cpp: 50 (JSC::DFG::SpeculativeJIT::compile): 51 * dfg/DFGSpeculativeJIT64.cpp: 52 (JSC::DFG::SpeculativeJIT::compile): 53 * dfg/DFGStoreBarrierInsertionPhase.cpp: 54 * ftl/FTLLowerDFGToB3.cpp: 55 (JSC::FTL::DFG::LowerDFGToB3::compileArrayPush): 56 * jit/JITOperations.h: 57 * runtime/ArrayPrototype.cpp: 58 (JSC::arrayProtoFuncPush): 59 * runtime/JSArray.cpp: 60 (JSC::JSArray::push): 61 * runtime/JSArray.h: 62 * runtime/JSArrayInlines.h: 63 (JSC::JSArray::pushInline): 64 1 65 2017-09-29 Saam Barati <sbarati@apple.com> 2 66 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r222658 r222675 2335 2335 2336 2336 case ArrayPushIntrinsic: { 2337 if (argumentCountIncludingThis != 2) 2337 #if USE(JSVALUE32_64) 2338 if (isX86() || isMIPS()) { 2339 if (argumentCountIncludingThis > 2) 2340 return false; 2341 } 2342 #endif 2343 2344 if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX) 2338 2345 return false; 2339 2346 … … 2347 2354 case Array::ArrayStorage: { 2348 2355 insertChecks(); 2349 Node* arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset))); 2356 2357 addVarArgChild(nullptr); // For storage. 2358 for (int i = 0; i < argumentCountIncludingThis; ++i) 2359 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset))); 2360 Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction)); 2350 2361 set(VirtualRegister(resultOperand), arrayPush); 2351 2362 -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r222658 r222675 1009 1009 // array-related - so if refine() turned this into a "Generic" ArrayPush then 1010 1010 // that would break things. 1011 node->setArrayMode( 1012 node->arrayMode().refine( 1013 m_graph, node, 1014 node->child1()->prediction() & SpecCell, 1015 SpecInt32Only, 1016 node->child2()->prediction())); 1017 blessArrayOperation(node->child1(), Edge(), node->child3()); 1018 fixEdge<KnownCellUse>(node->child1()); 1019 1020 switch (node->arrayMode().type()) { 1021 case Array::Int32: 1022 fixEdge<Int32Use>(node->child2()); 1023 break; 1024 case Array::Double: 1025 fixEdge<DoubleRepRealUse>(node->child2()); 1026 break; 1027 case Array::Contiguous: 1028 case Array::ArrayStorage: 1029 speculateForBarrier(node->child2()); 1030 break; 1031 default: 1032 break; 1011 Edge& storageEdge = m_graph.varArgChild(node, 0); 1012 Edge& arrayEdge = m_graph.varArgChild(node, 1); 1013 unsigned elementOffset = 2; 1014 unsigned elementCount = node->numChildren() - elementOffset; 1015 for (unsigned i = 0; i < elementCount; ++i) { 1016 Edge& element = m_graph.varArgChild(node, i + elementOffset); 1017 node->setArrayMode( 1018 node->arrayMode().refine( 1019 m_graph, node, 1020 arrayEdge->prediction() & SpecCell, 1021 SpecInt32Only, 1022 element->prediction())); 1023 } 1024 blessArrayOperation(arrayEdge, Edge(), storageEdge); 1025 fixEdge<KnownCellUse>(arrayEdge); 1026 1027 // Convert `array.push()` to GetArrayLength. 1028 if (!elementCount && node->arrayMode().supportsSelfLength()) { 1029 node->setOpAndDefaultFlags(GetArrayLength); 1030 node->child1() = arrayEdge; 1031 node->child2() = storageEdge; 1032 fixEdge<KnownCellUse>(node->child1()); 1033 break; 1034 } 1035 1036 // We do not want to perform osr exit and retry for ArrayPush. We insert Check with appropriate type, 1037 // and ArrayPush uses the edge as known typed edge. Therefore, ArrayPush do not need to perform type checks. 1038 for (unsigned i = 0; i < elementCount; ++i) { 1039 Edge& element = m_graph.varArgChild(node, i + elementOffset); 1040 switch (node->arrayMode().type()) { 1041 case Array::Int32: 1042 insertCheck<Int32Use>(element.node()); 1043 fixEdge<KnownInt32Use>(element); 1044 break; 1045 case Array::Double: 1046 insertCheck<DoubleRepRealUse>(element.node()); 1047 fixEdge<DoubleRepUse>(element); 1048 break; 1049 case Array::Contiguous: 1050 case Array::ArrayStorage: 1051 speculateForBarrier(element); 1052 break; 1053 default: 1054 break; 1055 } 1056 ASSERT(shouldNotHaveTypeCheck(element.useKind())); 1033 1057 } 1034 1058 break; -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r222658 r222675 266 266 \ 267 267 /* Optimizations for array mutation. */\ 268 macro(ArrayPush, NodeResultJS | NodeMustGenerate ) \268 macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ 269 269 macro(ArrayPop, NodeResultJS | NodeMustGenerate) \ 270 270 macro(ArraySlice, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r222658 r222675 870 870 NativeCallFrameTracer tracer(vm, exec); 871 871 872 array->push (exec, JSValue::decode(encodedValue));872 array->pushInline(exec, JSValue::decode(encodedValue)); 873 873 return JSValue::encode(jsNumber(array->length())); 874 874 } … … 879 879 NativeCallFrameTracer tracer(vm, exec); 880 880 881 array->push(exec, JSValue(JSValue::EncodeAsDouble, value)); 881 array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, value)); 882 return JSValue::encode(jsNumber(array->length())); 883 } 884 885 EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount) 886 { 887 VM& vm = exec->vm(); 888 NativeCallFrameTracer tracer(&vm, exec); 889 auto scope = DECLARE_THROW_SCOPE(vm); 890 891 // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps. 892 // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the 893 // content of ScratchBuffer. If the IndexingType is now ArrayWithInt32/ArrayWithContiguous, we can ensure 894 // that there is no indexed accessors in this object and its prototype chain. 895 // 896 // ArrayWithArrayStorage is also OK. It can have indexed accessors. But if you define an indexed accessor, the array's length 897 // becomes larger than that index. So Array#push never overlaps with this accessor. So accessors are never called unless 898 // the IndexingType is ArrayWithSlowPutArrayStorage which could have an indexed accessor in a prototype chain. 899 RELEASE_ASSERT(!shouldUseSlowPut(array->indexingType())); 900 901 EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer); 902 for (int32_t i = 0; i < elementCount; ++i) { 903 array->pushInline(exec, JSValue::decode(values[i])); 904 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 905 } 906 return JSValue::encode(jsNumber(array->length())); 907 } 908 909 EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount) 910 { 911 VM& vm = exec->vm(); 912 NativeCallFrameTracer tracer(&vm, exec); 913 auto scope = DECLARE_THROW_SCOPE(vm); 914 915 // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps. 916 // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the 917 // content of ScratchBuffer. If the IndexingType is now ArrayWithDouble, we can ensure 918 // that there is no indexed accessors in this object and its prototype chain. 919 ASSERT(array->indexingType() == ArrayWithDouble); 920 921 double* values = static_cast<double*>(buffer); 922 for (int32_t i = 0; i < elementCount; ++i) { 923 array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, values[i])); 924 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 925 } 882 926 return JSValue::encode(jsNumber(array->length())); 883 927 } -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r222658 r222675 137 137 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState*, JSObject*, Symbol*, JSObject*, JSObject*, int32_t) WTF_INTERNAL; 138 138 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*) WTF_INTERNAL; 139 EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState*, JSArray*, void* buffer, int32_t elementCount) WTF_INTERNAL; 139 140 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState*, double value, JSArray*) WTF_INTERNAL; 141 EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState*, JSArray*, void* buffer, int32_t elementCount) WTF_INTERNAL; 140 142 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState*, JSArray*) WTF_INTERNAL; 141 143 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState*, JSArray*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r222658 r222675 7872 7872 } 7873 7873 7874 void SpeculativeJIT::compileArrayPush(Node* node) 7875 { 7876 ASSERT(node->arrayMode().isJSArray()); 7877 7878 Edge& storageEdge = m_jit.graph().varArgChild(node, 0); 7879 Edge& arrayEdge = m_jit.graph().varArgChild(node, 1); 7880 7881 SpeculateCellOperand base(this, arrayEdge); 7882 GPRTemporary storageLength(this); 7883 7884 GPRReg baseGPR = base.gpr(); 7885 GPRReg storageLengthGPR = storageLength.gpr(); 7886 7887 StorageOperand storage(this, storageEdge); 7888 GPRReg storageGPR = storage.gpr(); 7889 unsigned elementOffset = 2; 7890 unsigned elementCount = node->numChildren() - elementOffset; 7891 7892 #if USE(JSVALUE32_64) 7893 GPRTemporary tag(this); 7894 GPRReg tagGPR = tag.gpr(); 7895 JSValueRegs resultRegs { tagGPR, storageLengthGPR }; 7896 #else 7897 JSValueRegs resultRegs { storageLengthGPR }; 7898 #endif 7899 7900 auto getStorageBufferAddress = [&] (GPRReg storageGPR, GPRReg indexGPR, int32_t offset, GPRReg bufferGPR) { 7901 #if USE(JSVALUE32_64) 7902 static_assert(sizeof(JSValue) == 8 && 1 << 3 == 8, "This is strongly assumed in the code below."); 7903 m_jit.move(indexGPR, bufferGPR); 7904 m_jit.lshift32(TrustedImm32(3), bufferGPR); 7905 m_jit.add32(storageGPR, bufferGPR); 7906 if (offset) 7907 m_jit.add32(TrustedImm32(offset), bufferGPR); 7908 #else 7909 m_jit.getEffectiveAddress64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, offset), bufferGPR); 7910 #endif 7911 }; 7912 7913 switch (node->arrayMode().type()) { 7914 case Array::Int32: 7915 case Array::Contiguous: { 7916 if (elementCount == 1) { 7917 Edge& element = m_jit.graph().varArgChild(node, elementOffset); 7918 JSValueOperand value(this, element, ManualOperandSpeculation); 7919 JSValueRegs valueRegs = value.jsValueRegs(); 7920 7921 if (node->arrayMode().type() == Array::Int32) 7922 RELEASE_ASSERT(!needsTypeCheck(element, SpecInt32Only)); 7923 7924 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 7925 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 7926 m_jit.storeValue(valueRegs, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); 7927 m_jit.add32(TrustedImm32(1), storageLengthGPR); 7928 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 7929 m_jit.boxInt32(storageLengthGPR, resultRegs); 7930 7931 addSlowPathGenerator( 7932 slowPathCall(slowPath, this, operationArrayPush, resultRegs, valueRegs, baseGPR)); 7933 7934 jsValueResult(resultRegs, node); 7935 return; 7936 } 7937 7938 GPRTemporary buffer(this); 7939 GPRReg bufferGPR = buffer.gpr(); 7940 7941 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 7942 m_jit.move(storageLengthGPR, bufferGPR); 7943 m_jit.add32(TrustedImm32(elementCount), bufferGPR); 7944 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::Above, bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 7945 7946 m_jit.store32(bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 7947 getStorageBufferAddress(storageGPR, storageLengthGPR, 0, bufferGPR); 7948 m_jit.add32(TrustedImm32(elementCount), storageLengthGPR); 7949 m_jit.boxInt32(storageLengthGPR, resultRegs); 7950 auto storageDone = m_jit.jump(); 7951 7952 slowPath.link(&m_jit); 7953 7954 size_t scratchSize = sizeof(EncodedJSValue) * elementCount; 7955 ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize); 7956 m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR); 7957 m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR); 7958 m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR)); 7959 7960 storageDone.link(&m_jit); 7961 for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) { 7962 Edge& element = m_jit.graph().varArgChild(node, elementIndex + elementOffset); 7963 JSValueOperand value(this, element, ManualOperandSpeculation); 7964 JSValueRegs valueRegs = value.jsValueRegs(); 7965 7966 if (node->arrayMode().type() == Array::Int32) 7967 RELEASE_ASSERT(!needsTypeCheck(element, SpecInt32Only)); 7968 7969 m_jit.storeValue(valueRegs, MacroAssembler::Address(bufferGPR, sizeof(EncodedJSValue) * elementIndex)); 7970 value.use(); 7971 } 7972 7973 MacroAssembler::Jump fastPath = m_jit.branchPtr(MacroAssembler::NotEqual, bufferGPR, TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()))); 7974 7975 addSlowPathGenerator(slowPathCall(m_jit.jump(), this, operationArrayPushMultiple, resultRegs, baseGPR, bufferGPR, TrustedImm32(elementCount))); 7976 7977 m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR); 7978 m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR)); 7979 7980 base.use(); 7981 storage.use(); 7982 7983 fastPath.link(&m_jit); 7984 jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly); 7985 return; 7986 } 7987 7988 case Array::Double: { 7989 if (elementCount == 1) { 7990 Edge& element = m_jit.graph().varArgChild(node, elementOffset); 7991 SpeculateDoubleOperand value(this, element); 7992 FPRReg valueFPR = value.fpr(); 7993 7994 RELEASE_ASSERT(!needsTypeCheck(element, SpecDoubleReal)); 7995 7996 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 7997 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 7998 m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); 7999 m_jit.add32(TrustedImm32(1), storageLengthGPR); 8000 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 8001 m_jit.boxInt32(storageLengthGPR, resultRegs); 8002 8003 addSlowPathGenerator( 8004 slowPathCall(slowPath, this, operationArrayPushDouble, resultRegs, valueFPR, baseGPR)); 8005 8006 jsValueResult(resultRegs, node); 8007 return; 8008 } 8009 8010 GPRTemporary buffer(this); 8011 GPRReg bufferGPR = buffer.gpr(); 8012 8013 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 8014 m_jit.move(storageLengthGPR, bufferGPR); 8015 m_jit.add32(TrustedImm32(elementCount), bufferGPR); 8016 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::Above, bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 8017 8018 m_jit.store32(bufferGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 8019 getStorageBufferAddress(storageGPR, storageLengthGPR, 0, bufferGPR); 8020 m_jit.add32(TrustedImm32(elementCount), storageLengthGPR); 8021 m_jit.boxInt32(storageLengthGPR, resultRegs); 8022 auto storageDone = m_jit.jump(); 8023 8024 slowPath.link(&m_jit); 8025 8026 size_t scratchSize = sizeof(double) * elementCount; 8027 ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize); 8028 m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR); 8029 m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR); 8030 m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR)); 8031 8032 storageDone.link(&m_jit); 8033 for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) { 8034 Edge& element = m_jit.graph().varArgChild(node, elementIndex + elementOffset); 8035 SpeculateDoubleOperand value(this, element); 8036 FPRReg valueFPR = value.fpr(); 8037 8038 RELEASE_ASSERT(!needsTypeCheck(element, SpecDoubleReal)); 8039 8040 m_jit.storeDouble(valueFPR, MacroAssembler::Address(bufferGPR, sizeof(double) * elementIndex)); 8041 value.use(); 8042 } 8043 8044 MacroAssembler::Jump fastPath = m_jit.branchPtr(MacroAssembler::NotEqual, bufferGPR, TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()))); 8045 8046 addSlowPathGenerator(slowPathCall(m_jit.jump(), this, operationArrayPushDoubleMultiple, resultRegs, baseGPR, bufferGPR, TrustedImm32(elementCount))); 8047 8048 m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR); 8049 m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR)); 8050 8051 base.use(); 8052 storage.use(); 8053 8054 fastPath.link(&m_jit); 8055 jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly); 8056 return; 8057 } 8058 8059 case Array::ArrayStorage: { 8060 // This ensures that the result of ArrayPush is Int32 in AI. 8061 int32_t largestPositiveInt32Length = 0x7fffffff - elementCount; 8062 if (elementCount == 1) { 8063 Edge& element = m_jit.graph().varArgChild(node, elementOffset); 8064 JSValueOperand value(this, element); 8065 JSValueRegs valueRegs = value.jsValueRegs(); 8066 8067 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); 8068 8069 // Refuse to handle bizarre lengths. 8070 speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(largestPositiveInt32Length))); 8071 8072 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 8073 8074 m_jit.storeValue(valueRegs, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())); 8075 8076 m_jit.add32(TrustedImm32(1), storageLengthGPR); 8077 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset())); 8078 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); 8079 m_jit.boxInt32(storageLengthGPR, resultRegs); 8080 8081 addSlowPathGenerator( 8082 slowPathCall(slowPath, this, operationArrayPush, resultRegs, valueRegs, baseGPR)); 8083 8084 jsValueResult(resultRegs, node); 8085 return; 8086 } 8087 8088 GPRTemporary buffer(this); 8089 GPRReg bufferGPR = buffer.gpr(); 8090 8091 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); 8092 8093 // Refuse to handle bizarre lengths. 8094 speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(largestPositiveInt32Length))); 8095 8096 m_jit.move(storageLengthGPR, bufferGPR); 8097 m_jit.add32(TrustedImm32(elementCount), bufferGPR); 8098 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::Above, bufferGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 8099 8100 m_jit.store32(bufferGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset())); 8101 getStorageBufferAddress(storageGPR, storageLengthGPR, ArrayStorage::vectorOffset(), bufferGPR); 8102 m_jit.add32(TrustedImm32(elementCount), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); 8103 m_jit.add32(TrustedImm32(elementCount), storageLengthGPR); 8104 m_jit.boxInt32(storageLengthGPR, resultRegs); 8105 auto storageDone = m_jit.jump(); 8106 8107 slowPath.link(&m_jit); 8108 8109 size_t scratchSize = sizeof(EncodedJSValue) * elementCount; 8110 ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize); 8111 m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR); 8112 m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR); 8113 m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR)); 8114 8115 storageDone.link(&m_jit); 8116 for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) { 8117 Edge& element = m_jit.graph().varArgChild(node, elementIndex + elementOffset); 8118 JSValueOperand value(this, element); 8119 JSValueRegs valueRegs = value.jsValueRegs(); 8120 8121 m_jit.storeValue(valueRegs, MacroAssembler::Address(bufferGPR, sizeof(EncodedJSValue) * elementIndex)); 8122 value.use(); 8123 } 8124 8125 MacroAssembler::Jump fastPath = m_jit.branchPtr(MacroAssembler::NotEqual, bufferGPR, TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()))); 8126 8127 addSlowPathGenerator( 8128 slowPathCall(m_jit.jump(), this, operationArrayPushMultiple, resultRegs, baseGPR, bufferGPR, TrustedImm32(elementCount))); 8129 8130 m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR); 8131 m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR)); 8132 8133 base.use(); 8134 storage.use(); 8135 8136 fastPath.link(&m_jit); 8137 jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly); 8138 return; 8139 } 8140 8141 default: 8142 RELEASE_ASSERT_NOT_REACHED(); 8143 } 8144 } 8145 7874 8146 void SpeculativeJIT::compileNotifyWrite(Node* node) 7875 8147 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r222658 r222675 1614 1614 return appendCallSetResult(operation, result); 1615 1615 } 1616 JITCompiler::Call callOperation(J_JITOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1616 JITCompiler::Call callOperation(J_JITOperation_EJA operation, JSValueRegs result, JSValueRegs arg1, GPRReg arg2) 1617 { 1618 m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2); 1619 return appendCallSetResult(operation, result.payloadGPR()); 1620 } 1621 JITCompiler::Call callOperation(J_JITOperation_EJA operation, GPRReg result, JSValueRegs arg1, GPRReg arg2) 1622 { 1623 m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2); 1624 return appendCallSetResult(operation, result); 1625 } 1626 JITCompiler::Call callOperation(J_JITOperation_EP operation, GPRReg result, GPRReg arg1) 1627 { 1628 m_jit.setupArgumentsWithExecState(arg1); 1629 return appendCallSetResult(operation, result); 1630 } 1631 JITCompiler::Call callOperation(J_JITOperation_EZ operation, GPRReg result, GPRReg arg1) 1632 { 1633 m_jit.setupArgumentsWithExecState(arg1); 1634 return appendCallSetResult(operation, result); 1635 } 1636 JITCompiler::Call callOperation(J_JITOperation_EZ operation, GPRReg result, int32_t arg1) 1637 { 1638 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1)); 1639 return appendCallSetResult(operation, result); 1640 } 1641 JITCompiler::Call callOperation(J_JITOperation_EZZ operation, GPRReg result, int32_t arg1, GPRReg arg2) 1642 { 1643 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2); 1644 return appendCallSetResult(operation, result); 1645 } 1646 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1617 1647 { 1618 1648 m_jit.setupArgumentsWithExecState(arg1, arg2); 1619 1649 return appendCallSetResult(operation, result); 1620 1650 } 1621 JITCompiler::Call callOperation(J_JITOperation_EP operation, GPRReg result, GPRReg arg1) 1651 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2) 1652 { 1653 m_jit.setupArgumentsWithExecState(arg1, arg2); 1654 return appendCallSetResult(operation, result); 1655 } 1656 1657 JITCompiler::Call callOperation(J_JITOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2) 1658 { 1659 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2); 1660 return appendCallSetResult(operation, result); 1661 } 1662 1663 JITCompiler::Call callOperation(P_JITOperation_EJS operation, GPRReg result, GPRReg value, size_t index) 1664 { 1665 m_jit.setupArgumentsWithExecState(value, TrustedImmPtr(index)); 1666 return appendCallSetResult(operation, result); 1667 } 1668 1669 JITCompiler::Call callOperation(P_JITOperation_EStJ operation, GPRReg result, RegisteredStructure structure, GPRReg arg2) 1670 { 1671 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2); 1672 return appendCallSetResult(operation, result); 1673 } 1674 1675 JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1) 1676 { 1677 m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1); 1678 return appendCallSetResult(operation, result); 1679 } 1680 1681 JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1) 1682 { 1683 return callOperation(operation, result, globalObject, arg1.gpr()); 1684 } 1685 1686 JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, GPRReg arg1) 1622 1687 { 1623 1688 m_jit.setupArgumentsWithExecState(arg1); 1624 1689 return appendCallSetResult(operation, result); 1625 1690 } 1626 JITCompiler::Call callOperation(J_JITOperation_EZ operation, GPRReg result, GPRReg arg1) 1691 JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1) 1692 { 1693 m_jit.setupArgumentsWithExecState(arg1.gpr()); 1694 return appendCallSetResult(operation, result); 1695 } 1696 JITCompiler::Call callOperation(C_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1697 { 1698 m_jit.setupArgumentsWithExecState(arg1, arg2); 1699 return appendCallSetResult(operation, result); 1700 } 1701 JITCompiler::Call callOperation(C_JITOperation_EJJC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1702 { 1703 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1704 return appendCallSetResult(operation, result); 1705 } 1706 JITCompiler::Call callOperation(C_JITOperation_EJJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1707 { 1708 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1709 return appendCallSetResult(operation, result); 1710 } 1711 JITCompiler::Call callOperation(C_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1712 { 1713 m_jit.setupArgumentsWithExecState(arg1, arg2); 1714 return appendCallSetResult(operation, result); 1715 } 1716 JITCompiler::Call callOperation(C_JITOperation_EJZC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1717 { 1718 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1719 return appendCallSetResult(operation, result); 1720 } 1721 JITCompiler::Call callOperation(S_JITOperation_J operation, GPRReg result, GPRReg arg1) 1722 { 1723 m_jit.setupArguments(arg1); 1724 return appendCallSetResult(operation, result); 1725 } 1726 JITCompiler::Call callOperation(S_JITOperation_EJ operation, GPRReg result, GPRReg arg1) 1627 1727 { 1628 1728 m_jit.setupArgumentsWithExecState(arg1); 1629 1729 return appendCallSetResult(operation, result); 1630 1730 } 1631 JITCompiler::Call callOperation(J_JITOperation_EZ operation, GPRReg result, int32_t arg1) 1632 { 1633 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1)); 1634 return appendCallSetResult(operation, result); 1635 } 1636 JITCompiler::Call callOperation(J_JITOperation_EZZ operation, GPRReg result, int32_t arg1, GPRReg arg2) 1637 { 1638 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2); 1639 return appendCallSetResult(operation, result); 1640 } 1641 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1731 JITCompiler::Call callOperation(S_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1) 1732 { 1733 return callOperation(operation, result, arg1.gpr()); 1734 } 1735 JITCompiler::Call callOperation(J_JITOperation_EJ operation, JSValueRegs result, JSValueRegs arg1) 1736 { 1737 return callOperation(operation, result.payloadGPR(), arg1.payloadGPR()); 1738 } 1739 JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1) 1740 { 1741 return callOperation(operation, result, arg1.payloadGPR()); 1742 } 1743 JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, GPRReg arg1) 1744 { 1745 m_jit.setupArgumentsWithExecState(arg1); 1746 return appendCallSetResult(operation, result); 1747 } 1748 JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, GPRReg arg1, UniquedStringImpl* uid) 1749 { 1750 m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(uid)); 1751 return appendCallSetResult(operation, result); 1752 } 1753 JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, JSValueRegs arg1, UniquedStringImpl* uid) 1754 { 1755 return callOperation(operation, result, arg1.gpr(), uid); 1756 } 1757 JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1642 1758 { 1643 1759 m_jit.setupArgumentsWithExecState(arg1, arg2); 1644 1760 return appendCallSetResult(operation, result); 1645 1761 } 1646 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2) 1762 JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, JSValueRegs arg1, JSValueRegs arg2) 1763 { 1764 return callOperation(operation, result, arg1.gpr(), arg2.gpr()); 1765 } 1766 JITCompiler::Call callOperation(S_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1767 { 1768 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1769 return appendCallSetResult(operation, result); 1770 } 1771 JITCompiler::Call callOperation(S_JITOperation_EGReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1772 { 1773 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1774 return appendCallSetResult(operation, result); 1775 } 1776 JITCompiler::Call callOperation(S_JITOperation_EGReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1777 { 1778 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1779 return appendCallSetResult(operation, result); 1780 } 1781 1782 JITCompiler::Call callOperation(J_JITOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1647 1783 { 1648 1784 m_jit.setupArgumentsWithExecState(arg1, arg2); 1649 1785 return appendCallSetResult(operation, result); 1650 1786 } 1651 1652 JITCompiler::Call callOperation(J_JITOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2) 1653 { 1654 m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2); 1655 return appendCallSetResult(operation, result); 1656 } 1657 1658 JITCompiler::Call callOperation(P_JITOperation_EJS operation, GPRReg result, GPRReg value, size_t index) 1659 { 1660 m_jit.setupArgumentsWithExecState(value, TrustedImmPtr(index)); 1661 return appendCallSetResult(operation, result); 1662 } 1663 1664 JITCompiler::Call callOperation(P_JITOperation_EStJ operation, GPRReg result, RegisteredStructure structure, GPRReg arg2) 1665 { 1666 m_jit.setupArgumentsWithExecState(TrustedImmPtr(structure), arg2); 1667 return appendCallSetResult(operation, result); 1668 } 1669 1670 JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, GPRReg arg1) 1671 { 1672 m_jit.setupArgumentsWithExecState(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), arg1); 1673 return appendCallSetResult(operation, result); 1674 } 1675 1676 JITCompiler::Call callOperation(C_JITOperation_EGJ operation, GPRReg result, JSGlobalObject* globalObject, JSValueRegs arg1) 1677 { 1678 return callOperation(operation, result, globalObject, arg1.gpr()); 1679 } 1680 1681 JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, GPRReg arg1) 1682 { 1683 m_jit.setupArgumentsWithExecState(arg1); 1684 return appendCallSetResult(operation, result); 1685 } 1686 JITCompiler::Call callOperation(C_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1) 1687 { 1688 m_jit.setupArgumentsWithExecState(arg1.gpr()); 1689 return appendCallSetResult(operation, result); 1690 } 1691 JITCompiler::Call callOperation(C_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1787 JITCompiler::Call callOperation(J_JITOperation_EPPP operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3) 1788 { 1789 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1790 return appendCallSetResult(operation, result); 1791 } 1792 JITCompiler::Call callOperation(J_JITOperation_EGP operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1692 1793 { 1693 1794 m_jit.setupArgumentsWithExecState(arg1, arg2); 1694 1795 return appendCallSetResult(operation, result); 1695 1796 } 1696 JITCompiler::Call callOperation( C_JITOperation_EJJC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRRegarg3)1797 JITCompiler::Call callOperation(J_JITOperation_EAPZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3) 1697 1798 { 1698 1799 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1699 return appendCallSetResult(operation, result );1700 } 1701 JITCompiler::Call callOperation( C_JITOperation_EJJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRRegarg3)1800 return appendCallSetResult(operation, result.payloadGPR()); 1801 } 1802 JITCompiler::Call callOperation(J_JITOperation_EAPZ operation, GPRReg result, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3) 1702 1803 { 1703 1804 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 1704 return appendCallSetResult(operation, result);1705 }1706 JITCompiler::Call callOperation(C_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)1707 {1708 m_jit.setupArgumentsWithExecState(arg1, arg2);1709 return appendCallSetResult(operation, result);1710 }1711 JITCompiler::Call callOperation(C_JITOperation_EJZC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)1712 {1713 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);1714 return appendCallSetResult(operation, result);1715 }1716 JITCompiler::Call callOperation(S_JITOperation_J operation, GPRReg result, GPRReg arg1)1717 {1718 m_jit.setupArguments(arg1);1719 return appendCallSetResult(operation, result);1720 }1721 JITCompiler::Call callOperation(S_JITOperation_EJ operation, GPRReg result, GPRReg arg1)1722 {1723 m_jit.setupArgumentsWithExecState(arg1);1724 return appendCallSetResult(operation, result);1725 }1726 JITCompiler::Call callOperation(S_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)1727 {1728 return callOperation(operation, result, arg1.gpr());1729 }1730 JITCompiler::Call callOperation(J_JITOperation_EJ operation, JSValueRegs result, JSValueRegs arg1)1731 {1732 return callOperation(operation, result.payloadGPR(), arg1.payloadGPR());1733 }1734 JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)1735 {1736 return callOperation(operation, result, arg1.payloadGPR());1737 }1738 JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg result, GPRReg arg1)1739 {1740 m_jit.setupArgumentsWithExecState(arg1);1741 return appendCallSetResult(operation, result);1742 }1743 JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, GPRReg arg1, UniquedStringImpl* uid)1744 {1745 m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(uid));1746 return appendCallSetResult(operation, result);1747 }1748 JITCompiler::Call callOperation(S_JITOperation_EJI operation, GPRReg result, JSValueRegs arg1, UniquedStringImpl* uid)1749 {1750 return callOperation(operation, result, arg1.gpr(), uid);1751 }1752 JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)1753 {1754 m_jit.setupArgumentsWithExecState(arg1, arg2);1755 return appendCallSetResult(operation, result);1756 }1757 JITCompiler::Call callOperation(S_JITOperation_EJJ operation, GPRReg result, JSValueRegs arg1, JSValueRegs arg2)1758 {1759 return callOperation(operation, result, arg1.gpr(), arg2.gpr());1760 }1761 JITCompiler::Call callOperation(S_JITOperation_EGJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)1762 {1763 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);1764 return appendCallSetResult(operation, result);1765 }1766 JITCompiler::Call callOperation(S_JITOperation_EGReoJ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)1767 {1768 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);1769 return appendCallSetResult(operation, result);1770 }1771 JITCompiler::Call callOperation(S_JITOperation_EGReoJss operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)1772 {1773 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);1774 return appendCallSetResult(operation, result);1775 }1776 1777 JITCompiler::Call callOperation(J_JITOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2)1778 {1779 m_jit.setupArgumentsWithExecState(arg1, arg2);1780 return appendCallSetResult(operation, result);1781 }1782 JITCompiler::Call callOperation(J_JITOperation_EPPP operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)1783 {1784 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);1785 return appendCallSetResult(operation, result);1786 }1787 JITCompiler::Call callOperation(J_JITOperation_EGP operation, GPRReg result, GPRReg arg1, GPRReg arg2)1788 {1789 m_jit.setupArgumentsWithExecState(arg1, arg2);1790 1805 return appendCallSetResult(operation, result); 1791 1806 } … … 2113 2128 { 2114 2129 m_jit.setupArgumentsWithExecState(arg1, arg2); 2130 return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR()); 2131 } 2132 JITCompiler::Call callOperation(J_JITOperation_EAPZ operation, JSValueRegs result, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3) 2133 { 2134 m_jit.setupArgumentsWithExecState(arg1, arg2, arg3); 2115 2135 return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR()); 2116 2136 } … … 2929 2949 void compileArraySlice(Node*); 2930 2950 void compileArrayIndexOf(Node*); 2951 void compileArrayPush(Node*); 2931 2952 void compileNotifyWrite(Node*); 2932 2953 bool compileRegExpExec(Node*); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r222658 r222675 3385 3385 3386 3386 case ArrayPush: { 3387 ASSERT(node->arrayMode().isJSArray()); 3388 3389 SpeculateCellOperand base(this, node->child1()); 3390 GPRTemporary storageLength(this); 3391 3392 GPRReg baseGPR = base.gpr(); 3393 GPRReg storageLengthGPR = storageLength.gpr(); 3394 3395 StorageOperand storage(this, node->child3()); 3396 GPRReg storageGPR = storage.gpr(); 3397 3398 switch (node->arrayMode().type()) { 3399 case Array::Int32: { 3400 SpeculateInt32Operand value(this, node->child2()); 3401 GPRReg valuePayloadGPR = value.gpr(); 3402 3403 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 3404 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 3405 m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 3406 m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 3407 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3408 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 3409 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 3410 3411 addSlowPathGenerator( 3412 slowPathCall( 3413 slowPath, this, operationArrayPush, 3414 JSValueRegs(storageGPR, storageLengthGPR), 3415 TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR)); 3416 3417 jsValueResult(storageGPR, storageLengthGPR, node); 3418 break; 3419 } 3420 3421 case Array::Contiguous: { 3422 JSValueOperand value(this, node->child2()); 3423 GPRReg valueTagGPR = value.tagGPR(); 3424 GPRReg valuePayloadGPR = value.payloadGPR(); 3425 3426 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 3427 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 3428 m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 3429 m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 3430 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3431 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 3432 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 3433 3434 addSlowPathGenerator( 3435 slowPathCall( 3436 slowPath, this, operationArrayPush, 3437 JSValueRegs(storageGPR, storageLengthGPR), 3438 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR)); 3439 3440 jsValueResult(storageGPR, storageLengthGPR, node); 3441 break; 3442 } 3443 3444 case Array::Double: { 3445 SpeculateDoubleOperand value(this, node->child2()); 3446 FPRReg valueFPR = value.fpr(); 3447 3448 DFG_TYPE_CHECK( 3449 JSValueRegs(), node->child2(), SpecDoubleReal, 3450 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 3451 3452 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 3453 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 3454 m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); 3455 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3456 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 3457 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 3458 3459 addSlowPathGenerator( 3460 slowPathCall( 3461 slowPath, this, operationArrayPushDouble, 3462 JSValueRegs(storageGPR, storageLengthGPR), 3463 valueFPR, baseGPR)); 3464 3465 jsValueResult(storageGPR, storageLengthGPR, node); 3466 break; 3467 } 3468 3469 case Array::ArrayStorage: { 3470 JSValueOperand value(this, node->child2()); 3471 GPRReg valueTagGPR = value.tagGPR(); 3472 GPRReg valuePayloadGPR = value.payloadGPR(); 3473 3474 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); 3475 3476 // Refuse to handle bizarre lengths. 3477 speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe))); 3478 3479 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 3480 3481 m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 3482 m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 3483 3484 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3485 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset())); 3486 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); 3487 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 3488 3489 addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), 3490 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR)); 3491 3492 jsValueResult(storageGPR, storageLengthGPR, node); 3493 break; 3494 } 3495 3496 default: 3497 CRASH(); 3498 break; 3499 } 3387 compileArrayPush(node); 3500 3388 break; 3501 3389 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r222658 r222675 3664 3664 3665 3665 case ArrayPush: { 3666 ASSERT(node->arrayMode().isJSArray()); 3667 3668 SpeculateCellOperand base(this, node->child1()); 3669 GPRTemporary storageLength(this); 3670 3671 GPRReg baseGPR = base.gpr(); 3672 GPRReg storageLengthGPR = storageLength.gpr(); 3673 3674 StorageOperand storage(this, node->child3()); 3675 GPRReg storageGPR = storage.gpr(); 3676 3677 switch (node->arrayMode().type()) { 3678 case Array::Int32: 3679 case Array::Contiguous: { 3680 JSValueOperand value(this, node->child2(), ManualOperandSpeculation); 3681 GPRReg valueGPR = value.gpr(); 3682 3683 if (node->arrayMode().type() == Array::Int32) { 3684 DFG_TYPE_CHECK( 3685 JSValueRegs(valueGPR), node->child2(), SpecInt32Only, 3686 m_jit.branch64( 3687 MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister)); 3688 } 3689 3690 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 3691 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 3692 m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); 3693 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3694 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 3695 m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR); 3696 3697 addSlowPathGenerator( 3698 slowPathCall( 3699 slowPath, this, operationArrayPush, storageLengthGPR, 3700 valueGPR, baseGPR)); 3701 3702 jsValueResult(storageLengthGPR, node); 3703 break; 3704 } 3705 3706 case Array::Double: { 3707 SpeculateDoubleOperand value(this, node->child2()); 3708 FPRReg valueFPR = value.fpr(); 3709 3710 DFG_TYPE_CHECK( 3711 JSValueRegs(), node->child2(), SpecDoubleReal, 3712 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 3713 3714 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 3715 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 3716 m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); 3717 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3718 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 3719 m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR); 3720 3721 addSlowPathGenerator( 3722 slowPathCall( 3723 slowPath, this, operationArrayPushDouble, storageLengthGPR, 3724 valueFPR, baseGPR)); 3725 3726 jsValueResult(storageLengthGPR, node); 3727 break; 3728 } 3729 3730 case Array::ArrayStorage: { 3731 JSValueOperand value(this, node->child2()); 3732 GPRReg valueGPR = value.gpr(); 3733 3734 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); 3735 3736 // Refuse to handle bizarre lengths. 3737 speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe))); 3738 3739 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 3740 3741 m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())); 3742 3743 m_jit.add32(TrustedImm32(1), storageLengthGPR); 3744 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset())); 3745 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); 3746 m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR); 3747 3748 addSlowPathGenerator( 3749 slowPathCall( 3750 slowPath, this, operationArrayPush, NoResult, storageLengthGPR, 3751 valueGPR, baseGPR)); 3752 3753 jsValueResult(storageLengthGPR, node); 3754 break; 3755 } 3756 3757 default: 3758 CRASH(); 3759 break; 3760 } 3666 compileArrayPush(node); 3761 3667 break; 3762 3668 } -
trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp
r222658 r222675 251 251 switch (m_node->arrayMode().type()) { 252 252 case Array::Contiguous: 253 case Array::ArrayStorage: 254 considerBarrier(m_node->child1(), m_node->child2()); 253 case Array::ArrayStorage: { 254 unsigned elementOffset = 2; 255 unsigned elementCount = m_node->numChildren() - elementOffset; 256 Edge& arrayEdge = m_graph.varArgChild(m_node, 1); 257 for (unsigned i = 0; i < elementCount; ++i) { 258 Edge& element = m_graph.varArgChild(m_node, i + elementOffset); 259 considerBarrier(arrayEdge, element); 260 } 255 261 break; 262 } 256 263 default: 257 264 break; -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r222658 r222675 4089 4089 void compileArrayPush() 4090 4090 { 4091 LValue base = lowCell(m_node->child1()); 4092 LValue storage = lowStorage(m_node->child3()); 4093 4091 LValue base = lowCell(m_graph.varArgChild(m_node, 1)); 4092 LValue storage = lowStorage(m_graph.varArgChild(m_node, 0)); 4093 unsigned elementOffset = 2; 4094 unsigned elementCount = m_node->numChildren() - elementOffset; 4095 4094 4096 switch (m_node->arrayMode().type()) { 4095 4097 case Array::Int32: 4096 4098 case Array::Contiguous: 4097 4099 case Array::Double: { 4098 LValue value; 4099 Output::StoreType storeType; 4100 4101 if (m_node->arrayMode().type() != Array::Double) { 4102 value = lowJSValue(m_node->child2(), ManualOperandSpeculation); 4103 if (m_node->arrayMode().type() == Array::Int32) { 4104 FTL_TYPE_CHECK( 4105 jsValueValue(value), m_node->child2(), SpecInt32Only, isNotInt32(value)); 4100 IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type()); 4101 4102 if (elementCount == 1) { 4103 LValue value; 4104 Output::StoreType storeType; 4105 4106 Edge& element = m_graph.varArgChild(m_node, elementOffset); 4107 if (m_node->arrayMode().type() != Array::Double) { 4108 value = lowJSValue(element, ManualOperandSpeculation); 4109 if (m_node->arrayMode().type() == Array::Int32) 4110 RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecInt32Only)); 4111 storeType = Output::Store64; 4112 } else { 4113 value = lowDouble(element); 4114 RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecDoubleReal)); 4115 storeType = Output::StoreDouble; 4106 4116 } 4107 storeType = Output::Store64; 4108 } else { 4109 value = lowDouble(m_node->child2()); 4110 FTL_TYPE_CHECK( 4111 doubleValue(value), m_node->child2(), SpecDoubleReal, 4112 m_out.doubleNotEqualOrUnordered(value, value)); 4113 storeType = Output::StoreDouble; 4117 4118 LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength); 4119 4120 LBasicBlock fastPath = m_out.newBlock(); 4121 LBasicBlock slowPath = m_out.newBlock(); 4122 LBasicBlock continuation = m_out.newBlock(); 4123 4124 m_out.branch( 4125 m_out.aboveOrEqual( 4126 prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)), 4127 unsure(slowPath), unsure(fastPath)); 4128 4129 LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath); 4130 m_out.store( 4131 value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), storeType); 4132 LValue newLength = m_out.add(prevLength, m_out.int32One); 4133 m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength); 4134 4135 ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength)); 4136 m_out.jump(continuation); 4137 4138 m_out.appendTo(slowPath, continuation); 4139 LValue operation; 4140 if (m_node->arrayMode().type() != Array::Double) 4141 operation = m_out.operation(operationArrayPush); 4142 else 4143 operation = m_out.operation(operationArrayPushDouble); 4144 ValueFromBlock slowResult = m_out.anchor( 4145 vmCall(Int64, operation, m_callFrame, value, base)); 4146 m_out.jump(continuation); 4147 4148 m_out.appendTo(continuation, lastNext); 4149 setJSValue(m_out.phi(Int64, fastResult, slowResult)); 4150 return; 4114 4151 } 4115 4116 IndexedAbstractHeap& heap = m_heaps.forArrayType(m_node->arrayMode().type());4117 4152 4118 4153 LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength); 4119 4154 LValue newLength = m_out.add(prevLength, m_out.constInt32(elementCount)); 4155 4120 4156 LBasicBlock fastPath = m_out.newBlock(); 4121 4157 LBasicBlock slowPath = m_out.newBlock(); 4158 LBasicBlock setup = m_out.newBlock(); 4159 LBasicBlock slowCallPath = m_out.newBlock(); 4122 4160 LBasicBlock continuation = m_out.newBlock(); 4123 4124 m_out.branch( 4125 m_out.aboveOrEqual( 4126 prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)), 4127 unsure(slowPath), unsure(fastPath)); 4128 4161 4162 LValue beyondVectorLength = m_out.above(newLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)); 4163 4164 m_out.branch(beyondVectorLength, unsure(slowPath), unsure(fastPath)); 4165 4129 4166 LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath); 4130 m_out.store(4131 value, m_out.baseIndex(heap, storage, m_out.zeroExtPtr(prevLength)), storeType);4132 LValue newLength = m_out.add(prevLength, m_out.int32One);4133 4167 m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength); 4134 4168 ValueFromBlock fastBufferResult = m_out.anchor(m_out.baseIndex(storage, m_out.zeroExtPtr(prevLength), ScaleEight)); 4169 m_out.jump(setup); 4170 4171 m_out.appendTo(slowPath, setup); 4172 size_t scratchSize = sizeof(EncodedJSValue) * elementCount; 4173 static_assert(sizeof(EncodedJSValue) == sizeof(double), ""); 4174 ASSERT(scratchSize); 4175 ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize); 4176 m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength())); 4177 ValueFromBlock slowBufferResult = m_out.anchor(m_out.constIntPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()))); 4178 m_out.jump(setup); 4179 4180 m_out.appendTo(setup, slowCallPath); 4181 LValue buffer = m_out.phi(pointerType(), fastBufferResult, slowBufferResult); 4182 for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) { 4183 Edge& element = m_graph.varArgChild(m_node, elementIndex + elementOffset); 4184 4185 LValue value; 4186 Output::StoreType storeType; 4187 if (m_node->arrayMode().type() != Array::Double) { 4188 value = lowJSValue(element, ManualOperandSpeculation); 4189 if (m_node->arrayMode().type() == Array::Int32) 4190 RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecInt32Only)); 4191 storeType = Output::Store64; 4192 } else { 4193 value = lowDouble(element); 4194 RELEASE_ASSERT(!m_interpreter.needsTypeCheck(element, SpecDoubleReal)); 4195 storeType = Output::StoreDouble; 4196 } 4197 4198 m_out.store(value, m_out.baseIndex(heap, buffer, m_out.constInt32(elementIndex), jsNumber(elementIndex)), storeType); 4199 } 4135 4200 ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength)); 4136 m_out.jump(continuation); 4137 4138 m_out.appendTo(slowPath, continuation); 4201 4202 m_out.branch(beyondVectorLength, unsure(slowCallPath), unsure(continuation)); 4203 4204 m_out.appendTo(slowCallPath, continuation); 4139 4205 LValue operation; 4140 4206 if (m_node->arrayMode().type() != Array::Double) 4141 operation = m_out.operation(operationArrayPush );4207 operation = m_out.operation(operationArrayPushMultiple); 4142 4208 else 4143 operation = m_out.operation(operationArrayPushDouble );4144 ValueFromBlock slowResult = m_out.anchor( 4145 vmCall(Int64, operation, m_callFrame, value, base));4209 operation = m_out.operation(operationArrayPushDoubleMultiple); 4210 ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, operation, m_callFrame, base, buffer, m_out.constInt32(elementCount))); 4211 m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->addressOfActiveLength())); 4146 4212 m_out.jump(continuation); 4147 4213 4148 4214 m_out.appendTo(continuation, lastNext); 4149 4215 setJSValue(m_out.phi(Int64, fastResult, slowResult)); 4150 4216 return; 4151 4217 } 4152 4218 4153 4219 default: 4154 4220 DFG_CRASH(m_graph, m_node, "Bad array type"); -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r222658 r222675 142 142 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJC)(ExecState*, EncodedJSValue, JSCell*); 143 143 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJA)(ExecState*, EncodedJSValue, JSArray*); 144 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EAPZ)(ExecState*, JSArray*, void*, int32_t); 144 145 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJArp)(ExecState*, EncodedJSValue, ArithProfile*); 145 146 typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJI)(ExecState*, EncodedJSValue, UniquedStringImpl*); -
trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
r222658 r222675 765 765 JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); 766 766 767 if ( isJSArray(thisValue) && exec->argumentCount() == 1) {767 if (LIKELY(isJSArray(thisValue) && exec->argumentCount() == 1)) { 768 768 JSArray* array = asArray(thisValue); 769 769 scope.release(); 770 array->push (exec, exec->uncheckedArgument(0));770 array->pushInline(exec, exec->uncheckedArgument(0)); 771 771 return JSValue::encode(jsNumber(array->length())); 772 772 } -
trunk/Source/JavaScriptCore/runtime/JSArray.cpp
r222658 r222675 41 41 namespace JSC { 42 42 43 staticconst char* const LengthExceededTheMaximumArrayLengthError = "Length exceeded the maximum array length";43 const char* const LengthExceededTheMaximumArrayLengthError = "Length exceeded the maximum array length"; 44 44 45 45 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSArray); … … 726 726 // - we always are writing beyond the current array bounds, so it is always necessary to update m_length & m_numValuesInVector. 727 727 // - pushing to an array of length 2^32-1 stores the property, but throws a range error. 728 void JSArray::push(ExecState* exec, JSValue value) 729 { 730 VM& vm = exec->vm(); 731 auto scope = DECLARE_THROW_SCOPE(vm); 732 733 Butterfly* butterfly = m_butterfly.getMayBeNull(); 734 735 switch (indexingType()) { 736 case ArrayClass: { 737 createInitialUndecided(vm, 0); 738 FALLTHROUGH; 739 } 740 741 case ArrayWithUndecided: { 742 convertUndecidedForValue(vm, value); 743 scope.release(); 744 push(exec, value); 745 return; 746 } 747 748 case ArrayWithInt32: { 749 if (!value.isInt32()) { 750 convertInt32ForValue(vm, value); 751 scope.release(); 752 push(exec, value); 753 return; 754 } 755 756 unsigned length = butterfly->publicLength(); 757 ASSERT(length <= butterfly->vectorLength()); 758 if (length < butterfly->vectorLength()) { 759 butterfly->contiguousInt32()[length].setWithoutWriteBarrier(value); 760 butterfly->setPublicLength(length + 1); 761 return; 762 } 763 764 if (UNLIKELY(length > MAX_ARRAY_INDEX)) { 765 methodTable(vm)->putByIndex(this, exec, length, value, true); 766 if (!scope.exception()) 767 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 768 return; 769 } 770 771 scope.release(); 772 putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, length, value); 773 return; 774 } 775 776 case ArrayWithContiguous: { 777 unsigned length = butterfly->publicLength(); 778 ASSERT(length <= butterfly->vectorLength()); 779 if (length < butterfly->vectorLength()) { 780 butterfly->contiguous()[length].set(vm, this, value); 781 butterfly->setPublicLength(length + 1); 782 return; 783 } 784 785 if (UNLIKELY(length > MAX_ARRAY_INDEX)) { 786 methodTable(vm)->putByIndex(this, exec, length, value, true); 787 if (!scope.exception()) 788 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 789 return; 790 } 791 792 scope.release(); 793 putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, length, value); 794 return; 795 } 796 797 case ArrayWithDouble: { 798 if (!value.isNumber()) { 799 convertDoubleToContiguous(vm); 800 scope.release(); 801 push(exec, value); 802 return; 803 } 804 double valueAsDouble = value.asNumber(); 805 if (valueAsDouble != valueAsDouble) { 806 convertDoubleToContiguous(vm); 807 scope.release(); 808 push(exec, value); 809 return; 810 } 811 812 unsigned length = butterfly->publicLength(); 813 ASSERT(length <= butterfly->vectorLength()); 814 if (length < butterfly->vectorLength()) { 815 butterfly->contiguousDouble()[length] = valueAsDouble; 816 butterfly->setPublicLength(length + 1); 817 return; 818 } 819 820 if (UNLIKELY(length > MAX_ARRAY_INDEX)) { 821 methodTable(vm)->putByIndex(this, exec, length, value, true); 822 if (!scope.exception()) 823 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 824 return; 825 } 826 827 scope.release(); 828 putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, length, value); 829 return; 830 } 831 832 case ArrayWithSlowPutArrayStorage: { 833 unsigned oldLength = length(); 834 bool putResult = false; 835 if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult)) { 836 if (!scope.exception() && oldLength < 0xFFFFFFFFu) { 837 scope.release(); 838 setLength(exec, oldLength + 1, true); 839 } 840 return; 841 } 842 FALLTHROUGH; 843 } 844 845 case ArrayWithArrayStorage: { 846 ArrayStorage* storage = butterfly->arrayStorage(); 847 848 // Fast case - push within vector, always update m_length & m_numValuesInVector. 849 unsigned length = storage->length(); 850 if (length < storage->vectorLength()) { 851 storage->m_vector[length].set(vm, this, value); 852 storage->setLength(length + 1); 853 ++storage->m_numValuesInVector; 854 return; 855 } 856 857 // Pushing to an array of invalid length (2^31-1) stores the property, but throws a range error. 858 if (UNLIKELY(storage->length() > MAX_ARRAY_INDEX)) { 859 methodTable(vm)->putByIndex(this, exec, storage->length(), value, true); 860 // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d. 861 if (!scope.exception()) 862 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 863 return; 864 } 865 866 // Handled the same as putIndex. 867 scope.release(); 868 putByIndexBeyondVectorLengthWithArrayStorage(exec, storage->length(), value, true, storage); 869 return; 870 } 871 872 default: 873 RELEASE_ASSERT_NOT_REACHED(); 874 } 728 NEVER_INLINE void JSArray::push(ExecState* exec, JSValue value) 729 { 730 pushInline(exec, value); 875 731 } 876 732 -
trunk/Source/JavaScriptCore/runtime/JSArray.h
r222658 r222675 32 32 class LLIntOffsetsExtractor; 33 33 34 extern const char* const LengthExceededTheMaximumArrayLengthError; 35 34 36 class JSArray : public JSNonFinalObject { 35 37 friend class LLIntOffsetsExtractor; … … 91 93 JS_EXPORT_PRIVATE bool setLength(ExecState*, unsigned, bool throwException = false); 92 94 95 void pushInline(ExecState*, JSValue); 93 96 JS_EXPORT_PRIVATE void push(ExecState*, JSValue); 94 97 JS_EXPORT_PRIVATE JSValue pop(ExecState*); -
trunk/Source/JavaScriptCore/runtime/JSArrayInlines.h
r222658 r222675 20 20 #pragma once 21 21 22 #include "Error.h" 22 23 #include "JSArray.h" 23 24 #include "JSCellInlines.h" … … 83 84 } 84 85 86 ALWAYS_INLINE void JSArray::pushInline(ExecState* exec, JSValue value) 87 { 88 VM& vm = exec->vm(); 89 auto scope = DECLARE_THROW_SCOPE(vm); 90 91 Butterfly* butterfly = m_butterfly.getMayBeNull(); 92 93 switch (indexingType()) { 94 case ArrayClass: { 95 createInitialUndecided(vm, 0); 96 FALLTHROUGH; 97 } 98 99 case ArrayWithUndecided: { 100 convertUndecidedForValue(vm, value); 101 scope.release(); 102 push(exec, value); 103 return; 104 } 105 106 case ArrayWithInt32: { 107 if (!value.isInt32()) { 108 convertInt32ForValue(vm, value); 109 scope.release(); 110 push(exec, value); 111 return; 112 } 113 114 unsigned length = butterfly->publicLength(); 115 ASSERT(length <= butterfly->vectorLength()); 116 if (length < butterfly->vectorLength()) { 117 butterfly->contiguousInt32()[length].setWithoutWriteBarrier(value); 118 butterfly->setPublicLength(length + 1); 119 return; 120 } 121 122 if (UNLIKELY(length > MAX_ARRAY_INDEX)) { 123 methodTable(vm)->putByIndex(this, exec, length, value, true); 124 if (!scope.exception()) 125 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 126 return; 127 } 128 129 scope.release(); 130 putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, length, value); 131 return; 132 } 133 134 case ArrayWithContiguous: { 135 unsigned length = butterfly->publicLength(); 136 ASSERT(length <= butterfly->vectorLength()); 137 if (length < butterfly->vectorLength()) { 138 butterfly->contiguous()[length].set(vm, this, value); 139 butterfly->setPublicLength(length + 1); 140 return; 141 } 142 143 if (UNLIKELY(length > MAX_ARRAY_INDEX)) { 144 methodTable(vm)->putByIndex(this, exec, length, value, true); 145 if (!scope.exception()) 146 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 147 return; 148 } 149 150 scope.release(); 151 putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, length, value); 152 return; 153 } 154 155 case ArrayWithDouble: { 156 if (!value.isNumber()) { 157 convertDoubleToContiguous(vm); 158 scope.release(); 159 push(exec, value); 160 return; 161 } 162 double valueAsDouble = value.asNumber(); 163 if (valueAsDouble != valueAsDouble) { 164 convertDoubleToContiguous(vm); 165 scope.release(); 166 push(exec, value); 167 return; 168 } 169 170 unsigned length = butterfly->publicLength(); 171 ASSERT(length <= butterfly->vectorLength()); 172 if (length < butterfly->vectorLength()) { 173 butterfly->contiguousDouble()[length] = valueAsDouble; 174 butterfly->setPublicLength(length + 1); 175 return; 176 } 177 178 if (UNLIKELY(length > MAX_ARRAY_INDEX)) { 179 methodTable(vm)->putByIndex(this, exec, length, value, true); 180 if (!scope.exception()) 181 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 182 return; 183 } 184 185 scope.release(); 186 putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, length, value); 187 return; 188 } 189 190 case ArrayWithSlowPutArrayStorage: { 191 unsigned oldLength = length(); 192 bool putResult = false; 193 if (attemptToInterceptPutByIndexOnHole(exec, oldLength, value, true, putResult)) { 194 if (!scope.exception() && oldLength < 0xFFFFFFFFu) { 195 scope.release(); 196 setLength(exec, oldLength + 1, true); 197 } 198 return; 199 } 200 FALLTHROUGH; 201 } 202 203 case ArrayWithArrayStorage: { 204 ArrayStorage* storage = butterfly->arrayStorage(); 205 206 // Fast case - push within vector, always update m_length & m_numValuesInVector. 207 unsigned length = storage->length(); 208 if (length < storage->vectorLength()) { 209 storage->m_vector[length].set(vm, this, value); 210 storage->setLength(length + 1); 211 ++storage->m_numValuesInVector; 212 return; 213 } 214 215 // Pushing to an array of invalid length (2^31-1) stores the property, but throws a range error. 216 if (UNLIKELY(storage->length() > MAX_ARRAY_INDEX)) { 217 methodTable(vm)->putByIndex(this, exec, storage->length(), value, true); 218 // Per ES5.1 15.4.4.7 step 6 & 15.4.5.1 step 3.d. 219 if (!scope.exception()) 220 throwException(exec, scope, createRangeError(exec, ASCIILiteral(LengthExceededTheMaximumArrayLengthError))); 221 return; 222 } 223 224 // Handled the same as putIndex. 225 scope.release(); 226 putByIndexBeyondVectorLengthWithArrayStorage(exec, storage->length(), value, true, storage); 227 return; 228 } 229 230 default: 231 RELEASE_ASSERT_NOT_REACHED(); 232 } 233 } 234 85 235 } // namespace JSC
Note: See TracChangeset
for help on using the changeset viewer.