Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(838)

Unified Diff: runtime/vm/intrinsifier_arm.cc

Issue 292433008: Allows unboxed doubles to be disabled. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/object.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intrinsifier_arm.cc
===================================================================
--- runtime/vm/intrinsifier_arm.cc (revision 36258)
+++ runtime/vm/intrinsifier_arm.cc (working copy)
@@ -978,229 +978,245 @@
// returns false. Any non-double arg1 causes control flow to fall through to the
// slow case (compiled method body).
static void CompareDoubles(Assembler* assembler, Condition true_condition) {
- Label fall_through, is_smi, double_op;
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label fall_through, is_smi, double_op;
- TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
- // Both arguments are double, right operand is in R0.
+ TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
+ // Both arguments are double, right operand is in R0.
- __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
- __ Bind(&double_op);
- __ ldr(R0, Address(SP, 1 * kWordSize)); // Left argument.
- __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
+ __ Bind(&double_op);
+ __ ldr(R0, Address(SP, 1 * kWordSize)); // Left argument.
+ __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ vcmpd(D0, D1);
- __ vmstat();
- __ LoadObject(R0, Bool::False());
- // Return false if D0 or D1 was NaN before checking true condition.
- __ bx(LR, VS);
- __ LoadObject(R0, Bool::True(), true_condition);
- __ Ret();
+ __ vcmpd(D0, D1);
+ __ vmstat();
+ __ LoadObject(R0, Bool::False());
+ // Return false if D0 or D1 was NaN before checking true condition.
+ __ bx(LR, VS);
+ __ LoadObject(R0, Bool::True(), true_condition);
+ __ Ret();
- __ Bind(&is_smi); // Convert R0 to a double.
- __ SmiUntag(R0);
- __ vmovsr(S0, R0);
- __ vcvtdi(D1, S0);
- __ b(&double_op); // Then do the comparison.
- __ Bind(&fall_through);
+ __ Bind(&is_smi); // Convert R0 to a double.
+ __ SmiUntag(R0);
+ __ vmovsr(S0, R0);
+ __ vcvtdi(D1, S0);
+ __ b(&double_op); // Then do the comparison.
+ __ Bind(&fall_through);
+ }
}
void Intrinsifier::Double_greaterThan(Assembler* assembler) {
- return CompareDoubles(assembler, HI);
+ CompareDoubles(assembler, HI);
}
void Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
- return CompareDoubles(assembler, CS);
+ CompareDoubles(assembler, CS);
}
void Intrinsifier::Double_lessThan(Assembler* assembler) {
- return CompareDoubles(assembler, CC);
+ CompareDoubles(assembler, CC);
}
void Intrinsifier::Double_equal(Assembler* assembler) {
- return CompareDoubles(assembler, EQ);
+ CompareDoubles(assembler, EQ);
}
void Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
- return CompareDoubles(assembler, LS);
+ CompareDoubles(assembler, LS);
}
// Expects left argument to be double (receiver). Right argument is unknown.
// Both arguments are on stack.
static void DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
- Label fall_through;
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label fall_through;
- TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
- // Both arguments are double, right operand is in R0.
- __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
- __ ldr(R0, Address(SP, 1 * kWordSize)); // Left argument.
- __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- switch (kind) {
- case Token::kADD: __ vaddd(D0, D0, D1); break;
- case Token::kSUB: __ vsubd(D0, D0, D1); break;
- case Token::kMUL: __ vmuld(D0, D0, D1); break;
- case Token::kDIV: __ vdivd(D0, D0, D1); break;
- default: UNREACHABLE();
+ TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
+ // Both arguments are double, right operand is in R0.
+ __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
+ __ ldr(R0, Address(SP, 1 * kWordSize)); // Left argument.
+ __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ switch (kind) {
+ case Token::kADD: __ vaddd(D0, D0, D1); break;
+ case Token::kSUB: __ vsubd(D0, D0, D1); break;
+ case Token::kMUL: __ vmuld(D0, D0, D1); break;
+ case Token::kDIV: __ vdivd(D0, D0, D1); break;
+ default: UNREACHABLE();
+ }
+ const Class& double_class = Class::Handle(
+ Isolate::Current()->object_store()->double_class());
+ __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
+ __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ Ret();
+ __ Bind(&fall_through);
}
- const Class& double_class = Class::Handle(
- Isolate::Current()->object_store()->double_class());
- __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
- __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ Ret();
- __ Bind(&fall_through);
}
void Intrinsifier::Double_add(Assembler* assembler) {
- return DoubleArithmeticOperations(assembler, Token::kADD);
+ DoubleArithmeticOperations(assembler, Token::kADD);
}
void Intrinsifier::Double_mul(Assembler* assembler) {
- return DoubleArithmeticOperations(assembler, Token::kMUL);
+ DoubleArithmeticOperations(assembler, Token::kMUL);
}
void Intrinsifier::Double_sub(Assembler* assembler) {
- return DoubleArithmeticOperations(assembler, Token::kSUB);
+ DoubleArithmeticOperations(assembler, Token::kSUB);
}
void Intrinsifier::Double_div(Assembler* assembler) {
- return DoubleArithmeticOperations(assembler, Token::kDIV);
+ DoubleArithmeticOperations(assembler, Token::kDIV);
}
// Left is double right is integer (Bigint, Mint or Smi)
void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
- Label fall_through;
- // Only smis allowed.
- __ ldr(R0, Address(SP, 0 * kWordSize));
- __ tst(R0, ShifterOperand(kSmiTagMask));
- __ b(&fall_through, NE);
- // Is Smi.
- __ SmiUntag(R0);
- __ vmovsr(S0, R0);
- __ vcvtdi(D1, S0);
- __ ldr(R0, Address(SP, 1 * kWordSize));
- __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ vmuld(D0, D0, D1);
- const Class& double_class = Class::Handle(
- Isolate::Current()->object_store()->double_class());
- __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
- __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ Ret();
- __ Bind(&fall_through);
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label fall_through;
+ // Only smis allowed.
+ __ ldr(R0, Address(SP, 0 * kWordSize));
+ __ tst(R0, ShifterOperand(kSmiTagMask));
+ __ b(&fall_through, NE);
+ // Is Smi.
+ __ SmiUntag(R0);
+ __ vmovsr(S0, R0);
+ __ vcvtdi(D1, S0);
+ __ ldr(R0, Address(SP, 1 * kWordSize));
+ __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ vmuld(D0, D0, D1);
+ const Class& double_class = Class::Handle(
+ Isolate::Current()->object_store()->double_class());
+ __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
+ __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ Ret();
+ __ Bind(&fall_through);
+ }
}
void Intrinsifier::Double_fromInteger(Assembler* assembler) {
- Label fall_through;
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label fall_through;
- __ ldr(R0, Address(SP, 0 * kWordSize));
- __ tst(R0, ShifterOperand(kSmiTagMask));
- __ b(&fall_through, NE);
- // Is Smi.
- __ SmiUntag(R0);
- __ vmovsr(S0, R0);
- __ vcvtdi(D0, S0);
- const Class& double_class = Class::Handle(
- Isolate::Current()->object_store()->double_class());
- __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
- __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ Ret();
- __ Bind(&fall_through);
+ __ ldr(R0, Address(SP, 0 * kWordSize));
+ __ tst(R0, ShifterOperand(kSmiTagMask));
+ __ b(&fall_through, NE);
+ // Is Smi.
+ __ SmiUntag(R0);
+ __ vmovsr(S0, R0);
+ __ vcvtdi(D0, S0);
+ const Class& double_class = Class::Handle(
+ Isolate::Current()->object_store()->double_class());
+ __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
+ __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ Ret();
+ __ Bind(&fall_through);
+ }
}
void Intrinsifier::Double_getIsNaN(Assembler* assembler) {
- Label is_true;
- __ ldr(R0, Address(SP, 0 * kWordSize));
- __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ vcmpd(D0, D0);
- __ vmstat();
- __ LoadObject(R0, Bool::False(), VC);
- __ LoadObject(R0, Bool::True(), VS);
- __ Ret();
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label is_true;
+ __ ldr(R0, Address(SP, 0 * kWordSize));
+ __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ vcmpd(D0, D0);
+ __ vmstat();
+ __ LoadObject(R0, Bool::False(), VC);
+ __ LoadObject(R0, Bool::True(), VS);
+ __ Ret();
+ }
}
void Intrinsifier::Double_getIsNegative(Assembler* assembler) {
- Label is_false, is_true, is_zero;
- __ ldr(R0, Address(SP, 0 * kWordSize));
- __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ LoadDImmediate(D1, 0.0, R1);
- __ vcmpd(D0, D1);
- __ vmstat();
- __ b(&is_false, VS); // NaN -> false.
- __ b(&is_zero, EQ); // Check for negative zero.
- __ b(&is_false, CS); // >= 0 -> false.
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label is_false, is_true, is_zero;
+ __ ldr(R0, Address(SP, 0 * kWordSize));
+ __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ LoadDImmediate(D1, 0.0, R1);
+ __ vcmpd(D0, D1);
+ __ vmstat();
+ __ b(&is_false, VS); // NaN -> false.
+ __ b(&is_zero, EQ); // Check for negative zero.
+ __ b(&is_false, CS); // >= 0 -> false.
- __ Bind(&is_true);
- __ LoadObject(R0, Bool::True());
- __ Ret();
+ __ Bind(&is_true);
+ __ LoadObject(R0, Bool::True());
+ __ Ret();
- __ Bind(&is_false);
- __ LoadObject(R0, Bool::False());
- __ Ret();
+ __ Bind(&is_false);
+ __ LoadObject(R0, Bool::False());
+ __ Ret();
- __ Bind(&is_zero);
- // Check for negative zero by looking at the sign bit.
- __ vmovrrd(R0, R1, D0); // R1:R0 <- D0, so sign bit is in bit 31 of R1.
- __ mov(R1, ShifterOperand(R1, LSR, 31));
- __ tst(R1, ShifterOperand(1));
- __ b(&is_true, NE); // Sign bit set.
- __ b(&is_false);
+ __ Bind(&is_zero);
+ // Check for negative zero by looking at the sign bit.
+ __ vmovrrd(R0, R1, D0); // R1:R0 <- D0, so sign bit is in bit 31 of R1.
+ __ mov(R1, ShifterOperand(R1, LSR, 31));
+ __ tst(R1, ShifterOperand(1));
+ __ b(&is_true, NE); // Sign bit set.
+ __ b(&is_false);
+ }
}
void Intrinsifier::Double_toInt(Assembler* assembler) {
- Label fall_through;
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label fall_through;
- __ ldr(R0, Address(SP, 0 * kWordSize));
- __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ ldr(R0, Address(SP, 0 * kWordSize));
+ __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- // Explicit NaN check, since ARM gives an FPU exception if you try to
- // convert NaN to an int.
- __ vcmpd(D0, D0);
- __ vmstat();
- __ b(&fall_through, VS);
+ // Explicit NaN check, since ARM gives an FPU exception if you try to
+ // convert NaN to an int.
+ __ vcmpd(D0, D0);
+ __ vmstat();
+ __ b(&fall_through, VS);
- __ vcvtid(S0, D0);
- __ vmovrs(R0, S0);
- // Overflow is signaled with minint.
- // Check for overflow and that it fits into Smi.
- __ CompareImmediate(R0, 0xC0000000);
- __ b(&fall_through, MI);
- __ SmiTag(R0);
- __ Ret();
- __ Bind(&fall_through);
+ __ vcvtid(S0, D0);
+ __ vmovrs(R0, S0);
+ // Overflow is signaled with minint.
+ // Check for overflow and that it fits into Smi.
+ __ CompareImmediate(R0, 0xC0000000);
+ __ b(&fall_through, MI);
+ __ SmiTag(R0);
+ __ Ret();
+ __ Bind(&fall_through);
+ }
}
void Intrinsifier::Math_sqrt(Assembler* assembler) {
- Label fall_through, is_smi, double_op;
- TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
- // Argument is double and is in R0.
- __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
- __ Bind(&double_op);
- __ vsqrtd(D0, D1);
- const Class& double_class = Class::Handle(
- Isolate::Current()->object_store()->double_class());
- __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
- __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
- __ Ret();
- __ Bind(&is_smi);
- __ SmiUntag(R0);
- __ vmovsr(S0, R0);
- __ vcvtdi(D1, S0);
- __ b(&double_op);
- __ Bind(&fall_through);
+ if (TargetCPUFeatures::vfp_supported()) {
+ Label fall_through, is_smi, double_op;
+ TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
+ // Argument is double and is in R0.
+ __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
+ __ Bind(&double_op);
+ __ vsqrtd(D0, D1);
+ const Class& double_class = Class::Handle(
+ Isolate::Current()->object_store()->double_class());
+ __ TryAllocate(double_class, &fall_through, R0, R1); // Result register.
+ __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+ __ Ret();
+ __ Bind(&is_smi);
+ __ SmiUntag(R0);
+ __ vmovsr(S0, R0);
+ __ vcvtdi(D1, S0);
+ __ b(&double_op);
+ __ Bind(&fall_through);
+ }
}
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698