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

Unified Diff: runtime/vm/intermediate_language.cc

Issue 670263007: IR refactoring: consolidate all boxing and unboxing instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 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.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language.cc
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index 7a800233acfb0e9099b434284e344994f9850cc6..d4b72bf696561a1455b5e1452a47297e91a50e8f 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -390,12 +390,12 @@ UnboxedConstantInstr::UnboxedConstantInstr(const Object& value,
bool Value::BindsTo32BitMaskConstant() const {
- if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) {
+ if (!definition()->IsUnboxInt64() || !definition()->IsUnboxUint32()) {
return false;
}
- // Two cases to consider: UnboxInteger and UnboxUint32.
- if (definition()->IsUnboxInteger()) {
- UnboxIntegerInstr* instr = definition()->AsUnboxInteger();
+ // Two cases to consider: UnboxInt64 and UnboxUint32.
+ if (definition()->IsUnboxInt64()) {
+ UnboxInt64Instr* instr = definition()->AsUnboxInt64();
if (!instr->value()->BindsToConstant()) {
return false;
}
@@ -1262,9 +1262,9 @@ bool BinaryIntegerOpInstr::RightIsPowerOfTwoConstant() const {
static bool ToIntegerConstant(Value* value, int64_t* result) {
if (!value->BindsToConstant()) {
- if (value->definition()->IsUnboxDouble()) {
- return ToIntegerConstant(value->definition()->AsUnboxDouble()->value(),
- result);
+ UnboxInstr* unbox = value->definition()->AsUnbox();
+ if ((unbox != NULL) && (unbox->representation() == kUnboxedDouble)) {
+ return ToIntegerConstant(unbox->value(), result);
}
return false;
}
@@ -1904,29 +1904,32 @@ static bool HasTryBlockUse(Value* use_list) {
}
-Definition* BoxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
+Definition* BoxInstr::Canonicalize(FlowGraph* flow_graph) {
if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
// Environments can accomodate any representation. No need to box.
return value()->definition();
}
- // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double.
- UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble();
- if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) {
- return defn->value()->definition();
+ // Fold away Box<rep>(Unbox<rep>(v)) if value is known to be of the
+ // right class.
+ UnboxInstr* unbox_defn = value()->definition()->AsUnbox();
+ if ((unbox_defn != NULL) &&
+ (unbox_defn->representation() == from_representation()) &&
+ (unbox_defn->value()->Type()->ToCid() == Type()->ToCid())) {
+ return unbox_defn->value()->definition();
}
return this;
}
-bool BoxIntNInstr::ValueFitsSmi() const {
+bool BoxIntegerInstr::ValueFitsSmi() const {
Range* range = value()->definition()->range();
return RangeUtils::Fits(range, RangeBoundary::kRangeBoundarySmi);
}
-Definition* BoxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
+Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
// Environments can accomodate any representation. No need to box.
return value()->definition();
@@ -1936,132 +1939,12 @@ Definition* BoxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
}
-Definition* UnboxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasUses()) return NULL;
-
- // Fold away UnboxInt<N>Instr(BoxInt<N>Instr(v)).
- BoxIntNInstr* box_defn = value()->definition()->AsBoxIntN();
- if (box_defn != NULL) {
- if (box_defn->value()->definition()->representation() == representation()) {
- return box_defn->value()->definition();
- } else {
- UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
- box_defn->value()->definition()->representation(),
- representation(),
- box_defn->value()->CopyWithType(),
- (representation() == kUnboxedInt32) ?
- GetDeoptId() : Isolate::kNoDeoptId);
- if ((representation() == kUnboxedInt32) && is_truncating()) {
- converter->mark_truncating();
- }
- flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
- return converter;
- }
- }
-
- return this;
-}
-
-
-Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasUses()) return NULL;
-
- UnboxedIntConverterInstr* box_defn =
- value()->definition()->AsUnboxedIntConverter();
- if ((box_defn != NULL) && (box_defn->representation() == from())) {
- if (box_defn->from() == to()) {
- return box_defn->value()->definition();
- }
-
- UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
- box_defn->from(),
- representation(),
- box_defn->value()->CopyWithType(),
- (to() == kUnboxedInt32) ? GetDeoptId() : Isolate::kNoDeoptId);
- if ((representation() == kUnboxedInt32) && is_truncating()) {
- converter->mark_truncating();
- }
- flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
- return converter;
- }
-
- UnboxIntegerInstr* unbox_defn = value()->definition()->AsUnboxInteger();
- if (unbox_defn != NULL &&
- (from() == kUnboxedMint) &&
- (to() == kUnboxedInt32) &&
- unbox_defn->HasOnlyInputUse(value())) {
- // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter
- // and code path that unboxes Mint into Int32. We should just schedule
- // these instructions close to each other instead of fusing them.
- Definition* replacement =
- new UnboxInt32Instr(unbox_defn->value()->CopyWithType(), GetDeoptId());
- if (is_truncating()) {
- replacement->AsUnboxInt32()->mark_truncating();
- }
- flow_graph->InsertBefore(this,
- replacement,
- env(),
- FlowGraph::kValue);
- return replacement;
- }
-
- return this;
-}
-
-
-Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
- Definition* replacement = UnboxIntNInstr::Canonicalize(flow_graph);
+Definition* BoxInt64Instr::Canonicalize(FlowGraph* flow_graph) {
+ Definition* replacement = BoxIntegerInstr::Canonicalize(flow_graph);
if (replacement != this) {
return replacement;
}
- ConstantInstr* c = value()->definition()->AsConstant();
- if ((c != NULL) && c->value().IsSmi()) {
- if (!is_truncating() && (kSmiBits > 32)) {
- // Check that constant fits into 32-bit integer.
- const int64_t value =
- static_cast<int64_t>(Smi::Cast(c->value()).Value());
- if (!Utils::IsInt(32, value)) {
- return this;
- }
- }
-
- UnboxedConstantInstr* uc =
- new UnboxedConstantInstr(c->value(), kUnboxedInt32);
- flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
- return uc;
- }
-
- return this;
-}
-
-
-Definition* UnboxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasUses()) return NULL;
- // Fold away UnboxDouble(BoxDouble(v)).
- BoxDoubleInstr* box_defn = value()->definition()->AsBoxDouble();
- if (box_defn != NULL) {
- return box_defn->value()->definition();
- }
-
- ConstantInstr* c = value()->definition()->AsConstant();
- if ((c != NULL) && c->value().IsDouble()) {
- UnboxedConstantInstr* uc =
- new UnboxedConstantInstr(c->value(), kUnboxedDouble);
- flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
- return uc;
- }
-
- return this;
-}
-
-
-Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
- if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
- // Environments can accomodate any representation. No need to box.
- return value()->definition();
- }
-
UnboxedIntConverterInstr* conv =
value()->definition()->AsUnboxedIntConverter();
if (conv != NULL) {
@@ -2093,82 +1976,138 @@ Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
}
-Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
+Definition* UnboxInstr::Canonicalize(FlowGraph* flow_graph) {
if (!HasUses()) return NULL;
- return this;
-}
-
-Definition* BoxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) {
- if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
- // Environments can accomodate any representation. No need to box.
- return value()->definition();
+ // Fold away Unbox<rep>(Box<rep>(v)).
+ BoxInstr* box_defn = value()->definition()->AsBox();
+ if ((box_defn != NULL) &&
+ (box_defn->from_representation() == representation())) {
+ return box_defn->value()->definition();
}
- // Fold away BoxFloat32x4(UnboxFloat32x4(v)).
- UnboxFloat32x4Instr* defn = value()->definition()->AsUnboxFloat32x4();
- if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat32x4Cid)) {
- return defn->value()->definition();
+ if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) {
+ UnboxedConstantInstr* uc = NULL;
+
+ const Object& val = value()->BoundConstant();
+ if (val.IsSmi()) {
+ const Double& double_val = Double::ZoneHandle(flow_graph->isolate(),
+ Double::NewCanonical(Smi::Cast(val).AsDoubleValue()));
+ uc = new UnboxedConstantInstr(double_val, kUnboxedDouble);
+ } else if (val.IsDouble()) {
+ uc = new UnboxedConstantInstr(val, kUnboxedDouble);
+ }
+
+ if (uc != NULL) {
+ flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
+ return uc;
+ }
}
return this;
}
-Definition* UnboxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) {
- // Fold away UnboxFloat32x4(BoxFloat32x4(v)).
- BoxFloat32x4Instr* defn = value()->definition()->AsBoxFloat32x4();
- return (defn != NULL) ? defn->value()->definition() : this;
+Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
+ if (!HasUses()) return NULL;
+
+ // Fold away UnboxInteger<rep_to>(BoxInteger<rep_from>(v)).
+ BoxIntegerInstr* box_defn = value()->definition()->AsBoxInteger();
+ if (box_defn != NULL) {
+ if (box_defn->value()->definition()->representation() == representation()) {
+ return box_defn->value()->definition();
+ } else {
+ UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
+ box_defn->value()->definition()->representation(),
+ representation(),
+ box_defn->value()->CopyWithType(),
+ (representation() == kUnboxedInt32) ?
+ GetDeoptId() : Isolate::kNoDeoptId);
+ if ((representation() == kUnboxedInt32) && is_truncating()) {
+ converter->mark_truncating();
+ }
+ flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
+ return converter;
+ }
+ }
+
+ return this;
}
-Definition* BoxFloat64x2Instr::Canonicalize(FlowGraph* flow_graph) {
- if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
- // Environments can accomodate any representation. No need to box.
- return value()->definition();
+Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
+ Definition* replacement = UnboxIntegerInstr::Canonicalize(flow_graph);
+ if (replacement != this) {
+ return replacement;
}
- // Fold away BoxFloat64x2(UnboxFloat64x2(v)).
- UnboxFloat64x2Instr* defn = value()->definition()->AsUnboxFloat64x2();
- if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat64x2Cid)) {
- return defn->value()->definition();
+ ConstantInstr* c = value()->definition()->AsConstant();
+ if ((c != NULL) && c->value().IsSmi()) {
+ if (!is_truncating() && (kSmiBits > 32)) {
+ // Check that constant fits into 32-bit integer.
+ const int64_t value =
+ static_cast<int64_t>(Smi::Cast(c->value()).Value());
+ if (!Utils::IsInt(32, value)) {
+ return this;
+ }
+ }
+
+ UnboxedConstantInstr* uc =
+ new UnboxedConstantInstr(c->value(), kUnboxedInt32);
+ flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
+ return uc;
}
return this;
}
-Definition* UnboxFloat64x2Instr::Canonicalize(FlowGraph* flow_graph) {
- // Fold away UnboxFloat64x2(BoxFloat64x2(v)).
- BoxFloat64x2Instr* defn = value()->definition()->AsBoxFloat64x2();
- return (defn != NULL) ? defn->value()->definition() : this;
-}
-
+Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
+ if (!HasUses()) return NULL;
+ UnboxedIntConverterInstr* box_defn =
+ value()->definition()->AsUnboxedIntConverter();
+ if ((box_defn != NULL) && (box_defn->representation() == from())) {
+ if (box_defn->from() == to()) {
+ return box_defn->value()->definition();
+ }
-Definition* BoxInt32x4Instr::Canonicalize(FlowGraph* flow_graph) {
- if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
- // Environments can accomodate any representation. No need to box.
- return value()->definition();
+ UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
+ box_defn->from(),
+ representation(),
+ box_defn->value()->CopyWithType(),
+ (to() == kUnboxedInt32) ? GetDeoptId() : Isolate::kNoDeoptId);
+ if ((representation() == kUnboxedInt32) && is_truncating()) {
+ converter->mark_truncating();
+ }
+ flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
+ return converter;
}
- // Fold away BoxInt32x4(UnboxInt32x4(v)).
- UnboxInt32x4Instr* defn = value()->definition()->AsUnboxInt32x4();
- if ((defn != NULL) && (defn->value()->Type()->ToCid() == kInt32x4Cid)) {
- return defn->value()->definition();
+ UnboxInt64Instr* unbox_defn = value()->definition()->AsUnboxInt64();
+ if (unbox_defn != NULL &&
+ (from() == kUnboxedMint) &&
+ (to() == kUnboxedInt32) &&
+ unbox_defn->HasOnlyInputUse(value())) {
+ // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter
+ // and code path that unboxes Mint into Int32. We should just schedule
+ // these instructions close to each other instead of fusing them.
+ Definition* replacement =
+ new UnboxInt32Instr(is_truncating() ? UnboxInt32Instr::kTruncate
+ : UnboxInt32Instr::kNoTruncation,
+ unbox_defn->value()->CopyWithType(),
+ GetDeoptId());
+ flow_graph->InsertBefore(this,
+ replacement,
+ env(),
+ FlowGraph::kValue);
+ return replacement;
}
return this;
}
-Definition* UnboxInt32x4Instr::Canonicalize(FlowGraph* flow_graph) {
- // Fold away UnboxInt32x4(BoxInt32x4(v)).
- BoxInt32x4Instr* defn = value()->definition()->AsBoxInt32x4();
- return (defn != NULL) ? defn->value()->definition() : this;
-}
-
-
Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) {
Definition* defn = value()->definition();
if (defn->IsComparison() && defn->HasOnlyUse(value())) {
@@ -2460,6 +2399,75 @@ Instruction* CheckEitherNonSmiInstr::Canonicalize(FlowGraph* flow_graph) {
}
+BoxInstr* BoxInstr::Create(Representation from, Value* value) {
+ switch (from) {
+ case kUnboxedInt32:
+ return new BoxInt32Instr(value);
+
+ case kUnboxedUint32:
+ return new BoxUint32Instr(value);
+
+ case kUnboxedMint:
+ return new BoxInt64Instr(value);
+
+ case kUnboxedDouble:
+ case kUnboxedFloat32x4:
+ case kUnboxedFloat64x2:
+ case kUnboxedInt32x4:
+ return new BoxInstr(from, value);
+
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+UnboxInstr* UnboxInstr::Create(Representation to,
+ Value* value,
+ intptr_t deopt_id) {
+ switch (to) {
+ case kUnboxedInt32:
+ return new UnboxInt32Instr(
+ UnboxInt32Instr::kNoTruncation, value, deopt_id);
+
+ case kUnboxedUint32:
+ return new UnboxUint32Instr(value, deopt_id);
+
+ case kUnboxedMint:
+ return new UnboxInt64Instr(value, deopt_id);
+
+ case kUnboxedDouble:
+ case kUnboxedFloat32x4:
+ case kUnboxedFloat64x2:
+ case kUnboxedInt32x4:
+ return new UnboxInstr(to, value, deopt_id);
+
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+bool UnboxInstr::CanConvertSmi() const {
+ switch (representation()) {
+ case kUnboxedDouble:
+ case kUnboxedMint:
+ return true;
+
+ case kUnboxedFloat32x4:
+ case kUnboxedFloat64x2:
+ case kUnboxedInt32x4:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+
// Shared code generation methods (EmitNativeCode and
// MakeLocationSummary). Only assembly code that can be shared across all
// architectures can be used. Machine specific register allocation and code
« no previous file with comments | « runtime/vm/intermediate_language.h ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698