Changeset 156029 in webkit for trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
- Timestamp:
- Sep 18, 2013, 12:25:52 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r156019 r156029 336 336 else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage) 337 337 spillAction = StorePtr; 338 else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52)339 spillAction = Store64;340 338 else { 341 339 ASSERT(registerFormat & DataFormatJS); … … 389 387 ASSERT(info.gpr() == source); 390 388 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 never404 // be turned into a cell (immediate spec fail) or a double (to-double405 // 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 never422 // be turned into a cell (immediate spec fail) or a double (to-double423 // conversions involve a separate node).424 RELEASE_ASSERT_NOT_REACHED();425 fillAction = Load64; // Make GCC happy.426 }427 389 } else { 428 390 ASSERT(registerFormat & DataFormatJS); … … 432 394 if (valueOfJSConstant(node).isCell()) 433 395 fillAction = SetTrustedJSConstant; 396 else 434 397 fillAction = SetJSConstant; 435 398 } else if (info.spillFormat() == DataFormatInt32) { … … 550 513 m_jit.move(Imm32(valueOfInt32Constant(plan.node())), plan.gpr()); 551 514 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)560 515 case SetBooleanConstant: 561 516 m_jit.move(TrustedImm32(valueOfBooleanConstant(plan.node())), plan.gpr()); … … 579 534 m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr()); 580 535 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;590 536 case LoadDoubleBoxDouble: 591 537 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); … … 628 574 case Load64: 629 575 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());638 576 break; 639 577 #endif … … 1479 1417 if (node->isBinaryUseKind(Int32Use)) 1480 1418 compilePeepHoleInt32Branch(node, branchNode, condition); 1481 #if USE(JSVALUE64)1482 else if (node->isBinaryUseKind(MachineIntUse))1483 compilePeepHoleInt52Branch(node, branchNode, condition);1484 #endif // USE(JSVALUE64)1485 1419 else if (node->isBinaryUseKind(NumberUse)) 1486 1420 compilePeepHoleDoubleBranch(node, branchNode, doubleCondition); … … 1573 1507 case FlushedInt32: 1574 1508 valueSource = ValueSource(Int32InJSStack); 1575 break;1576 case FlushedInt52:1577 valueSource = ValueSource(Int52InJSStack);1578 1509 break; 1579 1510 case FlushedCell: … … 1943 1874 1944 1875 DFG_TYPE_CHECK( 1945 JSValueRegs(), child3, Spec FullRealNumber,1876 JSValueRegs(), child3, SpecRealNumber, 1946 1877 m_jit.branchDouble( 1947 1878 MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg)); … … 2219 2150 return; 2220 2151 } 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)2233 2152 2234 2153 case NumberUse: … … 2269 2188 if (node->child1().useKind() == NumberUse) { 2270 2189 DFG_TYPE_CHECK( 2271 JSValueRegs(gpr), node->child1(), Spec FullNumber,2190 JSValueRegs(gpr), node->child1(), SpecNumber, 2272 2191 m_jit.branchTest64( 2273 2192 MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); … … 2325 2244 if (node->child1().useKind() == NumberUse) { 2326 2245 DFG_TYPE_CHECK( 2327 JSValueRegs(tagGPR, payloadGPR), node->child1(), Spec FullNumber,2246 JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecNumber, 2328 2247 m_jit.branch32( 2329 2248 MacroAssembler::AboveOrEqual, tagGPR, … … 2471 2390 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 2472 2391 2473 if (needsTypeCheck(node->child1(), Spec FullNumber)) {2392 if (needsTypeCheck(node->child1(), SpecNumber)) { 2474 2393 if (node->flags() & NodeExitsForward) { 2475 2394 forwardTypeCheck( 2476 JSValueRegs(op1GPR), node->child1(), Spec FullNumber,2395 JSValueRegs(op1GPR), node->child1(), SpecNumber, 2477 2396 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister), 2478 2397 ValueRecovery::inGPR(op1GPR, DataFormatJS)); 2479 2398 } else { 2480 2399 backwardTypeCheck( 2481 JSValueRegs(op1GPR), node->child1(), Spec FullNumber,2400 JSValueRegs(op1GPR), node->child1(), SpecNumber, 2482 2401 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 2483 2402 } … … 2502 2421 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 2503 2422 2504 if (needsTypeCheck(node->child1(), Spec FullNumber)) {2423 if (needsTypeCheck(node->child1(), SpecNumber)) { 2505 2424 if (node->flags() & NodeExitsForward) { 2506 2425 forwardTypeCheck( 2507 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), Spec FullNumber,2426 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber, 2508 2427 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)), 2509 2428 ValueRecovery::inPair(op1TagGPR, op1PayloadGPR)); 2510 2429 } else { 2511 2430 backwardTypeCheck( 2512 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), Spec FullNumber,2431 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber, 2513 2432 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 2514 2433 } … … 2630 2549 return; 2631 2550 } 2632 2633 #if USE(JSVALUE64)2634 if (node->shouldSpeculateMachineInt()) {2635 m_jit.zeroExtend32ToPtr(resultReg, resultReg);2636 strictInt52Result(resultReg, node);2637 return;2638 }2639 #endif2640 2551 2641 2552 FPRTemporary fresult(this); … … 2691 2602 break; 2692 2603 } 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)2718 2604 2719 2605 case NumberUse: { … … 2985 2871 return; 2986 2872 } 2987 2873 2988 2874 if (isNumberConstant(node->child2().node())) { 2989 2875 SpeculateInt32Operand op1(this, node->child1()); … … 3030 2916 return; 3031 2917 } 3032 3033 #if USE(JSVALUE64)3034 case MachineIntUse: {3035 // Will we need an overflow check? If we can prove that neither input can be3036 // 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)3059 2918 3060 2919 case NumberUse: { … … 3202 3061 } 3203 3062 3204 #if USE(JSVALUE64)3205 case MachineIntUse: {3206 // Will we need an overflow check? If we can prove that neither input can be3207 // 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 3231 3063 case NumberUse: { 3232 3064 SpeculateDoubleOperand op1(this, node->child1()); … … 3257 3089 m_jit.move(op1.gpr(), result.gpr()); 3258 3090 3259 // Note: there is no notion of being not used as a number, but someone3260 // caring about negative zero.3261 3262 3091 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) 3263 3092 m_jit.neg32(result.gpr()); … … 3272 3101 return; 3273 3102 } 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)3310 3103 3311 3104 case NumberUse: { … … 3373 3166 return; 3374 3167 } 3375 3376 #if USE(JSVALUE64)3377 case MachineIntUse: {3378 // This is super clever. We want to do an int52 multiplication and check the3379 // int52 overflow bit. There is no direct hardware support for this, but we do3380 // have the ability to do an int64 multiplication and check the int64 overflow3381 // bit. We leverage that. Consider that a, b are int52 numbers inside int643382 // 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 163387 // bits are zero) plus the int52 overflow bit. I.e. whether this 64-bit3388 // multiplication overflows is identical to whether the 'a * b' 52-bit3389 // multiplication overflows.3390 //3391 // In our nomenclature, this is:3392 //3393 // strictInt52(a) * int52(b) => int523394 //3395 // That is "strictInt52" means unshifted and "int52" means left-shifted by 163396 // bits.3397 //3398 // We don't care which of op1 or op2 serves as the left-shifted operand, so3399 // we just do whatever is more convenient for op1 and have op2 do the3400 // 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)3431 3168 3432 3169 case NumberUse: { … … 3852 3589 return false; 3853 3590 } 3854 3855 #if USE(JSVALUE64) 3856 if (node->isBinaryUseKind(MachineIntUse)) { 3857 compileInt52Compare(node, condition); 3858 return false; 3859 } 3860 #endif // USE(JSVALUE64) 3861 3591 3862 3592 if (node->isBinaryUseKind(NumberUse)) { 3863 3593 compileDoubleCompare(node, doubleCondition); … … 4009 3739 return false; 4010 3740 } 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)4028 3741 4029 3742 case NumberUse: { … … 4781 4494 } 4782 4495 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 4796 4496 void SpeculativeJIT::speculateNumber(Edge edge) 4797 4497 { 4798 if (!needsTypeCheck(edge, Spec FullNumber))4498 if (!needsTypeCheck(edge, SpecNumber)) 4799 4499 return; 4800 4500 … … 4804 4504 void SpeculativeJIT::speculateRealNumber(Edge edge) 4805 4505 { 4806 if (!needsTypeCheck(edge, Spec FullRealNumber))4506 if (!needsTypeCheck(edge, SpecRealNumber)) 4807 4507 return; 4808 4508 … … 4810 4510 FPRReg fpr = operand.fpr(); 4811 4511 DFG_TYPE_CHECK( 4812 JSValueRegs(), edge, Spec FullRealNumber,4512 JSValueRegs(), edge, SpecRealNumber, 4813 4513 m_jit.branchDouble( 4814 4514 MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr)); … … 5072 4772 break; 5073 4773 case KnownNumberUse: 5074 ASSERT(!needsTypeCheck(edge, Spec FullNumber));4774 ASSERT(!needsTypeCheck(edge, SpecNumber)); 5075 4775 break; 5076 4776 case KnownCellUse: … … 5082 4782 case Int32Use: 5083 4783 speculateInt32(edge); 5084 break;5085 case MachineIntUse:5086 speculateMachineInt(edge);5087 4784 break; 5088 4785 case RealNumberUse:
Note:
See TracChangeset
for help on using the changeset viewer.