Changeset 267373 in webkit
- Timestamp:
- Sep 21, 2020 3:10:24 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r267348 r267373 1 2020-09-21 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] BigInt should work with Map / Set 4 https://bugs.webkit.org/show_bug.cgi?id=216667 5 <rdar://problem/69107221> 6 7 Reviewed by Robin Morisset. 8 9 * stress/bigint-and-map-set.js: Added. 10 (shouldBe): 11 (opaque1n): 12 (testMap): 13 (let.set new): 14 * stress/bigint-string-map-set.js: Added. 15 (shouldBe): 16 (testMap): 17 * stress/bigint32-map-set.js: Added. 18 (shouldBe): 19 (testMap): 20 1 21 2020-09-21 Yusuke Suzuki <ysuzuki@apple.com> 2 22 -
trunk/Source/JavaScriptCore/ChangeLog
r267371 r267373 1 2020-09-21 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] BigInt should work with Map / Set 4 https://bugs.webkit.org/show_bug.cgi?id=216667 5 6 Reviewed by Robin Morisset. 7 8 This patch makes BigInt supported in Map / Set. 9 10 1. In NormalizeMapKey, we always attempt to convert HeapBigInt to BigInt32 (if supported). So we ensure that, 11 normalized BigInt has one unique form for BigInt32 range. This allows us to use hashing for BigInt32 bit pattern directly. 12 2. In MapHash, for BigInt32, we directly has the JSValue bits. For HeapBigInt, we calculate hash via Hasher. 13 3. In GetMapBucket, we consider HeapBigInt case correctly. 14 15 * dfg/DFGAbstractInterpreterInlines.h: 16 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 17 * dfg/DFGConstantFoldingPhase.cpp: 18 (JSC::DFG::ConstantFoldingPhase::foldConstants): 19 * dfg/DFGDoesGC.cpp: 20 (JSC::DFG::doesGC): 21 * dfg/DFGFixupPhase.cpp: 22 (JSC::DFG::FixupPhase::fixupNode): 23 (JSC::DFG::FixupPhase::fixupNormalizeMapKey): 24 * dfg/DFGOperations.cpp: 25 * dfg/DFGOperations.h: 26 * dfg/DFGSpeculativeJIT.cpp: 27 (JSC::DFG::SpeculativeJIT::compileNormalizeMapKey): 28 * dfg/DFGSpeculativeJIT64.cpp: 29 (JSC::DFG::SpeculativeJIT::compile): 30 * ftl/FTLLowerDFGToB3.cpp: 31 (JSC::FTL::DFG::LowerDFGToB3::compileMapHash): 32 (JSC::FTL::DFG::LowerDFGToB3::compileNormalizeMapKey): 33 (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket): 34 * runtime/HashMapImpl.h: 35 (JSC::normalizeMapKey): 36 (JSC::jsMapHash): 37 (JSC::concurrentJSMapHash): 38 * runtime/JSBigInt.cpp: 39 (JSC::JSBigInt::concurrentHash): 40 * runtime/JSBigInt.h: 41 (JSC::tryConvertToBigInt32): 42 1 43 2020-09-21 Mark Lam <mark.lam@apple.com> 2 44 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r266254 r267373 1382 1382 } 1383 1383 1384 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only) ;1384 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only) | SpecHeapBigInt; 1385 1385 if (!(forNode(node->child1()).m_type & typeMaybeNormalized)) { 1386 1386 m_state.setShouldTryConstantFolding(true); -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r265934 r267373 995 995 996 996 case NormalizeMapKey: { 997 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only) ;997 SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only) | SpecHeapBigInt; 998 998 if (m_state.forNode(node->child1()).m_type & typeMaybeNormalized) 999 999 break; -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r266095 r267373 165 165 case SuperSamplerEnd: 166 166 case CPUIntrinsic: 167 case NormalizeMapKey: 167 case NormalizeMapKey: // HeapBigInt => BigInt32 conversion does not involve GC. 168 168 case GetMapBucketHead: 169 169 case GetMapBucketNext: … … 518 518 case SymbolUse: 519 519 case ObjectUse: 520 #if USE(BIGINT32) 521 case BigInt32Use: 522 #endif 523 case HeapBigIntUse: 520 524 return false; 521 525 default: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r266095 r267373 2378 2378 else if (node->child2()->shouldSpeculateInt32()) 2379 2379 fixEdge<Int32Use>(node->child2()); 2380 #if USE(BIGINT32) 2381 else if (node->child2()->shouldSpeculateBigInt32()) 2382 fixEdge<BigInt32Use>(node->child2()); 2383 #endif 2380 2384 else if (node->child2()->shouldSpeculateSymbol()) 2381 2385 fixEdge<SymbolUse>(node->child2()); … … 2384 2388 else if (node->child2()->shouldSpeculateString()) 2385 2389 fixEdge<StringUse>(node->child2()); 2390 else if (node->child2()->shouldSpeculateHeapBigInt()) 2391 fixEdge<HeapBigIntUse>(node->child2()); 2386 2392 else if (node->child2()->shouldSpeculateCell()) 2387 2393 fixEdge<CellUse>(node->child2()); … … 2434 2440 if (node->child1()->shouldSpeculateString()) { 2435 2441 fixEdge<StringUse>(node->child1()); 2442 break; 2443 } 2444 2445 #if USE(BIGINT32) 2446 if (node->child1()->shouldSpeculateBigInt32()) { 2447 fixEdge<BigInt32Use>(node->child1()); 2448 break; 2449 } 2450 #endif 2451 2452 if (node->child1()->shouldSpeculateHeapBigInt()) { 2453 fixEdge<HeapBigIntUse>(node->child1()); 2436 2454 break; 2437 2455 } … … 3997 4015 } 3998 4016 3999 if (node->child1()->shouldSpeculateCell()) { 4000 fixEdge<CellUse>(node->child1()); 4017 #if USE(BIGINT32) 4018 if (node->child1()->shouldSpeculateBigInt32()) { 4019 fixEdge<BigInt32Use>(node->child1()); 4001 4020 node->convertToIdentity(); 4002 4021 return; 4003 4022 } 4023 #endif 4004 4024 4005 4025 fixEdge<UntypedUse>(node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r266223 r267373 3213 3213 } 3214 3214 3215 EncodedJSValue JIT_OPERATION operationNormalizeMapKey(VM* vmPointer, EncodedJSValue input) 3216 { 3217 VM& vm = *vmPointer; 3218 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 3219 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 3220 return JSValue::encode(normalizeMapKey(JSValue::decode(input))); 3221 } 3222 3215 3223 UCPUStrictInt32 JIT_OPERATION operationMapHash(JSGlobalObject* globalObject, EncodedJSValue input) 3216 3224 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r265934 r267373 244 244 char* JIT_OPERATION operationDoubleToStringWithValidRadix(JSGlobalObject*, double, int32_t); 245 245 246 EncodedJSValue JIT_OPERATION operationNormalizeMapKey(VM*, EncodedJSValue input) WTF_INTERNAL; 246 247 UCPUStrictInt32 JIT_OPERATION operationMapHash(JSGlobalObject*, EncodedJSValue input); 247 248 JSCell* JIT_OPERATION operationJSMapFindBucket(JSGlobalObject*, JSCell*, EncodedJSValue, int32_t); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r266095 r267373 12518 12518 CCallHelpers::JumpList doneCases; 12519 12519 12520 auto isNotCell = m_jit.branchIfNotCell(keyRegs); 12521 passThroughCases.append(m_jit.branchIfNotHeapBigInt(keyRegs.payloadGPR())); 12522 auto slowPath = m_jit.jump(); 12523 isNotCell.link(&m_jit); 12524 12520 12525 passThroughCases.append(m_jit.branchIfNotNumber(keyRegs, scratchGPR)); 12521 12526 passThroughCases.append(m_jit.branchIfInt32(keyRegs)); … … 12540 12545 passThroughCases.link(&m_jit); 12541 12546 m_jit.moveValueRegs(keyRegs, resultRegs); 12547 addSlowPathGenerator(slowPathCall(slowPath, this, operationNormalizeMapKey, resultRegs, &vm(), keyRegs)); 12542 12548 12543 12549 doneCases.link(&m_jit); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r266770 r267373 4432 4432 case MapHash: { 4433 4433 switch (node->child1().useKind()) { 4434 #if USE(BIGINT32) 4435 case BigInt32Use: 4436 #endif 4434 4437 case BooleanUse: 4435 4438 case Int32Use: … … 4451 4454 break; 4452 4455 } 4456 case HeapBigIntUse: { 4457 SpeculateCellOperand input(this, node->child1()); 4458 GPRReg inputGPR = input.gpr(); 4459 4460 speculateHeapBigInt(node->child1(), inputGPR); 4461 4462 flushRegisters(); 4463 GPRFlushedCallResult result(this); 4464 GPRReg resultGPR = result.gpr(); 4465 callOperation(operationMapHash, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), inputGPR); 4466 m_jit.exceptionCheck(); 4467 strictInt32Result(resultGPR, node); 4468 break; 4469 } 4453 4470 case CellUse: 4454 4471 case StringUse: { … … 4473 4490 else { 4474 4491 auto isString = m_jit.branchIfString(inputGPR); 4492 auto isHeapBigInt = m_jit.branchIfHeapBigInt(inputGPR); 4475 4493 m_jit.move(inputGPR, resultGPR); 4476 4494 m_jit.wangsInt64Hash(resultGPR, tempGPR); 4495 addSlowPathGenerator(slowPathCall(isHeapBigInt, this, operationMapHash, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), inputGPR)); 4477 4496 done.append(m_jit.jump()); 4478 4497 isString.link(&m_jit); … … 4516 4535 straightHash.append(m_jit.branchIfNotCell(inputGPR)); 4517 4536 MacroAssembler::JumpList slowPath; 4537 auto isHeapBigInt = m_jit.branchIfHeapBigInt(inputGPR); 4518 4538 straightHash.append(m_jit.branchIfNotString(inputGPR)); 4519 4539 m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR); … … 4527 4547 m_jit.move(inputGPR, resultGPR); 4528 4548 m_jit.wangsInt64Hash(resultGPR, tempGPR); 4549 addSlowPathGenerator(slowPathCall(isHeapBigInt, this, operationMapHash, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), inputGPR)); 4529 4550 done.append(m_jit.jump()); 4530 4551 … … 4597 4618 switch (node->child2().useKind()) { 4598 4619 case BooleanUse: 4620 #if USE(BIGINT32) 4621 case BigInt32Use: 4622 #endif 4599 4623 case Int32Use: 4600 4624 case SymbolUse: … … 4605 4629 } 4606 4630 case CellUse: { 4631 // if (bucket.isString()) { 4632 // if (key.isString()) 4633 // => slow path 4634 // } else if (bucket.isHeapBigInt()) { 4635 // if (key.isHeapBigInt()) 4636 // => slow path 4637 // } 4607 4638 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); 4608 4639 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR))); 4609 loopAround.append(m_jit.branchIfNotString(bucketGPR)); 4640 4641 auto isBucketString = m_jit.branchIfString(bucketGPR); 4642 loopAround.append(m_jit.branchIfNotHeapBigInt(bucketGPR)); 4643 4644 // bucket is HeapBigInt. 4645 slowPathCases.append(m_jit.branchIfHeapBigInt(keyGPR)); 4646 loopAround.append(m_jit.jump()); 4647 4648 // bucket is String. 4649 isBucketString.link(&m_jit); 4610 4650 loopAround.append(m_jit.branchIfNotString(keyGPR)); 4611 // They're both strings.4612 4651 slowPathCases.append(m_jit.jump()); 4613 4652 break; … … 4617 4656 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR))); 4618 4657 loopAround.append(m_jit.branchIfNotString(bucketGPR)); 4658 slowPathCases.append(m_jit.jump()); 4659 break; 4660 } 4661 case HeapBigIntUse: { 4662 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for! 4663 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR))); 4664 loopAround.append(m_jit.branchIfNotHeapBigInt(bucketGPR)); 4619 4665 slowPathCases.append(m_jit.jump()); 4620 4666 break; … … 4627 4673 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR))); 4628 4674 // Both are cells here. 4629 loopAround.append(m_jit.branchIfNotString(bucketGPR)); 4630 // The first is a string here. 4631 slowPathCases.append(m_jit.branchIfString(keyGPR)); 4632 // The first is a string, but the second is not, we continue to loop around. 4675 auto isBucketString = m_jit.branchIfString(bucketGPR); 4676 // bucket is not String. 4677 loopAround.append(m_jit.branchIfNotHeapBigInt(bucketGPR)); 4678 // bucket is HeapBigInt. 4679 slowPathCases.append(m_jit.branchIfHeapBigInt(keyGPR)); 4633 4680 loopAround.append(m_jit.jump()); 4681 // bucket is String. 4682 isBucketString.link(&m_jit); 4683 loopAround.append(m_jit.branchIfNotString(keyGPR)); 4684 slowPathCases.append(m_jit.jump()); 4634 4685 break; 4635 4686 } -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r267032 r267373 11245 11245 JSGlobalObject* globalObject = m_graph.globalObjectFor(m_origin.semantic); 11246 11246 switch (m_node->child1().useKind()) { 11247 #if USE(BIGINT32) 11248 case BigInt32Use: 11249 #endif 11247 11250 case BooleanUse: 11248 11251 case Int32Use: … … 11255 11258 } 11256 11259 11260 case HeapBigIntUse: { 11261 LValue key = lowHeapBigInt(m_node->child1()); 11262 setInt32(m_out.castToInt32(vmCall(Int64, operationMapHash, weakPointer(globalObject), key))); 11263 return; 11264 } 11265 11257 11266 case CellUse: { 11258 11267 LBasicBlock isString = m_out.newBlock(); 11259 11268 LBasicBlock notString = m_out.newBlock(); 11269 LBasicBlock isHeapBigIntCase = m_out.newBlock(); 11270 LBasicBlock notStringHeapBigIntCase = m_out.newBlock(); 11260 11271 LBasicBlock continuation = m_out.newBlock(); 11261 11272 … … 11269 11280 m_out.jump(continuation); 11270 11281 11271 m_out.appendTo(notString, continuation); 11282 m_out.appendTo(notString, isHeapBigIntCase); 11283 m_out.branch(isHeapBigInt(value, (provenType(m_node->child1()) & ~SpecString)), unsure(isHeapBigIntCase), unsure(notStringHeapBigIntCase)); 11284 11285 m_out.appendTo(isHeapBigIntCase, notStringHeapBigIntCase); 11286 ValueFromBlock heapBigIntResult = m_out.anchor(m_out.castToInt32(vmCall(Int64, operationMapHash, weakPointer(globalObject), value))); 11287 m_out.jump(continuation); 11288 11289 m_out.appendTo(notStringHeapBigIntCase, continuation); 11272 11290 ValueFromBlock notStringResult = m_out.anchor(wangsInt64Hash(value)); 11273 11291 m_out.jump(continuation); 11274 11292 11275 11293 m_out.appendTo(continuation, lastNext); 11276 setInt32(m_out.phi(Int32, stringResult, notStringResult));11294 setInt32(m_out.phi(Int32, stringResult, heapBigIntResult, notStringResult)); 11277 11295 return; 11278 11296 } … … 11295 11313 LBasicBlock straightHash = m_out.newBlock(); 11296 11314 LBasicBlock isStringCase = m_out.newBlock(); 11315 LBasicBlock notStringCase = m_out.newBlock(); 11297 11316 LBasicBlock nonEmptyStringCase = m_out.newBlock(); 11298 11317 LBasicBlock continuation = m_out.newBlock(); … … 11301 11320 isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(straightHash)); 11302 11321 11303 LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);11322 LBasicBlock lastNext = m_out.appendTo(isCellCase, notStringCase); 11304 11323 LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType)); 11305 11324 m_out.branch( 11306 isString, unsure(isStringCase), unsure(straightHash)); 11325 isString, unsure(isStringCase), unsure(notStringCase)); 11326 11327 m_out.appendTo(notStringCase, isStringCase); 11328 m_out.branch(isHeapBigInt(value, (provenType(m_node->child1()) & ~SpecString)), unsure(slowCase), unsure(straightHash)); 11307 11329 11308 11330 m_out.appendTo(isStringCase, nonEmptyStringCase); … … 11332 11354 ASSERT(m_node->child1().useKind() == UntypedUse); 11333 11355 11356 LBasicBlock isCellCase = m_out.newBlock(); 11357 LBasicBlock notCellCase = m_out.newBlock(); 11358 LBasicBlock isHeapBigIntCase = m_out.newBlock(); 11334 11359 LBasicBlock isNumberCase = m_out.newBlock(); 11335 11360 LBasicBlock notInt32NumberCase = m_out.newBlock(); … … 11338 11363 LBasicBlock continuation = m_out.newBlock(); 11339 11364 11340 LBasicBlock lastNext = m_out.insertNewBlocksBefore(is NumberCase);11365 LBasicBlock lastNext = m_out.insertNewBlocksBefore(isCellCase); 11341 11366 11342 11367 LValue key = lowJSValue(m_node->child1()); 11343 11368 ValueFromBlock fastResult = m_out.anchor(key); 11369 m_out.branch(isNotCell(key, provenType(m_node->child1())), unsure(notCellCase), unsure(isCellCase)); 11370 11371 m_out.appendTo(isCellCase, isHeapBigIntCase); 11372 m_out.branch(isNotHeapBigInt(key, (provenType(m_node->child1()) & SpecCellCheck)), unsure(continuation), unsure(isHeapBigIntCase)); 11373 11374 m_out.appendTo(isHeapBigIntCase, notCellCase); 11375 ValueFromBlock bigIntResult = m_out.anchor(vmCall(Int64, operationNormalizeMapKey, m_vmValue, key)); 11376 m_out.jump(continuation); 11377 11378 m_out.appendTo(notCellCase, isNumberCase); 11344 11379 m_out.branch(isNotNumber(key), unsure(continuation), unsure(isNumberCase)); 11345 11380 … … 11363 11398 11364 11399 m_out.appendTo(continuation, lastNext); 11365 setJSValue(m_out.phi(Int64, fastResult, normalizedNaNResult, doubleResult, boxedIntResult));11400 setJSValue(m_out.phi(Int64, fastResult, bigIntResult, normalizedNaNResult, doubleResult, boxedIntResult)); 11366 11401 } 11367 11402 … … 11419 11454 switch (m_node->child2().useKind()) { 11420 11455 case BooleanUse: 11456 #if USE(BIGINT32) 11457 case BigInt32Use: 11458 #endif 11421 11459 case Int32Use: 11422 11460 case SymbolUse: … … 11442 11480 break; 11443 11481 } 11482 case HeapBigIntUse: { 11483 LBasicBlock notBitEqual = m_out.newBlock(); 11484 LBasicBlock bucketKeyIsCell = m_out.newBlock(); 11485 11486 m_out.branch(m_out.equal(key, bucketKey), 11487 unsure(continuation), unsure(notBitEqual)); 11488 11489 m_out.appendTo(notBitEqual, bucketKeyIsCell); 11490 m_out.branch(isCell(bucketKey), 11491 unsure(bucketKeyIsCell), unsure(loopAround)); 11492 11493 m_out.appendTo(bucketKeyIsCell, loopAround); 11494 m_out.branch(isHeapBigInt(bucketKey), 11495 unsure(slowPath), unsure(loopAround)); 11496 break; 11497 } 11444 11498 case CellUse: { 11445 11499 LBasicBlock notBitEqual = m_out.newBlock(); 11446 11500 LBasicBlock bucketKeyIsCell = m_out.newBlock(); 11447 11501 LBasicBlock bucketKeyIsString = m_out.newBlock(); 11502 LBasicBlock bucketKeyIsNotString = m_out.newBlock(); 11503 LBasicBlock bucketKeyIsHeapBigInt = m_out.newBlock(); 11448 11504 11449 11505 m_out.branch(m_out.equal(key, bucketKey), … … 11456 11512 m_out.appendTo(bucketKeyIsCell, bucketKeyIsString); 11457 11513 m_out.branch(isString(bucketKey), 11458 unsure(bucketKeyIsString), unsure(loopAround)); 11459 11460 m_out.appendTo(bucketKeyIsString, loopAround); 11461 m_out.branch(isString(key), 11514 unsure(bucketKeyIsString), unsure(bucketKeyIsNotString)); 11515 11516 m_out.appendTo(bucketKeyIsString, bucketKeyIsNotString); 11517 m_out.branch(isString(key, provenType(m_node->child2())), 11518 unsure(slowPath), unsure(loopAround)); 11519 11520 m_out.appendTo(bucketKeyIsNotString, bucketKeyIsHeapBigInt); 11521 m_out.branch(isHeapBigInt(bucketKey), 11522 unsure(bucketKeyIsHeapBigInt), unsure(loopAround)); 11523 11524 m_out.appendTo(bucketKeyIsHeapBigInt, loopAround); 11525 m_out.branch(isHeapBigInt(key, provenType(m_node->child2())), 11462 11526 unsure(slowPath), unsure(loopAround)); 11463 11527 break; … … 11468 11532 LBasicBlock bothAreCells = m_out.newBlock(); 11469 11533 LBasicBlock bucketKeyIsString = m_out.newBlock(); 11534 LBasicBlock bucketKeyIsNotString = m_out.newBlock(); 11535 LBasicBlock bucketKeyIsHeapBigInt = m_out.newBlock(); 11470 11536 11471 11537 m_out.branch(m_out.equal(key, bucketKey), … … 11482 11548 m_out.appendTo(bothAreCells, bucketKeyIsString); 11483 11549 m_out.branch(isString(bucketKey), 11484 unsure(bucketKeyIsString), unsure(loopAround)); 11485 11486 m_out.appendTo(bucketKeyIsString, loopAround); 11487 m_out.branch(isString(key), 11550 unsure(bucketKeyIsString), unsure(bucketKeyIsNotString)); 11551 11552 m_out.appendTo(bucketKeyIsString, bucketKeyIsNotString); 11553 m_out.branch(isString(key, provenType(m_node->child2())), 11554 unsure(slowPath), unsure(loopAround)); 11555 11556 m_out.appendTo(bucketKeyIsNotString, bucketKeyIsHeapBigInt); 11557 m_out.branch(isHeapBigInt(bucketKey), 11558 unsure(bucketKeyIsHeapBigInt), unsure(loopAround)); 11559 11560 m_out.appendTo(bucketKeyIsHeapBigInt, loopAround); 11561 m_out.branch(isHeapBigInt(key, provenType(m_node->child2())), 11488 11562 unsure(slowPath), unsure(loopAround)); 11489 11563 break; -
trunk/Source/JavaScriptCore/runtime/HashMapImpl.h
r254087 r267373 244 244 ALWAYS_INLINE JSValue normalizeMapKey(JSValue key) 245 245 { 246 if (!key.isNumber()) 246 if (!key.isNumber()) { 247 if (key.isHeapBigInt()) 248 return tryConvertToBigInt32(key.asHeapBigInt()); 247 249 return key; 250 } 248 251 249 252 if (key.isInt32()) … … 288 291 } 289 292 293 if (value.isHeapBigInt()) 294 return value.asHeapBigInt()->hash(); 295 290 296 return wangsInt64Hash(JSValue::encode(value)); 291 297 } … … 303 309 return impl->concurrentHash(); 304 310 } 311 312 if (key.isHeapBigInt()) 313 return key.asHeapBigInt()->concurrentHash(); 305 314 306 315 uint64_t rawValue = JSValue::encode(key); -
trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp
r266250 r267373 55 55 #include "StructureInlines.h" 56 56 #include <algorithm> 57 #include <wtf/Hasher.h> 57 58 #include <wtf/MathExtras.h> 58 59 … … 430 431 : payload(value) 431 432 { } 432 433 static ALWAYS_INLINE JSValue tryConvertToBigInt32(JSBigInt* bigInt)434 {435 #if USE(BIGINT32)436 if (UNLIKELY(!bigInt))437 return JSValue();438 439 if (bigInt->length() <= 1) {440 if (!bigInt->length())441 return jsBigInt32(0);442 JSBigInt::Digit digit = bigInt->digit(0);443 if (bigInt->sign()) {444 static constexpr uint64_t maxValue = -static_cast<int64_t>(std::numeric_limits<int32_t>::min());445 if (digit <= maxValue)446 return jsBigInt32(static_cast<int32_t>(-static_cast<int64_t>(digit)));447 } else {448 static constexpr uint64_t maxValue = static_cast<uint64_t>(std::numeric_limits<int32_t>::max());449 if (digit <= maxValue)450 return jsBigInt32(static_cast<int32_t>(digit));451 }452 }453 #endif454 455 return bigInt;456 }457 433 458 434 static ALWAYS_INLINE JSValue tryConvertToBigInt32(JSBigInt::ImplResult implResult) … … 3074 3050 #endif 3075 3051 3052 static ALWAYS_INLINE unsigned computeHash(JSBigInt::Digit* digits, unsigned length, bool sign) 3053 { 3054 Hasher hasher; 3055 WTF::add(hasher, sign); 3056 for (unsigned index = 0; index < length; ++index) 3057 WTF::add(hasher, digits[index]); 3058 return hasher.hash(); 3059 } 3060 3061 Optional<unsigned> JSBigInt::concurrentHash() 3062 { 3063 // FIXME: Implement JSBigInt::concurrentHash by inserting right store barriers. 3064 // https://bugs.webkit.org/show_bug.cgi?id=216801 3065 return WTF::nullopt; 3066 } 3067 3068 unsigned JSBigInt::hashSlow() 3069 { 3070 ASSERT(!m_hash); 3071 m_hash = computeHash(dataStorage(), length(), m_sign); 3072 return m_hash; 3073 } 3074 3076 3075 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSBigInt.h
r266795 r267373 428 428 JS_EXPORT_PRIVATE JSBigInt* tryRightTrim(VM&); 429 429 430 JS_EXPORT_PRIVATE Optional<unsigned> concurrentHash(); 431 unsigned hash() 432 { 433 if (m_hash) 434 return m_hash; 435 return hashSlow(); 436 } 437 430 438 private: 431 439 JSBigInt(VM&, Structure*, Digit*, unsigned length); 432 440 433 441 JSBigInt* rightTrim(JSGlobalObject*, VM&); 442 443 JS_EXPORT_PRIVATE unsigned hashSlow(); 434 444 435 445 static JSBigInt* createFromImpl(JSGlobalObject*, uint64_t value, bool sign); … … 573 583 574 584 inline Digit* dataStorage() { return m_data.get(m_length); } 585 inline Digit* dataStorageUnsafe() { return m_data.getUnsafe(); } 575 586 576 587 const unsigned m_length; 588 unsigned m_hash { 0 }; 577 589 bool m_sign { false }; 578 590 CagedBarrierPtr<Gigacage::Primitive, Digit, tagCagedPtr> m_data; … … 609 621 } 610 622 623 ALWAYS_INLINE JSValue tryConvertToBigInt32(JSBigInt* bigInt) 624 { 625 #if USE(BIGINT32) 626 if (UNLIKELY(!bigInt)) 627 return JSValue(); 628 629 if (bigInt->length() <= 1) { 630 if (!bigInt->length()) 631 return jsBigInt32(0); 632 JSBigInt::Digit digit = bigInt->digit(0); 633 if (bigInt->sign()) { 634 static constexpr uint64_t maxValue = -static_cast<int64_t>(std::numeric_limits<int32_t>::min()); 635 if (digit <= maxValue) 636 return jsBigInt32(static_cast<int32_t>(-static_cast<int64_t>(digit))); 637 } else { 638 static constexpr uint64_t maxValue = static_cast<uint64_t>(std::numeric_limits<int32_t>::max()); 639 if (digit <= maxValue) 640 return jsBigInt32(static_cast<int32_t>(digit)); 641 } 642 } 643 #endif 644 645 return bigInt; 646 } 647 611 648 } // namespace JSC -
trunk/Source/WTF/ChangeLog
r267371 r267373 1 2020-09-21 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] BigInt should work with Map / Set 4 https://bugs.webkit.org/show_bug.cgi?id=216667 5 6 Reviewed by Robin Morisset. 7 8 * wtf/Hasher.h: 9 (WTF::Hasher::hash const): 10 (WTF::add): 11 1 12 2020-09-21 Mark Lam <mark.lam@apple.com> 2 13 -
trunk/Source/WTF/wtf/Hasher.h
r264277 r267373 48 48 template<typename... Types> uint32_t computeHash(const Types&...); 49 49 template<typename T, typename... OtherTypes> uint32_t computeHash(std::initializer_list<T>, std::initializer_list<OtherTypes>...); 50 template<typename UnsignedInteger> std::enable_if_t<std::is_unsigned<UnsignedInteger>::value && sizeof(UnsignedInteger) <= sizeof(uint32_t), void> add(Hasher&, UnsignedInteger); 50 51 51 52 class Hasher { … … 76 77 } 77 78 79 unsigned hash() const 80 { 81 return m_underlyingHasher.hash(); 82 } 83 78 84 private: 79 85 StringHasher m_underlyingHasher; … … 90 96 // We overloaded for double and float below, just deal with integers here. 91 97 add(hasher, static_cast<std::make_unsigned_t<SignedArithmetic>>(number)); 98 } 99 100 inline void add(Hasher& hasher, bool boolean) 101 { 102 add(hasher, static_cast<uint8_t>(boolean)); 92 103 } 93 104 -
trunk/Source/WebCore/ChangeLog
r267372 r267373 1 2020-09-21 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] BigInt should work with Map / Set 4 https://bugs.webkit.org/show_bug.cgi?id=216667 5 <rdar://problem/69107221> 6 7 Reviewed by Robin Morisset. 8 9 Strongly ensure that BigInt32 is always selected since Map / Set could use it as a key. 10 11 * bindings/js/SerializedScriptValue.cpp: 12 (WebCore::CloneDeserializer::readBigInt): 13 1 14 2020-09-21 Peng Liu <peng.liu6@apple.com> 2 15 -
trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp
r266470 r267373 3055 3055 } 3056 3056 m_gcBuffer.appendWithCrashOnOverflow(bigInt); 3057 return bigInt;3057 return tryConvertToBigInt32(bigInt); 3058 3058 } 3059 3059 #endif … … 3095 3095 } 3096 3096 m_gcBuffer.appendWithCrashOnOverflow(bigInt); 3097 return bigInt;3097 return tryConvertToBigInt32(bigInt); 3098 3098 } 3099 3099
Note: See TracChangeset
for help on using the changeset viewer.