Chromium Code Reviews| Index: runtime/vm/intrinsifier_ia32.cc |
| =================================================================== |
| --- runtime/vm/intrinsifier_ia32.cc (revision 3812) |
| +++ runtime/vm/intrinsifier_ia32.cc (working copy) |
| @@ -64,6 +64,8 @@ |
| V(Double, toDouble, Double_toDouble) \ |
| V(Double, mulFromInteger, Double_mulFromInteger) \ |
| V(Double, Double.fromInteger, Double_fromInteger) \ |
| + V(Double, isNaN, Double_isNaN) \ |
| + V(Double, isNegative, Double_isNegative) \ |
| V(ObjectArray, ObjectArray., ObjectArray_Allocate) \ |
| V(ObjectArray, get:length, Array_getLength) \ |
| V(ObjectArray, [], Array_getIndexed) \ |
| @@ -74,6 +76,8 @@ |
| V(ImmutableArray, [], Array_getIndexed) \ |
| V(ImmutableArray, get:length, Array_getLength) \ |
| V(Math, sqrt, Math_sqrt) \ |
| + V(Math, sin, Math_sin) \ |
| + V(Math, cos, Math_cos) \ |
| V(Object, ==, Object_equal) \ |
| V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \ |
| V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \ |
| @@ -859,6 +863,51 @@ |
| } |
| +static bool Double_isNaN(Assembler* assembler) { |
| + const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| + const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| + Label is_true; |
| + __ movl(EAX, Address(ESP, +1 * kWordSize)); |
| + __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
| + __ comisd(XMM0, XMM0); |
| + __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; |
| + __ LoadObject(EAX, bool_false); |
| + __ ret(); |
| + __ Bind(&is_true); |
| + __ LoadObject(EAX, bool_true); |
| + __ ret(); |
| + return true; // Method is complete, no slow case. |
| +} |
| + |
| + |
| +static bool Double_isNegative(Assembler* assembler) { |
| + const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| + const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| + Label is_false, is_true, is_zero, is_nan; |
| + __ movl(EAX, Address(ESP, +1 * kWordSize)); |
| + __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); |
| + __ xorps(XMM1, XMM1); // 0.0 -> XMM1. |
| + __ comisd(XMM0, XMM1); |
| + __ j(PARITY_EVEN, &is_nan, Assembler::kNearJump); // NaN -> false. |
| + __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. |
| + __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. |
| + __ Bind(&is_true); |
| + __ LoadObject(EAX, bool_true); |
| + __ ret(); |
| + __ Bind(&is_false); |
| + __ Bind(&is_nan); |
|
siva
2012/02/02 00:04:26
Why do you have two labels pointing to the same lo
|
| + __ LoadObject(EAX, bool_false); |
| + __ ret(); |
| + __ Bind(&is_zero); |
| + // Check for negative zero (get the sign bit). |
| + __ movmskpd(EAX, XMM0); |
| + __ testl(EAX, Immediate(1)); |
| + __ j(NOT_ZERO, &is_true, Assembler::kNearJump); |
| + __ jmp(&is_false, Assembler::kNearJump); |
| + return true; // Method is complete, no slow case. |
| +} |
| + |
| + |
| // Argument type is not known |
| static bool Math_sqrt(Assembler* assembler) { |
| Label fall_through, is_smi, double_op; |
| @@ -886,6 +935,59 @@ |
| } |
| +enum TrigonometricFunctions { |
| + kSine, |
| + kCosine, |
| +}; |
| + |
| + |
| +static bool EmitTrigonometric(Assembler* assembler, |
| + TrigonometricFunctions kind) { |
| + Label fall_through, is_smi, double_op; |
| + TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); |
| + // Argument is double and is in EAX. |
| + __ fldl(FieldAddress(EAX, Double::value_offset())); |
| + __ Bind(&double_op); |
| + switch (kind) { |
| + case kSine: __ fsin(); break; |
| + case kCosine: __ fcos(); break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + const Class& double_class = Class::ZoneHandle( |
| + Isolate::Current()->object_store()->double_class()); |
| + __ LoadObject(EBX, double_class); |
| + AssemblerMacros::TryAllocate(assembler, |
| + double_class, |
| + EBX, // Class register. |
| + &fall_through, |
| + EAX); // Result register. |
| + __ fstpl(FieldAddress(EAX, Double::value_offset())); |
| + __ ret(); |
| + |
| + __ Bind(&is_smi); // smi -> double. |
| + __ SmiUntag(EAX); |
| + __ pushl(EAX); |
| + __ filds(Address(ESP, 0)); |
| + __ popl(EAX); |
| + __ jmp(&double_op); |
| + |
| + __ Bind(&fall_through); |
| +} |
| + |
| + |
| +static bool Math_sin(Assembler* assembler) { |
| + EmitTrigonometric(assembler, kSine); |
| + return false; // Compile method for slow case. |
| +} |
| + |
| + |
| +static bool Math_cos(Assembler* assembler) { |
| + EmitTrigonometric(assembler, kCosine); |
| + return false; // Compile method for slow case. |
| +} |
| + |
| + |
| // Identity comparison. |
| static bool Object_equal(Assembler* assembler) { |
| Label is_true; |