Changeset 202413 in webkit
- Timestamp:
- Jun 23, 2016 8:41:52 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 47 added
- 44 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r202412 r202413 1 2016-06-23 Joseph Pecoraro <pecoraro@apple.com> and Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Implement isFinite / isNaN in JS and make DFG ToNumber accept non number values 4 https://bugs.webkit.org/show_bug.cgi?id=154022 5 6 Reviewed by Filip Pizlo. 7 8 * js/regress/Number-isNaN-expected.txt: Added. 9 * js/regress/Number-isNaN.html: Added. 10 * js/regress/global-isNaN-expected.txt: Added. 11 * js/regress/global-isNaN.html: Added. 12 * js/regress/script-tests/Number-isNaN.js: Added. 13 * js/regress/script-tests/global-isNaN.js: Added. 14 * js/regress/script-tests/many-foreach-calls.js: 15 (i.4.forEach): 16 (i.array.forEach): Deleted. 17 * js/regress/script-tests/to-number-constructor-number-string-number-string.js: Added. 18 (test): 19 * js/regress/script-tests/to-number-constructor-only-number.js: Added. 20 (test): 21 * js/regress/script-tests/to-number-constructor-only-string.js: Added. 22 (test): 23 * js/regress/script-tests/to-number-constructor-string-number-string-number.js: Added. 24 (test): 25 * js/regress/script-tests/to-number-number-string-number-string.js: Added. 26 (test): 27 * js/regress/script-tests/to-number-only-number.js: Added. 28 (test): 29 * js/regress/script-tests/to-number-only-string.js: Added. 30 (test): 31 * js/regress/script-tests/to-number-string-number-string-number.js: Added. 32 (test): 33 * js/regress/to-number-constructor-number-string-number-string-expected.txt: Added. 34 * js/regress/to-number-constructor-number-string-number-string.html: Added. 35 * js/regress/to-number-constructor-only-number-expected.txt: Added. 36 * js/regress/to-number-constructor-only-number.html: Added. 37 * js/regress/to-number-constructor-only-string-expected.txt: Added. 38 * js/regress/to-number-constructor-only-string.html: Added. 39 * js/regress/to-number-constructor-string-number-string-number-expected.txt: Added. 40 * js/regress/to-number-constructor-string-number-string-number.html: Added. 41 * js/regress/to-number-number-string-number-string-expected.txt: Added. 42 * js/regress/to-number-number-string-number-string.html: Added. 43 * js/regress/to-number-only-number-expected.txt: Added. 44 * js/regress/to-number-only-number.html: Added. 45 * js/regress/to-number-only-string-expected.txt: Added. 46 * js/regress/to-number-only-string.html: Added. 47 * js/regress/to-number-string-number-string-number-expected.txt: Added. 48 * js/regress/to-number-string-number-string-number.html: Added. 49 1 50 2016-06-23 Simon Fraser <simon.fraser@apple.com> 2 51 -
trunk/LayoutTests/js/regress/script-tests/many-foreach-calls.js
r198981 r202413 1 var sum = 0; 2 var array = [1, 2, 3]; 3 for (var i = 0; i < 1e5; ++i) { 4 array.forEach(function (value) { 1 for (var i = 0; i < 1e4; ++i) { 2 var sum = 0; 3 [1, 2, 3, 4].forEach(function (value) { 5 4 sum += value; 6 5 }); -
trunk/Source/JavaScriptCore/CMakeLists.txt
r202280 r202413 1218 1218 ${JAVASCRIPTCORE_DIR}/builtins/GeneratorPrototype.js 1219 1219 ${JAVASCRIPTCORE_DIR}/builtins/GlobalObject.js 1220 ${JAVASCRIPTCORE_DIR}/builtins/GlobalOperations.js 1220 1221 ${JAVASCRIPTCORE_DIR}/builtins/InspectorInstrumentationObject.js 1221 1222 ${JAVASCRIPTCORE_DIR}/builtins/InternalPromiseConstructor.js … … 1223 1224 ${JAVASCRIPTCORE_DIR}/builtins/MapPrototype.js 1224 1225 ${JAVASCRIPTCORE_DIR}/builtins/ModuleLoaderObject.js 1226 ${JAVASCRIPTCORE_DIR}/builtins/NumberConstructor.js 1225 1227 ${JAVASCRIPTCORE_DIR}/builtins/NumberPrototype.js 1226 1228 ${JAVASCRIPTCORE_DIR}/builtins/ObjectConstructor.js -
trunk/Source/JavaScriptCore/ChangeLog
r202402 r202413 1 2016-06-23 Joseph Pecoraro <pecoraro@apple.com> and Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Implement isFinite / isNaN in JS and make DFG ToNumber accept non number values 4 https://bugs.webkit.org/show_bug.cgi?id=154022 5 6 Reviewed by Filip Pizlo. 7 8 We aim at optimizing @toInteger operation. 9 While it still has an unoptimized part[1], this patch should be a first step. 10 11 We introduce the @toNumber builtin intrinsic operation. 12 This converts the given value to the JS number by emitting op_to_number bytecode. 13 Previously @toInteger called C++ @Number constructor for that purpose. 14 15 And in DFG, op_to_number is converted to DFG ToNumber node. 16 During DFG, we attempt to convert this to edge filtering and Identity, but if we fail, 17 we just fall back to calling the C++ function. 18 19 To utilize ToNumber in user-land side, we add a path attempting to convert Number constructor calls 20 to ToNumber DFG nodes. This conversion is useful because `Number(value)` is used to convert a value to a number in JS. 21 22 Before this patch, we emit simple edge filtering (NumberUse) instead of emitting DFG node like ToNumber for op_to_number. 23 But emitting ToNumber is useful, because in the case of `Number(value)`, considering `value` may not be a number is reasonable. 24 25 By leveraging @toNumber operation, we rewrite Number.{isFinite, isNaN}, global.{isFinite, isNaN} and @toInteger. 26 27 ToNumber DFG node has a value profiling. This profiling is leveraged to determine the result number type of the ToNumber operation. 28 This value profiling is provided from either NumberConstructor's call operation or op_to_number. 29 30 The results (with the added performance tests) show that, while existing cases are performance neutral, the newly added cases gain the performance benefit. 31 And ASMBench/n-body.c also shows stable ~2% progression. 32 33 [1]: https://bugs.webkit.org/show_bug.cgi?id=153738 34 35 * CMakeLists.txt: 36 * DerivedSources.make: 37 * JavaScriptCore.xcodeproj/project.pbxproj: 38 * builtins/BuiltinNames.h: 39 * builtins/GlobalObject.js: 40 (globalPrivate.isFinite): 41 (globalPrivate.isNaN): 42 (globalPrivate.toInteger): Deleted. 43 (globalPrivate.toLength): Deleted. 44 (globalPrivate.isDictionary): Deleted. 45 (globalPrivate.speciesGetter): Deleted. 46 (globalPrivate.speciesConstructor): Deleted. 47 * builtins/GlobalOperations.js: Copied from Source/JavaScriptCore/builtins/GlobalObject.js. 48 (globalPrivate.toInteger): 49 (globalPrivate.toLength): 50 (globalPrivate.isDictionary): 51 (globalPrivate.speciesGetter): 52 (globalPrivate.speciesConstructor): 53 * builtins/NumberConstructor.js: Added. 54 (isFinite): 55 (isNaN): 56 * bytecode/BytecodeIntrinsicRegistry.cpp: 57 (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry): 58 * bytecode/BytecodeIntrinsicRegistry.h: 59 * bytecode/BytecodeList.json: 60 * bytecode/CodeBlock.cpp: 61 (JSC::CodeBlock::dumpBytecode): 62 (JSC::CodeBlock::finishCreation): 63 * bytecompiler/BytecodeGenerator.cpp: 64 (JSC::BytecodeGenerator::emitUnaryOp): 65 (JSC::BytecodeGenerator::emitUnaryOpProfiled): 66 * bytecompiler/BytecodeGenerator.h: 67 (JSC::BytecodeGenerator::emitToNumber): 68 * bytecompiler/NodesCodegen.cpp: 69 (JSC::BytecodeIntrinsicNode::emit_intrinsic_toNumber): 70 (JSC::UnaryPlusNode::emitBytecode): 71 * dfg/DFGAbstractInterpreterInlines.h: 72 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 73 * dfg/DFGByteCodeParser.cpp: 74 (JSC::DFG::ByteCodeParser::attemptToInlineCall): 75 (JSC::DFG::ByteCodeParser::handleConstantInternalFunction): 76 (JSC::DFG::ByteCodeParser::parseBlock): 77 We use `getPrediction()` to retrieve the heap prediction from the to_number bytecode. 78 According to the benchmark results, choosing `getPredictionWithoutOSRExit()` causes performance regression (1.5%) in kraken stanford-crypto-aes. 79 80 * dfg/DFGClobberize.h: 81 (JSC::DFG::clobberize): 82 * dfg/DFGConstantFoldingPhase.cpp: 83 (JSC::DFG::ConstantFoldingPhase::foldConstants): 84 * dfg/DFGDoesGC.cpp: 85 (JSC::DFG::doesGC): 86 * dfg/DFGFixupPhase.cpp: 87 (JSC::DFG::FixupPhase::fixupNode): 88 (JSC::DFG::FixupPhase::fixupToNumber): 89 * dfg/DFGNode.h: 90 (JSC::DFG::Node::hasHeapPrediction): 91 * dfg/DFGNodeType.h: 92 * dfg/DFGOperations.cpp: 93 * dfg/DFGOperations.h: 94 * dfg/DFGPredictionPropagationPhase.cpp: 95 Alway rely on the heap prediction. 96 97 * dfg/DFGSafeToExecute.h: 98 (JSC::DFG::safeToExecute): 99 * dfg/DFGSpeculativeJIT32_64.cpp: 100 (JSC::DFG::SpeculativeJIT::compile): 101 As of 64bit version, we carefully manage the register reuse. The largest difference between 32bit and 64bit is 102 `branchIfNotNumber()` requires the temporary register. We should not use the result registers for that since 103 it may be reuse the argument registers and it can break the argument registers before using them to call the operation. 104 Currently, we allocate the additional temporary register for that scratch register. 105 106 * dfg/DFGSpeculativeJIT64.cpp: 107 (JSC::DFG::SpeculativeJIT::compile): 108 Reuse the argument register for the result if possible. And manually decrement the use count in the middle of the node. 109 This is similar technique used in ToPrimitive. Typically, the child of ToNumber is only used by this ToNumber node since 110 we would like to perform the type conversion onto this child node here. So this careful register reuse effectively removes 111 the spills to call the operation. The example of the actually emitted code is the following. 112 113 76:<!2:loc11> ToNumber(Untyped:@68, JS|MustGen|UseAsOther, DoubleimpurenanTopEmpty, R:World, W:Heap, Exits, ClobbersExit, bc#48) predicting DoubleimpurenanTopEmpty 114 0x7f986d5fe693: test %rax, %r14 115 0x7f986d5fe696: jz 0x7f986d5fe6a1 116 0x7f986d5fe69c: jmp 0x7f986d5fe6d1 117 0x7f986d5fe6a1: mov %rax, %rsi 118 0x7f986d5fe6a4: mov %rbp, %rdi 119 0x7f986d5fe6a7: mov $0x2, 0x24(%rbp) 120 0x7f986d5fe6ae: mov $0x7f98711ea5f0, %r11 121 0x7f986d5fe6b8: call *%r11 122 0x7f986d5fe6bb: mov $0x7f982d3f72d0, %r11 123 0x7f986d5fe6c5: mov (%r11), %r11 124 0x7f986d5fe6c8: test %r11, %r11 125 0x7f986d5fe6cb: jnz 0x7f986d5fe88c 126 127 It effectively removes the unnecessary spill to call the operation! 128 129 * ftl/FTLCapabilities.cpp: 130 (JSC::FTL::canCompile): 131 * ftl/FTLLowerDFGToB3.cpp: 132 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 133 (JSC::FTL::DFG::LowerDFGToB3::compileToNumber): 134 (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq): 135 * jit/AssemblyHelpers.h: 136 (JSC::AssemblyHelpers::branchIfNumber): 137 (JSC::AssemblyHelpers::branchIfNotNumber): 138 * jit/JITOpcodes.cpp: 139 (JSC::JIT::emit_op_to_number): 140 * jit/JITOpcodes32_64.cpp: 141 (JSC::JIT::emit_op_to_number): 142 * llint/LowLevelInterpreter32_64.asm: 143 * llint/LowLevelInterpreter64.asm: 144 * parser/Nodes.h: 145 (JSC::UnaryOpNode::opcodeID): 146 * runtime/CommonSlowPaths.cpp: 147 (JSC::SLOW_PATH_DECL): 148 * runtime/JSGlobalObject.cpp: 149 (JSC::JSGlobalObject::init): 150 * runtime/JSGlobalObjectFunctions.cpp: 151 (JSC::globalFuncIsNaN): Deleted. 152 (JSC::globalFuncIsFinite): Deleted. 153 * runtime/JSGlobalObjectFunctions.h: 154 * runtime/MathCommon.h: 155 (JSC::maxSafeInteger): 156 (JSC::minSafeInteger): 157 * runtime/NumberConstructor.cpp: 158 (JSC::NumberConstructor::finishCreation): 159 (JSC::numberConstructorFuncIsFinite): Deleted. 160 (JSC::numberConstructorFuncIsNaN): Deleted. 161 * runtime/NumberConstructor.h: 162 * tests/stress/Number-isNaN-basics.js: Added. 163 (numberIsNaNOnInteger): 164 (testNumberIsNaNOnIntegers): 165 (verifyNumberIsNaNOnIntegerWithOtherTypes): 166 (numberIsNaNOnDouble): 167 (testNumberIsNaNOnDoubles): 168 (verifyNumberIsNaNOnDoublesWithOtherTypes): 169 (numberIsNaNNoArguments): 170 (numberIsNaNTooManyArguments): 171 (testNumberIsNaNOnConstants): 172 (numberIsNaNStructTransition): 173 (Number.isNaN): 174 * tests/stress/global-is-finite.js: Added. 175 (shouldBe): 176 * tests/stress/global-is-nan.js: Added. 177 (shouldBe): 178 * tests/stress/global-isNaN-basics.js: Added. 179 (isNaNOnInteger): 180 (testIsNaNOnIntegers): 181 (verifyIsNaNOnIntegerWithOtherTypes): 182 (isNaNOnDouble): 183 (testIsNaNOnDoubles): 184 (verifyIsNaNOnDoublesWithOtherTypes): 185 (verifyIsNaNOnCoercedTypes): 186 (isNaNNoArguments): 187 (isNaNTooManyArguments): 188 (testIsNaNOnConstants): 189 (isNaNTypeCoercionSideEffects): 190 (i.value.isNaNTypeCoercionSideEffects.valueOf): 191 (isNaNStructTransition): 192 (isNaN): 193 * tests/stress/number-is-finite.js: Added. 194 (shouldBe): 195 (test2): 196 (test3): 197 * tests/stress/number-is-nan.js: Added. 198 (shouldBe): 199 (test2): 200 (test3): 201 * tests/stress/to-number-basics.js: Added. 202 (shouldBe): 203 * tests/stress/to-number-convert-identity-without-execution.js: Added. 204 (shouldBe): 205 (object.valueOf): 206 (valueOf): 207 * tests/stress/to-number-int52.js: Added. 208 (shouldBe): 209 (object.valueOf): 210 * tests/stress/to-number-intrinsic-convert-to-identity-without-execution.js: Added. 211 (shouldBe): 212 (object.valueOf): 213 (valueOf): 214 * tests/stress/to-number-intrinsic-int52.js: Added. 215 (shouldBe): 216 (object.valueOf): 217 * tests/stress/to-number-intrinsic-object-without-execution.js: Added. 218 (shouldBe): 219 (object.valueOf): 220 * tests/stress/to-number-intrinsic-value-profiling.js: Added. 221 (shouldBe): 222 (object.valueOf): 223 * tests/stress/to-number-object-without-execution.js: Added. 224 (shouldBe): 225 (object.valueOf): 226 * tests/stress/to-number-object.js: Added. 227 (shouldBe): 228 (test12): 229 (object1.valueOf): 230 (test2): 231 (test22): 232 (object2.valueOf): 233 (test3): 234 (test32): 235 (object3.valueOf): 236 * tests/stress/to-number-value-profiling.js: Added. 237 (shouldBe): 238 (object.valueOf): 239 1 240 2016-06-23 Saam Barati <sbarati@apple.com> 2 241 -
trunk/Source/JavaScriptCore/DerivedSources.make
r201542 r202413 89 89 $(JavaScriptCore)/builtins/GeneratorPrototype.js \ 90 90 $(JavaScriptCore)/builtins/GlobalObject.js \ 91 $(JavaScriptCore)/builtins/GlobalOperations.js \ 91 92 $(JavaScriptCore)/builtins/InspectorInstrumentationObject.js \ 92 93 $(JavaScriptCore)/builtins/InternalPromiseConstructor.js \ … … 94 95 $(JavaScriptCore)/builtins/MapPrototype.js \ 95 96 $(JavaScriptCore)/builtins/ModuleLoaderObject.js \ 97 $(JavaScriptCore)/builtins/NumberConstructor.js \ 96 98 $(JavaScriptCore)/builtins/NumberPrototype.js \ 97 99 $(JavaScriptCore)/builtins/ObjectConstructor.js \ -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r202287 r202413 3773 3773 A514B2C0185A684400F3C7CB /* InjectedScriptBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedScriptBase.cpp; sourceTree = "<group>"; }; 3774 3774 A514B2C1185A684400F3C7CB /* InjectedScriptBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedScriptBase.h; sourceTree = "<group>"; }; 3775 A52704851D027C8800354C37 /* GlobalOperations.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = GlobalOperations.js; sourceTree = "<group>"; }; 3776 A52704861D027C8800354C37 /* NumberConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = NumberConstructor.js; sourceTree = "<group>"; }; 3775 3777 A5311C341C77CEAC00E6B1B6 /* HeapSnapshotBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapSnapshotBuilder.cpp; sourceTree = "<group>"; }; 3776 3778 A5311C351C77CEAC00E6B1B6 /* HeapSnapshotBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapSnapshotBuilder.h; sourceTree = "<group>"; }; … … 6884 6886 70B7918F1C0244EC002481E2 /* GeneratorPrototype.js */, 6885 6887 7CF9BC5A1B65D9A3009DB1EF /* GlobalObject.js */, 6888 A52704851D027C8800354C37 /* GlobalOperations.js */, 6886 6889 E35E03611B7AB4850073AD2A /* InspectorInstrumentationObject.js */, 6887 6890 E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */, … … 6889 6892 7035587C1C418419004BD7BF /* MapPrototype.js */, 6890 6893 E30677971B8BC6F5003F87F0 /* ModuleLoaderObject.js */, 6894 A52704861D027C8800354C37 /* NumberConstructor.js */, 6891 6895 A15DE5C51C0FBF8D0089133D /* NumberPrototype.js */, 6892 6896 7CF9BC5C1B65D9B1009DB1EF /* ObjectConstructor.js */, -
trunk/Source/JavaScriptCore/builtins/BuiltinNames.h
r202363 r202413 65 65 macro(floor) \ 66 66 macro(trunc) \ 67 macro(isFinite) \68 macro(isNaN) \69 67 macro(create) \ 70 68 macro(defineProperty) \ -
trunk/Source/JavaScriptCore/builtins/GlobalObject.js
r202280 r202413 1 1 /* 2 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.2 * Copyright (C) 2015-2016 Yusuke Suzuki <utatane.tea@gmail.com>. 3 3 * Copyright (C) 2016 Apple Inc. All rights reserved. 4 4 * … … 25 25 */ 26 26 27 // @internal28 29 27 @globalPrivate 30 function toInteger(target)28 function isFinite(value) 31 29 { 32 30 "use strict"; 33 31 34 var numberValue = @Number(target); 35 36 // isNaN(numberValue) 32 var numberValue = @toNumber(value); 33 // Return false if numberValue is |NaN|. 37 34 if (numberValue !== numberValue) 38 return 0;39 return @trunc(numberValue);35 return false; 36 return numberValue !== @Infinity && numberValue !== -@Infinity; 40 37 } 41 38 42 39 @globalPrivate 43 function toLength(target)40 function isNaN(value) 44 41 { 45 42 "use strict"; 46 43 47 var maxSafeInteger = 0x1FFFFFFFFFFFFF; 48 var length = @toInteger(target); 49 // originally Math.min(Math.max(length, 0), maxSafeInteger)); 50 return length > 0 ? (length < maxSafeInteger ? length : maxSafeInteger) : 0; 44 var numberValue = @toNumber(value); 45 return numberValue !== numberValue; 51 46 } 52 53 @globalPrivate54 function isDictionary(object)55 {56 "use strict";57 58 return object === @undefined || object == null || typeof object === "object";59 }60 61 // FIXME: this needs to have it's name changed to "get [Symbol.species]".62 // see: https://bugs.webkit.org/show_bug.cgi?id=15136363 @globalPrivate64 function speciesGetter()65 {66 return this;67 }68 69 @globalPrivate70 function speciesConstructor(obj, defaultConstructor)71 {72 var constructor = obj.constructor;73 if (constructor === @undefined)74 return defaultConstructor;75 if (!@isObject(constructor))76 throw new @TypeError("|this|.constructor is not an Object or undefined");77 constructor = constructor.@speciesSymbol;78 if (constructor == null)79 return defaultConstructor;80 if (@isConstructor(constructor))81 return constructor;82 throw new @TypeError("|this|.constructor[Symbol.species] is not a constructor");83 } -
trunk/Source/JavaScriptCore/builtins/GlobalOperations.js
r202412 r202413 1 1 /* 2 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>. 3 * Copyright (C) 2016 Apple Inc. All rights reserved. 2 * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>. 4 3 * 5 4 * Redistribution and use in source and binary forms, with or without … … 45 44 "use strict"; 46 45 47 var maxSafeInteger = 0x1FFFFFFFFFFFFF;48 46 var length = @toInteger(target); 49 47 // originally Math.min(Math.max(length, 0), maxSafeInteger)); 50 return length > 0 ? (length < maxSafeInteger ? length : maxSafeInteger) : 0; 48 return length > 0 ? (length < @MAX_SAFE_INTEGER? length : @MAX_SAFE_INTEGER) : 0; 49 51 50 } 52 51 -
trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
r202280 r202413 55 55 m_arrayIterationKindKeyValue.set(m_vm, jsNumber(ArrayIterateKeyValue)); 56 56 m_MAX_STRING_LENGTH.set(m_vm, jsNumber(JSString::MaxLength)); 57 m_MAX_SAFE_INTEGER.set(m_vm, jsDoubleNumber( 9007199254740991.0)); // 2 ^ 53 - 157 m_MAX_SAFE_INTEGER.set(m_vm, jsDoubleNumber(maxSafeInteger())); 58 58 m_ModuleFetch.set(m_vm, jsNumber(static_cast<unsigned>(ModuleLoaderObject::Status::Fetch))); 59 59 m_ModuleTranslate.set(m_vm, jsNumber(static_cast<unsigned>(ModuleLoaderObject::Status::Translate))); -
trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
r202261 r202413 48 48 macro(tryGetById) \ 49 49 macro(putByValDirect) \ 50 macro(toNumber) \ 50 51 macro(toString) 51 52 -
trunk/Source/JavaScriptCore/bytecode/BytecodeList.json
r202125 r202413 32 32 { "name" : "op_inc", "length" : 2 }, 33 33 { "name" : "op_dec", "length" : 2 }, 34 { "name" : "op_to_number", "length" : 3},34 { "name" : "op_to_number", "length" : 4 }, 35 35 { "name" : "op_to_string", "length" : 3 }, 36 36 { "name" : "op_negate", "length" : 3 }, -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r202397 r202413 993 993 case op_to_number: { 994 994 printUnaryOp(out, exec, location, it, "to_number"); 995 dumpValueProfiling(out, it, hasPrintedProfiling); 995 996 break; 996 997 } … … 2094 2095 case op_get_direct_pname: 2095 2096 case op_get_by_id: 2096 case op_get_from_arguments: { 2097 case op_get_from_arguments: 2098 case op_to_number: { 2097 2099 ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand]; 2098 2100 ASSERT(profile->m_bytecodeOffset == -1); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r202280 r202413 1526 1526 RegisterID* BytecodeGenerator::emitUnaryOp(OpcodeID opcodeID, RegisterID* dst, RegisterID* src) 1527 1527 { 1528 ASSERT_WITH_MESSAGE(op_to_number != opcodeID, "op_to_number is profiled."); 1528 1529 emitOpcode(opcodeID); 1529 1530 instructions().append(dst->index()); 1530 1531 instructions().append(src->index()); 1532 return dst; 1533 } 1534 1535 RegisterID* BytecodeGenerator::emitUnaryOpProfiled(OpcodeID opcodeID, RegisterID* dst, RegisterID* src) 1536 { 1537 UnlinkedValueProfile profile = emitProfiledOpcode(opcodeID); 1538 instructions().append(dst->index()); 1539 instructions().append(src->index()); 1540 instructions().append(profile); 1531 1541 return dst; 1532 1542 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r202125 r202413 511 511 512 512 RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src); 513 RegisterID* emitUnaryOpProfiled(OpcodeID, RegisterID* dst, RegisterID* src); 513 514 RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes); 514 515 RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2); … … 537 538 RegisterID* emitMove(RegisterID* dst, RegisterID* src); 538 539 539 RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp (op_to_number, dst, src); }540 RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOpProfiled(op_to_number, dst, src); } 540 541 RegisterID* emitToString(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_string, dst, src); } 541 542 RegisterID* emitInc(RegisterID* srcDst); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r202280 r202413 917 917 RefPtr<RegisterID> finalDest = generator.finalDestination(dst); 918 918 return generator.emitTryGetById(finalDest.get(), base.get(), ident); 919 } 920 921 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_toNumber(BytecodeGenerator& generator, RegisterID* dst) 922 { 923 ArgumentListNode* node = m_args->m_listNode; 924 RefPtr<RegisterID> src = generator.emitNode(node); 925 ASSERT(!node->m_next); 926 927 return generator.moveToDestinationIfNeeded(dst, generator.emitToNumber(generator.tempDestination(dst), src.get())); 919 928 } 920 929 … … 1550 1559 } 1551 1560 1561 // ------------------------------ UnaryPlusNode ----------------------------------- 1562 1563 RegisterID* UnaryPlusNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1564 { 1565 ASSERT(opcodeID() == op_to_number); 1566 RefPtr<RegisterID> src = generator.emitNode(expr()); 1567 generator.emitExpressionInfo(position(), position(), position()); 1568 return generator.emitToNumber(generator.finalDestination(dst), src.get()); 1569 } 1570 1552 1571 // ------------------------------ BitwiseNotNode ----------------------------------- 1553 1572 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r202363 r202413 1828 1828 ASSERT(node->child1().useKind() == UntypedUse); 1829 1829 1830 if (!forNode(node->child1()).m_type) {1831 m_state.setIsValid(false);1832 break;1833 }1834 1835 1830 if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol))) { 1836 1831 m_state.setFoundConstants(true); … … 1842 1837 1843 1838 forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject); 1839 break; 1840 } 1841 1842 case ToNumber: { 1843 JSValue childConst = forNode(node->child1()).value(); 1844 if (childConst && childConst.isNumber()) { 1845 setConstant(node, childConst); 1846 break; 1847 } 1848 1849 ASSERT(node->child1().useKind() == UntypedUse); 1850 1851 if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) { 1852 m_state.setFoundConstants(true); 1853 forNode(node) = forNode(node->child1()); 1854 break; 1855 } 1856 1857 clobberWorld(node->origin.semantic, clobberLimit); 1858 forNode(node).setType(m_graph, SpecBytecodeNumber); 1844 1859 break; 1845 1860 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r202397 r202413 43 43 #include "GetByIdStatus.h" 44 44 #include "Heap.h" 45 #include "JSCInlines.h" 45 46 #include "JSLexicalEnvironment.h" 46 #include "JSCInlines.h"47 47 #include "JSModuleEnvironment.h" 48 #include "NumberConstructor.h" 48 49 #include "ObjectConstructor.h" 49 50 #include "PreciseJumpTargets.h" … … 216 217 bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks); 217 218 template<typename ChecksFunctor> 218 bool handleConstantInternalFunction(Node* callTargetNode, int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor& insertChecks);219 bool handleConstantInternalFunction(Node* callTargetNode, int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, SpeculatedType, const ChecksFunctor& insertChecks); 219 220 Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value); 220 221 Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset); … … 1652 1653 1653 1654 if (InternalFunction* function = callee.internalFunction()) { 1654 if (handleConstantInternalFunction(callTargetNode, resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, insertChecksWithAccounting)) {1655 if (handleConstantInternalFunction(callTargetNode, resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, prediction, insertChecksWithAccounting)) { 1655 1656 RELEASE_ASSERT(didInsertChecks); 1656 1657 addToGraph(Phantom, callTargetNode); … … 2638 2639 bool ByteCodeParser::handleConstantInternalFunction( 2639 2640 Node* callTargetNode, int resultOperand, InternalFunction* function, int registerOffset, 2640 int argumentCountIncludingThis, CodeSpecializationKind kind, const ChecksFunctor& insertChecks)2641 int argumentCountIncludingThis, CodeSpecializationKind kind, SpeculatedType prediction, const ChecksFunctor& insertChecks) 2641 2642 { 2642 2643 if (verbose) … … 2667 2668 set(VirtualRegister(resultOperand), 2668 2669 addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0))); 2670 return true; 2671 } 2672 2673 if (function->classInfo() == NumberConstructor::info()) { 2674 if (kind == CodeForConstruct) 2675 return false; 2676 2677 insertChecks(); 2678 if (argumentCountIncludingThis <= 1) 2679 set(VirtualRegister(resultOperand), jsConstant(jsNumber(0))); 2680 else 2681 set(VirtualRegister(resultOperand), addToGraph(ToNumber, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)))); 2682 2669 2683 return true; 2670 2684 } … … 5047 5061 5048 5062 case op_to_number: { 5049 Node* node = get(VirtualRegister(currentInstruction[2].u.operand));5050 addToGraph(Phantom, Edge(node, NumberUse));5051 set(VirtualRegister(currentInstruction[1].u.operand), node);5063 SpeculatedType prediction = getPrediction(); 5064 Node* value = get(VirtualRegister(currentInstruction[2].u.operand)); 5065 set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToNumber, OpInfo(0), OpInfo(prediction), value)); 5052 5066 NEXT_OPCODE(op_to_number); 5053 5067 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r202363 r202413 1174 1174 write(Heap); 1175 1175 return; 1176 1177 case ToNumber: { 1178 read(World); 1179 write(Heap); 1180 return; 1181 } 1176 1182 1177 1183 case ToString: -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r201900 r202413 567 567 } 568 568 569 case ToNumber: { 570 if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber) 571 break; 572 573 node->convertToIdentity(); 574 changed = true; 575 break; 576 } 577 569 578 case Check: { 570 579 alreadyHandled = true; -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r202363 r202413 170 170 case LogicalNot: 171 171 case ToPrimitive: 172 case ToNumber: 172 173 case ToString: 173 174 case CallStringConstructor: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r202364 r202413 988 988 case ToPrimitive: { 989 989 fixupToPrimitive(node); 990 break; 991 } 992 993 case ToNumber: { 994 fixupToNumber(node); 990 995 break; 991 996 } … … 1799 1804 } 1800 1805 } 1806 1807 void fixupToNumber(Node* node) 1808 { 1809 if (node->child1()->shouldSpeculateInt32()) { 1810 fixEdge<Int32Use>(node->child1()); 1811 node->convertToIdentity(); 1812 return; 1813 } 1814 1815 if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) { 1816 fixEdge<Int52RepUse>(node->child1()); 1817 node->convertToIdentity(); 1818 node->setResult(NodeResultInt52); 1819 return; 1820 } 1821 1822 if (node->child1()->shouldSpeculateNumber()) { 1823 fixEdge<DoubleRepUse>(node->child1()); 1824 node->convertToIdentity(); 1825 node->setResult(NodeResultDouble); 1826 return; 1827 } 1828 1829 fixEdge<UntypedUse>(node->child1()); 1830 node->setResult(NodeResultJS); 1831 } 1801 1832 1802 1833 void fixupToStringOrCallStringConstructor(Node* node) -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r202003 r202413 1440 1440 case StringReplace: 1441 1441 case StringReplaceRegExp: 1442 case ToNumber: 1442 1443 return true; 1443 1444 default: -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r202363 r202413 323 323 macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \ 324 324 macro(ToString, NodeResultJS | NodeMustGenerate) \ 325 macro(ToNumber, NodeResultJS | NodeMustGenerate) \ 325 326 macro(CallObjectConstructor, NodeResultJS) \ 326 327 macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r202402 r202413 732 732 } 733 733 734 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value) 735 { 736 VM* vm = &exec->vm(); 737 NativeCallFrameTracer tracer(vm, exec); 738 739 return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec))); 740 } 741 734 742 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl) 735 743 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r202125 r202413 59 59 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState*, JSString*, int32_t) WTF_INTERNAL; 60 60 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState*, EncodedJSValue) WTF_INTERNAL; 61 EncodedJSValue JIT_OPERATION operationToNumber(ExecState*, EncodedJSValue) WTF_INTERNAL; 61 62 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState*, EncodedJSValue, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL; 62 63 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r202363 r202413 713 713 case GetGlobalLexicalVariable: 714 714 case GetClosureVar: 715 case GetFromArguments: { 715 case GetFromArguments: 716 case ToNumber: { 716 717 setPrediction(m_currentNode->getHeapPrediction()); 717 718 break; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r202363 r202413 273 273 case ToPrimitive: 274 274 case ToString: 275 case ToNumber: 275 276 case SetFunctionName: 276 277 case StrCat: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r202363 r202413 3568 3568 case ToPrimitive: { 3569 3569 RELEASE_ASSERT(node->child1().useKind() == UntypedUse); 3570 JSValueOperand op1(this, node->child1());3571 GPRTemporary resultTag(this, Reuse, op1, TagWord);3572 GPRTemporary resultPayload(this, Reuse, op1, PayloadWord);3573 3574 GPRReg op1TagGPR = op1.tagGPR();3575 GPRReg op1PayloadGPR = op1.payloadGPR();3570 JSValueOperand argument(this, node->child1()); 3571 GPRTemporary resultTag(this, Reuse, argument, TagWord); 3572 GPRTemporary resultPayload(this, Reuse, argument, PayloadWord); 3573 3574 GPRReg argumentTagGPR = argument.tagGPR(); 3575 GPRReg argumentPayloadGPR = argument.payloadGPR(); 3576 3576 GPRReg resultTagGPR = resultTag.gpr(); 3577 3577 GPRReg resultPayloadGPR = resultPayload.gpr(); 3578 3578 3579 op1.use();3580 3581 MacroAssembler::Jump alreadyPrimitive = m_jit.branchIfNotCell( op1.jsValueRegs());3582 MacroAssembler::Jump notPrimitive = m_jit.branchIfObject( op1PayloadGPR);3579 argument.use(); 3580 3581 MacroAssembler::Jump alreadyPrimitive = m_jit.branchIfNotCell(argument.jsValueRegs()); 3582 MacroAssembler::Jump notPrimitive = m_jit.branchIfObject(argumentPayloadGPR); 3583 3583 3584 3584 alreadyPrimitive.link(&m_jit); 3585 m_jit.move( op1TagGPR, resultTagGPR);3586 m_jit.move( op1PayloadGPR, resultPayloadGPR);3585 m_jit.move(argumentTagGPR, resultTagGPR); 3586 m_jit.move(argumentPayloadGPR, resultPayloadGPR); 3587 3587 3588 3588 addSlowPathGenerator( 3589 3589 slowPathCall( 3590 3590 notPrimitive, this, operationToPrimitive, 3591 JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR));3591 JSValueRegs(resultTagGPR, resultPayloadGPR), argumentTagGPR, argumentPayloadGPR)); 3592 3592 3593 3593 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3594 break; 3595 } 3596 3597 case ToNumber: { 3598 JSValueOperand argument(this, node->child1()); 3599 GPRTemporary resultTag(this, Reuse, argument, TagWord); 3600 GPRTemporary resultPayload(this, Reuse, argument, PayloadWord); 3601 3602 GPRReg argumentPayloadGPR = argument.payloadGPR(); 3603 GPRReg argumentTagGPR = argument.tagGPR(); 3604 JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr()); 3605 3606 argument.use(); 3607 3608 // We have several attempts to remove ToNumber. But ToNumber still exists. 3609 // It means that converting non-numbers to numbers by this ToNumber is not rare. 3610 // Instead of the slow path generator, we emit callOperation here. 3611 if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) { 3612 flushRegisters(); 3613 callOperation(operationToNumber, resultRegs, argumentTagGPR, argumentPayloadGPR); 3614 m_jit.exceptionCheck(); 3615 } else { 3616 MacroAssembler::Jump notNumber; 3617 { 3618 GPRTemporary scratch(this); 3619 notNumber = m_jit.branchIfNotNumber(argument.jsValueRegs(), scratch.gpr()); 3620 } 3621 m_jit.move(argumentTagGPR, resultRegs.tagGPR()); 3622 m_jit.move(argumentPayloadGPR, resultRegs.payloadGPR()); 3623 MacroAssembler::Jump done = m_jit.jump(); 3624 3625 notNumber.link(&m_jit); 3626 silentSpillAllRegisters(resultRegs); 3627 callOperation(operationToNumber, resultRegs, argumentTagGPR, argumentPayloadGPR); 3628 silentFillAllRegisters(resultRegs); 3629 m_jit.exceptionCheck(); 3630 3631 done.link(&m_jit); 3632 } 3633 3634 jsValueResult(resultRegs.tagGPR(), resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly); 3594 3635 break; 3595 3636 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r202363 r202413 3521 3521 case ToPrimitive: { 3522 3522 DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse); 3523 JSValueOperand op1(this, node->child1());3524 GPRTemporary result(this, Reuse, op1);3525 3526 GPRReg op1GPR = op1.gpr();3523 JSValueOperand argument(this, node->child1()); 3524 GPRTemporary result(this, Reuse, argument); 3525 3526 GPRReg argumentGPR = argument.gpr(); 3527 3527 GPRReg resultGPR = result.gpr(); 3528 3528 3529 op1.use();3530 3531 MacroAssembler::Jump alreadyPrimitive = m_jit.branchIfNotCell(JSValueRegs( op1GPR));3532 MacroAssembler::Jump notPrimitive = m_jit.branchIfObject( op1GPR);3529 argument.use(); 3530 3531 MacroAssembler::Jump alreadyPrimitive = m_jit.branchIfNotCell(JSValueRegs(argumentGPR)); 3532 MacroAssembler::Jump notPrimitive = m_jit.branchIfObject(argumentGPR); 3533 3533 3534 3534 alreadyPrimitive.link(&m_jit); 3535 m_jit.move( op1GPR, resultGPR);3535 m_jit.move(argumentGPR, resultGPR); 3536 3536 3537 3537 addSlowPathGenerator( 3538 slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR)); 3539 3538 slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, argumentGPR)); 3539 3540 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3541 break; 3542 } 3543 3544 case ToNumber: { 3545 JSValueOperand argument(this, node->child1()); 3546 GPRTemporary result(this, Reuse, argument); 3547 3548 GPRReg argumentGPR = argument.gpr(); 3549 GPRReg resultGPR = result.gpr(); 3550 3551 argument.use(); 3552 3553 // We have several attempts to remove ToNumber. But ToNumber still exists. 3554 // It means that converting non-numbers to numbers by this ToNumber is not rare. 3555 // Instead of the slow path generator, we emit callOperation here. 3556 if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) { 3557 flushRegisters(); 3558 callOperation(operationToNumber, resultGPR, argumentGPR); 3559 m_jit.exceptionCheck(); 3560 } else { 3561 MacroAssembler::Jump notNumber = m_jit.branchIfNotNumber(argumentGPR); 3562 m_jit.move(argumentGPR, resultGPR); 3563 MacroAssembler::Jump done = m_jit.jump(); 3564 3565 notNumber.link(&m_jit); 3566 silentSpillAllRegisters(resultGPR); 3567 callOperation(operationToNumber, resultGPR, argumentGPR); 3568 silentFillAllRegisters(resultGPR); 3569 m_jit.exceptionCheck(); 3570 3571 done.link(&m_jit); 3572 } 3573 3540 3574 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly); 3541 3575 break; -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r202363 r202413 162 162 case GetCallee: 163 163 case GetArgumentCountIncludingThis: 164 case ToNumber: 165 case ToString: 164 166 case CallObjectConstructor: 165 case ToString:166 167 case CallStringConstructor: 167 168 case MakeRope: … … 404 405 break; 405 406 if (node->isBinaryUseKind(BooleanUse)) 407 break; 408 if (node->isBinaryUseKind(UntypedUse)) 406 409 break; 407 410 if (node->isBinaryUseKind(SymbolUse)) -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r202363 r202413 728 728 case ReallocatePropertyStorage: 729 729 compileReallocatePropertyStorage(); 730 break; 731 case ToNumber: 732 compileToNumber(); 730 733 break; 731 734 case ToString: … … 4100 4103 object, oldStorage, transition->previous, transition->next)); 4101 4104 } 4105 4106 void compileToNumber() 4107 { 4108 LValue value = lowJSValue(m_node->child1()); 4109 4110 if (!(abstractValue(m_node->child1()).m_type & SpecBytecodeNumber)) 4111 setJSValue(vmCall(m_out.int64, m_out.operation(operationToNumber), m_callFrame, value)); 4112 else { 4113 LBasicBlock notNumber = m_out.newBlock(); 4114 LBasicBlock continuation = m_out.newBlock(); 4115 4116 ValueFromBlock fastResult = m_out.anchor(value); 4117 m_out.branch(isNumber(value, provenType(m_node->child1())), unsure(continuation), unsure(notNumber)); 4118 4119 // notNumber case. 4120 LBasicBlock lastNext = m_out.appendTo(notNumber, continuation); 4121 // We have several attempts to remove ToNumber. But ToNumber still exists. 4122 // It means that converting non-numbers to numbers by this ToNumber is not rare. 4123 // Instead of the lazy slow path generator, we call the operation here. 4124 ValueFromBlock slowResult = m_out.anchor(vmCall(m_out.int64, m_out.operation(operationToNumber), m_callFrame, value)); 4125 m_out.jump(continuation); 4126 4127 // continuation case. 4128 m_out.appendTo(continuation, lastNext); 4129 setJSValue(m_out.phi(m_out.int64, fastResult, slowResult)); 4130 } 4131 } 4102 4132 4103 4133 void compileToStringOrCallStringConstructor() … … 4887 4917 setBoolean( 4888 4918 m_out.equal(lowBoolean(m_node->child1()), lowBoolean(m_node->child2()))); 4919 return; 4920 } 4921 4922 if (m_node->isBinaryUseKind(UntypedUse)) { 4923 nonSpeculativeCompare( 4924 [&] (LValue left, LValue right) { 4925 return m_out.equal(left, right); 4926 }, 4927 operationCompareStrictEq); 4889 4928 return; 4890 4929 } -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r200879 r202413 756 756 #if USE(JSVALUE64) 757 757 UNUSED_PARAM(tempGPR); 758 if (mode == HaveTagRegisters) 759 return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister); 760 return branchTest64(NonZero, regs.gpr(), TrustedImm64(TagTypeNumber)); 758 return branchIfNumber(regs.gpr(), mode); 761 759 #else 762 760 UNUSED_PARAM(mode); … … 765 763 #endif 766 764 } 765 766 #if USE(JSVALUE64) 767 Jump branchIfNumber(GPRReg reg, TagRegistersMode mode = HaveTagRegisters) 768 { 769 if (mode == HaveTagRegisters) 770 return branchTest64(NonZero, reg, GPRInfo::tagTypeNumberRegister); 771 return branchTest64(NonZero, reg, TrustedImm64(TagTypeNumber)); 772 } 773 #endif 767 774 768 775 // Note that the tempGPR is not used in 64-bit mode. … … 771 778 #if USE(JSVALUE64) 772 779 UNUSED_PARAM(tempGPR); 773 if (mode == HaveTagRegisters) 774 return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister); 775 return branchTest64(Zero, regs.gpr(), TrustedImm64(TagTypeNumber)); 780 return branchIfNotNumber(regs.gpr(), mode); 776 781 #else 777 782 UNUSED_PARAM(mode); … … 780 785 #endif 781 786 } 787 788 #if USE(JSVALUE64) 789 Jump branchIfNotNumber(GPRReg reg, TagRegistersMode mode = HaveTagRegisters) 790 { 791 if (mode == HaveTagRegisters) 792 return branchTest64(Zero, reg, GPRInfo::tagTypeNumberRegister); 793 return branchTest64(Zero, reg, TrustedImm64(TagTypeNumber)); 794 } 795 #endif 782 796 783 797 Jump branchIfNotDoubleKnownNotInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters) -
trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp
r202125 r202413 517 517 void JIT::emit_op_to_number(Instruction* currentInstruction) 518 518 { 519 int dstVReg = currentInstruction[1].u.operand; 519 520 int srcVReg = currentInstruction[2].u.operand; 520 521 emitGetVirtualRegister(srcVReg, regT0); … … 522 523 addSlowCase(emitJumpIfNotNumber(regT0)); 523 524 524 emitPutVirtualRegister(currentInstruction[1].u.operand); 525 emitValueProfilingSite(); 526 if (srcVReg != dstVReg) 527 emitPutVirtualRegister(dstVReg); 525 528 } 526 529 -
trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
r202125 r202413 829 829 isInt32.link(this); 830 830 831 emitValueProfilingSite(); 831 832 if (src != dst) 832 833 emitStore(dst, regT1, regT0); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
r202131 r202413 956 956 storei t2, TagOffset[cfr, t1, 8] 957 957 storei t3, PayloadOffset[cfr, t1, 8] 958 dispatch(3) 958 valueProfile(t2, t3, 12, t1) 959 dispatch(4) 959 960 960 961 .opToNumberSlow: -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r202244 r202413 835 835 .opToNumberIsImmediate: 836 836 storeq t2, [cfr, t1, 8] 837 dispatch(3) 837 valueProfile(t2, 3, t0) 838 dispatch(4) 838 839 839 840 .opToNumberSlow: 840 841 callOpcodeSlowPath(_slow_path_to_number) 841 dispatch( 3)842 dispatch(4) 842 843 843 844 -
trunk/Source/JavaScriptCore/parser/Nodes.h
r202280 r202413 968 968 ExpressionNode* expr() { return m_expr; } 969 969 const ExpressionNode* expr() const { return m_expr; } 970 971 private:972 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;973 974 970 OpcodeID opcodeID() const { return m_opcodeID; } 971 972 private: 973 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; 975 974 976 975 ExpressionNode* m_expr; … … 983 982 984 983 private: 984 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; 985 985 986 ExpressionNode* stripUnaryPlus() override { return expr(); } 986 987 }; -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r202280 r202413 347 347 } 348 348 349 SLOW_PATH_DECL(slow_path_to_number)350 {351 BEGIN();352 RETURN(jsNumber(OP_C(2).jsValue().toNumber(exec)));353 }354 355 349 SLOW_PATH_DECL(slow_path_to_string) 356 350 { … … 398 392 static void updateResultProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { } 399 393 #endif 394 395 SLOW_PATH_DECL(slow_path_to_number) 396 { 397 BEGIN(); 398 JSValue argument = OP_C(2).jsValue(); 399 JSValue result = jsNumber(argument.toNumber(exec)); 400 RETURN_PROFILED(op_to_number, result); 401 } 400 402 401 403 SLOW_PATH_DECL(slow_path_add) -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r202363 r202413 212 212 @begin globalObjectTable 213 213 parseFloat globalFuncParseFloat DontEnum|Function 1 214 isNaN globalFuncIsNaNDontEnum|Function 1215 isFinite globalFuncIsFiniteDontEnum|Function 1214 isNaN JSBuiltin DontEnum|Function 1 215 isFinite JSBuiltin DontEnum|Function 1 216 216 escape globalFuncEscape DontEnum|Function 1 217 217 unescape globalFuncUnescape DontEnum|Function 1 … … 403 403 404 404 m_speciesGetterSetter.set(vm, this, GetterSetter::create(vm, this)); 405 m_speciesGetterSetter->setGetter(vm, this, JSFunction::createBuiltinFunction(vm, globalO bjectSpeciesGetterCodeGenerator(vm), this, "get [Symbol.species]"));405 m_speciesGetterSetter->setGetter(vm, this, JSFunction::createBuiltinFunction(vm, globalOperationsSpeciesGetterCodeGenerator(vm), this, "get [Symbol.species]")); 406 406 407 407 m_typedArrayProto.initLater( … … 648 648 JSFunction* privateFuncAbs = JSFunction::create(vm, this, 0, String(), mathProtoFuncAbs, AbsIntrinsic); 649 649 JSFunction* privateFuncFloor = JSFunction::create(vm, this, 0, String(), mathProtoFuncFloor, FloorIntrinsic); 650 JSFunction* privateFuncIsFinite = JSFunction::create(vm, this, 0, String(), globalFuncIsFinite);651 JSFunction* privateFuncIsNaN = JSFunction::create(vm, this, 0, String(), globalFuncIsNaN);652 650 JSFunction* privateFuncTrunc = JSFunction::create(vm, this, 0, String(), mathProtoFuncTrunc, TruncIntrinsic); 653 651 … … 716 714 GlobalPropertyInfo(vm.propertyNames->builtinNames().floorPrivateName(), privateFuncFloor, DontEnum | DontDelete | ReadOnly), 717 715 GlobalPropertyInfo(vm.propertyNames->builtinNames().truncPrivateName(), privateFuncTrunc, DontEnum | DontDelete | ReadOnly), 718 GlobalPropertyInfo(vm.propertyNames->builtinNames().isFinitePrivateName(), privateFuncIsFinite, DontEnum | DontDelete | ReadOnly),719 GlobalPropertyInfo(vm.propertyNames->builtinNames().isNaNPrivateName(), privateFuncIsNaN, DontEnum | DontDelete | ReadOnly),720 716 GlobalPropertyInfo(vm.propertyNames->builtinNames().PromisePrivateName(), promiseConstructor, DontEnum | DontDelete | ReadOnly), 721 717 GlobalPropertyInfo(vm.propertyNames->builtinNames().ReflectPrivateName(), reflectObject, DontEnum | DontDelete | ReadOnly), -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r201756 r202413 707 707 } 708 708 709 EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)710 {711 return JSValue::encode(jsBoolean(std::isnan(exec->argument(0).toNumber(exec))));712 }713 714 EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec)715 {716 double n = exec->argument(0).toNumber(exec);717 return JSValue::encode(jsBoolean(std::isfinite(n)));718 }719 720 709 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec) 721 710 { -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
r201619 r202413 41 41 EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState*); 42 42 EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*); 43 EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*);44 EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*);45 43 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*); 46 44 EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*); -
trunk/Source/JavaScriptCore/runtime/MathCommon.h
r202092 r202413 35 35 double JIT_OPERATION operationMathPow(double x, double y) WTF_INTERNAL; 36 36 int32_t JIT_OPERATION operationToInt32(double) WTF_INTERNAL; 37 38 inline constexpr double maxSafeInteger() 39 { 40 // 2 ^ 53 - 1 41 return 9007199254740991.0; 42 } 43 44 inline constexpr double minSafeInteger() 45 { 46 // -(2 ^ 53 - 1) 47 return -9007199254740991.0; 48 } 37 49 38 50 inline int clz32(uint32_t number) -
trunk/Source/JavaScriptCore/runtime/NumberConstructor.cpp
r197614 r202413 32 32 namespace JSC { 33 33 34 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsFinite(ExecState*);35 34 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsInteger(ExecState*); 36 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsNaN(ExecState*);37 35 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsSafeInteger(ExecState*); 38 36 39 37 } // namespace JSC 38 39 #include "NumberConstructor.lut.h" 40 40 41 41 namespace JSC { … … 43 43 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(NumberConstructor); 44 44 45 const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, 0, CREATE_METHOD_TABLE(NumberConstructor) }; 45 const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, &numberConstructorTable, CREATE_METHOD_TABLE(NumberConstructor) }; 46 47 /* Source for NumberConstructor.lut.h 48 @begin numberConstructorTable 49 isFinite JSBuiltin DontEnum|Function 1 50 isInteger numberConstructorFuncIsInteger DontEnum|Function 1 51 isNaN JSBuiltin DontEnum|Function 1 52 isSafeInteger numberConstructorFuncIsSafeInteger DontEnum|Function 1 53 parseFloat globalFuncParseFloat DontEnum|Function 1 54 @end 55 */ 46 56 47 57 NumberConstructor::NumberConstructor(VM& vm, Structure* structure) … … 64 74 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MAX_VALUE"), jsDoubleNumber(1.7976931348623157E+308), DontDelete | DontEnum | ReadOnly); 65 75 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MIN_VALUE"), jsDoubleNumber(5E-324), DontDelete | DontEnum | ReadOnly); 66 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MAX_SAFE_INTEGER"), jsDoubleNumber( 9007199254740991.0), DontDelete | DontEnum | ReadOnly);67 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MIN_SAFE_INTEGER"), jsDoubleNumber( -9007199254740991.0), DontDelete | DontEnum | ReadOnly);76 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MAX_SAFE_INTEGER"), jsDoubleNumber(maxSafeInteger()), DontDelete | DontEnum | ReadOnly); 77 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "MIN_SAFE_INTEGER"), jsDoubleNumber(minSafeInteger()), DontDelete | DontEnum | ReadOnly); 68 78 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "NEGATIVE_INFINITY"), jsDoubleNumber(-std::numeric_limits<double>::infinity()), DontDelete | DontEnum | ReadOnly); 69 79 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "POSITIVE_INFINITY"), jsDoubleNumber(std::numeric_limits<double>::infinity()), DontDelete | DontEnum | ReadOnly); 70 80 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "NaN"), jsNaN(), DontDelete | DontEnum | ReadOnly); 71 81 72 putDirectNativeFunctionWithoutTransition(vm, numberPrototype->globalObject(), Identifier::fromString(&vm, "isFinite"), 1, numberConstructorFuncIsFinite, NoIntrinsic, DontEnum);73 putDirectNativeFunctionWithoutTransition(vm, numberPrototype->globalObject(), Identifier::fromString(&vm, "isInteger"), 1, numberConstructorFuncIsInteger, NoIntrinsic, DontEnum);74 putDirectNativeFunctionWithoutTransition(vm, numberPrototype->globalObject(), Identifier::fromString(&vm, "isNaN"), 1, numberConstructorFuncIsNaN, NoIntrinsic, DontEnum);75 putDirectNativeFunctionWithoutTransition(vm, numberPrototype->globalObject(), Identifier::fromString(&vm, "isSafeInteger"), 1, numberConstructorFuncIsSafeInteger, NoIntrinsic, DontEnum);76 putDirectNativeFunctionWithoutTransition(vm, numberPrototype->globalObject(), Identifier::fromString(&vm, "parseFloat"), 1, globalFuncParseFloat, NoIntrinsic, DontEnum);77 82 putDirectWithoutTransition(vm, Identifier::fromString(&vm, "parseInt"), numberPrototype->globalObject()->parseIntFunction(), DontEnum); 78 83 } … … 109 114 } 110 115 111 // ECMA-262 20.1.2.2112 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsFinite(ExecState* exec)113 {114 JSValue argument = exec->argument(0);115 return JSValue::encode(jsBoolean(argument.isNumber() && (argument.isInt32() || std::isfinite(argument.asDouble()))));116 }117 118 116 // ECMA-262 20.1.2.3 119 117 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsInteger(ExecState* exec) … … 130 128 } 131 129 return JSValue::encode(jsBoolean(isInteger)); 132 }133 134 // ECMA-262 20.1.2.4135 static EncodedJSValue JSC_HOST_CALL numberConstructorFuncIsNaN(ExecState* exec)136 {137 JSValue argument = exec->argument(0);138 return JSValue::encode(jsBoolean(argument.isDouble() && std::isnan(argument.asDouble())));139 130 } 140 131 -
trunk/Source/JavaScriptCore/runtime/NumberConstructor.h
r195460 r202413 32 32 public: 33 33 typedef InternalFunction Base; 34 static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | ImplementsHasInstance | ImplementsDefaultHasInstance;34 static const unsigned StructureFlags = Base::StructureFlags | ImplementsHasInstance | HasStaticPropertyTable; 35 35 36 36 static NumberConstructor* create(VM& vm, Structure* structure, NumberPrototype* numberPrototype, GetterSetter*)
Note: See TracChangeset
for help on using the changeset viewer.