OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1407 __ cmp(right, Operand::Zero()); | 1407 __ cmp(right, Operand::Zero()); |
1408 } | 1408 } |
1409 __ b(pl, &positive); | 1409 __ b(pl, &positive); |
1410 __ cmp(left, Operand::Zero()); | 1410 __ cmp(left, Operand::Zero()); |
1411 DeoptimizeIf(eq, instr->environment()); | 1411 DeoptimizeIf(eq, instr->environment()); |
1412 __ bind(&positive); | 1412 __ bind(&positive); |
1413 } | 1413 } |
1414 | 1414 |
1415 // Check for (kMinInt / -1). | 1415 // Check for (kMinInt / -1). |
1416 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1416 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1417 Label left_not_min_int; | |
1418 __ cmp(left, Operand(kMinInt)); | 1417 __ cmp(left, Operand(kMinInt)); |
1419 __ b(ne, &left_not_min_int); | 1418 __ cmp(right, Operand(-1), eq); |
Sven Panne
2013/12/12 13:43:23
Is conditional non-execution of 2 instructions rea
Rodolph Perfetta
2013/12/13 11:31:14
conditional execution of two "simple" instructions
| |
1420 __ cmp(right, Operand(-1)); | |
1421 DeoptimizeIf(eq, instr->environment()); | 1419 DeoptimizeIf(eq, instr->environment()); |
1422 __ bind(&left_not_min_int); | |
1423 } | 1420 } |
1424 | 1421 |
1425 if (CpuFeatures::IsSupported(SUDIV)) { | 1422 if (CpuFeatures::IsSupported(SUDIV)) { |
1426 CpuFeatureScope scope(masm(), SUDIV); | 1423 CpuFeatureScope scope(masm(), SUDIV); |
1427 __ sdiv(result, left, right); | 1424 __ sdiv(result, left, right); |
1428 | 1425 |
1429 if (!instr->hydrogen()->CheckFlag( | 1426 if (!instr->hydrogen()->CheckFlag( |
1430 HInstruction::kAllUsesTruncatingToInt32)) { | 1427 HInstruction::kAllUsesTruncatingToInt32)) { |
1431 // Compute remainder and deopt if it's not zero. | 1428 // Compute remainder and deopt if it's not zero. |
1432 const Register remainder = scratch0(); | 1429 const Register remainder = scratch0(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 } else { | 1508 } else { |
1512 CpuFeatureScope scope(masm(), SUDIV); | 1509 CpuFeatureScope scope(masm(), SUDIV); |
1513 const Register right = ToRegister(instr->right()); | 1510 const Register right = ToRegister(instr->right()); |
1514 | 1511 |
1515 // Check for x / 0. | 1512 // Check for x / 0. |
1516 __ cmp(right, Operand::Zero()); | 1513 __ cmp(right, Operand::Zero()); |
1517 DeoptimizeIf(eq, instr->environment()); | 1514 DeoptimizeIf(eq, instr->environment()); |
1518 | 1515 |
1519 // Check for (kMinInt / -1). | 1516 // Check for (kMinInt / -1). |
1520 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1517 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1521 Label left_not_min_int; | |
1522 __ cmp(left, Operand(kMinInt)); | 1518 __ cmp(left, Operand(kMinInt)); |
1523 __ b(ne, &left_not_min_int); | 1519 __ cmp(right, Operand(-1), eq); |
Sven Panne
2013/12/12 13:43:23
Same here...
| |
1524 __ cmp(right, Operand(-1)); | |
1525 DeoptimizeIf(eq, instr->environment()); | 1520 DeoptimizeIf(eq, instr->environment()); |
1526 __ bind(&left_not_min_int); | |
1527 } | 1521 } |
1528 | 1522 |
1529 // Check for (0 / -x) that will produce negative zero. | 1523 // Check for (0 / -x) that will produce negative zero. |
1530 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1524 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1531 __ cmp(right, Operand::Zero()); | 1525 __ cmp(right, Operand::Zero()); |
1532 __ cmp(left, Operand::Zero(), mi); | 1526 __ cmp(left, Operand::Zero(), mi); |
1533 // "right" can't be null because the code would have already been | 1527 // "right" can't be null because the code would have already been |
1534 // deoptimized. The Z flag is set only if (right < 0) and (left == 0). | 1528 // deoptimized. The Z flag is set only if (right < 0) and (left == 0). |
1535 // In this case we need to deoptimize to produce a -0. | 1529 // In this case we need to deoptimize to produce a -0. |
1536 DeoptimizeIf(eq, instr->environment()); | 1530 DeoptimizeIf(eq, instr->environment()); |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1885 if (!instr->hydrogen()->value()->IsHeapObject()) { | 1879 if (!instr->hydrogen()->value()->IsHeapObject()) { |
1886 // If the object is a smi return the object. | 1880 // If the object is a smi return the object. |
1887 __ SmiTst(input); | 1881 __ SmiTst(input); |
1888 __ Move(result, input, eq); | 1882 __ Move(result, input, eq); |
1889 __ b(eq, &done); | 1883 __ b(eq, &done); |
1890 } | 1884 } |
1891 | 1885 |
1892 // If the object is not a value type, return the object. | 1886 // If the object is not a value type, return the object. |
1893 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | 1887 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); |
1894 __ Move(result, input, ne); | 1888 __ Move(result, input, ne); |
1895 __ b(ne, &done); | 1889 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset), eq); |
1896 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset)); | |
1897 | 1890 |
1898 __ bind(&done); | 1891 __ bind(&done); |
1899 } | 1892 } |
1900 | 1893 |
1901 | 1894 |
1902 void LCodeGen::DoDateField(LDateField* instr) { | 1895 void LCodeGen::DoDateField(LDateField* instr) { |
1903 Register object = ToRegister(instr->date()); | 1896 Register object = ToRegister(instr->date()); |
1904 Register result = ToRegister(instr->result()); | 1897 Register result = ToRegister(instr->result()); |
1905 Register scratch = ToRegister(instr->temp()); | 1898 Register scratch = ToRegister(instr->temp()); |
1906 Smi* index = instr->index(); | 1899 Smi* index = instr->index(); |
(...skipping 1533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3440 | 3433 |
3441 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 3434 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
3442 Register elem = ToRegister(instr->elements()); | 3435 Register elem = ToRegister(instr->elements()); |
3443 Register result = ToRegister(instr->result()); | 3436 Register result = ToRegister(instr->result()); |
3444 | 3437 |
3445 Label done; | 3438 Label done; |
3446 | 3439 |
3447 // If no arguments adaptor frame the number of arguments is fixed. | 3440 // If no arguments adaptor frame the number of arguments is fixed. |
3448 __ cmp(fp, elem); | 3441 __ cmp(fp, elem); |
3449 __ mov(result, Operand(scope()->num_parameters())); | 3442 __ mov(result, Operand(scope()->num_parameters())); |
3450 __ b(eq, &done); | |
3451 | 3443 |
3452 // Arguments adaptor frame present. Get argument length from there. | 3444 // Arguments adaptor frame present. Get argument length from there. |
3453 __ ldr(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3445 __ ldr(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset), ne); |
Sven Panne
2013/12/12 13:43:23
... and here (3 instructions now)
Rodolph Perfetta
2013/12/13 11:31:14
Here the answer would depend on the surrounding co
Benedikt Meurer
2014/01/02 06:49:28
Reverted this one.
| |
3454 __ ldr(result, | 3446 __ ldr(result, |
3455 MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3447 MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset), ne); |
3456 __ SmiUntag(result); | 3448 __ SmiUntag(result, LeaveCC, ne); |
3457 | |
3458 // Argument length is in result register. | |
3459 __ bind(&done); | |
3460 } | 3449 } |
3461 | 3450 |
3462 | 3451 |
3463 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3452 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
3464 Register receiver = ToRegister(instr->receiver()); | 3453 Register receiver = ToRegister(instr->receiver()); |
3465 Register function = ToRegister(instr->function()); | 3454 Register function = ToRegister(instr->function()); |
3466 Register result = ToRegister(instr->result()); | 3455 Register result = ToRegister(instr->result()); |
3467 Register scratch = scratch0(); | 3456 Register scratch = scratch0(); |
3468 | 3457 |
3469 // If the receiver is null or undefined, we have to pass the global | 3458 // If the receiver is null or undefined, we have to pass the global |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3871 | 3860 |
3872 | 3861 |
3873 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { | 3862 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { |
3874 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3863 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3875 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3864 DwVfpRegister result = ToDoubleRegister(instr->result()); |
3876 DwVfpRegister temp = double_scratch0(); | 3865 DwVfpRegister temp = double_scratch0(); |
3877 | 3866 |
3878 // Note that according to ECMA-262 15.8.2.13: | 3867 // Note that according to ECMA-262 15.8.2.13: |
3879 // Math.pow(-Infinity, 0.5) == Infinity | 3868 // Math.pow(-Infinity, 0.5) == Infinity |
3880 // Math.sqrt(-Infinity) == NaN | 3869 // Math.sqrt(-Infinity) == NaN |
3881 Label done; | |
3882 __ vmov(temp, -V8_INFINITY, scratch0()); | 3870 __ vmov(temp, -V8_INFINITY, scratch0()); |
3883 __ VFPCompareAndSetFlags(input, temp); | 3871 __ VFPCompareAndSetFlags(input, temp); |
3884 __ vneg(result, temp, eq); | 3872 __ vneg(result, temp, eq); |
3885 __ b(&done, eq); | |
3886 | 3873 |
3887 // Add +0 to convert -0 to +0. | 3874 // Add +0 to convert -0 to +0. |
3888 __ vadd(result, input, kDoubleRegZero); | 3875 __ vadd(result, input, kDoubleRegZero, ne); |
Sven Panne
2013/12/12 13:43:23
... and here.
Rodolph Perfetta
2013/12/13 11:31:14
vadd and especially vsqrt are complex instructions
Benedikt Meurer
2014/01/02 06:49:28
Done.
| |
3889 __ vsqrt(result, result); | 3876 __ vsqrt(result, result, ne); |
3890 __ bind(&done); | |
3891 } | 3877 } |
3892 | 3878 |
3893 | 3879 |
3894 void LCodeGen::DoPower(LPower* instr) { | 3880 void LCodeGen::DoPower(LPower* instr) { |
3895 Representation exponent_type = instr->hydrogen()->right()->representation(); | 3881 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3896 // Having marked this as a call, we can use any registers. | 3882 // Having marked this as a call, we can use any registers. |
3897 // Just make sure that the input/output registers are the expected ones. | 3883 // Just make sure that the input/output registers are the expected ones. |
3898 ASSERT(!instr->right()->IsDoubleRegister() || | 3884 ASSERT(!instr->right()->IsDoubleRegister() || |
3899 ToDoubleRegister(instr->right()).is(d1)); | 3885 ToDoubleRegister(instr->right()).is(d1)); |
3900 ASSERT(!instr->right()->IsRegister() || | 3886 ASSERT(!instr->right()->IsRegister() || |
(...skipping 1679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5580 EmitBranch(instr, eq); | 5566 EmitBranch(instr, eq); |
5581 } | 5567 } |
5582 | 5568 |
5583 | 5569 |
5584 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { | 5570 void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) { |
5585 ASSERT(!temp1.is(temp2)); | 5571 ASSERT(!temp1.is(temp2)); |
5586 // Get the frame pointer for the calling frame. | 5572 // Get the frame pointer for the calling frame. |
5587 __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 5573 __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
5588 | 5574 |
5589 // Skip the arguments adaptor frame if it exists. | 5575 // Skip the arguments adaptor frame if it exists. |
5590 Label check_frame_marker; | |
5591 __ ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset)); | 5576 __ ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset)); |
5592 __ cmp(temp2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 5577 __ cmp(temp2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
5593 __ b(ne, &check_frame_marker); | 5578 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset), eq); |
5594 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | |
5595 | 5579 |
5596 // Check the marker in the calling frame. | 5580 // Check the marker in the calling frame. |
5597 __ bind(&check_frame_marker); | |
5598 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 5581 __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); |
5599 __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 5582 __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
5600 } | 5583 } |
5601 | 5584 |
5602 | 5585 |
5603 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 5586 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { |
5604 if (info()->IsStub()) return; | 5587 if (info()->IsStub()) return; |
5605 // Ensure that we have enough space after the previous lazy-bailout | 5588 // Ensure that we have enough space after the previous lazy-bailout |
5606 // instruction for patching the code here. | 5589 // instruction for patching the code here. |
5607 int current_pc = masm()->pc_offset(); | 5590 int current_pc = masm()->pc_offset(); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5824 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5807 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5825 __ ldr(result, FieldMemOperand(scratch, | 5808 __ ldr(result, FieldMemOperand(scratch, |
5826 FixedArray::kHeaderSize - kPointerSize)); | 5809 FixedArray::kHeaderSize - kPointerSize)); |
5827 __ bind(&done); | 5810 __ bind(&done); |
5828 } | 5811 } |
5829 | 5812 |
5830 | 5813 |
5831 #undef __ | 5814 #undef __ |
5832 | 5815 |
5833 } } // namespace v8::internal | 5816 } } // namespace v8::internal |
OLD | NEW |