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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 16799003: Support type arguments for allocation sinking in certain conditions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased Created 7 years, 6 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 | « no previous file | tests/language/allocation_sinking_vm_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 24457)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -4346,6 +4346,18 @@
}
+static bool HasSimpleTypeArguments(AllocateObjectInstr* alloc) {
+ if (alloc->ArgumentCount() == 0) return true;
+ ASSERT(alloc->ArgumentCount() == 2);
+ Value* arg1 = alloc->PushArgumentAt(1)->value();
+ if (!arg1->BindsToConstant()) return false;
+
+ const Object& obj = arg1->BoundConstant();
+ return obj.IsSmi()
+ && (Smi::Cast(obj).Value() == StubCode::kNoInstantiator);
+}
+
+
class LoadOptimizer : public ValueObject {
public:
LoadOptimizer(FlowGraph* graph,
@@ -4507,11 +4519,10 @@
// constructor invocation.
// TODO(vegorov): record null-values at least for not final fields of
// escaping object.
- // TODO(vegorov): enable forwarding of type arguments.
AllocateObjectInstr* alloc = instr->AsAllocateObject();
if ((alloc != NULL) &&
(alloc->identity() == AllocateObjectInstr::kNotAliased) &&
- (alloc->ArgumentCount() == 0)) {
+ HasSimpleTypeArguments(alloc)) {
for (Value* use = alloc->input_use_list();
use != NULL;
use = use->next_use()) {
@@ -4522,9 +4533,21 @@
LoadFieldInstr* load = use->instruction()->AsLoadField();
if (load != NULL) {
- // Found a load. Initialize current value of the field to null.
+ // Found a load. Initialize current value of the field to null for
+ // normal fields, or with type arguments.
gen->Add(load->place_id());
if (out_values == NULL) out_values = CreateBlockOutValues();
+
+ if (alloc->ArgumentCount() > 0) {
+ ASSERT(alloc->ArgumentCount() == 2);
+ const Class& cls = Class::Handle(alloc->constructor().Owner());
+ intptr_t type_args_offset = cls.type_arguments_field_offset();
+ if (load->offset_in_bytes() == type_args_offset) {
+ (*out_values)[load->place_id()] =
+ alloc->PushArgumentAt(0)->value()->definition();
+ continue;
+ }
+ }
(*out_values)[load->place_id()] = graph_->constant_null();
}
}
@@ -6877,10 +6900,7 @@
// instructions that write into fields of the allocated object.
// We do not support materialization of the object that has type arguments.
static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) {
- // TODO(vegorov): support AllocateObject with type arguments.
- if (alloc->ArgumentCount() > 0) {
- return false;
- }
+ if (!HasSimpleTypeArguments(alloc)) return false;
for (Value* use = alloc->input_use_list();
use != NULL;
@@ -6918,6 +6938,12 @@
ASSERT(alloc->env_use_list() == NULL);
ASSERT(alloc->input_use_list() == NULL);
alloc->RemoveFromGraph();
+ if (alloc->ArgumentCount() > 0) {
+ ASSERT(alloc->ArgumentCount() == 2);
+ for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) {
+ alloc->PushArgumentAt(i)->RemoveFromGraph();
+ }
+ }
}
@@ -6968,6 +6994,10 @@
// external effects from calls.
LoadOptimizer::OptimizeGraph(flow_graph_);
+ if (FLAG_trace_optimization) {
+ FlowGraphPrinter::PrintGraph("Sinking", flow_graph_);
+ }
+
// At this point we have computed the state of object at each deoptimization
// point and we can eliminate it. Loads inserted above were forwarded so there
// are no uses of the allocation just as in the begging of the pass.
@@ -7083,6 +7113,22 @@
AddField(fields, use->instruction()->AsStoreInstanceField()->field());
}
+ if (alloc->ArgumentCount() > 0) {
+ ASSERT(alloc->ArgumentCount() == 2);
+ const String& name = String::Handle(Symbols::New(":type_args"));
+ const Field& type_args_field =
+ Field::ZoneHandle(Field::New(
+ name,
+ false, // !static
+ false, // !final
+ false, // !const
+ Class::Handle(alloc->constructor().Owner()),
+ 0)); // No token position.
+ const Class& cls = Class::Handle(alloc->constructor().Owner());
+ type_args_field.SetOffset(cls.type_arguments_field_offset());
+ AddField(fields, type_args_field);
+ }
+
// Collect all instructions that mention this object in the environment.
GrowableArray<Instruction*> exits(10);
for (Value* use = alloc->env_use_list();
« no previous file with comments | « no previous file | tests/language/allocation_sinking_vm_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698