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

Unified Diff: runtime/vm/intermediate_language_x64.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
Index: runtime/vm/intermediate_language_x64.cc
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 06c52785fa222ee67cb0778b8e4a566a4e36b87a..9f5c89f809ddf151a6d22470e1f79d563f64f226 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.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"
@@ -1332,6 +1333,256 @@ 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) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
+ if (field().guarded_cid() == kIllegalCid) {
+ summary->AddTemp(Location::RequiresRegister());
+ }
+ return summary;
+}
+
+
+static void PushCid(FlowGraphCompiler* compiler, const Immediate& imm) {
+ __ pushq(Immediate(Smi::RawValue(imm.value())));
+}
+
+
+static void PushCid(FlowGraphCompiler* compiler, Register reg) {
+ __ SmiTag(reg);
+ __ pushq(reg);
+}
+
+
+template<typename ValueCidOperandType>
+static void EmitCidGuardInit(FlowGraphCompiler* compiler,
+ ValueCidOperandType value_cid,
+ const Immediate& field_cid,
+ const Immediate& nullability,
+ Label* deopt,
+ Label* ok) {
+ // nothing to do.
+}
+
+
+template<typename ValueCidOperandType>
+static void EmitCidGuardInit(FlowGraphCompiler* compiler,
+ ValueCidOperandType value_cid,
+ const FieldAddress& field_cid,
+ const FieldAddress& nullability,
+ Label* deopt,
+ Label* ok) {
+ // Check if field is initialized for the first time.
+ Label fail;
+ __ cmpq(field_cid, Immediate(kIllegalCid));
+ __ j(NOT_EQUAL, (deopt != NULL) ? deopt : &fail);
+ __ movq(field_cid, value_cid);
+ __ movq(nullability, value_cid);
+ __ jmp(ok);
+ if (deopt == NULL) {
+ __ Bind(&fail);
+ }
+}
+
+
+static void CompareJump(FlowGraphCompiler* compiler,
+ Condition cond,
+ const Immediate& left,
+ const Immediate& right,
+ Label* target) {
+ if ((left.value() == right.value()) && (cond == EQUAL)) {
+ __ jmp(target);
+ } else if ((left.value() != right.value()) && cond == NOT_EQUAL) {
+ __ jmp(target);
+ }
+}
+
+
+static void CompareJump(FlowGraphCompiler* compiler,
+ Condition cond,
+ Immediate left,
+ Register right,
+ Label* target) {
+ ASSERT((cond == EQUAL) || (cond == NOT_EQUAL));
+ __ cmpq(right, left);
+ __ j(cond, target);
+}
+
+
+template<typename LeftOperandType, typename RightOperandType>
+static void CompareJump(FlowGraphCompiler* compiler,
+ Condition cond,
+ LeftOperandType left,
+ RightOperandType right,
+ Label* target) {
+ __ cmpq(left, right);
+ __ j(cond, target);
+}
+
+
+template<typename ValueCidOperandType,
+ typename FieldCidOperandType,
+ typename FieldNullabilityOperandType>
+static void EmitCidGuard(FlowGraphCompiler* compiler,
+ const Field& field,
+ ValueCidOperandType value_cid,
+ FieldCidOperandType field_cid,
+ FieldNullabilityOperandType nullability,
+ Label* deopt) {
+ Label ok, update;
+ CompareJump(compiler, EQUAL, field_cid, value_cid, &ok);
+ if ((deopt != NULL) && (field.guarded_cid() != kIllegalCid)) {
+ CompareJump(compiler, NOT_EQUAL, nullability, value_cid, deopt);
+ } else {
+ CompareJump(compiler, EQUAL, nullability, value_cid, &ok);
+ }
+
+ EmitCidGuardInit(compiler, value_cid, field_cid, nullability, deopt, &ok);
+
+ if (deopt == NULL) {
+ // Switch field's cid to dynamic and notify runtime.
+ CompareJump(compiler, EQUAL, field_cid, Immediate(kDynamicCid), &ok);
+ __ PushObject(field);
+ PushCid(compiler, value_cid);
+ __ CallRuntime(kUpdateFieldCidRuntimeEntry);
+ __ Drop(2);
+ }
+
+ __ Bind(&ok);
+}
+
+
+template<typename FieldCidOperandType, typename FieldNullabilityOperandType>
+static void EmitCidGuard(FlowGraphCompiler* compiler,
+ const Field& field,
+ intptr_t value_cid,
+ Register value_cid_reg,
+ FieldCidOperandType field_cid,
+ FieldNullabilityOperandType nullability,
+ Label* deopt) {
+ if (value_cid == kDynamicCid) {
+ EmitCidGuard(compiler, field, value_cid_reg, field_cid, nullability, deopt);
+ } else {
+ EmitCidGuard(compiler,
+ field,
+ Immediate(value_cid),
+ field_cid,
+ nullability,
+ deopt);
+ }
+}
+
+
+static void EmitFieldGuard(FlowGraphCompiler* compiler,
+ Register value_reg,
+ const Field& field,
+ intptr_t value_cid,
+ Register value_cid_reg,
+ intptr_t field_cid,
+ intptr_t nullability,
+ Register field_reg,
+ Label* deopt) {
+ if (value_cid == kDynamicCid) {
+ Label not_smi, cid_loaded;
+ __ testq(value_reg, Immediate(kSmiTagMask));
+ __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
+ __ movq(value_cid_reg, Immediate(kSmiCid));
+ __ jmp(&cid_loaded);
+ __ Bind(&not_smi);
+ __ LoadClassId(value_cid_reg, value_reg);
+ __ Bind(&cid_loaded);
+ }
+
+ if (field_cid == kIllegalCid) {
+ __ LoadObject(field_reg, Field::ZoneHandle(field.raw()));
+ EmitCidGuard(compiler,
+ field,
+ value_cid,
+ value_cid_reg,
+ FieldAddress(field_reg, Field::guarded_cid_offset()),
+ FieldAddress(field_reg, Field::is_nullable_offset()),
+ deopt);
+ } else {
+ EmitCidGuard(compiler,
+ field,
+ value_cid,
+ value_cid_reg,
+ Immediate(field_cid),
+ Immediate(nullability),
+ deopt);
+ }
+}
+
+
+void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const intptr_t field_cid = field().guarded_cid();
+
+ if (field_cid == kDynamicCid) {
+ ASSERT(!compiler->is_optimizing());
+ return; // Nothing to emit.
+ }
+
+
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid;
+
+ Register value_reg = locs()->in(0).reg();
+
+ Register value_cid_reg = (value_cid == kDynamicCid) ?
+ locs()->temp(0).reg() : kNoRegister;
+
+ Label* deopt = compiler->is_optimizing() && CanDeoptimize() ?
+ compiler->AddDeoptStub(deopt_id(), kDeoptStoreInstanceField) : NULL;
+
+ if ((deopt != NULL) && (field_cid != kIllegalCid)) {
+ if (value_cid != kDynamicCid) {
+ ASSERT(field_cid != value_cid);
+ __ jmp(deopt);
+ return;
+ }
+
+ if (field_cid == kSmiCid) {
+ __ testq(value_reg, Immediate(kSmiTagMask));
+ } else {
+ ASSERT(value_cid_reg != kNoRegister);
+ __ testq(value_reg, Immediate(kSmiTagMask));
+ __ j(ZERO, deopt);
+ __ LoadClassId(value_cid_reg, value_reg);
+ __ cmpq(value_cid_reg, Immediate(field_cid));
+ }
+
+ if (field().is_nullable()) {
+ Label ok;
+ __ j(EQUAL, &ok);
+ const Immediate& raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
+ __ cmpq(value_reg, raw_null);
+ __ j(NOT_EQUAL, deopt);
+ __ Bind(&ok);
+ } else {
+ __ j(NOT_EQUAL, deopt);
+ }
+
+ return;
+ }
+
+ Register field_reg = (field_cid == kIllegalCid) ?
+ locs()->temp(value_cid_reg == kNoRegister ? 0 : 1).reg() : kNoRegister;
+
+ EmitFieldGuard(compiler,
+ value_reg,
+ field(),
+ value_cid, value_cid_reg,
+ field_cid, nullability, field_reg,
+ deopt);
+}
+
+
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary() const {
const intptr_t kNumInputs = 2;
const intptr_t num_temps = 0;
@@ -2680,16 +2931,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()));
+ __ cmpq(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();

Powered by Google App Engine
This is Rietveld 408576698