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

Unified Diff: runtime/vm/intermediate_language_ia32.cc

Issue 12529008: Collect type feedback for fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rewritten instruction pattern on ia32 Created 7 years, 9 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/intermediate_language_mips.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language_ia32.cc
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index ad278969fa2cec01bd270a3125373bd443d4b9dc..ef9998ceb7e0695933b7763874c1a3545d217a5e 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -13,6 +13,7 @@
#include "vm/locations.h"
#include "vm/object_store.h"
#include "vm/parser.h"
+#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
@@ -1508,6 +1509,163 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
+LocationSummary* GuardFieldInstr::MakeLocationSummary() const {
+ const intptr_t kNumInputs = 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, 0, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ if ((value()->Type()->ToCid() == kDynamicCid) &&
+ (field().guarded_cid() != kSmiCid)) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
+ if (field().guarded_cid() == kIllegalCid) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
+ return summary;
+}
+
+
+static void LoadValueCid(FlowGraphCompiler* compiler,
Kevin Millikin (Google) 2013/03/15 12:17:21 I think we have this pattern in a few places. Emit
Vyacheslav Egorov (Google) 2013/03/15 13:01:10 Done.
+ Register value_reg,
+ Register value_cid_reg) {
Kevin Millikin (Google) 2013/03/15 12:17:21 I guess the order of these registers should be swa
Vyacheslav Egorov (Google) 2013/03/15 13:01:10 Done.
+ Label not_smi, cid_loaded;
+ __ testl(value_reg, Immediate(kSmiTagMask));
+ __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
+ __ movl(value_cid_reg, Immediate(kSmiCid));
+ __ jmp(&cid_loaded);
+ __ Bind(&not_smi);
+ __ LoadClassId(value_cid_reg, value_reg);
+ __ Bind(&cid_loaded);
+}
+
+void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const intptr_t field_cid = field().guarded_cid();
+ const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
+
+ if (field_cid == kDynamicCid) {
+ ASSERT(!compiler->is_optimizing());
+ return; // Nothing to emit.
+ }
+
+ const intptr_t value_cid = value()->Type()->ToCid();
+
+ Register value_reg = locs()->in(0).reg();
+
+ Register value_cid_reg = ((value_cid == kDynamicCid) &&
+ (field_cid != kSmiCid)) ? locs()->temp(0).reg() : kNoRegister;
+
+ Register field_reg = (field_cid == kIllegalCid) ?
+ locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister;
+
+ Label ok, fail_label;
+
+ Label* deopt = compiler->is_optimizing() ?
+ compiler->AddDeoptStub(deopt_id(), kDeoptGuardField) : NULL;
+
+ Label* fail = (deopt != NULL) ? deopt : &fail_label;
+
+ const bool ok_is_fall_through = (deopt != NULL);
+
+ if (!compiler->is_optimizing() || (field_cid == kIllegalCid)) {
+ if (field_reg == kNoRegister) {
Kevin Millikin (Google) 2013/03/15 12:17:21 It seems to me that (field_reg == kNoRegister) if
Vyacheslav Egorov (Google) 2013/03/15 13:01:10 Done.
+ field_reg = EBX;
+ ASSERT((field_reg != value_reg) && (field_reg != value_cid_reg));
+ }
+
+ __ LoadObject(field_reg, Field::ZoneHandle(field().raw()));
+
+ FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset());
+ FieldAddress field_nullability_operand(
+ field_reg, Field::is_nullable_offset());
+
+ if (value_cid == kDynamicCid) {
+ if (value_cid_reg == kNoRegister) {
+ ASSERT(!compiler->is_optimizing());
+ value_cid_reg = EDX;
+ ASSERT((value_cid_reg != value_reg) && (field_reg != value_cid_reg));
+ }
+
+ LoadValueCid(compiler, value_reg, value_cid_reg);
+
+ __ cmpl(value_cid_reg, field_cid_operand);
+ __ j(EQUAL, &ok);
+ __ cmpl(value_cid_reg, field_nullability_operand);
+ } else if (value_cid == kNullCid) {
+ __ cmpl(field_nullability_operand, Immediate(value_cid));
+ } else {
+ __ cmpl(field_cid_operand, Immediate(value_cid));
+ }
+ __ j(EQUAL, &ok);
+
+ __ cmpl(field_cid_operand, Immediate(kIllegalCid));
+ __ j(NOT_EQUAL, fail);
+
+ if (value_cid == kDynamicCid) {
+ __ movl(field_cid_operand, value_cid_reg);
+ __ movl(field_nullability_operand, value_cid_reg);
+ } else {
+ __ movl(field_cid_operand, Immediate(value_cid));
+ __ movl(field_nullability_operand, Immediate(value_cid));
+ }
+
+ if (!ok_is_fall_through) {
+ __ jmp(&ok);
+ }
+ } else {
+ if (value_cid == kDynamicCid) {
+ // Field's guarded class id is fixed by value's class id is not known.
Kevin Millikin (Google) 2013/03/15 12:17:21 by ==> but
Vyacheslav Egorov (Google) 2013/03/15 13:01:10 Done.
+ __ testl(value_reg, Immediate(kSmiTagMask));
+
+ if (field_cid != kSmiCid) {
+ __ j(ZERO, fail);
+ __ LoadClassId(value_cid_reg, value_reg);
+ __ cmpl(value_cid_reg, Immediate(field_cid));
+ }
+
+ if (field().is_nullable() && (field_cid != kNullCid)) {
+ __ j(EQUAL, &ok);
+ const Immediate& raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ __ cmpl(value_reg, raw_null);
+ }
+
+ if (ok_is_fall_through) {
+ __ j(NOT_EQUAL, fail);
+ } else {
+ __ j(EQUAL, &ok);
+ }
+ } else {
+ // Both value's and field's class id is known.
+ if ((value_cid != field_cid) && (value_cid != nullability)) {
+ if (ok_is_fall_through) {
+ __ jmp(fail);
+ }
+ } else {
+ // Nothing to emit.
+ ASSERT(!compiler->is_optimizing());
+ return;
+ }
+ }
+ }
+
+ if (deopt == NULL) {
+ ASSERT(!compiler->is_optimizing());
+ __ Bind(fail);
+
+ __ cmpl(FieldAddress(field_reg, Field::guarded_cid_offset()),
+ Immediate(kDynamicCid));
+ __ j(EQUAL, &ok);
+
+ __ pushl(field_reg);
+ __ pushl(value_reg);
+ __ CallRuntime(kUpdateFieldCidRuntimeEntry);
+ __ Drop(2); // Drop the field and the value.
Kevin Millikin (Google) 2013/03/15 12:17:21 You're right, it's still spaghetti. But now it's
+ }
+
+ __ Bind(&ok);
+}
+
+
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t num_temps = 0;
@@ -2828,16 +2986,28 @@ void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* CheckClassInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 1;
+ const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresRegister());
- summary->set_temp(0, Location::RequiresRegister());
+ if (!null_check()) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
return summary;
}
void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (null_check()) {
+ Label* deopt = compiler->AddDeoptStub(deopt_id(),
+ kDeoptCheckClass);
+ const Immediate& raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ __ cmpl(locs()->in(0).reg(), raw_null);
+ __ j(EQUAL, deopt);
+ return;
+ }
+
ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
(unary_checks().NumberOfChecks() > 1));
Register value = locs()->in(0).reg();
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698