Changeset 210244 in webkit
- Timestamp:
- Jan 3, 2017 12:24:36 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r210229 r210244 1 2017-01-03 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: check and test in-call / out-call values 4 https://bugs.webkit.org/show_bug.cgi?id=164876 5 <rdar://problem/29844107> 6 7 Reviewed by Saam Barati. 8 9 * wasm.yaml: 10 * wasm/assert.js: add an assert for NaN comparison 11 * wasm/fuzz/export-function.js: Added. Generate random wasm export 12 signatures, and call them with random parameters. 13 (const.paramExporter): 14 (const.setBuffer): 15 (const.types.generate): 16 (generate): 17 * wasm/js-api/export-arity.js: Added. 18 (const.paramExporter): Test that mismatched arities when JS calls 19 wasm follow the defined semantics: i32 is 0, f32 / f64 are NaN. 20 https://github.com/WebAssembly/design/blob/master/JS.md#exported-function-exotic-objects 21 * wasm/js-api/export-void-is-undef.js: Added. Test that "void" 22 wasm functions return "undefined" in JS. 23 1 24 2017-01-02 JF Bastien <jfbastien@apple.com> 2 25 -
trunk/JSTests/wasm.yaml
r210228 r210244 27 27 cmd: runWebAssembly 28 28 - path: wasm/function-tests 29 cmd: runWebAssembly 30 - path: wasm/fuzz 29 31 cmd: runWebAssembly 30 32 -
trunk/JSTests/wasm/Builder.js
r210229 r210244 753 753 section: this._sections 754 754 }; 755 return JSON.stringify(obj); 755 // JSON.stringify serializes -0.0 as 0.0. 756 const replacer = (key, value) => { 757 if (value === 0.0 && 1.0 / value === -Infinity) 758 return "NEGATIVE_ZERO"; 759 return value; 760 }; 761 return JSON.stringify(obj, replacer); 756 762 } 757 763 AsmJS() { -
trunk/JSTests/wasm/assert.js
r210073 r210244 73 73 74 74 export const eq = (lhs, rhs, msg) => { 75 if (typeof lhs !== typeof rhs) 76 _fail(`Not the same: "${lhs}" and "${rhs}"`, msg); 75 77 if (Array.isArray(lhs) && Array.isArray(rhs) && (lhs.length === rhs.length)) { 76 78 for (let i = 0; i !== lhs.length; ++i) 77 79 eq(lhs[i], rhs[i], msg); 78 } else if (lhs !== rhs) 80 } else if (lhs !== rhs) { 81 if (typeof lhs === "number" && isNaN(lhs) && isNaN(rhs)) 82 return; 79 83 _fail(`Not the same: "${lhs}" and "${rhs}"`, msg); 84 } else { 85 if (typeof lhs === "number" && (1.0 / lhs !== 1.0 / rhs)) // Distinguish -0.0 from 0.0. 86 _fail(`Not the same: "${lhs}" and "${rhs}"`, msg); 87 } 80 88 }; 81 89 -
trunk/JSTests/wasm/self-test/test_BuilderJSON.js
r209863 r210244 511 511 assert.eq(j.section[1].data[0].code[0].arguments.length, 0); 512 512 assert.eq(j.section[1].data[0].code[0].immediates.length, 1); 513 assert.eq(j.section[1].data[0].code[0].immediates[0] , c);513 assert.eq(j.section[1].data[0].code[0].immediates[0] === "NEGATIVE_ZERO" ? -0.0 : j.section[1].data[0].code[0].immediates[0], c); 514 514 } 515 515 })(); … … 527 527 assert.eq(j.section[1].data[0].code[0].arguments.length, 0); 528 528 assert.eq(j.section[1].data[0].code[0].immediates.length, 1); 529 assert.eq(j.section[1].data[0].code[0].immediates[0] , c);529 assert.eq(j.section[1].data[0].code[0].immediates[0] === "NEGATIVE_ZERO" ? -0.0 : j.section[1].data[0].code[0].immediates[0], c); 530 530 } 531 531 })(); -
trunk/Source/JavaScriptCore/ChangeLog
r210237 r210244 1 2017-01-03 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: check and test in-call / out-call values 4 https://bugs.webkit.org/show_bug.cgi?id=164876 5 <rdar://problem/29844107> 6 7 Reviewed by Saam Barati. 8 9 * wasm/WasmBinding.cpp: 10 (JSC::Wasm::wasmToJs): fix the wasm -> JS call coercions for f32 / 11 f64 which the assotiated tests inadvertently tripped on: the 12 previous code wasn't correctly performing JSValue boxing for 13 "double" values. This change is slightly involved because it 14 requires two scratch registers to materialize the 15 `DoubleEncodeOffset` value. This change therefore reorganizes the 16 code to first generate traps, then handle all integers (freeing 17 all GPRs), and then all the floating-point values. 18 * wasm/js/WebAssemblyFunction.cpp: 19 (JSC::callWebAssemblyFunction): Implement the defined semantics 20 for mismatched arities when JS calls wasm: 21 https://github.com/WebAssembly/design/blob/master/JS.md#exported-function-exotic-objects 22 - i32 is 0, f32 / f64 are NaN. 23 - wasm functions which return "void" are "undefined" in JS. 24 1 25 2017-01-03 Per Arne Vollan <pvollan@apple.com> 2 26 -
trunk/Source/JavaScriptCore/wasm/WasmBinding.cpp
r210229 r210244 75 75 jit.subPtr(MacroAssembler::TrustedImm32(stackOffset), MacroAssembler::stackPointerRegister); 76 76 JIT::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))); 77 78 // FIXME make this a loop which switches on Signature if there are many arguments on the stack. It'll otherwise be huge for huge signatures. https://bugs.webkit.org/show_bug.cgi?id=165547 79 unsigned marshalledGPRs = 0; 80 unsigned marshalledFPRs = 0; 81 unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register)); 82 unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register)); 77 83 78 for (unsigned argNum = 0; argNum < argCount; ++argNum) { 84 79 Type argType = signature->argument(argNum); … … 87 82 case Func: 88 83 case Anyfunc: 89 case I64: 90 // FIXME: Figure out the correct behavior here. I suspect we want such a stub to throw an exception immediately 84 case I64: { 85 // FIXME: Figure out the correct behavior here. I suspect we want such a stub to throw an exception immediately. 91 86 // if called. https://bugs.webkit.org/show_bug.cgi?id=165991 92 87 jit.breakpoint(); 93 break; 94 case I32: { 95 GPRReg gprReg; 96 if (marshalledGPRs < wasmCC.m_gprArgs.size()) 97 gprReg = wasmCC.m_gprArgs[marshalledGPRs].gpr(); 98 else { 99 // We've already spilled all arguments, these registers are available as scratch. 100 gprReg = GPRInfo::argumentGPR0; 101 jit.load64(JIT::Address(GPRInfo::callFrameRegister, frOffset), gprReg); 102 frOffset += sizeof(Register); 103 } 104 ++marshalledGPRs; 105 jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters); 106 jit.store64(gprReg, calleeFrame.withOffset(calleeFrameOffset)); 107 calleeFrameOffset += sizeof(Register); 108 break; 88 LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID); 89 return FINALIZE_CODE(patchBuffer, ("WebAssembly import[%i] stub for signature %i", importIndex, signatureIndex)); 109 90 } 110 case F32: { 111 FPRReg fprReg; 112 if (marshalledFPRs < wasmCC.m_fprArgs.size()) 113 fprReg = wasmCC.m_fprArgs[marshalledFPRs].fpr(); 114 else { 115 // We've already spilled all arguments, these registers are available as scratch. 116 fprReg = FPRInfo::argumentFPR0; 117 jit.loadFloat(JIT::Address(GPRInfo::callFrameRegister, frOffset), fprReg); 118 frOffset += sizeof(Register); 119 } 120 jit.convertFloatToDouble(fprReg, fprReg); 121 jit.purifyNaN(fprReg); 122 jit.storeDouble(fprReg, calleeFrame.withOffset(calleeFrameOffset)); 123 calleeFrameOffset += sizeof(Register); 124 ++marshalledFPRs; 125 break; 91 case I32: 92 case F32: 93 case F64: 94 continue; 126 95 } 127 case F64: { 128 FPRReg fprReg; 129 if (marshalledFPRs < wasmCC.m_fprArgs.size()) 130 fprReg = wasmCC.m_fprArgs[marshalledFPRs].fpr(); 131 else { 132 // We've already spilled all arguments, these registers are available as scratch. 133 fprReg = FPRInfo::argumentFPR0; 134 jit.loadDouble(JIT::Address(GPRInfo::callFrameRegister, frOffset), fprReg); 135 frOffset += sizeof(Register); 136 } 137 jit.purifyNaN(fprReg); 138 jit.storeDouble(fprReg, calleeFrame.withOffset(calleeFrameOffset)); 139 calleeFrameOffset += sizeof(Register); 140 ++marshalledFPRs; 141 break; 96 } 97 98 // FIXME make these loops which switch on Signature if there are many arguments on the stack. It'll otherwise be huge for huge signatures. https://bugs.webkit.org/show_bug.cgi?id=165547 99 100 // First go through the integer parameters, freeing up their register for use afterwards. 101 { 102 unsigned marshalledGPRs = 0; 103 unsigned marshalledFPRs = 0; 104 unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register)); 105 unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register)); 106 for (unsigned argNum = 0; argNum < argCount; ++argNum) { 107 Type argType = signature->argument(argNum); 108 switch (argType) { 109 case Void: 110 case Func: 111 case Anyfunc: 112 case I64: 113 RELEASE_ASSERT_NOT_REACHED(); // Handled above. 114 case I32: { 115 GPRReg gprReg; 116 if (marshalledGPRs < wasmCC.m_gprArgs.size()) 117 gprReg = wasmCC.m_gprArgs[marshalledGPRs].gpr(); 118 else { 119 // We've already spilled all arguments, these registers are available as scratch. 120 gprReg = GPRInfo::argumentGPR0; 121 jit.load64(JIT::Address(GPRInfo::callFrameRegister, frOffset), gprReg); 122 frOffset += sizeof(Register); 123 } 124 ++marshalledGPRs; 125 jit.boxInt32(gprReg, JSValueRegs(gprReg), DoNotHaveTagRegisters); 126 jit.store64(gprReg, calleeFrame.withOffset(calleeFrameOffset)); 127 calleeFrameOffset += sizeof(Register); 128 break; 129 } 130 case F32: 131 case F64: 132 // Skipped: handled below. 133 if (marshalledFPRs >= wasmCC.m_fprArgs.size()) 134 frOffset += sizeof(Register); 135 ++marshalledFPRs; 136 calleeFrameOffset += sizeof(Register); 137 break; 138 } 142 139 } 140 } 141 142 { 143 // Integer registers have already been spilled, these are now available. 144 GPRReg doubleEncodeOffsetGPRReg = GPRInfo::argumentGPR0; 145 GPRReg scratch = GPRInfo::argumentGPR1; 146 bool hasMaterializedDoubleEncodeOffset = false; 147 auto materializeDoubleEncodeOffset = [&hasMaterializedDoubleEncodeOffset, &jit] (GPRReg dest) { 148 if (!hasMaterializedDoubleEncodeOffset) { 149 static_assert(DoubleEncodeOffset == 1ll << 48, "codegen assumes this below"); 150 jit.move(JIT::TrustedImm32(1), dest); 151 jit.lshift64(JIT::TrustedImm32(48), dest); 152 hasMaterializedDoubleEncodeOffset = true; 153 } 154 }; 155 156 unsigned marshalledGPRs = 0; 157 unsigned marshalledFPRs = 0; 158 unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register)); 159 unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register)); 160 for (unsigned argNum = 0; argNum < argCount; ++argNum) { 161 Type argType = signature->argument(argNum); 162 switch (argType) { 163 case Void: 164 case Func: 165 case Anyfunc: 166 case I64: 167 RELEASE_ASSERT_NOT_REACHED(); // Handled above. 168 case I32: 169 // Skipped: handled above. 170 if (marshalledGPRs < wasmCC.m_gprArgs.size()) 171 frOffset += sizeof(Register); 172 ++marshalledGPRs; 173 calleeFrameOffset += sizeof(Register); 174 break; 175 case F32: { 176 FPRReg fprReg; 177 if (marshalledFPRs < wasmCC.m_fprArgs.size()) 178 fprReg = wasmCC.m_fprArgs[marshalledFPRs].fpr(); 179 else { 180 // We've already spilled all arguments, these registers are available as scratch. 181 fprReg = FPRInfo::argumentFPR0; 182 jit.loadFloat(JIT::Address(GPRInfo::callFrameRegister, frOffset), fprReg); 183 frOffset += sizeof(Register); 184 } 185 jit.convertFloatToDouble(fprReg, fprReg); 186 jit.purifyNaN(fprReg); 187 jit.moveDoubleTo64(fprReg, scratch); 188 materializeDoubleEncodeOffset(doubleEncodeOffsetGPRReg); 189 jit.add64(doubleEncodeOffsetGPRReg, scratch); 190 jit.store64(scratch, calleeFrame.withOffset(calleeFrameOffset)); 191 calleeFrameOffset += sizeof(Register); 192 ++marshalledFPRs; 193 break; 194 } 195 case F64: { 196 FPRReg fprReg; 197 if (marshalledFPRs < wasmCC.m_fprArgs.size()) 198 fprReg = wasmCC.m_fprArgs[marshalledFPRs].fpr(); 199 else { 200 // We've already spilled all arguments, these registers are available as scratch. 201 fprReg = FPRInfo::argumentFPR0; 202 jit.loadDouble(JIT::Address(GPRInfo::callFrameRegister, frOffset), fprReg); 203 frOffset += sizeof(Register); 204 } 205 jit.purifyNaN(fprReg); 206 jit.moveDoubleTo64(fprReg, scratch); 207 materializeDoubleEncodeOffset(doubleEncodeOffsetGPRReg); 208 jit.add64(doubleEncodeOffsetGPRReg, scratch); 209 jit.store64(scratch, calleeFrame.withOffset(calleeFrameOffset)); 210 calleeFrameOffset += sizeof(Register); 211 ++marshalledFPRs; 212 break; 213 } 214 } 143 215 } 144 216 } -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp
r210229 r210244 57 57 const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex); 58 58 59 // FIXME is this the right behavior? https://bugs.webkit.org/show_bug.cgi?id=16487660 if (exec->argumentCount() != signature->argumentCount())61 return JSValue::encode(throwException(exec, scope, createNotEnoughArgumentsError(exec, defaultSourceAppender)));62 63 59 { 64 60 // Check if we have a disallowed I64 use. … … 79 75 } 80 76 81 // FIXME is this boxing correct? https://bugs.webkit.org/show_bug.cgi?id=16487682 77 Vector<JSValue> boxedArgs; 83 78 for (unsigned argIndex = 0; argIndex < signature->argumentCount(); ++argIndex) { 84 JSValue arg = exec-> uncheckedArgument(argIndex);79 JSValue arg = exec->argument(argIndex); 85 80 switch (signature->argument(argIndex)) { 86 81 case Wasm::I32: … … 128 123 RETURN_IF_EXCEPTION(scope, { }); 129 124 130 // FIXME is this correct? https://bugs.webkit.org/show_bug.cgi?id=164876131 125 switch (signature->returnType()) { 132 126 case Wasm::Void:
Note: See TracChangeset
for help on using the changeset viewer.