OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "arm64/lithium-codegen-arm64.h" | 7 #include "arm64/lithium-codegen-arm64.h" |
8 #include "arm64/lithium-gap-resolver-arm64.h" | 8 #include "arm64/lithium-gap-resolver-arm64.h" |
9 #include "code-stubs.h" | 9 #include "code-stubs.h" |
10 #include "stub-cache.h" | 10 #include "stub-cache.h" |
(...skipping 2272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2283 | 2283 |
2284 __ Bind(&done); | 2284 __ Bind(&done); |
2285 } | 2285 } |
2286 | 2286 |
2287 | 2287 |
2288 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { | 2288 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { |
2289 DoubleRegister value_reg = ToDoubleRegister(instr->value()); | 2289 DoubleRegister value_reg = ToDoubleRegister(instr->value()); |
2290 Register result_reg = ToRegister(instr->result()); | 2290 Register result_reg = ToRegister(instr->result()); |
2291 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { | 2291 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { |
2292 __ Fmov(result_reg, value_reg); | 2292 __ Fmov(result_reg, value_reg); |
2293 __ Mov(result_reg, Operand(result_reg, LSR, 32)); | 2293 __ Lsr(result_reg, result_reg, 32); |
2294 } else { | 2294 } else { |
2295 __ Fmov(result_reg.W(), value_reg.S()); | 2295 __ Fmov(result_reg.W(), value_reg.S()); |
2296 } | 2296 } |
2297 } | 2297 } |
2298 | 2298 |
2299 | 2299 |
2300 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { | 2300 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { |
2301 Register hi_reg = ToRegister(instr->hi()); | 2301 Register hi_reg = ToRegister(instr->hi()); |
2302 Register lo_reg = ToRegister(instr->lo()); | 2302 Register lo_reg = ToRegister(instr->lo()); |
2303 Register temp = ToRegister(instr->temp()); | |
2304 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 2303 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
2305 | 2304 |
2306 __ And(temp, lo_reg, Operand(0xffffffff)); | 2305 // Insert the least significant 32 bits of hi_reg into the most significant |
2307 __ Orr(temp, temp, Operand(hi_reg, LSL, 32)); | 2306 // 32 bits of lo_reg, and move to a floating point register. |
2308 __ Fmov(result_reg, temp); | 2307 __ Bfi(lo_reg, hi_reg, 32, 32); |
| 2308 __ Fmov(result_reg, lo_reg); |
2309 } | 2309 } |
2310 | 2310 |
2311 | 2311 |
2312 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2312 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2313 Handle<String> class_name = instr->hydrogen()->class_name(); | 2313 Handle<String> class_name = instr->hydrogen()->class_name(); |
2314 Label* true_label = instr->TrueLabel(chunk_); | 2314 Label* true_label = instr->TrueLabel(chunk_); |
2315 Label* false_label = instr->FalseLabel(chunk_); | 2315 Label* false_label = instr->FalseLabel(chunk_); |
2316 Register input = ToRegister(instr->value()); | 2316 Register input = ToRegister(instr->value()); |
2317 Register scratch1 = ToRegister(instr->temp1()); | 2317 Register scratch1 = ToRegister(instr->temp1()); |
2318 Register scratch2 = ToRegister(instr->temp2()); | 2318 Register scratch2 = ToRegister(instr->temp2()); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2408 ASSERT(!rep.IsInteger32()); | 2408 ASSERT(!rep.IsInteger32()); |
2409 Register scratch = ToRegister(instr->temp()); | 2409 Register scratch = ToRegister(instr->temp()); |
2410 | 2410 |
2411 if (rep.IsDouble()) { | 2411 if (rep.IsDouble()) { |
2412 __ JumpIfMinusZero(ToDoubleRegister(instr->value()), | 2412 __ JumpIfMinusZero(ToDoubleRegister(instr->value()), |
2413 instr->TrueLabel(chunk())); | 2413 instr->TrueLabel(chunk())); |
2414 } else { | 2414 } else { |
2415 Register value = ToRegister(instr->value()); | 2415 Register value = ToRegister(instr->value()); |
2416 __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex, | 2416 __ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex, |
2417 instr->FalseLabel(chunk()), DO_SMI_CHECK); | 2417 instr->FalseLabel(chunk()), DO_SMI_CHECK); |
2418 __ Ldr(double_scratch(), FieldMemOperand(value, HeapNumber::kValueOffset)); | 2418 __ Ldr(scratch, FieldMemOperand(value, HeapNumber::kValueOffset)); |
2419 __ JumpIfMinusZero(double_scratch(), instr->TrueLabel(chunk())); | 2419 __ JumpIfMinusZero(scratch, instr->TrueLabel(chunk())); |
2420 } | 2420 } |
2421 EmitGoto(instr->FalseDestination(chunk())); | 2421 EmitGoto(instr->FalseDestination(chunk())); |
2422 } | 2422 } |
2423 | 2423 |
2424 | 2424 |
2425 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { | 2425 void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) { |
2426 LOperand* left = instr->left(); | 2426 LOperand* left = instr->left(); |
2427 LOperand* right = instr->right(); | 2427 LOperand* right = instr->right(); |
2428 Condition cond = TokenToCondition(instr->op(), false); | 2428 Condition cond = TokenToCondition(instr->op(), false); |
2429 | 2429 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2517 ASSERT(instr->IsMarkedAsCall()); | 2517 ASSERT(instr->IsMarkedAsCall()); |
2518 __ LoadTrueFalseRoots(x1, x2); | 2518 __ LoadTrueFalseRoots(x1, x2); |
2519 __ Cmp(x0, 0); | 2519 __ Cmp(x0, 0); |
2520 __ Csel(ToRegister(instr->result()), x1, x2, cond); | 2520 __ Csel(ToRegister(instr->result()), x1, x2, cond); |
2521 } | 2521 } |
2522 | 2522 |
2523 | 2523 |
2524 void LCodeGen::DoConstantD(LConstantD* instr) { | 2524 void LCodeGen::DoConstantD(LConstantD* instr) { |
2525 ASSERT(instr->result()->IsDoubleRegister()); | 2525 ASSERT(instr->result()->IsDoubleRegister()); |
2526 DoubleRegister result = ToDoubleRegister(instr->result()); | 2526 DoubleRegister result = ToDoubleRegister(instr->result()); |
2527 __ Fmov(result, instr->value()); | 2527 if (instr->value() == 0) { |
| 2528 if (copysign(1.0, instr->value()) == 1.0) { |
| 2529 __ Fmov(result, fp_zero); |
| 2530 } else { |
| 2531 __ Fneg(result, fp_zero); |
| 2532 } |
| 2533 } else { |
| 2534 __ Fmov(result, instr->value()); |
| 2535 } |
2528 } | 2536 } |
2529 | 2537 |
2530 | 2538 |
2531 void LCodeGen::DoConstantE(LConstantE* instr) { | 2539 void LCodeGen::DoConstantE(LConstantE* instr) { |
2532 __ Mov(ToRegister(instr->result()), Operand(instr->value())); | 2540 __ Mov(ToRegister(instr->result()), Operand(instr->value())); |
2533 } | 2541 } |
2534 | 2542 |
2535 | 2543 |
2536 void LCodeGen::DoConstantI(LConstantI* instr) { | 2544 void LCodeGen::DoConstantI(LConstantI* instr) { |
2537 ASSERT(is_int32(instr->value())); | 2545 ASSERT(is_int32(instr->value())); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2656 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 2664 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
2657 Register dividend = ToRegister32(instr->dividend()); | 2665 Register dividend = ToRegister32(instr->dividend()); |
2658 int32_t divisor = instr->divisor(); | 2666 int32_t divisor = instr->divisor(); |
2659 Register result = ToRegister32(instr->result()); | 2667 Register result = ToRegister32(instr->result()); |
2660 ASSERT(divisor == kMinInt || IsPowerOf2(Abs(divisor))); | 2668 ASSERT(divisor == kMinInt || IsPowerOf2(Abs(divisor))); |
2661 ASSERT(!result.is(dividend)); | 2669 ASSERT(!result.is(dividend)); |
2662 | 2670 |
2663 // Check for (0 / -x) that will produce negative zero. | 2671 // Check for (0 / -x) that will produce negative zero. |
2664 HDiv* hdiv = instr->hydrogen(); | 2672 HDiv* hdiv = instr->hydrogen(); |
2665 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 2673 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
2666 __ Cmp(dividend, 0); | 2674 DeoptimizeIfZero(dividend, instr->environment()); |
2667 DeoptimizeIf(eq, instr->environment()); | |
2668 } | 2675 } |
2669 // Check for (kMinInt / -1). | 2676 // Check for (kMinInt / -1). |
2670 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 2677 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
2671 __ Cmp(dividend, kMinInt); | 2678 // Test dividend for kMinInt by subtracting one (cmp) and checking for |
2672 DeoptimizeIf(eq, instr->environment()); | 2679 // overflow. |
| 2680 __ Cmp(dividend, 1); |
| 2681 DeoptimizeIf(vs, instr->environment()); |
2673 } | 2682 } |
2674 // Deoptimize if remainder will not be 0. | 2683 // Deoptimize if remainder will not be 0. |
2675 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 2684 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
2676 divisor != 1 && divisor != -1) { | 2685 divisor != 1 && divisor != -1) { |
2677 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 2686 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
2678 __ Tst(dividend, mask); | 2687 __ Tst(dividend, mask); |
2679 DeoptimizeIf(ne, instr->environment()); | 2688 DeoptimizeIf(ne, instr->environment()); |
2680 } | 2689 } |
2681 | 2690 |
2682 if (divisor == -1) { // Nice shortcut, not needed for correctness. | 2691 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3915 ASSERT(!AreAliased(dividend, result)); | 3924 ASSERT(!AreAliased(dividend, result)); |
3916 | 3925 |
3917 if (divisor == 0) { | 3926 if (divisor == 0) { |
3918 Deoptimize(instr->environment()); | 3927 Deoptimize(instr->environment()); |
3919 return; | 3928 return; |
3920 } | 3929 } |
3921 | 3930 |
3922 // Check for (0 / -x) that will produce negative zero. | 3931 // Check for (0 / -x) that will produce negative zero. |
3923 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 3932 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
3924 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 3933 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
3925 __ Cmp(dividend, 0); | 3934 DeoptimizeIfZero(dividend, instr->environment()); |
3926 DeoptimizeIf(eq, instr->environment()); | |
3927 } | 3935 } |
3928 | 3936 |
3929 // Easy case: We need no dynamic check for the dividend and the flooring | 3937 // Easy case: We need no dynamic check for the dividend and the flooring |
3930 // division is the same as the truncating division. | 3938 // division is the same as the truncating division. |
3931 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 3939 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
3932 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 3940 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
3933 __ TruncatingDiv(result, dividend, Abs(divisor)); | 3941 __ TruncatingDiv(result, dividend, Abs(divisor)); |
3934 if (divisor < 0) __ Neg(result, result); | 3942 if (divisor < 0) __ Neg(result, result); |
3935 return; | 3943 return; |
3936 } | 3944 } |
3937 | 3945 |
3938 // In the general case we may need to adjust before and after the truncating | 3946 // In the general case we may need to adjust before and after the truncating |
3939 // division to get a flooring division. | 3947 // division to get a flooring division. |
3940 Register temp = ToRegister32(instr->temp()); | 3948 Register temp = ToRegister32(instr->temp()); |
3941 ASSERT(!AreAliased(temp, dividend, result)); | 3949 ASSERT(!AreAliased(temp, dividend, result)); |
3942 Label needs_adjustment, done; | 3950 Label needs_adjustment, done; |
3943 __ Cmp(dividend, 0); | 3951 __ Cmp(dividend, 0); |
3944 __ B(divisor > 0 ? lt : gt, &needs_adjustment); | 3952 __ B(divisor > 0 ? lt : gt, &needs_adjustment); |
3945 __ TruncatingDiv(result, dividend, Abs(divisor)); | 3953 __ TruncatingDiv(result, dividend, Abs(divisor)); |
3946 if (divisor < 0) __ Neg(result, result); | 3954 if (divisor < 0) __ Neg(result, result); |
3947 __ B(&done); | 3955 __ B(&done); |
3948 __ bind(&needs_adjustment); | 3956 __ Bind(&needs_adjustment); |
3949 __ Add(temp, dividend, Operand(divisor > 0 ? 1 : -1)); | 3957 __ Add(temp, dividend, Operand(divisor > 0 ? 1 : -1)); |
3950 __ TruncatingDiv(result, temp, Abs(divisor)); | 3958 __ TruncatingDiv(result, temp, Abs(divisor)); |
3951 if (divisor < 0) __ Neg(result, result); | 3959 if (divisor < 0) __ Neg(result, result); |
3952 __ Sub(result, result, Operand(1)); | 3960 __ Sub(result, result, Operand(1)); |
3953 __ bind(&done); | 3961 __ Bind(&done); |
3954 } | 3962 } |
3955 | 3963 |
3956 | 3964 |
3957 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. | 3965 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. |
3958 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { | 3966 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
3959 Register dividend = ToRegister32(instr->dividend()); | 3967 Register dividend = ToRegister32(instr->dividend()); |
3960 Register divisor = ToRegister32(instr->divisor()); | 3968 Register divisor = ToRegister32(instr->divisor()); |
3961 Register remainder = ToRegister32(instr->temp()); | 3969 Register remainder = ToRegister32(instr->temp()); |
3962 Register result = ToRegister32(instr->result()); | 3970 Register result = ToRegister32(instr->result()); |
3963 | 3971 |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4210 // Theoretically, a variation of the branch-free code for integer division by | 4218 // Theoretically, a variation of the branch-free code for integer division by |
4211 // a power of 2 (calculating the remainder via an additional multiplication | 4219 // a power of 2 (calculating the remainder via an additional multiplication |
4212 // (which gets simplified to an 'and') and subtraction) should be faster, and | 4220 // (which gets simplified to an 'and') and subtraction) should be faster, and |
4213 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to | 4221 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to |
4214 // indicate that positive dividends are heavily favored, so the branching | 4222 // indicate that positive dividends are heavily favored, so the branching |
4215 // version performs better. | 4223 // version performs better. |
4216 HMod* hmod = instr->hydrogen(); | 4224 HMod* hmod = instr->hydrogen(); |
4217 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 4225 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
4218 Label dividend_is_not_negative, done; | 4226 Label dividend_is_not_negative, done; |
4219 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 4227 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
4220 __ Cmp(dividend, 0); | 4228 __ Tbz(dividend, kWSignBit, ÷nd_is_not_negative); |
4221 __ B(pl, ÷nd_is_not_negative); | |
4222 // Note that this is correct even for kMinInt operands. | 4229 // Note that this is correct even for kMinInt operands. |
4223 __ Neg(dividend, dividend); | 4230 __ Neg(dividend, dividend); |
4224 __ And(dividend, dividend, mask); | 4231 __ And(dividend, dividend, mask); |
4225 __ Negs(dividend, dividend); | 4232 __ Negs(dividend, dividend); |
4226 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4233 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
4227 DeoptimizeIf(eq, instr->environment()); | 4234 DeoptimizeIf(eq, instr->environment()); |
4228 } | 4235 } |
4229 __ B(&done); | 4236 __ B(&done); |
4230 } | 4237 } |
4231 | 4238 |
(...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6001 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 6008 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
6002 // Index is equal to negated out of object property index plus 1. | 6009 // Index is equal to negated out of object property index plus 1. |
6003 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 6010 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
6004 __ Ldr(result, FieldMemOperand(result, | 6011 __ Ldr(result, FieldMemOperand(result, |
6005 FixedArray::kHeaderSize - kPointerSize)); | 6012 FixedArray::kHeaderSize - kPointerSize)); |
6006 __ Bind(deferred->exit()); | 6013 __ Bind(deferred->exit()); |
6007 __ Bind(&done); | 6014 __ Bind(&done); |
6008 } | 6015 } |
6009 | 6016 |
6010 } } // namespace v8::internal | 6017 } } // namespace v8::internal |
OLD | NEW |