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

Unified Diff: runtime/vm/intermediate_language_ia32.cc

Issue 10968059: Support for unboxed 64-bit integer bitwise operations and equality on ia32. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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
Index: runtime/vm/intermediate_language_ia32.cc
===================================================================
--- runtime/vm/intermediate_language_ia32.cc (revision 12765)
+++ runtime/vm/intermediate_language_ia32.cc (working copy)
@@ -262,6 +262,16 @@
const intptr_t kNumInputs = 2;
const bool is_checked_strict_equal =
HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
+ if (receiver_class_id() == kMintCid) {
+ const intptr_t kNumTemps = 1;
+ LocationSummary* locs =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ locs->set_in(0, Location::RequiresXmmRegister());
+ locs->set_in(1, Location::RequiresXmmRegister());
+ locs->set_temp(0, Location::RequiresRegister());
+ locs->set_out(Location::RequiresRegister());
+ return locs;
+ }
if (receiver_class_id() == kDoubleCid) {
const intptr_t kNumTemps = 0;
LocationSummary* locs =
@@ -617,6 +627,47 @@
}
+static Condition TokenKindToMintCondition(Token::Kind kind) {
+ switch (kind) {
+ case Token::kEQ: return EQUAL;
+ case Token::kNE: return NOT_EQUAL;
+ default:
+ UNREACHABLE();
+ return OVERFLOW;
+ }
+}
+
+
+static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind,
+ BranchInstr* branch) {
+ ASSERT(Token::IsEqualityOperator(kind));
+ XmmRegister left = locs.in(0).xmm_reg();
+ XmmRegister right = locs.in(1).xmm_reg();
+ Register temp = locs.temp(0).reg();
+ __ movaps(XMM0, left);
+ __ pcmpeqq(XMM0, right);
+ __ movd(temp, XMM0);
+
+ Condition true_condition = TokenKindToMintCondition(kind);
+ __ cmpl(temp, Immediate(-1));
Vyacheslav Egorov (Google) 2012/09/24 14:53:42 you can also use test(temp, temp) and branch on ne
+
+ if (branch != NULL) {
+ branch->EmitBranchOnCondition(compiler, true_condition);
+ } else {
+ Register result = locs.out().reg();
+ Label done, is_true;
+ __ j(true_condition, &is_true);
+ __ LoadObject(result, compiler->bool_false());
+ __ jmp(&done);
+ __ Bind(&is_true);
+ __ LoadObject(result, compiler->bool_true());
+ __ Bind(&done);
+ }
+}
+
+
static Condition TokenKindToDoubleCondition(Token::Kind kind) {
switch (kind) {
case Token::kEQ: return EQUAL;
@@ -658,6 +709,10 @@
EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
}
+ if (receiver_class_id() == kMintCid) {
+ EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
+ return;
+ }
if (receiver_class_id() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
return;
@@ -691,6 +746,10 @@
EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
return;
}
+ if (receiver_class_id() == kMintCid) {
+ EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
+ return;
+ }
if (receiver_class_id() == kDoubleCid) {
EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
return;
@@ -1688,110 +1747,6 @@
}
-LocationSummary* BinaryMintOpInstr::MakeLocationSummary() const {
- const intptr_t kNumInputs = 2;
- ASSERT(op_kind() == Token::kBIT_AND);
- const intptr_t kNumTemps = 1;
- LocationSummary* summary =
- new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
- summary->set_in(0, Location::RegisterLocation(EAX));
- summary->set_in(1, Location::RegisterLocation(ECX));
- summary->set_temp(0, Location::RegisterLocation(EDX));
- summary->set_out(Location::RegisterLocation(EAX));
- return summary;
-}
-
-
-void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi
- // receiver and a Mint or Smi argument. We fall back to the run time call if
- // both receiver and argument are Mint or if one of them is Mint and the other
- // is a negative Smi.
- Register left = locs()->in(0).reg();
- Register right = locs()->in(1).reg();
- Register result = locs()->out().reg();
- Register temp = locs()->temp(0).reg();
- ASSERT(left == result);
- ASSERT(op_kind() == Token::kBIT_AND);
- Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
- kDeoptBinaryMintOp);
- Label mint_static_call, smi_static_call, non_smi, smi_smi, done;
- __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi?
- __ j(NOT_ZERO, &non_smi);
- __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi?
- __ j(ZERO, &smi_smi);
- __ CompareClassId(right, kMintCid, temp); // Is argument Mint?
- __ j(NOT_EQUAL, deopt); // Argument neither Smi nor Mint.
- __ cmpl(left, Immediate(0));
- __ j(LESS, &smi_static_call); // Negative Smi receiver, Mint argument.
-
- // Positive Smi receiver, Mint argument.
- // Load lower argument Mint word, convert to Smi. It is OK to loose bits.
- __ movl(right, FieldAddress(right, Mint::value_offset()));
- __ SmiTag(right);
- __ andl(result, right);
- __ jmp(&done);
-
- __ Bind(&non_smi); // Receiver is non-Smi.
- __ CompareClassId(left, kMintCid, temp); // Is receiver Mint?
- __ j(NOT_EQUAL, deopt); // Receiver neither Smi nor Mint.
- __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi?
- __ j(NOT_ZERO, &mint_static_call); // Mint receiver, non-Smi argument.
- __ cmpl(right, Immediate(0));
- __ j(LESS, &mint_static_call); // Mint receiver, negative Smi argument.
-
- // Mint receiver, positive Smi argument.
- // Load lower receiver Mint word, convert to Smi. It is OK to loose bits.
- __ movl(result, FieldAddress(left, Mint::value_offset()));
- __ SmiTag(result);
- __ Bind(&smi_smi);
- __ andl(result, right);
- __ jmp(&done);
-
- __ Bind(&smi_static_call);
- {
- Function& target = Function::ZoneHandle(
- ic_data()->GetTargetForReceiverClassId(kSmiCid));
- if (target.IsNull()) {
- __ jmp(deopt);
- } else {
- __ pushl(left);
- __ pushl(right);
- compiler->GenerateStaticCall(
- instance_call()->deopt_id(),
- instance_call()->token_pos(),
- target,
- instance_call()->ArgumentCount(),
- instance_call()->argument_names(),
- locs());
- ASSERT(result == EAX);
- __ jmp(&done);
- }
- }
-
- __ Bind(&mint_static_call);
- {
- Function& target = Function::ZoneHandle(
- ic_data()->GetTargetForReceiverClassId(kMintCid));
- if (target.IsNull()) {
- __ jmp(deopt);
- } else {
- __ pushl(left);
- __ pushl(right);
- compiler->GenerateStaticCall(
- instance_call()->deopt_id(),
- instance_call()->token_pos(),
- target,
- instance_call()->ArgumentCount(),
- instance_call()->argument_names(),
- locs());
- ASSERT(result == EAX);
- }
- }
- __ Bind(&done);
-}
-
-
LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
ASSERT((left()->ResultCid() != kDoubleCid) &&
(right()->ResultCid() != kDoubleCid));
@@ -2221,6 +2176,160 @@
}
+LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister());
+ summary->set_out(Location::RequiresXmmRegister());
+ return summary;
+}
+
+
+void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const intptr_t value_cid = value()->ResultCid();
+ const Register value = locs()->in(0).reg();
+ const XmmRegister result = locs()->out().xmm_reg();
+
+ if (value_cid == kMintCid) {
+ __ movsd(result, FieldAddress(value, Mint::value_offset()));
+ } else if (value_cid == kSmiCid) {
+ __ SmiUntag(value); // Untag input before conversion.
+ __ movd(result, value);
+ __ pmovsxdq(result, result);
+ __ SmiTag(value); // Restore input register.
+ } else {
+ Register temp = locs()->temp(0).reg();
+ Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
+ Label is_smi, done;
+ __ testl(value, Immediate(kSmiTagMask));
+ __ j(ZERO, &is_smi);
+ __ CompareClassId(value, kMintCid, temp);
+ __ j(NOT_EQUAL, deopt);
+ __ movsd(result, FieldAddress(value, Mint::value_offset()));
+ __ jmp(&done);
+ __ Bind(&is_smi);
+ __ movl(temp, value);
+ __ SmiUntag(temp);
+ __ movd(result, temp);
+ __ pmovsxdq(result, result);
+ __ Bind(&done);
+ }
+}
+
+
+LocationSummary* BoxIntegerInstr::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 2;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs,
+ kNumTemps,
+ LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, Location::RequiresXmmRegister());
+ summary->set_temp(0, Location::RegisterLocation(EAX));
+ summary->set_temp(1, Location::RegisterLocation(EDX));
+ // TODO(fschneider): Save one temp by using result register as a temp.
+ summary->set_out(Location::RequiresRegister());
+ return summary;
+}
+
+
+class BoxIntegerSlowPath : public SlowPathCode {
+ public:
+ explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
+ : instruction_(instruction) { }
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Bind(entry_label());
+ const Class& mint_class =
+ Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
+ const Code& stub =
+ Code::Handle(StubCode::GetAllocationStubForClass(mint_class));
+ const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint());
+
+ LocationSummary* locs = instruction_->locs();
+ locs->live_registers()->Remove(locs->out());
+ // Temps contain untagged values. Must only save tagged values.
+ locs->live_registers()->Remove(locs->temp(0));
+ locs->live_registers()->Remove(locs->temp(1));
Vyacheslav Egorov (Google) 2012/09/24 14:53:42 I think we don't assigned safepoints for temporary
Florian Schneider 2012/09/26 11:51:32 Done.
+
+ compiler->SaveLiveRegisters(locs);
+ compiler->GenerateCall(0, // No token pos.
+ &label,
+ PcDescriptors::kOther,
+ locs);
+ if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX);
+ compiler->RestoreLiveRegisters(locs);
+
+ __ jmp(exit_label());
+ }
+
+ private:
+ BoxIntegerInstr* instruction_;
+};
+
+
+void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
+ compiler->AddSlowPathCode(slow_path);
+
+ Register out_reg = locs()->out().reg();
+ XmmRegister value = locs()->in(0).xmm_reg();
+
+ // Check if result fits into a smi.
+ Label not_smi, done;
+ __ pextrd(EDX, value, Immediate(1)); // Upper half.
+ __ pextrd(EAX, value, Immediate(0)); // Lower half.
+ __ xorl(EDX, EAX);
+ __ testl(EDX, Immediate(0xc0000000));
Vyacheslav Egorov (Google) 2012/09/24 14:53:42 0x0000000100000001 is not a smi but passes this ch
Florian Schneider 2012/09/26 11:51:32 Thanks for catching. I'll fix it and add a test.
+ __ j(NOT_ZERO, &not_smi);
+ __ SmiTag(EAX);
+ __ movl(out_reg, EAX);
+ __ jmp(&done);
+
+ __ Bind(&not_smi);
+ AssemblerMacros::TryAllocate(
+ compiler->assembler(),
+ Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
+ slow_path->entry_label(),
+ Assembler::kFarJump,
+ out_reg);
+ __ Bind(slow_path->exit_label());
+ __ movsd(FieldAddress(out_reg, Mint::value_offset()), value);
+ __ Bind(&done);
+}
+
+
+LocationSummary* UnboxedMintBinaryOpInstr::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresXmmRegister());
+ summary->set_in(1, Location::RequiresXmmRegister());
+ summary->set_out(Location::SameAsFirstInput());
+ return summary;
+}
+
+
+void UnboxedMintBinaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ XmmRegister left = locs()->in(0).xmm_reg();
+ XmmRegister right = locs()->in(1).xmm_reg();
+
+ ASSERT(locs()->out().xmm_reg() == left);
+
+ switch (op_kind()) {
+ case Token::kBIT_AND: __ andpd(left, right); break;
+ case Token::kBIT_OR: __ orpd(left, right); break;
+ case Token::kBIT_XOR: __ xorpd(left, right); break;
+ default: UNREACHABLE();
+ }
+}
+
+
+
} // namespace dart
#undef __

Powered by Google App Engine
This is Rietveld 408576698