Changeset 156019 in webkit for trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
- Timestamp:
- Sep 17, 2013, 6:31:04 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r156016 r156019 336 336 else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage) 337 337 spillAction = StorePtr; 338 else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52) 339 spillAction = Store64; 338 340 else { 339 341 ASSERT(registerFormat & DataFormatJS); … … 387 389 ASSERT(info.gpr() == source); 388 390 fillAction = LoadPtr; 391 } else if (registerFormat == DataFormatInt52) { 392 if (node->hasConstant()) 393 fillAction = SetInt52Constant; 394 else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS) 395 fillAction = Load32PayloadConvertToInt52; 396 else if (info.spillFormat() == DataFormatInt52) 397 fillAction = Load64; 398 else if (info.spillFormat() == DataFormatStrictInt52) 399 fillAction = Load64ShiftInt52Left; 400 else if (info.spillFormat() == DataFormatNone) 401 fillAction = Load64; 402 else { 403 // Should never happen. Anything that qualifies as an int32 will never 404 // be turned into a cell (immediate spec fail) or a double (to-double 405 // conversions involve a separate node). 406 RELEASE_ASSERT_NOT_REACHED(); 407 fillAction = Load64; // Make GCC happy. 408 } 409 } else if (registerFormat == DataFormatStrictInt52) { 410 if (node->hasConstant()) 411 fillAction = SetStrictInt52Constant; 412 else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS) 413 fillAction = Load32PayloadSignExtend; 414 else if (info.spillFormat() == DataFormatInt52) 415 fillAction = Load64ShiftInt52Right; 416 else if (info.spillFormat() == DataFormatStrictInt52) 417 fillAction = Load64; 418 else if (info.spillFormat() == DataFormatNone) 419 fillAction = Load64; 420 else { 421 // Should never happen. Anything that qualifies as an int32 will never 422 // be turned into a cell (immediate spec fail) or a double (to-double 423 // conversions involve a separate node). 424 RELEASE_ASSERT_NOT_REACHED(); 425 fillAction = Load64; // Make GCC happy. 426 } 389 427 } else { 390 428 ASSERT(registerFormat & DataFormatJS); … … 394 432 if (valueOfJSConstant(node).isCell()) 395 433 fillAction = SetTrustedJSConstant; 396 else397 434 fillAction = SetJSConstant; 398 435 } else if (info.spillFormat() == DataFormatInt32) { … … 513 550 m_jit.move(Imm32(valueOfInt32Constant(plan.node())), plan.gpr()); 514 551 break; 552 #if USE(JSVALUE64) 553 case SetInt52Constant: 554 m_jit.move(Imm64(valueOfJSConstant(plan.node()).asMachineInt() << JSValue::int52ShiftAmount), plan.gpr()); 555 break; 556 case SetStrictInt52Constant: 557 m_jit.move(Imm64(valueOfJSConstant(plan.node()).asMachineInt()), plan.gpr()); 558 break; 559 #endif // USE(JSVALUE64) 515 560 case SetBooleanConstant: 516 561 m_jit.move(TrustedImm32(valueOfBooleanConstant(plan.node())), plan.gpr()); … … 534 579 m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr()); 535 580 break; 581 case Load32PayloadConvertToInt52: 582 m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr()); 583 m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr()); 584 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr()); 585 break; 586 case Load32PayloadSignExtend: 587 m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr()); 588 m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr()); 589 break; 536 590 case LoadDoubleBoxDouble: 537 591 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); … … 574 628 case Load64: 575 629 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); 630 break; 631 case Load64ShiftInt52Right: 632 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); 633 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr()); 634 break; 635 case Load64ShiftInt52Left: 636 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); 637 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr()); 576 638 break; 577 639 #endif … … 1417 1479 if (node->isBinaryUseKind(Int32Use)) 1418 1480 compilePeepHoleInt32Branch(node, branchNode, condition); 1481 #if USE(JSVALUE64) 1482 else if (node->isBinaryUseKind(MachineIntUse)) 1483 compilePeepHoleInt52Branch(node, branchNode, condition); 1484 #endif // USE(JSVALUE64) 1419 1485 else if (node->isBinaryUseKind(NumberUse)) 1420 1486 compilePeepHoleDoubleBranch(node, branchNode, doubleCondition); … … 1507 1573 case FlushedInt32: 1508 1574 valueSource = ValueSource(Int32InJSStack); 1575 break; 1576 case FlushedInt52: 1577 valueSource = ValueSource(Int52InJSStack); 1509 1578 break; 1510 1579 case FlushedCell: … … 1874 1943 1875 1944 DFG_TYPE_CHECK( 1876 JSValueRegs(), child3, Spec RealNumber,1945 JSValueRegs(), child3, SpecFullRealNumber, 1877 1946 m_jit.branchDouble( 1878 1947 MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg)); … … 2150 2219 return; 2151 2220 } 2221 2222 #if USE(JSVALUE64) 2223 case MachineIntUse: { 2224 SpeculateStrictInt52Operand op1(this, node->child1()); 2225 GPRTemporary result(this, Reuse, op1); 2226 GPRReg op1GPR = op1.gpr(); 2227 GPRReg resultGPR = result.gpr(); 2228 m_jit.zeroExtend32ToPtr(op1GPR, resultGPR); 2229 int32Result(resultGPR, node, DataFormatInt32); 2230 return; 2231 } 2232 #endif // USE(JSVALUE64) 2152 2233 2153 2234 case NumberUse: … … 2188 2269 if (node->child1().useKind() == NumberUse) { 2189 2270 DFG_TYPE_CHECK( 2190 JSValueRegs(gpr), node->child1(), Spec Number,2271 JSValueRegs(gpr), node->child1(), SpecFullNumber, 2191 2272 m_jit.branchTest64( 2192 2273 MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); … … 2244 2325 if (node->child1().useKind() == NumberUse) { 2245 2326 DFG_TYPE_CHECK( 2246 JSValueRegs(tagGPR, payloadGPR), node->child1(), Spec Number,2327 JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecFullNumber, 2247 2328 m_jit.branch32( 2248 2329 MacroAssembler::AboveOrEqual, tagGPR, … … 2390 2471 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 2391 2472 2392 if (needsTypeCheck(node->child1(), Spec Number)) {2473 if (needsTypeCheck(node->child1(), SpecFullNumber)) { 2393 2474 if (node->flags() & NodeExitsForward) { 2394 2475 forwardTypeCheck( 2395 JSValueRegs(op1GPR), node->child1(), Spec Number,2476 JSValueRegs(op1GPR), node->child1(), SpecFullNumber, 2396 2477 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister), 2397 2478 ValueRecovery::inGPR(op1GPR, DataFormatJS)); 2398 2479 } else { 2399 2480 backwardTypeCheck( 2400 JSValueRegs(op1GPR), node->child1(), Spec Number,2481 JSValueRegs(op1GPR), node->child1(), SpecFullNumber, 2401 2482 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 2402 2483 } … … 2421 2502 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 2422 2503 2423 if (needsTypeCheck(node->child1(), Spec Number)) {2504 if (needsTypeCheck(node->child1(), SpecFullNumber)) { 2424 2505 if (node->flags() & NodeExitsForward) { 2425 2506 forwardTypeCheck( 2426 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), Spec Number,2507 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, 2427 2508 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)), 2428 2509 ValueRecovery::inPair(op1TagGPR, op1PayloadGPR)); 2429 2510 } else { 2430 2511 backwardTypeCheck( 2431 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), Spec Number,2512 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, 2432 2513 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 2433 2514 } … … 2549 2630 return; 2550 2631 } 2632 2633 #if USE(JSVALUE64) 2634 if (node->shouldSpeculateMachineInt()) { 2635 m_jit.zeroExtend32ToPtr(resultReg, resultReg); 2636 strictInt52Result(resultReg, node); 2637 return; 2638 } 2639 #endif 2551 2640 2552 2641 FPRTemporary fresult(this); … … 2602 2691 break; 2603 2692 } 2693 2694 #if USE(JSVALUE64) 2695 case MachineIntUse: { 2696 SpeculateStrictInt52Operand valueOp(this, valueUse); 2697 GPRTemporary scratch(this); 2698 GPRReg scratchReg = scratch.gpr(); 2699 m_jit.move(valueOp.gpr(), scratchReg); 2700 if (isClamped(type)) { 2701 ASSERT(elementSize(type) == 1); 2702 MacroAssembler::Jump inBounds = m_jit.branch64( 2703 MacroAssembler::BelowOrEqual, scratchReg, JITCompiler::TrustedImm64(0xff)); 2704 MacroAssembler::Jump tooBig = m_jit.branch64( 2705 MacroAssembler::GreaterThan, scratchReg, JITCompiler::TrustedImm64(0xff)); 2706 m_jit.move(TrustedImm32(0), scratchReg); 2707 MacroAssembler::Jump clamped = m_jit.jump(); 2708 tooBig.link(&m_jit); 2709 m_jit.move(JITCompiler::TrustedImm32(255), scratchReg); 2710 clamped.link(&m_jit); 2711 inBounds.link(&m_jit); 2712 } 2713 value.adopt(scratch); 2714 valueGPR = scratchReg; 2715 break; 2716 } 2717 #endif // USE(JSVALUE64) 2604 2718 2605 2719 case NumberUse: { … … 2871 2985 return; 2872 2986 } 2873 2987 2874 2988 if (isNumberConstant(node->child2().node())) { 2875 2989 SpeculateInt32Operand op1(this, node->child1()); … … 2916 3030 return; 2917 3031 } 3032 3033 #if USE(JSVALUE64) 3034 case MachineIntUse: { 3035 // Will we need an overflow check? If we can prove that neither input can be 3036 // Int52 then the overflow check will not be necessary. 3037 if (!m_state.forNode(node->child1()).couldBeType(SpecInt52) 3038 && !m_state.forNode(node->child2()).couldBeType(SpecInt52)) { 3039 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3040 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); 3041 GPRTemporary result(this, Reuse, op1); 3042 m_jit.move(op1.gpr(), result.gpr()); 3043 m_jit.add64(op2.gpr(), result.gpr()); 3044 int52Result(result.gpr(), node, op1.format()); 3045 return; 3046 } 3047 3048 SpeculateInt52Operand op1(this, node->child1()); 3049 SpeculateInt52Operand op2(this, node->child2()); 3050 GPRTemporary result(this, Reuse, op1, op2); 3051 m_jit.move(op1.gpr(), result.gpr()); 3052 speculationCheck( 3053 Int52Overflow, JSValueRegs(), 0, 3054 m_jit.branchAdd64(MacroAssembler::Overflow, op2.gpr(), result.gpr())); 3055 int52Result(result.gpr(), node); 3056 return; 3057 } 3058 #endif // USE(JSVALUE64) 2918 3059 2919 3060 case NumberUse: { … … 3061 3202 } 3062 3203 3204 #if USE(JSVALUE64) 3205 case MachineIntUse: { 3206 // Will we need an overflow check? If we can prove that neither input can be 3207 // Int52 then the overflow check will not be necessary. 3208 if (!m_state.forNode(node->child1()).couldBeType(SpecInt52) 3209 && !m_state.forNode(node->child2()).couldBeType(SpecInt52)) { 3210 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3211 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); 3212 GPRTemporary result(this, Reuse, op1); 3213 m_jit.move(op1.gpr(), result.gpr()); 3214 m_jit.sub64(op2.gpr(), result.gpr()); 3215 int52Result(result.gpr(), node, op1.format()); 3216 return; 3217 } 3218 3219 SpeculateInt52Operand op1(this, node->child1()); 3220 SpeculateInt52Operand op2(this, node->child2()); 3221 GPRTemporary result(this, Reuse, op1, op2); 3222 m_jit.move(op1.gpr(), result.gpr()); 3223 speculationCheck( 3224 Int52Overflow, JSValueRegs(), 0, 3225 m_jit.branchSub64(MacroAssembler::Overflow, op2.gpr(), result.gpr())); 3226 int52Result(result.gpr(), node); 3227 return; 3228 } 3229 #endif // USE(JSVALUE64) 3230 3063 3231 case NumberUse: { 3064 3232 SpeculateDoubleOperand op1(this, node->child1()); … … 3089 3257 m_jit.move(op1.gpr(), result.gpr()); 3090 3258 3259 // Note: there is no notion of being not used as a number, but someone 3260 // caring about negative zero. 3261 3091 3262 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) 3092 3263 m_jit.neg32(result.gpr()); … … 3101 3272 return; 3102 3273 } 3274 3275 #if USE(JSVALUE64) 3276 case MachineIntUse: { 3277 if (!m_state.forNode(node->child1()).couldBeType(SpecInt52)) { 3278 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3279 GPRTemporary result(this); 3280 GPRReg op1GPR = op1.gpr(); 3281 GPRReg resultGPR = result.gpr(); 3282 m_jit.move(op1GPR, resultGPR); 3283 m_jit.neg64(resultGPR); 3284 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) { 3285 speculationCheck( 3286 NegativeZero, JSValueRegs(), 0, 3287 m_jit.branchTest64(MacroAssembler::Zero, resultGPR)); 3288 } 3289 int52Result(resultGPR, node, op1.format()); 3290 return; 3291 } 3292 3293 SpeculateInt52Operand op1(this, node->child1()); 3294 GPRTemporary result(this); 3295 GPRReg op1GPR = op1.gpr(); 3296 GPRReg resultGPR = result.gpr(); 3297 m_jit.move(op1GPR, resultGPR); 3298 speculationCheck( 3299 Int52Overflow, JSValueRegs(), 0, 3300 m_jit.branchNeg64(MacroAssembler::Overflow, resultGPR)); 3301 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) { 3302 speculationCheck( 3303 NegativeZero, JSValueRegs(), 0, 3304 m_jit.branchTest64(MacroAssembler::Zero, resultGPR)); 3305 } 3306 int52Result(resultGPR, node); 3307 return; 3308 } 3309 #endif // USE(JSVALUE64) 3103 3310 3104 3311 case NumberUse: { … … 3166 3373 return; 3167 3374 } 3375 3376 #if USE(JSVALUE64) 3377 case MachineIntUse: { 3378 // This is super clever. We want to do an int52 multiplication and check the 3379 // int52 overflow bit. There is no direct hardware support for this, but we do 3380 // have the ability to do an int64 multiplication and check the int64 overflow 3381 // bit. We leverage that. Consider that a, b are int52 numbers inside int64 3382 // registers, with the high 12 bits being sign-extended. We can do: 3383 // 3384 // (a * (b << 12)) 3385 // 3386 // This will give us a left-shifted int52 (value is in high 52 bits, low 16 3387 // bits are zero) plus the int52 overflow bit. I.e. whether this 64-bit 3388 // multiplication overflows is identical to whether the 'a * b' 52-bit 3389 // multiplication overflows. 3390 // 3391 // In our nomenclature, this is: 3392 // 3393 // strictInt52(a) * int52(b) => int52 3394 // 3395 // That is "strictInt52" means unshifted and "int52" means left-shifted by 16 3396 // bits. 3397 // 3398 // We don't care which of op1 or op2 serves as the left-shifted operand, so 3399 // we just do whatever is more convenient for op1 and have op2 do the 3400 // opposite. This ensures that we do at most one shift. 3401 3402 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3403 SpeculateWhicheverInt52Operand op2(this, node->child2(), OppositeShift, op1); 3404 GPRTemporary result(this); 3405 3406 GPRReg op1GPR = op1.gpr(); 3407 GPRReg op2GPR = op2.gpr(); 3408 GPRReg resultGPR = result.gpr(); 3409 3410 m_jit.move(op1GPR, resultGPR); 3411 speculationCheck( 3412 Int52Overflow, JSValueRegs(), 0, 3413 m_jit.branchMul64(MacroAssembler::Overflow, op2GPR, resultGPR)); 3414 3415 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) { 3416 MacroAssembler::Jump resultNonZero = m_jit.branchTest64( 3417 MacroAssembler::NonZero, resultGPR); 3418 speculationCheck( 3419 NegativeZero, JSValueRegs(), 0, 3420 m_jit.branch64(MacroAssembler::LessThan, op1GPR, TrustedImm64(0))); 3421 speculationCheck( 3422 NegativeZero, JSValueRegs(), 0, 3423 m_jit.branch64(MacroAssembler::LessThan, op2GPR, TrustedImm64(0))); 3424 resultNonZero.link(&m_jit); 3425 } 3426 3427 int52Result(resultGPR, node); 3428 return; 3429 } 3430 #endif // USE(JSVALUE64) 3168 3431 3169 3432 case NumberUse: { … … 3589 3852 return false; 3590 3853 } 3591 3854 3855 #if USE(JSVALUE64) 3856 if (node->isBinaryUseKind(MachineIntUse)) { 3857 compileInt52Compare(node, condition); 3858 return false; 3859 } 3860 #endif // USE(JSVALUE64) 3861 3592 3862 if (node->isBinaryUseKind(NumberUse)) { 3593 3863 compileDoubleCompare(node, doubleCondition); … … 3739 4009 return false; 3740 4010 } 4011 4012 #if USE(JSVALUE64) 4013 case MachineIntUse: { 4014 unsigned branchIndexInBlock = detectPeepHoleBranch(); 4015 if (branchIndexInBlock != UINT_MAX) { 4016 Node* branchNode = m_block->at(branchIndexInBlock); 4017 compilePeepHoleInt52Branch(node, branchNode, MacroAssembler::Equal); 4018 use(node->child1()); 4019 use(node->child2()); 4020 m_indexInBlock = branchIndexInBlock; 4021 m_currentNode = branchNode; 4022 return true; 4023 } 4024 compileInt52Compare(node, MacroAssembler::Equal); 4025 return false; 4026 } 4027 #endif // USE(JSVALUE64) 3741 4028 3742 4029 case NumberUse: { … … 4494 4781 } 4495 4782 4783 void SpeculativeJIT::speculateMachineInt(Edge edge) 4784 { 4785 #if USE(JSVALUE64) 4786 if (!needsTypeCheck(edge, SpecMachineInt)) 4787 return; 4788 4789 (SpeculateWhicheverInt52Operand(this, edge)).gpr(); 4790 #else // USE(JSVALUE64) 4791 UNUSED_PARAM(edge); 4792 UNREACHABLE_FOR_PLATFORM(); 4793 #endif // USE(JSVALUE64) 4794 } 4795 4496 4796 void SpeculativeJIT::speculateNumber(Edge edge) 4497 4797 { 4498 if (!needsTypeCheck(edge, Spec Number))4798 if (!needsTypeCheck(edge, SpecFullNumber)) 4499 4799 return; 4500 4800 … … 4504 4804 void SpeculativeJIT::speculateRealNumber(Edge edge) 4505 4805 { 4506 if (!needsTypeCheck(edge, Spec RealNumber))4806 if (!needsTypeCheck(edge, SpecFullRealNumber)) 4507 4807 return; 4508 4808 … … 4510 4810 FPRReg fpr = operand.fpr(); 4511 4811 DFG_TYPE_CHECK( 4512 JSValueRegs(), edge, Spec RealNumber,4812 JSValueRegs(), edge, SpecFullRealNumber, 4513 4813 m_jit.branchDouble( 4514 4814 MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr)); … … 4772 5072 break; 4773 5073 case KnownNumberUse: 4774 ASSERT(!needsTypeCheck(edge, Spec Number));5074 ASSERT(!needsTypeCheck(edge, SpecFullNumber)); 4775 5075 break; 4776 5076 case KnownCellUse: … … 4782 5082 case Int32Use: 4783 5083 speculateInt32(edge); 5084 break; 5085 case MachineIntUse: 5086 speculateMachineInt(edge); 4784 5087 break; 4785 5088 case RealNumberUse:
Note:
See TracChangeset
for help on using the changeset viewer.