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

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

Issue 1392893003: In precompilation, finalize all classes eagerly. Use the stable class hierarchy for doing CHA based… (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 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 unified diff | Download patch
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/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 2310 matching lines...) Expand 10 before | Expand all | Expand 10 after
2321 } 2321 }
2322 return Field::null(); 2322 return Field::null();
2323 } 2323 }
2324 2324
2325 2325
2326 // Use CHA to determine if the call needs a class check: if the callee's 2326 // Use CHA to determine if the call needs a class check: if the callee's
2327 // receiver is the same as the caller's receiver and there are no overriden 2327 // receiver is the same as the caller's receiver and there are no overriden
2328 // callee functions, then no class check is needed. 2328 // callee functions, then no class check is needed.
2329 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck( 2329 bool FlowGraphOptimizer::InstanceCallNeedsClassCheck(
2330 InstanceCallInstr* call, RawFunction::Kind kind) const { 2330 InstanceCallInstr* call, RawFunction::Kind kind) const {
2331 if (!FLAG_use_cha_deopt) { 2331 if (!FLAG_use_cha_deopt && !isolate()->all_classes_finalized()) {
2332 // Even if class or function are private, lazy class finalization 2332 // Even if class or function are private, lazy class finalization
2333 // may later add overriding methods. 2333 // may later add overriding methods.
2334 return true; 2334 return true;
2335 } 2335 }
2336 Definition* callee_receiver = call->ArgumentAt(0); 2336 Definition* callee_receiver = call->ArgumentAt(0);
2337 ASSERT(callee_receiver != NULL); 2337 ASSERT(callee_receiver != NULL);
2338 const Function& function = flow_graph_->function(); 2338 const Function& function = flow_graph_->function();
2339 if (function.IsDynamicFunction() && 2339 if (function.IsDynamicFunction() &&
2340 callee_receiver->IsParameter() && 2340 callee_receiver->IsParameter() &&
2341 (callee_receiver->AsParameter()->index() == 0)) { 2341 (callee_receiver->AsParameter()->index() == 0)) {
(...skipping 1694 matching lines...) Expand 10 before | Expand all | Expand 10 after
4036 if (type_class.IsSignatureClass()) return false; 4036 if (type_class.IsSignatureClass()) return false;
4037 // Could be an interface check? 4037 // Could be an interface check?
4038 if (CHA::IsImplemented(type_class)) return false; 4038 if (CHA::IsImplemented(type_class)) return false;
4039 // Check if there are subclasses. 4039 // Check if there are subclasses.
4040 if (CHA::HasSubclasses(type_class)) { 4040 if (CHA::HasSubclasses(type_class)) {
4041 return false; 4041 return false;
4042 } 4042 }
4043 4043
4044 // Private classes cannot be subclassed by later loaded libs. 4044 // Private classes cannot be subclassed by later loaded libs.
4045 if (!type_class.IsPrivate()) { 4045 if (!type_class.IsPrivate()) {
4046 if (FLAG_use_cha_deopt) { 4046 if (FLAG_use_cha_deopt || isolate()->all_classes_finalized()) {
4047 if (FLAG_trace_cha) { 4047 if (FLAG_trace_cha) {
4048 THR_Print(" **(CHA) Typecheck as class equality since no " 4048 THR_Print(" **(CHA) Typecheck as class equality since no "
4049 "subclasses: %s\n", 4049 "subclasses: %s\n",
4050 type_class.ToCString()); 4050 type_class.ToCString());
4051 } 4051 }
4052 thread()->cha()->AddToLeafClasses(type_class); 4052 if (FLAG_use_cha_deopt) {
4053 thread()->cha()->AddToLeafClasses(type_class);
4054 }
4053 } else { 4055 } else {
4054 return false; 4056 return false;
4055 } 4057 }
4056 } 4058 }
4057 const intptr_t num_type_args = type_class.NumTypeArguments(); 4059 const intptr_t num_type_args = type_class.NumTypeArguments();
4058 if (num_type_args > 0) { 4060 if (num_type_args > 0) {
4059 // Only raw types can be directly compared, thus disregarding type 4061 // Only raw types can be directly compared, thus disregarding type
4060 // arguments. 4062 // arguments.
4061 const intptr_t num_type_params = type_class.NumTypeParameters(); 4063 const intptr_t num_type_params = type_class.NumTypeParameters();
4062 const intptr_t from_index = num_type_args - num_type_params; 4064 const intptr_t from_index = num_type_args - num_type_params;
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
4301 call->deopt_id()); 4303 call->deopt_id());
4302 ReplaceCall(call, assert_as); 4304 ReplaceCall(call, assert_as);
4303 } 4305 }
4304 4306
4305 4307
4306 // Special optimizations when running in --noopt mode. 4308 // Special optimizations when running in --noopt mode.
4307 void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) { 4309 void FlowGraphOptimizer::InstanceCallNoopt(InstanceCallInstr* instr) {
4308 // TODO(srdjan): Investigate other attempts, as they are not allowed to 4310 // TODO(srdjan): Investigate other attempts, as they are not allowed to
4309 // deoptimize. 4311 // deoptimize.
4310 const Token::Kind op_kind = instr->token_kind(); 4312 const Token::Kind op_kind = instr->token_kind();
4313 if ((op_kind == Token::kGET) &&
4314 TryInlineInstanceGetter(instr, false /* no checks allowed */)) {
4315 return;
4316 }
4317 const ICData& unary_checks =
4318 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks());
4319 if ((instr->ic_data()->NumberOfChecks() > 0) &&
4320 (op_kind == Token::kSET) &&
4321 TryInlineInstanceSetter(instr, unary_checks, false /* no checks */)) {
4322 return;
4323 }
4311 if (instr->HasICData() && (instr->ic_data()->NumberOfUsedChecks() > 0)) { 4324 if (instr->HasICData() && (instr->ic_data()->NumberOfUsedChecks() > 0)) {
4312 const ICData& unary_checks = 4325 ASSERT(!FLAG_polymorphic_with_deopt);
4313 ICData::ZoneHandle(Z, instr->ic_data()->AsUnaryClassChecks()); 4326 // OK to use checks with PolymorphicInstanceCallInstr since no
4314 4327 // deoptimization is allowed.
4315 PolymorphicInstanceCallInstr* call = 4328 PolymorphicInstanceCallInstr* call =
4316 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 4329 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
4317 true /* call_with_checks*/); 4330 true /* call_with_checks */);
4318 instr->ReplaceWith(call, current_iterator()); 4331 instr->ReplaceWith(call, current_iterator());
4319 return; 4332 return;
4320 } 4333 }
4321 4334
4322 // Type test is special as it always gets converted into inlined code. 4335 // Type test is special as it always gets converted into inlined code.
4323 if (Token::IsTypeTestOperator(op_kind)) { 4336 if (Token::IsTypeTestOperator(op_kind)) {
4324 ReplaceWithInstanceOf(instr); 4337 ReplaceWithInstanceOf(instr);
4325 return; 4338 return;
4326 } 4339 }
4327 if (Token::IsTypeCastOperator(op_kind)) { 4340 if (Token::IsTypeCastOperator(op_kind)) {
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
4685 void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { 4698 void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
4686 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. 4699 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
4687 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) 4700 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
4688 if (!instr->can_pack_into_smi()) 4701 if (!instr->can_pack_into_smi())
4689 instr->set_representation(kUnboxedMint); 4702 instr->set_representation(kUnboxedMint);
4690 #endif 4703 #endif
4691 } 4704 }
4692 4705
4693 4706
4694 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, 4707 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr,
4695 const ICData& unary_ic_data) { 4708 const ICData& unary_ic_data,
4709 bool allow_checks) {
4696 ASSERT((unary_ic_data.NumberOfChecks() > 0) && 4710 ASSERT((unary_ic_data.NumberOfChecks() > 0) &&
4697 (unary_ic_data.NumArgsTested() == 1)); 4711 (unary_ic_data.NumArgsTested() == 1));
4698 if (I->flags().type_checks()) { 4712 if (I->flags().type_checks()) {
4699 // Checked mode setters are inlined like normal methods by conventional 4713 // Checked mode setters are inlined like normal methods by conventional
4700 // inlining. 4714 // inlining.
4701 return false; 4715 return false;
4702 } 4716 }
4703 4717
4704 ASSERT(instr->HasICData()); 4718 ASSERT(instr->HasICData());
4705 if (unary_ic_data.NumberOfChecks() == 0) { 4719 if (unary_ic_data.NumberOfChecks() == 0) {
(...skipping 13 matching lines...) Expand all
4719 return false; 4733 return false;
4720 } 4734 }
4721 // Inline implicit instance setter. 4735 // Inline implicit instance setter.
4722 const String& field_name = 4736 const String& field_name =
4723 String::Handle(Z, Field::NameFromSetter(instr->function_name())); 4737 String::Handle(Z, Field::NameFromSetter(instr->function_name()));
4724 const Field& field = 4738 const Field& field =
4725 Field::ZoneHandle(Z, GetField(class_id, field_name)); 4739 Field::ZoneHandle(Z, GetField(class_id, field_name));
4726 ASSERT(!field.IsNull()); 4740 ASSERT(!field.IsNull());
4727 4741
4728 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) { 4742 if (InstanceCallNeedsClassCheck(instr, RawFunction::kImplicitSetter)) {
4743 if (!allow_checks) {
4744 return false;
4745 }
4729 AddReceiverCheck(instr); 4746 AddReceiverCheck(instr);
4730 } 4747 }
4731 if (field.guarded_cid() != kDynamicCid) { 4748 if (field.guarded_cid() != kDynamicCid) {
4749 if (!allow_checks) {
4750 return false;
4751 }
4732 InsertBefore(instr, 4752 InsertBefore(instr,
4733 new(Z) GuardFieldClassInstr( 4753 new(Z) GuardFieldClassInstr(
4734 new(Z) Value(instr->ArgumentAt(1)), 4754 new(Z) Value(instr->ArgumentAt(1)),
4735 field, 4755 field,
4736 instr->deopt_id()), 4756 instr->deopt_id()),
4737 instr->env(), 4757 instr->env(),
4738 FlowGraph::kEffect); 4758 FlowGraph::kEffect);
4739 } 4759 }
4740 4760
4741 if (field.needs_length_check()) { 4761 if (field.needs_length_check()) {
4762 if (!allow_checks) {
4763 return false;
4764 }
4742 InsertBefore(instr, 4765 InsertBefore(instr,
4743 new(Z) GuardFieldLengthInstr( 4766 new(Z) GuardFieldLengthInstr(
4744 new(Z) Value(instr->ArgumentAt(1)), 4767 new(Z) Value(instr->ArgumentAt(1)),
4745 field, 4768 field,
4746 instr->deopt_id()), 4769 instr->deopt_id()),
4747 instr->env(), 4770 instr->env(),
4748 FlowGraph::kEffect); 4771 FlowGraph::kEffect);
4749 } 4772 }
4750 4773
4751 // Field guard was detached. 4774 // Field guard was detached.
(...skipping 4040 matching lines...) Expand 10 before | Expand all | Expand 10 after
8792 8815
8793 // Insert materializations at environment uses. 8816 // Insert materializations at environment uses.
8794 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 8817 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
8795 CreateMaterializationAt( 8818 CreateMaterializationAt(
8796 exits_collector_.exits()[i], alloc, *slots); 8819 exits_collector_.exits()[i], alloc, *slots);
8797 } 8820 }
8798 } 8821 }
8799 8822
8800 8823
8801 } // namespace dart 8824 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698