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

Side by Side Diff: runtime/vm/intermediate_language.cc

Issue 12335063: Add functions for setting an environment and rebinding a use. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/flow_graph_allocator.h" 9 #include "vm/flow_graph_allocator.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 #define DEFINE_ACCEPT(ShortName) \ 311 #define DEFINE_ACCEPT(ShortName) \
312 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ 312 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \
313 visitor->Visit##ShortName(this); \ 313 visitor->Visit##ShortName(this); \
314 } 314 }
315 315
316 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) 316 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT)
317 317
318 #undef DEFINE_ACCEPT 318 #undef DEFINE_ACCEPT
319 319
320 320
321 void Instruction::SetEnvironment(Environment* deopt_env) {
322 intptr_t use_index = 0;
323 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
324 Value* use = it.CurrentValue();
325 use->set_instruction(this);
326 use->set_use_index(use_index++);
327 }
328 env_ = deopt_env;
329 }
330
331
332 void Instruction::RemoveEnvironment() {
333 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) {
334 it.CurrentValue()->RemoveFromUseList();
335 }
336 env_ = NULL;
337 }
338
339
321 Instruction* Instruction::RemoveFromGraph(bool return_previous) { 340 Instruction* Instruction::RemoveFromGraph(bool return_previous) {
322 ASSERT(!IsBlockEntry()); 341 ASSERT(!IsBlockEntry());
323 ASSERT(!IsControl()); 342 ASSERT(!IsControl());
324 ASSERT(!IsThrow()); 343 ASSERT(!IsThrow());
325 ASSERT(!IsReturn()); 344 ASSERT(!IsReturn());
326 ASSERT(!IsReThrow()); 345 ASSERT(!IsReThrow());
327 ASSERT(!IsGoto()); 346 ASSERT(!IsGoto());
328 ASSERT(previous() != NULL); 347 ASSERT(previous() != NULL);
348 // We cannot assert that the instruction, if it is a definition, has no
349 // uses. This function is used to remove instructions from the graph and
350 // reinsert them elsewhere (e.g., hoisting).
329 Instruction* prev_instr = previous(); 351 Instruction* prev_instr = previous();
330 Instruction* next_instr = next(); 352 Instruction* next_instr = next();
331 ASSERT(next_instr != NULL); 353 ASSERT(next_instr != NULL);
332 ASSERT(!next_instr->IsBlockEntry()); 354 ASSERT(!next_instr->IsBlockEntry());
333 prev_instr->LinkTo(next_instr); 355 prev_instr->LinkTo(next_instr);
334 // Reset successor and previous instruction to indicate 356 UnuseAllInputs();
335 // that the instruction is removed from the graph. 357 // Reset the successor and previous instruction to indicate that the
358 // instruction is removed from the graph.
336 set_previous(NULL); 359 set_previous(NULL);
337 set_next(NULL); 360 set_next(NULL);
338 return return_previous ? prev_instr : next_instr; 361 return return_previous ? prev_instr : next_instr;
339 } 362 }
340 363
341 364
342 void Instruction::InsertBefore(Instruction* next) {
343 ASSERT(previous_ == NULL);
344 ASSERT(next_ == NULL);
345 next_ = next;
346 previous_ = next->previous_;
347 next->previous_ = this;
348 previous_->next_ = this;
349 }
350
351
352 void Instruction::InsertAfter(Instruction* prev) { 365 void Instruction::InsertAfter(Instruction* prev) {
353 ASSERT(previous_ == NULL); 366 ASSERT(previous_ == NULL);
354 ASSERT(next_ == NULL); 367 ASSERT(next_ == NULL);
355 previous_ = prev; 368 previous_ = prev;
356 next_ = prev->next_; 369 next_ = prev->next_;
357 next_->previous_ = this; 370 next_->previous_ = this;
358 previous_->next_ = this; 371 previous_->next_ = this;
372
373 // Update def-use chains whenever instructions are added to the graph
374 // after initial graph construction.
375 for (intptr_t i = InputCount() - 1; i >= 0; --i) {
376 Value* input = InputAt(i);
377 input->definition()->AddInputUse(input);
378 }
359 } 379 }
360 380
361 381
362 BlockEntryInstr* Instruction::GetBlock() const { 382 BlockEntryInstr* Instruction::GetBlock() const {
363 // TODO(fschneider): Implement a faster way to get the block of an 383 // TODO(fschneider): Implement a faster way to get the block of an
364 // instruction. 384 // instruction.
365 ASSERT(previous() != NULL); 385 ASSERT(previous() != NULL);
366 Instruction* result = previous(); 386 Instruction* result = previous();
367 while (!result->IsBlockEntry()) result = result->previous(); 387 while (!result->IsBlockEntry()) result = result->previous();
368 return result->AsBlockEntry(); 388 return result->AsBlockEntry();
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 if (next != NULL) next->set_previous_use(NULL); 485 if (next != NULL) next->set_previous_use(NULL);
466 } else if (this == def->env_use_list()) { 486 } else if (this == def->env_use_list()) {
467 def->set_env_use_list(next); 487 def->set_env_use_list(next);
468 if (next != NULL) next->set_previous_use(NULL); 488 if (next != NULL) next->set_previous_use(NULL);
469 } else { 489 } else {
470 Value* prev = previous_use(); 490 Value* prev = previous_use();
471 prev->set_next_use(next); 491 prev->set_next_use(next);
472 if (next != NULL) next->set_previous_use(prev); 492 if (next != NULL) next->set_previous_use(prev);
473 } 493 }
474 494
475 set_definition(NULL);
476 set_previous_use(NULL); 495 set_previous_use(NULL);
477 set_next_use(NULL); 496 set_next_use(NULL);
478 } 497 }
479 498
480 499
481 void Definition::ReplaceUsesWith(Definition* other) { 500 void Definition::ReplaceUsesWith(Definition* other) {
482 ASSERT(other != NULL); 501 ASSERT(other != NULL);
483 ASSERT(this != other); 502 ASSERT(this != other);
484 503
485 Value* current = NULL; 504 Value* current = NULL;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 549
531 void Definition::ReplaceWith(Definition* other, 550 void Definition::ReplaceWith(Definition* other,
532 ForwardInstructionIterator* iterator) { 551 ForwardInstructionIterator* iterator) {
533 // Record other's input uses. 552 // Record other's input uses.
534 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) { 553 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
535 Value* input = other->InputAt(i); 554 Value* input = other->InputAt(i);
536 input->definition()->AddInputUse(input); 555 input->definition()->AddInputUse(input);
537 } 556 }
538 // Take other's environment from this definition. 557 // Take other's environment from this definition.
539 ASSERT(other->env() == NULL); 558 ASSERT(other->env() == NULL);
540 intptr_t use_index = 0; 559 other->SetEnvironment(env());
541 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { 560 env_ = NULL;
542 Value* use = it.CurrentValue();
543 use->set_instruction(other);
544 use->set_use_index(use_index++);
545 }
546 other->set_env(env());
547 set_env(NULL);
548 // Replace all uses of this definition with other. 561 // Replace all uses of this definition with other.
549 ReplaceUsesWith(other); 562 ReplaceUsesWith(other);
550 // Reuse this instruction's SSA name for other. 563 // Reuse this instruction's SSA name for other.
551 ASSERT(!other->HasSSATemp()); 564 ASSERT(!other->HasSSATemp());
552 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index()); 565 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index());
553 // Remove this definition's input uses.
554 UnuseAllInputs();
555 566
556 // Finally remove this definition from the graph. 567 // Finally insert the other definition in place of this one in the graph.
557 previous()->LinkTo(other); 568 previous()->LinkTo(other);
558 if ((iterator != NULL) && (this == iterator->Current())) { 569 if ((iterator != NULL) && (this == iterator->Current())) {
559 // Remove through the iterator. 570 // Remove through the iterator.
560 other->LinkTo(this); 571 other->LinkTo(this);
561 iterator->RemoveCurrentFromGraph(); 572 iterator->RemoveCurrentFromGraph();
562 } else { 573 } else {
563 other->LinkTo(next()); 574 other->LinkTo(next());
575 // Remove this definition's input uses.
576 UnuseAllInputs();
564 } 577 }
565 set_previous(NULL); 578 set_previous(NULL);
566 set_next(NULL); 579 set_next(NULL);
567 } 580 }
568 581
569 582
570 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) 583 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked)
571 : comparison_(comparison), is_checked_(is_checked) { 584 : comparison_(comparison), is_checked_(is_checked) {
572 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { 585 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
573 comparison->InputAt(i)->set_instruction(this); 586 comparison->InputAt(i)->set_instruction(this);
574 } 587 }
575 } 588 }
576 589
577 590
578 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { 591 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) {
579 comparison()->RawSetInputAt(i, value); 592 comparison()->RawSetInputAt(i, value);
580 } 593 }
581 594
582 595
583 // A misleadingly named function for use in template functions that replace 596 // A misleadingly named function for use in template functions that replace
584 // both definitions with definitions and branch comparisons with 597 // both definitions with definitions and branch comparisons with
585 // comparisons. In the branch case, leave the branch intact and replace its 598 // comparisons. In the branch case, leave the branch intact and replace its
586 // comparison with another comparison. 599 // comparison with a new comparison not currently in the graph.
587 void BranchInstr::ReplaceWith(ComparisonInstr* other, 600 void BranchInstr::ReplaceWith(ComparisonInstr* other,
588 ForwardInstructionIterator* ignored) { 601 ForwardInstructionIterator* ignored) {
589 // Record the new comparison's input uses.
590 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) {
591 Value* input = other->InputAt(i);
592 input->definition()->AddInputUse(input);
593 }
594 SetComparison(other); 602 SetComparison(other);
595 } 603 }
596 604
597 605
598 void BranchInstr::SetComparison(ComparisonInstr* comp) { 606 void BranchInstr::SetComparison(ComparisonInstr* comp) {
599 // The new comparison's input uses are already recorded in their
600 // definition's use lists.
601 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { 607 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) {
602 comp->InputAt(i)->set_instruction(this); 608 Value* input = comp->InputAt(i);
609 input->definition()->AddInputUse(input);
610 input->set_instruction(this);
603 } 611 }
604 // There should be no need to copy or unuse an environment. 612 // There should be no need to copy or unuse an environment.
605 ASSERT(comparison()->env() == NULL); 613 ASSERT(comparison()->env() == NULL);
606 // Remove the current comparison's input uses. 614 // Remove the current comparison's input uses.
607 comparison()->UnuseAllInputs(); 615 comparison()->UnuseAllInputs();
608 ASSERT(!comp->HasUses()); 616 ASSERT(!comp->HasUses());
609 comparison_ = comp; 617 comparison_ = comp;
610 } 618 }
611 619
612 620
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
1167 constant_type_args->value().IsTypeArguments()) { 1175 constant_type_args->value().IsTypeArguments()) {
1168 const TypeArguments& instantiator_type_args = 1176 const TypeArguments& instantiator_type_args =
1169 TypeArguments::Cast(constant_type_args->value()); 1177 TypeArguments::Cast(constant_type_args->value());
1170 const AbstractType& new_dst_type = AbstractType::Handle( 1178 const AbstractType& new_dst_type = AbstractType::Handle(
1171 dst_type().InstantiateFrom(instantiator_type_args)); 1179 dst_type().InstantiateFrom(instantiator_type_args));
1172 set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize())); 1180 set_dst_type(AbstractType::ZoneHandle(new_dst_type.Canonicalize()));
1173 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle()); 1181 ConstantInstr* null_constant = new ConstantInstr(Object::ZoneHandle());
1174 // It is ok to insert instructions before the current during 1182 // It is ok to insert instructions before the current during
1175 // forward iteration. 1183 // forward iteration.
1176 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue); 1184 optimizer->InsertBefore(this, null_constant, NULL, Definition::kValue);
1177 instantiator_type_arguments()->RemoveFromUseList(); 1185 instantiator_type_arguments()->BindTo(null_constant);
1178 instantiator_type_arguments()->set_definition(null_constant);
1179 null_constant->AddInputUse(instantiator_type_arguments());
1180 } 1186 }
1181 return this; 1187 return this;
1182 } 1188 }
1183 1189
1184 1190
1185 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) { 1191 Instruction* BranchInstr::Canonicalize(FlowGraphOptimizer* optimizer) {
1186 // Only handle strict-compares. 1192 // Only handle strict-compares.
1187 if (comparison()->IsStrictCompare()) { 1193 if (comparison()->IsStrictCompare()) {
1188 Definition* replacement = comparison()->Canonicalize(optimizer); 1194 Definition* replacement = comparison()->Canonicalize(optimizer);
1189 if (replacement == comparison() || replacement == NULL) return this; 1195 if (replacement == comparison() || replacement == NULL) return this;
1190 ComparisonInstr* comp = replacement->AsComparison(); 1196 ComparisonInstr* comp = replacement->AsComparison();
1191 if ((comp == NULL) || comp->CanDeoptimize()) return this; 1197 if ((comp == NULL) || comp->CanDeoptimize()) return this;
1192 1198
1193 // Check that comparison is not serving as a pending deoptimization target 1199 // Check that comparison is not serving as a pending deoptimization target
1194 // for conversions. 1200 // for conversions.
1195 for (intptr_t i = 0; i < comp->InputCount(); i++) { 1201 for (intptr_t i = 0; i < comp->InputCount(); i++) {
1196 if (comp->RequiredInputRepresentation(i) != 1202 if (comp->RequiredInputRepresentation(i) !=
1197 comp->InputAt(i)->definition()->representation()) { 1203 comp->InputAt(i)->definition()->representation()) {
1198 return this; 1204 return this;
1199 } 1205 }
1200 } 1206 }
1201 1207
1202 // Replace the comparison if the replacement is used at this branch, 1208 // Replace the comparison if the replacement is used at this branch,
1203 // and has exactly one use. 1209 // and has exactly one use.
1204 if ((comp->input_use_list()->instruction() == this) && 1210 if ((comp->input_use_list()->instruction() == this) &&
1205 (comp->input_use_list()->next_use() == NULL) && 1211 (comp->input_use_list()->next_use() == NULL) &&
1206 (comp->env_use_list() == NULL)) { 1212 (comp->env_use_list() == NULL)) {
1207 comp->RemoveFromGraph(); 1213 comp->RemoveFromGraph();
1208 // It is safe to pass a NULL iterator because we're replacing the
1209 // comparison wrapped in a BranchInstr which does not modify the
1210 // linked list of instructions.
1211 SetComparison(comp); 1214 SetComparison(comp);
1212 if (FLAG_trace_optimization) { 1215 if (FLAG_trace_optimization) {
1213 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); 1216 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index());
1214 } 1217 }
1215 // Clear the comparison's temp index and ssa temp index since the 1218 // Clear the comparison's temp index and ssa temp index since the
1216 // value of the comparison is not used outside the branch anymore. 1219 // value of the comparison is not used outside the branch anymore.
1217 ASSERT(comp->input_use_list() == NULL); 1220 ASSERT(comp->input_use_list() == NULL);
1218 comp->ClearSSATempIndex(); 1221 comp->ClearSSATempIndex();
1219 comp->ClearTempIndex(); 1222 comp->ClearTempIndex();
1220 } 1223 }
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 } 1537 }
1535 1538
1536 1539
1537 // Copies the environment and updates the environment use lists. 1540 // Copies the environment and updates the environment use lists.
1538 void Environment::DeepCopyTo(Instruction* instr) const { 1541 void Environment::DeepCopyTo(Instruction* instr) const {
1539 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 1542 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
1540 it.CurrentValue()->RemoveFromUseList(); 1543 it.CurrentValue()->RemoveFromUseList();
1541 } 1544 }
1542 1545
1543 Environment* copy = DeepCopy(); 1546 Environment* copy = DeepCopy();
1544 intptr_t use_index = 0; 1547 instr->SetEnvironment(copy);
1545 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 1548 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
1546 Value* value = it.CurrentValue(); 1549 Value* value = it.CurrentValue();
1547 value->set_instruction(instr);
1548 value->set_use_index(use_index++);
1549 value->definition()->AddEnvUse(value); 1550 value->definition()->AddEnvUse(value);
1550 } 1551 }
1551 instr->set_env(copy);
1552 } 1552 }
1553 1553
1554 1554
1555 // Copies the environment as outer on an inlined instruction and updates the 1555 // Copies the environment as outer on an inlined instruction and updates the
1556 // environment use lists. 1556 // environment use lists.
1557 void Environment::DeepCopyToOuter(Instruction* instr) const { 1557 void Environment::DeepCopyToOuter(Instruction* instr) const {
1558 // Create a deep copy removing caller arguments from the environment. 1558 // Create a deep copy removing caller arguments from the environment.
1559 ASSERT(this != NULL); 1559 ASSERT(this != NULL);
1560 ASSERT(instr->env()->outer() == NULL); 1560 ASSERT(instr->env()->outer() == NULL);
1561 intptr_t argument_count = instr->env()->fixed_parameter_count(); 1561 intptr_t argument_count = instr->env()->fixed_parameter_count();
1562 Environment* copy = DeepCopy(values_.length() - argument_count); 1562 Environment* copy = DeepCopy(values_.length() - argument_count);
1563 instr->env()->outer_ = copy;
1563 intptr_t use_index = instr->env()->Length(); // Start index after inner. 1564 intptr_t use_index = instr->env()->Length(); // Start index after inner.
1564 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 1565 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
1565 Value* value = it.CurrentValue(); 1566 Value* value = it.CurrentValue();
1566 value->set_instruction(instr); 1567 value->set_instruction(instr);
1567 value->set_use_index(use_index++); 1568 value->set_use_index(use_index++);
1568 value->definition()->AddEnvUse(value); 1569 value->definition()->AddEnvUse(value);
1569 } 1570 }
1570 instr->env()->outer_ = copy;
1571 } 1571 }
1572 1572
1573 1573
1574 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { 1574 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) {
1575 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { 1575 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) {
1576 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); 1576 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs);
1577 } 1577 }
1578 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); 1578 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs);
1579 } 1579 }
1580 1580
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after
2258 default: 2258 default:
2259 UNREACHABLE(); 2259 UNREACHABLE();
2260 } 2260 }
2261 return kPowRuntimeEntry; 2261 return kPowRuntimeEntry;
2262 } 2262 }
2263 2263
2264 2264
2265 #undef __ 2265 #undef __
2266 2266
2267 } // namespace dart 2267 } // namespace dart
OLDNEW
« runtime/vm/flow_graph_optimizer.h ('K') | « runtime/vm/intermediate_language.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698