| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 AddInstruction(new ReturnInstr(node->token_pos(), return_value)); | 378 AddInstruction(new ReturnInstr(node->token_pos(), return_value)); |
| 379 CloseFragment(); | 379 CloseFragment(); |
| 380 } | 380 } |
| 381 | 381 |
| 382 | 382 |
| 383 // <Expression> ::= Literal { literal: Instance } | 383 // <Expression> ::= Literal { literal: Instance } |
| 384 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 384 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 385 return; | 385 return; |
| 386 } | 386 } |
| 387 | 387 |
| 388 |
| 388 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 389 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
| 389 ReturnComputation(new ConstantVal(node->literal())); | 390 ReturnComputation(new ConstantVal(node->literal())); |
| 390 } | 391 } |
| 391 | 392 |
| 393 |
| 392 // Type nodes only occur as the right-hand side of instanceof comparisons, | 394 // Type nodes only occur as the right-hand side of instanceof comparisons, |
| 393 // and they are handled specially in that context. | 395 // and they are handled specially in that context. |
| 394 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } | 396 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } |
| 395 | 397 |
| 396 | 398 |
| 397 // Helper routine returning true if the static type of the given value is more | 399 // Helper routine returning true if the static type of the given value is more |
| 398 // specific than the given dst_type. | 400 // specific than the given dst_type. |
| 399 static bool IsStaticTypeMoreSpecific(Value* value, | 401 static bool IsStaticTypeMoreSpecific(Value* value, |
| 400 const AbstractType& dst_type) { | 402 const AbstractType& dst_type) { |
| 401 ASSERT(!dst_type.IsMalformed()); | 403 ASSERT(!dst_type.IsMalformed()); |
| (...skipping 2126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2528 | 2530 |
| 2529 | 2531 |
| 2530 void FlowGraphBuilder::Rename(intptr_t var_count) { | 2532 void FlowGraphBuilder::Rename(intptr_t var_count) { |
| 2531 // TODO(fschneider): Store var_count in the FlowGraphBuilder instead of | 2533 // TODO(fschneider): Store var_count in the FlowGraphBuilder instead of |
| 2532 // passing it around. | 2534 // passing it around. |
| 2533 // TODO(fschneider): Support catch-entry. | 2535 // TODO(fschneider): Support catch-entry. |
| 2534 if (graph_entry_->SuccessorCount() > 1) { | 2536 if (graph_entry_->SuccessorCount() > 1) { |
| 2535 Bailout("Catch-entry support in SSA."); | 2537 Bailout("Catch-entry support in SSA."); |
| 2536 } | 2538 } |
| 2537 // TODO(fschneider): Support copied parameters. | 2539 // TODO(fschneider): Support copied parameters. |
| 2538 if (parsed_function().copied_parameter_count()) { | 2540 if (parsed_function().copied_parameter_count() != 0) { |
| 2539 Bailout("Copied parameter support in SSA"); | 2541 Bailout("Copied parameter support in SSA"); |
| 2540 } | 2542 } |
| 2541 ASSERT(var_count == (parsed_function().stack_local_count() + | 2543 ASSERT(var_count == (parsed_function().stack_local_count() + |
| 2542 parsed_function().function().num_fixed_parameters())); | 2544 parsed_function().function().num_fixed_parameters())); |
| 2543 | 2545 |
| 2544 // Initialize start environment. | 2546 // Initialize start environment. |
| 2545 GrowableArray<Value*> start_env(var_count); | 2547 GrowableArray<Value*> start_env(var_count); |
| 2546 intptr_t i = 0; | 2548 intptr_t i = 0; |
| 2547 for (; i < parsed_function().function().num_fixed_parameters(); ++i) { | 2549 for (; i < parsed_function().function().num_fixed_parameters(); ++i) { |
| 2548 ParameterInstr* param = new ParameterInstr(i); | 2550 ParameterInstr* param = new ParameterInstr(i); |
| 2549 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 2551 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 2550 start_env.Add(new UseVal(param)); | 2552 start_env.Add(new UseVal(param)); |
| 2551 } | 2553 } |
| 2552 | 2554 |
| 2553 // All locals are initialized with #null. | 2555 // All locals are initialized with #null. |
| 2554 Value* null_value = new ConstantVal(Object::ZoneHandle()); | 2556 Value* null_value = new ConstantVal(Object::ZoneHandle()); |
| 2555 for (; i < var_count; i++) { | 2557 for (; i < var_count; i++) { |
| 2556 start_env.Add(null_value); | 2558 start_env.Add(null_value); |
| 2557 } | 2559 } |
| 2558 graph_entry_->set_start_env(new Environment(start_env)); | 2560 graph_entry_->set_start_env(new Environment(start_env)); |
| 2559 | 2561 |
| 2560 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); | 2562 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); |
| 2561 ASSERT(normal_entry != NULL); // Must have entry. | 2563 ASSERT(normal_entry != NULL); // Must have entry. |
| 2562 GrowableArray<Value*> env(var_count); | 2564 GrowableArray<Value*> env(var_count); |
| 2563 env.AddArray(start_env); | 2565 env.AddArray(start_env); |
| 2564 RenameRecursive(normal_entry, &env, var_count); | 2566 RenameRecursive(normal_entry, &env, var_count); |
| 2565 } | 2567 } |
| 2566 | 2568 |
| 2567 | 2569 |
| 2568 static intptr_t WhichPred(BlockEntryInstr* predecessor, | |
| 2569 JoinEntryInstr* join_block) { | |
| 2570 for (intptr_t i = 0; i < join_block->PredecessorCount(); ++i) { | |
| 2571 if (join_block->PredecessorAt(i) == predecessor) return i; | |
| 2572 } | |
| 2573 UNREACHABLE(); | |
| 2574 return -1; | |
| 2575 } | |
| 2576 | |
| 2577 | |
| 2578 // Helper to a copy a value iff it is a UseVal. | 2570 // Helper to a copy a value iff it is a UseVal. |
| 2579 static Value* CopyValue(Value* value) { | 2571 static Value* CopyValue(Value* value) { |
| 2580 return value->IsUse() | 2572 return value->IsUse() |
| 2581 ? new UseVal(value->AsUse()->definition()) | 2573 ? new UseVal(value->AsUse()->definition()) |
| 2582 : value; | 2574 : value; |
| 2583 } | 2575 } |
| 2584 | 2576 |
| 2585 | 2577 |
| 2586 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, | 2578 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, |
| 2587 GrowableArray<Value*>* env, | 2579 GrowableArray<Value*>* env, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2612 // 2a. Handle uses: | 2604 // 2a. Handle uses: |
| 2613 // Update expression stack environment for each use. | 2605 // Update expression stack environment for each use. |
| 2614 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 2606 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
| 2615 // from the environment. | 2607 // from the environment. |
| 2616 for (intptr_t i = 0; i < current->InputCount(); ++i) { | 2608 for (intptr_t i = 0; i < current->InputCount(); ++i) { |
| 2617 Value* v = current->InputAt(i); | 2609 Value* v = current->InputAt(i); |
| 2618 if (!v->IsUse()) continue; | 2610 if (!v->IsUse()) continue; |
| 2619 // Update expression stack. | 2611 // Update expression stack. |
| 2620 ASSERT(env->length() > var_count); | 2612 ASSERT(env->length() > var_count); |
| 2621 env->RemoveLast(); | 2613 env->RemoveLast(); |
| 2622 if (v->AsUse()->definition()->IsBind() && | 2614 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); |
| 2623 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { | 2615 if ((as_bind != NULL) && as_bind->computation()->IsLoadLocal()) { |
| 2624 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | 2616 Computation* comp = as_bind->computation(); |
| 2625 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count); | 2617 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count); |
| 2626 current->SetInputAt(i, CopyValue((*env)[index])); | 2618 current->SetInputAt(i, CopyValue((*env)[index])); |
| 2627 } | 2619 } |
| 2628 if (v->AsUse()->definition()->IsBind() && | 2620 if ((as_bind != NULL) && as_bind->computation()->IsStoreLocal()) { |
| 2629 v->AsUse()->definition()->AsBind()->computation()->IsStoreLocal()) { | |
| 2630 // For each use of a StoreLocal: Replace it with the value from the | 2621 // For each use of a StoreLocal: Replace it with the value from the |
| 2631 // environment. | 2622 // environment. |
| 2632 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | 2623 Computation* comp = as_bind->computation(); |
| 2633 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count); | 2624 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count); |
| 2634 current->SetInputAt(i, CopyValue((*env)[index])); | 2625 current->SetInputAt(i, CopyValue((*env)[index])); |
| 2635 } | 2626 } |
| 2636 } | 2627 } |
| 2637 | 2628 |
| 2638 // 2b. Handle LoadLocal and StoreLocal. | 2629 // 2b. Handle LoadLocal and StoreLocal. |
| 2639 // For each LoadLocal: Remove it from the graph. | 2630 // For each LoadLocal: Remove it from the graph. |
| 2640 // For each StoreLocal: Remove it from the graph and update the environment. | 2631 // For each StoreLocal: Remove it from the graph and update the environment. |
| 2641 BindInstr* bind = current->AsBind(); | 2632 BindInstr* bind = current->AsBind(); |
| 2642 if (bind != NULL) { | 2633 if (bind != NULL) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2677 new_env.AddArray(*env); | 2668 new_env.AddArray(*env); |
| 2678 RenameRecursive(block, &new_env, var_count); | 2669 RenameRecursive(block, &new_env, var_count); |
| 2679 } | 2670 } |
| 2680 | 2671 |
| 2681 // 4. Process successor block. We have edge-split form, so that only blocks | 2672 // 4. Process successor block. We have edge-split form, so that only blocks |
| 2682 // with one successor can have a join block as successor. | 2673 // with one successor can have a join block as successor. |
| 2683 if ((block_entry->last_instruction()->SuccessorCount() == 1) && | 2674 if ((block_entry->last_instruction()->SuccessorCount() == 1) && |
| 2684 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { | 2675 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { |
| 2685 JoinEntryInstr* successor = | 2676 JoinEntryInstr* successor = |
| 2686 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); | 2677 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); |
| 2687 intptr_t pred_index = WhichPred(block_entry, successor); | 2678 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); |
| 2679 ASSERT(pred_index >= 0); |
| 2688 if (successor->phis() != NULL) { | 2680 if (successor->phis() != NULL) { |
| 2689 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { | 2681 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { |
| 2690 PhiInstr* phi = (*successor->phis())[i]; | 2682 PhiInstr* phi = (*successor->phis())[i]; |
| 2691 if (phi != NULL) { | 2683 if (phi != NULL) { |
| 2692 // Rename input operand and make a copy if it is a UseVal. | 2684 // Rename input operand and make a copy if it is a UseVal. |
| 2693 Value* new_val = (*env)[i]->IsUse() | 2685 Value* new_val = (*env)[i]->IsUse() |
| 2694 ? new UseVal((*env)[i]->AsUse()->definition()) | 2686 ? new UseVal((*env)[i]->AsUse()->definition()) |
| 2695 : (*env)[i]; | 2687 : (*env)[i]; |
| 2696 phi->SetInputAt(pred_index, new_val); | 2688 phi->SetInputAt(pred_index, new_val); |
| 2697 } | 2689 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2708 char* chars = reinterpret_cast<char*>( | 2700 char* chars = reinterpret_cast<char*>( |
| 2709 Isolate::Current()->current_zone()->Allocate(len)); | 2701 Isolate::Current()->current_zone()->Allocate(len)); |
| 2710 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2702 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2711 const Error& error = Error::Handle( | 2703 const Error& error = Error::Handle( |
| 2712 LanguageError::New(String::Handle(String::New(chars)))); | 2704 LanguageError::New(String::Handle(String::New(chars)))); |
| 2713 Isolate::Current()->long_jump_base()->Jump(1, error); | 2705 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2714 } | 2706 } |
| 2715 | 2707 |
| 2716 | 2708 |
| 2717 } // namespace dart | 2709 } // namespace dart |
| OLD | NEW |