| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 case CodeStub::RegExpExec: { | 752 case CodeStub::RegExpExec: { |
| 753 RegExpExecStub stub; | 753 RegExpExecStub stub; |
| 754 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 754 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 755 break; | 755 break; |
| 756 } | 756 } |
| 757 case CodeStub::SubString: { | 757 case CodeStub::SubString: { |
| 758 SubStringStub stub; | 758 SubStringStub stub; |
| 759 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 759 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 760 break; | 760 break; |
| 761 } | 761 } |
| 762 case CodeStub::StringCharAt: { | |
| 763 StringCharAtStub stub; | |
| 764 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | |
| 765 break; | |
| 766 } | |
| 767 case CodeStub::NumberToString: { | 762 case CodeStub::NumberToString: { |
| 768 NumberToStringStub stub; | 763 NumberToStringStub stub; |
| 769 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 764 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 770 break; | 765 break; |
| 771 } | 766 } |
| 772 case CodeStub::StringAdd: { | 767 case CodeStub::StringAdd: { |
| 773 StringAddStub stub(NO_STRING_ADD_FLAGS); | 768 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 774 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 769 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 775 break; | 770 break; |
| 776 } | 771 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 791 } | 786 } |
| 792 } | 787 } |
| 793 | 788 |
| 794 | 789 |
| 795 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 790 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 796 // Nothing to do. | 791 // Nothing to do. |
| 797 } | 792 } |
| 798 | 793 |
| 799 | 794 |
| 800 void LCodeGen::DoModI(LModI* instr) { | 795 void LCodeGen::DoModI(LModI* instr) { |
| 796 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 797 Register dividend = ToRegister(instr->InputAt(0)); |
| 798 |
| 799 int32_t divisor = |
| 800 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
| 801 |
| 802 if (divisor < 0) divisor = -divisor; |
| 803 |
| 804 Label positive_dividend, done; |
| 805 __ tst(dividend, Operand(dividend)); |
| 806 __ b(pl, &positive_dividend); |
| 807 __ rsb(dividend, dividend, Operand(0)); |
| 808 __ and_(dividend, dividend, Operand(divisor - 1)); |
| 809 __ rsb(dividend, dividend, Operand(0), SetCC); |
| 810 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 811 __ b(ne, &done); |
| 812 DeoptimizeIf(al, instr->environment()); |
| 813 } |
| 814 __ bind(&positive_dividend); |
| 815 __ and_(dividend, dividend, Operand(divisor - 1)); |
| 816 __ bind(&done); |
| 817 return; |
| 818 } |
| 819 |
| 801 class DeferredModI: public LDeferredCode { | 820 class DeferredModI: public LDeferredCode { |
| 802 public: | 821 public: |
| 803 DeferredModI(LCodeGen* codegen, LModI* instr) | 822 DeferredModI(LCodeGen* codegen, LModI* instr) |
| 804 : LDeferredCode(codegen), instr_(instr) { } | 823 : LDeferredCode(codegen), instr_(instr) { } |
| 805 virtual void Generate() { | 824 virtual void Generate() { |
| 806 codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD); | 825 codegen()->DoDeferredBinaryOpStub(instr_, Token::MOD); |
| 807 } | 826 } |
| 808 private: | 827 private: |
| 809 LModI* instr_; | 828 LModI* instr_; |
| 810 }; | 829 }; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 __ b(lt, &done); | 870 __ b(lt, &done); |
| 852 // If not, reduce the left hand side by the right hand | 871 // If not, reduce the left hand side by the right hand |
| 853 // side and check again. | 872 // side and check again. |
| 854 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); | 873 if (i < kUnfolds - 1) __ sub(scratch, scratch, right); |
| 855 } | 874 } |
| 856 | 875 |
| 857 // Check for power of two on the right hand side. | 876 // Check for power of two on the right hand side. |
| 858 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub); | 877 __ JumpIfNotPowerOfTwoOrZero(right, scratch, &call_stub); |
| 859 // Perform modulo operation (scratch contains right - 1). | 878 // Perform modulo operation (scratch contains right - 1). |
| 860 __ and_(result, scratch, Operand(left)); | 879 __ and_(result, scratch, Operand(left)); |
| 880 __ b(&done); |
| 861 | 881 |
| 862 __ bind(&call_stub); | 882 __ bind(&call_stub); |
| 863 // Call the stub. The numbers in r0 and r1 have | 883 // Call the stub. The numbers in r0 and r1 have |
| 864 // to be tagged to Smis. If that is not possible, deoptimize. | 884 // to be tagged to Smis. If that is not possible, deoptimize. |
| 865 DeferredModI* deferred = new DeferredModI(this, instr); | 885 DeferredModI* deferred = new DeferredModI(this, instr); |
| 866 __ TrySmiTag(left, &deoptimize, scratch); | 886 __ TrySmiTag(left, &deoptimize, scratch); |
| 867 __ TrySmiTag(right, &deoptimize, scratch); | 887 __ TrySmiTag(right, &deoptimize, scratch); |
| 868 | 888 |
| 869 __ b(al, deferred->entry()); | 889 __ b(al, deferred->entry()); |
| 870 __ bind(deferred->exit()); | 890 __ bind(deferred->exit()); |
| (...skipping 2230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3101 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); | 3121 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); |
| 3102 if (FLAG_debug_code) { | 3122 if (FLAG_debug_code) { |
| 3103 __ AbortIfNotSmi(r0); | 3123 __ AbortIfNotSmi(r0); |
| 3104 } | 3124 } |
| 3105 __ SmiUntag(r0); | 3125 __ SmiUntag(r0); |
| 3106 __ StoreToSafepointRegisterSlot(r0, result); | 3126 __ StoreToSafepointRegisterSlot(r0, result); |
| 3107 __ PopSafepointRegisters(); | 3127 __ PopSafepointRegisters(); |
| 3108 } | 3128 } |
| 3109 | 3129 |
| 3110 | 3130 |
| 3131 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 3132 class DeferredStringCharFromCode: public LDeferredCode { |
| 3133 public: |
| 3134 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| 3135 : LDeferredCode(codegen), instr_(instr) { } |
| 3136 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
| 3137 private: |
| 3138 LStringCharFromCode* instr_; |
| 3139 }; |
| 3140 |
| 3141 DeferredStringCharFromCode* deferred = |
| 3142 new DeferredStringCharFromCode(this, instr); |
| 3143 |
| 3144 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 3145 Register char_code = ToRegister(instr->char_code()); |
| 3146 Register result = ToRegister(instr->result()); |
| 3147 ASSERT(!char_code.is(result)); |
| 3148 |
| 3149 __ cmp(char_code, Operand(String::kMaxAsciiCharCode)); |
| 3150 __ b(hi, deferred->entry()); |
| 3151 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); |
| 3152 __ add(result, result, Operand(char_code, LSL, kPointerSizeLog2)); |
| 3153 __ ldr(result, FieldMemOperand(result, FixedArray::kHeaderSize)); |
| 3154 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 3155 __ cmp(result, ip); |
| 3156 __ b(eq, deferred->entry()); |
| 3157 __ bind(deferred->exit()); |
| 3158 } |
| 3159 |
| 3160 |
| 3161 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
| 3162 Register char_code = ToRegister(instr->char_code()); |
| 3163 Register result = ToRegister(instr->result()); |
| 3164 |
| 3165 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3166 // result register contain a valid pointer because it is already |
| 3167 // contained in the register pointer map. |
| 3168 __ mov(result, Operand(0)); |
| 3169 |
| 3170 __ PushSafepointRegisters(); |
| 3171 __ SmiTag(char_code); |
| 3172 __ push(char_code); |
| 3173 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode); |
| 3174 RecordSafepointWithRegisters( |
| 3175 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex); |
| 3176 __ StoreToSafepointRegisterSlot(r0, result); |
| 3177 __ PopSafepointRegisters(); |
| 3178 } |
| 3179 |
| 3180 |
| 3111 void LCodeGen::DoStringLength(LStringLength* instr) { | 3181 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 3112 Register string = ToRegister(instr->InputAt(0)); | 3182 Register string = ToRegister(instr->InputAt(0)); |
| 3113 Register result = ToRegister(instr->result()); | 3183 Register result = ToRegister(instr->result()); |
| 3114 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); | 3184 __ ldr(result, FieldMemOperand(string, String::kLengthOffset)); |
| 3115 } | 3185 } |
| 3116 | 3186 |
| 3117 | 3187 |
| 3118 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3188 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 3119 LOperand* input = instr->InputAt(0); | 3189 LOperand* input = instr->InputAt(0); |
| 3120 ASSERT(input->IsRegister() || input->IsStackSlot()); | 3190 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3313 public: | 3383 public: |
| 3314 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 3384 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 3315 : LDeferredCode(codegen), instr_(instr) { } | 3385 : LDeferredCode(codegen), instr_(instr) { } |
| 3316 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 3386 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 3317 private: | 3387 private: |
| 3318 LTaggedToI* instr_; | 3388 LTaggedToI* instr_; |
| 3319 }; | 3389 }; |
| 3320 | 3390 |
| 3321 | 3391 |
| 3322 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3392 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 3393 Register input_reg = ToRegister(instr->InputAt(0)); |
| 3394 Register scratch1 = scratch0(); |
| 3395 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 3396 DwVfpRegister double_scratch = double_scratch0(); |
| 3397 SwVfpRegister single_scratch = double_scratch.low(); |
| 3398 |
| 3399 ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); |
| 3400 ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); |
| 3401 |
| 3323 Label done; | 3402 Label done; |
| 3324 Register input_reg = ToRegister(instr->InputAt(0)); | |
| 3325 Register scratch = scratch0(); | |
| 3326 DoubleRegister dbl_scratch = d0; | |
| 3327 SwVfpRegister flt_scratch = s0; | |
| 3328 DoubleRegister dbl_tmp = ToDoubleRegister(instr->TempAt(0)); | |
| 3329 | 3403 |
| 3330 // Heap number map check. | 3404 // Heap number map check. |
| 3331 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 3405 __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 3332 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3406 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 3333 __ cmp(scratch, Operand(ip)); | 3407 __ cmp(scratch1, Operand(ip)); |
| 3334 | 3408 |
| 3335 if (instr->truncating()) { | 3409 if (instr->truncating()) { |
| 3410 Register scratch3 = ToRegister(instr->TempAt(1)); |
| 3411 DwVfpRegister double_scratch2 = ToDoubleRegister(instr->TempAt(2)); |
| 3412 ASSERT(!scratch3.is(input_reg) && |
| 3413 !scratch3.is(scratch1) && |
| 3414 !scratch3.is(scratch2)); |
| 3415 // Performs a truncating conversion of a floating point number as used by |
| 3416 // the JS bitwise operations. |
| 3336 Label heap_number; | 3417 Label heap_number; |
| 3337 __ b(eq, &heap_number); | 3418 __ b(eq, &heap_number); |
| 3338 // Check for undefined. Undefined is converted to zero for truncating | 3419 // Check for undefined. Undefined is converted to zero for truncating |
| 3339 // conversions. | 3420 // conversions. |
| 3340 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 3421 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 3341 __ cmp(input_reg, Operand(ip)); | 3422 __ cmp(input_reg, Operand(ip)); |
| 3342 DeoptimizeIf(ne, instr->environment()); | 3423 DeoptimizeIf(ne, instr->environment()); |
| 3343 __ mov(input_reg, Operand(0)); | 3424 __ mov(input_reg, Operand(0)); |
| 3344 __ b(&done); | 3425 __ b(&done); |
| 3345 | 3426 |
| 3346 __ bind(&heap_number); | 3427 __ bind(&heap_number); |
| 3347 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 3428 __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); |
| 3348 __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset); | 3429 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); |
| 3349 __ vcmp(dbl_tmp, 0.0); // Sets overflow bit in FPSCR flags if NaN. | 3430 |
| 3350 __ vcvt_s32_f64(flt_scratch, dbl_tmp); | 3431 __ EmitECMATruncate(input_reg, |
| 3351 __ vmov(input_reg, flt_scratch); // 32-bit result of conversion. | 3432 double_scratch2, |
| 3352 __ vmrs(pc); // Move vector status bits to normal status bits. | 3433 single_scratch, |
| 3353 // Overflow bit is set if dbl_tmp is Nan. | 3434 scratch1, |
| 3354 __ cmn(input_reg, Operand(1), vc); // 0x7fffffff + 1 -> overflow. | 3435 scratch2, |
| 3355 __ cmp(input_reg, Operand(1), vc); // 0x80000000 - 1 -> overflow. | 3436 scratch3); |
| 3356 DeoptimizeIf(vs, instr->environment()); // Saturation may have occured. | |
| 3357 | 3437 |
| 3358 } else { | 3438 } else { |
| 3439 CpuFeatures::Scope scope(VFP3); |
| 3359 // Deoptimize if we don't have a heap number. | 3440 // Deoptimize if we don't have a heap number. |
| 3360 DeoptimizeIf(ne, instr->environment()); | 3441 DeoptimizeIf(ne, instr->environment()); |
| 3361 | 3442 |
| 3362 __ sub(ip, input_reg, Operand(kHeapObjectTag)); | 3443 __ sub(ip, input_reg, Operand(kHeapObjectTag)); |
| 3363 __ vldr(dbl_tmp, ip, HeapNumber::kValueOffset); | 3444 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); |
| 3364 __ vcvt_s32_f64(flt_scratch, dbl_tmp); | 3445 __ EmitVFPTruncate(kRoundToZero, |
| 3365 __ vmov(input_reg, flt_scratch); // 32-bit result of conversion. | 3446 single_scratch, |
| 3366 // Non-truncating conversion means that we cannot lose bits, so we convert | 3447 double_scratch, |
| 3367 // back to check; note that using non-overlapping s and d regs would be | 3448 scratch1, |
| 3368 // slightly faster. | 3449 scratch2, |
| 3369 __ vcvt_f64_s32(dbl_scratch, flt_scratch); | 3450 kCheckForInexactConversion); |
| 3370 __ VFPCompareAndSetFlags(dbl_scratch, dbl_tmp); | 3451 DeoptimizeIf(ne, instr->environment()); |
| 3371 DeoptimizeIf(ne, instr->environment()); // Not equal or unordered. | 3452 // Load the result. |
| 3453 __ vmov(input_reg, single_scratch); |
| 3454 |
| 3372 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3455 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3373 __ tst(input_reg, Operand(input_reg)); | 3456 __ cmp(input_reg, Operand(0)); |
| 3374 __ b(ne, &done); | 3457 __ b(ne, &done); |
| 3375 __ vmov(lr, ip, dbl_tmp); | 3458 __ vmov(scratch1, double_scratch.high()); |
| 3376 __ tst(ip, Operand(1 << 31)); // Test sign bit. | 3459 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
| 3377 DeoptimizeIf(ne, instr->environment()); | 3460 DeoptimizeIf(ne, instr->environment()); |
| 3378 } | 3461 } |
| 3379 } | 3462 } |
| 3380 __ bind(&done); | 3463 __ bind(&done); |
| 3381 } | 3464 } |
| 3382 | 3465 |
| 3383 | 3466 |
| 3384 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 3467 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 3385 LOperand* input = instr->InputAt(0); | 3468 LOperand* input = instr->InputAt(0); |
| 3386 ASSERT(input->IsRegister()); | 3469 ASSERT(input->IsRegister()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3408 ASSERT(result->IsDoubleRegister()); | 3491 ASSERT(result->IsDoubleRegister()); |
| 3409 | 3492 |
| 3410 Register input_reg = ToRegister(input); | 3493 Register input_reg = ToRegister(input); |
| 3411 DoubleRegister result_reg = ToDoubleRegister(result); | 3494 DoubleRegister result_reg = ToDoubleRegister(result); |
| 3412 | 3495 |
| 3413 EmitNumberUntagD(input_reg, result_reg, instr->environment()); | 3496 EmitNumberUntagD(input_reg, result_reg, instr->environment()); |
| 3414 } | 3497 } |
| 3415 | 3498 |
| 3416 | 3499 |
| 3417 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3500 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 3418 LOperand* input = instr->InputAt(0); | 3501 Register result_reg = ToRegister(instr->result()); |
| 3419 ASSERT(input->IsDoubleRegister()); | |
| 3420 LOperand* result = instr->result(); | |
| 3421 ASSERT(result->IsRegister()); | |
| 3422 | |
| 3423 DoubleRegister double_input = ToDoubleRegister(input); | |
| 3424 Register result_reg = ToRegister(result); | |
| 3425 SwVfpRegister single_scratch = double_scratch0().low(); | |
| 3426 Register scratch1 = scratch0(); | 3502 Register scratch1 = scratch0(); |
| 3427 Register scratch2 = ToRegister(instr->TempAt(0)); | 3503 Register scratch2 = ToRegister(instr->TempAt(0)); |
| 3504 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); |
| 3505 DwVfpRegister double_scratch = double_scratch0(); |
| 3506 SwVfpRegister single_scratch = double_scratch0().low(); |
| 3428 | 3507 |
| 3429 __ EmitVFPTruncate(kRoundToZero, | 3508 Label done; |
| 3430 single_scratch, | |
| 3431 double_input, | |
| 3432 scratch1, | |
| 3433 scratch2); | |
| 3434 | 3509 |
| 3435 // Deoptimize if we had a vfp invalid exception. | 3510 if (instr->truncating()) { |
| 3436 DeoptimizeIf(ne, instr->environment()); | 3511 Register scratch3 = ToRegister(instr->TempAt(1)); |
| 3437 | 3512 __ EmitECMATruncate(result_reg, |
| 3438 // Retrieve the result. | 3513 double_input, |
| 3439 __ vmov(result_reg, single_scratch); | 3514 single_scratch, |
| 3440 | 3515 scratch1, |
| 3441 if (!instr->truncating()) { | 3516 scratch2, |
| 3442 // Convert result back to double and compare with input | 3517 scratch3); |
| 3443 // to check if the conversion was exact. | 3518 } else { |
| 3444 __ vmov(single_scratch, result_reg); | 3519 VFPRoundingMode rounding_mode = kRoundToMinusInf; |
| 3445 __ vcvt_f64_s32(double_scratch0(), single_scratch); | 3520 __ EmitVFPTruncate(rounding_mode, |
| 3446 __ VFPCompareAndSetFlags(double_scratch0(), double_input); | 3521 single_scratch, |
| 3522 double_input, |
| 3523 scratch1, |
| 3524 scratch2, |
| 3525 kCheckForInexactConversion); |
| 3526 // Deoptimize if we had a vfp invalid exception, |
| 3527 // including inexact operation. |
| 3447 DeoptimizeIf(ne, instr->environment()); | 3528 DeoptimizeIf(ne, instr->environment()); |
| 3448 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3529 // Retrieve the result. |
| 3449 Label done; | 3530 __ vmov(result_reg, single_scratch); |
| 3450 __ cmp(result_reg, Operand(0)); | |
| 3451 __ b(ne, &done); | |
| 3452 // Check for -0. | |
| 3453 __ vmov(scratch1, double_input.high()); | |
| 3454 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | |
| 3455 DeoptimizeIf(ne, instr->environment()); | |
| 3456 | |
| 3457 __ bind(&done); | |
| 3458 } | |
| 3459 } | 3531 } |
| 3532 __ bind(&done); |
| 3460 } | 3533 } |
| 3461 | 3534 |
| 3462 | 3535 |
| 3463 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3536 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 3464 LOperand* input = instr->InputAt(0); | 3537 LOperand* input = instr->InputAt(0); |
| 3465 ASSERT(input->IsRegister()); | 3538 ASSERT(input->IsRegister()); |
| 3466 __ tst(ToRegister(input), Operand(kSmiTagMask)); | 3539 __ tst(ToRegister(input), Operand(kSmiTagMask)); |
| 3467 DeoptimizeIf(instr->condition(), instr->environment()); | 3540 DeoptimizeIf(instr->condition(), instr->environment()); |
| 3468 } | 3541 } |
| 3469 | 3542 |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3887 ASSERT(!environment->HasBeenRegistered()); | 3960 ASSERT(!environment->HasBeenRegistered()); |
| 3888 RegisterEnvironmentForDeoptimization(environment); | 3961 RegisterEnvironmentForDeoptimization(environment); |
| 3889 ASSERT(osr_pc_offset_ == -1); | 3962 ASSERT(osr_pc_offset_ == -1); |
| 3890 osr_pc_offset_ = masm()->pc_offset(); | 3963 osr_pc_offset_ = masm()->pc_offset(); |
| 3891 } | 3964 } |
| 3892 | 3965 |
| 3893 | 3966 |
| 3894 #undef __ | 3967 #undef __ |
| 3895 | 3968 |
| 3896 } } // namespace v8::internal | 3969 } } // namespace v8::internal |
| OLD | NEW |