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

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

Issue 2300873002: VM: Compute static guarded cid for final instance fields. (Closed)
Patch Set: Clean up Created 4 years, 3 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
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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/precompiler.h" 5 #include "vm/precompiler.h"
6 6
7 #include "vm/aot_optimizer.h" 7 #include "vm/aot_optimizer.h"
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/ast_printer.h" 9 #include "vm/ast_printer.h"
10 #include "vm/branch_optimizer.h" 10 #include "vm/branch_optimizer.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 DECLARE_FLAG(bool, verify_compiler); 71 DECLARE_FLAG(bool, verify_compiler);
72 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); 72 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size);
73 DECLARE_FLAG(bool, trace_failed_optimization_attempts); 73 DECLARE_FLAG(bool, trace_failed_optimization_attempts);
74 DECLARE_FLAG(bool, trace_inlining_intervals); 74 DECLARE_FLAG(bool, trace_inlining_intervals);
75 DECLARE_FLAG(bool, trace_irregexp); 75 DECLARE_FLAG(bool, trace_irregexp);
76 76
77 #ifdef DART_PRECOMPILER 77 #ifdef DART_PRECOMPILER
78 78
79 class DartPrecompilationPipeline : public DartCompilationPipeline { 79 class DartPrecompilationPipeline : public DartCompilationPipeline {
80 public: 80 public:
81 DartPrecompilationPipeline() : result_type_(CompileType::None()) { } 81 explicit DartPrecompilationPipeline(Zone* zone,
82 FieldTypeMap* field_map = NULL)
83 : zone_(zone),
84 result_type_(CompileType::None()),
85 field_map_(field_map) { }
82 86
83 virtual void FinalizeCompilation(FlowGraph* flow_graph) { 87 virtual void FinalizeCompilation(FlowGraph* flow_graph) {
88 if ((field_map_ != NULL )&&
89 flow_graph->function().IsGenerativeConstructor()) {
90 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
91 !block_it.Done();
92 block_it.Advance()) {
93 ForwardInstructionIterator it(block_it.Current());
94 for (; !it.Done(); it.Advance()) {
95 StoreInstanceFieldInstr* store = it.Current()->AsStoreInstanceField();
96 if (store != NULL) {
97 if (!store->field().IsNull() && store->field().is_final()) {
98 if (FLAG_trace_precompiler) {
99 THR_Print("Found store to %s <- %s\n",
100 store->field().ToCString(),
101 store->value()->Type()->ToCString());
102 }
103 FieldTypePair* entry = field_map_->Lookup(&store->field());
104 if (entry == NULL) {
105 field_map_->Insert(FieldTypePair(
106 &Field::Handle(zone_, store->field().raw()), // Re-wrap.
107 store->value()->Type()->ToCid()));
108 if (FLAG_trace_precompiler) {
109 THR_Print(" initial type = %s\n",
110 store->value()->Type()->ToCString());
111 }
112 continue;
113 }
114 CompileType type = CompileType::FromCid(entry->cid_);
115 if (FLAG_trace_precompiler) {
116 THR_Print(" old type = %s\n", type.ToCString());
117 }
118 type.Union(store->value()->Type());
119 if (FLAG_trace_precompiler) {
120 THR_Print(" new type = %s\n", type.ToCString());
121 }
122 entry->cid_ = type.ToCid();
123 }
124 }
125 }
126 }
127 }
128
84 CompileType result_type = CompileType::None(); 129 CompileType result_type = CompileType::None();
85 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); 130 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
86 !block_it.Done(); 131 !block_it.Done();
87 block_it.Advance()) { 132 block_it.Advance()) {
88 ForwardInstructionIterator it(block_it.Current()); 133 ForwardInstructionIterator it(block_it.Current());
89 for (; !it.Done(); it.Advance()) { 134 for (; !it.Done(); it.Advance()) {
90 ReturnInstr* return_instr = it.Current()->AsReturn(); 135 ReturnInstr* return_instr = it.Current()->AsReturn();
91 if (return_instr != NULL) { 136 if (return_instr != NULL) {
92 result_type.Union(return_instr->InputAt(0)->Type()); 137 result_type.Union(return_instr->InputAt(0)->Type());
93 } 138 }
94 } 139 }
95 } 140 }
96 result_type_ = result_type; 141 result_type_ = result_type;
97 } 142 }
98 143
99 CompileType result_type() { return result_type_; } 144 CompileType result_type() { return result_type_; }
100 145
101 private: 146 private:
147 Zone* zone_;
102 CompileType result_type_; 148 CompileType result_type_;
149 FieldTypeMap* field_map_;
103 }; 150 };
104 151
105 152
106 class PrecompileParsedFunctionHelper : public ValueObject { 153 class PrecompileParsedFunctionHelper : public ValueObject {
107 public: 154 public:
108 PrecompileParsedFunctionHelper(ParsedFunction* parsed_function, 155 PrecompileParsedFunctionHelper(ParsedFunction* parsed_function,
109 bool optimized) 156 bool optimized)
110 : parsed_function_(parsed_function), 157 : parsed_function_(parsed_function),
111 optimized_(optimized), 158 optimized_(optimized),
112 thread_(Thread::Current()) { 159 thread_(Thread::Current()) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 pending_functions_( 220 pending_functions_(
174 GrowableObjectArray::Handle(GrowableObjectArray::New())), 221 GrowableObjectArray::Handle(GrowableObjectArray::New())),
175 sent_selectors_(), 222 sent_selectors_(),
176 enqueued_functions_(), 223 enqueued_functions_(),
177 fields_to_retain_(), 224 fields_to_retain_(),
178 functions_to_retain_(), 225 functions_to_retain_(),
179 classes_to_retain_(), 226 classes_to_retain_(),
180 typeargs_to_retain_(), 227 typeargs_to_retain_(),
181 types_to_retain_(), 228 types_to_retain_(),
182 consts_to_retain_(), 229 consts_to_retain_(),
230 field_type_map_(),
183 error_(Error::Handle()) { 231 error_(Error::Handle()) {
184 } 232 }
185 233
186 234
187 void Precompiler::DoCompileAll( 235 void Precompiler::DoCompileAll(
188 Dart_QualifiedFunctionName embedder_entry_points[]) { 236 Dart_QualifiedFunctionName embedder_entry_points[]) {
189 ASSERT(I->compilation_allowed()); 237 ASSERT(I->compilation_allowed());
190 238
191 { 239 {
192 StackZone stack_zone(T); 240 StackZone stack_zone(T);
193 zone_ = stack_zone.GetZone(); 241 zone_ = stack_zone.GetZone();
194 242
195 { HANDLESCOPE(T); 243 { HANDLESCOPE(T);
196 // Make sure class hierarchy is stable before compilation so that CHA 244 // Make sure class hierarchy is stable before compilation so that CHA
197 // can be used. Also ensures lookup of entry points won't miss functions 245 // can be used. Also ensures lookup of entry points won't miss functions
198 // because their class hasn't been finalized yet. 246 // because their class hasn't been finalized yet.
199 FinalizeAllClasses(); 247 FinalizeAllClasses();
200 248
201 SortClasses(); 249 SortClasses();
202 250
203 // Precompile static initializers to compute result type information. 251 // Precompile static initializers to compute result type information.
204 PrecompileStaticInitializers(); 252 PrecompileStaticInitializers();
205 253
254 // Precompile constructors to compute type information for final fields.
255 ClearAllCode();
256 PrecompileConstructors();
257
206 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { 258 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) {
207 if (FLAG_trace_precompiler) { 259 if (FLAG_trace_precompiler) {
208 THR_Print("Precompiler round %" Pd "\n", round); 260 THR_Print("Precompiler round %" Pd "\n", round);
209 } 261 }
210 262
211 if (round > 0) { 263 if (round > 0) {
212 ResetPrecompilerState(); 264 ResetPrecompilerState();
213 } 265 }
214 266
215 // TODO(rmacnak): We should be able to do a more thorough job and drop 267 // TODO(rmacnak): We should be able to do a more thorough job and drop
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 Field& field_; 384 Field& field_;
333 Function& function_; 385 Function& function_;
334 }; 386 };
335 387
336 HANDLESCOPE(T); 388 HANDLESCOPE(T);
337 StaticInitializerVisitor visitor(Z); 389 StaticInitializerVisitor visitor(Z);
338 VisitClasses(&visitor); 390 VisitClasses(&visitor);
339 } 391 }
340 392
341 393
394 void Precompiler::PrecompileConstructors() {
395 class ConstructorVisitor : public FunctionVisitor {
396 public:
397 explicit ConstructorVisitor(Zone* zone, FieldTypeMap* map)
398 : zone_(zone), field_type_map_(map) {
399 ASSERT(map != NULL);
400 }
401 void Visit(const Function& function) {
402 if (!function.IsGenerativeConstructor()) return;
403 if (function.HasCode()) return;
rmacnak 2016/09/06 20:38:41 This should only happen for const constructors rig
Florian Schneider 2016/09/06 21:00:31 Done. Yes, it happens for const-constructors.
404 if (FLAG_trace_precompiler) {
405 THR_Print("Precompiling constructor %s\n", function.ToCString());
406 }
407 CompileFunction(Thread::Current(),
408 zone_,
409 function,
410 field_type_map_);
411 }
412 private:
413 Zone* zone_;
414 FieldTypeMap* field_type_map_;
415 };
416
417 HANDLESCOPE(T);
418 ConstructorVisitor visitor(zone_, &field_type_map_);
419 VisitFunctions(&visitor);
420
421 FieldTypeMap::Iterator it(field_type_map_.GetIterator());
422 for (FieldTypePair* current = it.Next();
423 current != NULL;
424 current = it.Next()) {
425 const intptr_t cid = current->cid_;
426 current->field_->set_guarded_cid(cid);
427 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid);
428 if (FLAG_trace_precompiler) {
429 THR_Print("Field %s <- Type %s\n", current->field_->ToCString(),
430 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString());
431 }
432 }
433 }
434
435
342 void Precompiler::ClearAllCode() { 436 void Precompiler::ClearAllCode() {
343 class ClearCodeFunctionVisitor : public FunctionVisitor { 437 class ClearCodeFunctionVisitor : public FunctionVisitor {
344 void Visit(const Function& function) { 438 void Visit(const Function& function) {
345 function.ClearCode(); 439 function.ClearCode();
346 function.ClearICDataArray(); 440 function.ClearICDataArray();
347 } 441 }
348 }; 442 };
349 ClearCodeFunctionVisitor function_visitor; 443 ClearCodeFunctionVisitor function_visitor;
350 VisitFunctions(&function_visitor); 444 VisitFunctions(&function_visitor);
351 445
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 THR_Print("Precompiling %" Pd " %s (%s, %s)\n", 696 THR_Print("Precompiling %" Pd " %s (%s, %s)\n",
603 function_count_, 697 function_count_,
604 function.ToLibNamePrefixedQualifiedCString(), 698 function.ToLibNamePrefixedQualifiedCString(),
605 function.token_pos().ToCString(), 699 function.token_pos().ToCString(),
606 Function::KindToCString(function.kind())); 700 Function::KindToCString(function.kind()));
607 } 701 }
608 702
609 ASSERT(!function.is_abstract()); 703 ASSERT(!function.is_abstract());
610 ASSERT(!function.IsRedirectingFactory()); 704 ASSERT(!function.IsRedirectingFactory());
611 705
612 error_ = CompileFunction(thread_, function); 706 error_ = CompileFunction(thread_, zone_, function);
613 if (!error_.IsNull()) { 707 if (!error_.IsNull()) {
614 Jump(error_); 708 Jump(error_);
615 } 709 }
616 // Used in the JIT to save type-feedback across compilations. 710 // Used in the JIT to save type-feedback across compilations.
617 function.ClearICDataArray(); 711 function.ClearICDataArray();
618 } else { 712 } else {
619 if (FLAG_trace_precompiler) { 713 if (FLAG_trace_precompiler) {
620 // This function was compiled from somewhere other than Precompiler, 714 // This function was compiled from somewhere other than Precompiler,
621 // such as const constructors compiled by the parser. 715 // such as const constructors compiled by the parser.
622 THR_Print("Already has code: %s (%s, %s)\n", 716 THR_Print("Already has code: %s (%s, %s)\n",
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 1033
940 RawFunction* Precompiler::CompileStaticInitializer(const Field& field, 1034 RawFunction* Precompiler::CompileStaticInitializer(const Field& field,
941 bool compute_type) { 1035 bool compute_type) {
942 ASSERT(field.is_static()); 1036 ASSERT(field.is_static());
943 Thread* thread = Thread::Current(); 1037 Thread* thread = Thread::Current();
944 StackZone zone(thread); 1038 StackZone zone(thread);
945 1039
946 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 1040 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
947 1041
948 parsed_function->AllocateVariables(); 1042 parsed_function->AllocateVariables();
949 DartPrecompilationPipeline pipeline; 1043 DartPrecompilationPipeline pipeline(zone.GetZone());
950 PrecompileParsedFunctionHelper helper(parsed_function, 1044 PrecompileParsedFunctionHelper helper(parsed_function,
951 /* optimized = */ true); 1045 /* optimized = */ true);
952 bool success = helper.Compile(&pipeline); 1046 bool success = helper.Compile(&pipeline);
953 ASSERT(success); 1047 ASSERT(success);
954 1048
955 if (compute_type && field.is_final()) { 1049 if (compute_type && field.is_final()) {
956 intptr_t result_cid = pipeline.result_type().ToCid(); 1050 intptr_t result_cid = pipeline.result_type().ToCid();
957 if (result_cid != kDynamicCid) { 1051 if (result_cid != kDynamicCid) {
958 if (FLAG_trace_precompiler && FLAG_support_il_printer) { 1052 if (FLAG_trace_precompiler && FLAG_support_il_printer) {
959 THR_Print("Setting guarded_cid of %s to %s\n", field.ToCString(), 1053 THR_Print("Setting guarded_cid of %s to %s\n", field.ToCString(),
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1039 // would compile func automatically. We are checking fewer invariants 1133 // would compile func automatically. We are checking fewer invariants
1040 // here. 1134 // here.
1041 ParsedFunction* parsed_function = new ParsedFunction(thread, func); 1135 ParsedFunction* parsed_function = new ParsedFunction(thread, func);
1042 parsed_function->SetNodeSequence(fragment); 1136 parsed_function->SetNodeSequence(fragment);
1043 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); 1137 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp());
1044 fragment->scope()->AddVariable( 1138 fragment->scope()->AddVariable(
1045 parsed_function->current_context_var()); 1139 parsed_function->current_context_var());
1046 parsed_function->AllocateVariables(); 1140 parsed_function->AllocateVariables();
1047 1141
1048 // Non-optimized code generator. 1142 // Non-optimized code generator.
1049 DartPrecompilationPipeline pipeline; 1143 DartPrecompilationPipeline pipeline(Thread::Current()->zone());
1050 PrecompileParsedFunctionHelper helper(parsed_function, 1144 PrecompileParsedFunctionHelper helper(parsed_function,
1051 /* optimized = */ false); 1145 /* optimized = */ false);
1052 helper.Compile(&pipeline); 1146 helper.Compile(&pipeline);
1053 Code::Handle(func.unoptimized_code()).set_var_descriptors( 1147 Code::Handle(func.unoptimized_code()).set_var_descriptors(
1054 Object::empty_var_descriptors()); 1148 Object::empty_var_descriptors());
1055 1149
1056 const Object& result = PassiveObject::Handle( 1150 const Object& result = PassiveObject::Handle(
1057 DartEntry::InvokeFunction(func, Object::empty_array())); 1151 DartEntry::InvokeFunction(func, Object::empty_array()));
1058 return result.raw(); 1152 return result.raw();
1059 } else { 1153 } else {
(...skipping 2006 matching lines...) Expand 10 before | Expand all | Expand 10 after
3066 // Do not attempt to optimize functions that can cause errors. 3160 // Do not attempt to optimize functions that can cause errors.
3067 function.set_is_optimizable(false); 3161 function.set_is_optimizable(false);
3068 return error.raw(); 3162 return error.raw();
3069 } 3163 }
3070 UNREACHABLE(); 3164 UNREACHABLE();
3071 return Error::null(); 3165 return Error::null();
3072 } 3166 }
3073 3167
3074 3168
3075 RawError* Precompiler::CompileFunction(Thread* thread, 3169 RawError* Precompiler::CompileFunction(Thread* thread,
3076 const Function& function) { 3170 Zone* zone,
3171 const Function& function,
3172 FieldTypeMap* field_type_map) {
3077 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId); 3173 VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
3078 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function); 3174 TIMELINE_FUNCTION_COMPILATION_DURATION(thread, "CompileFunction", function);
3079 3175
3080 CompilationPipeline* pipeline =
3081 CompilationPipeline::New(thread->zone(), function);
3082
3083 ASSERT(FLAG_precompiled_mode); 3176 ASSERT(FLAG_precompiled_mode);
3084 const bool optimized = function.IsOptimizable(); // False for natives. 3177 const bool optimized = function.IsOptimizable(); // False for natives.
3085 return PrecompileFunctionHelper(pipeline, function, optimized); 3178 DartPrecompilationPipeline pipeline(zone, field_type_map);
3179 return PrecompileFunctionHelper(&pipeline, function, optimized);
3086 } 3180 }
3087 3181
3088 #endif // DART_PRECOMPILER 3182 #endif // DART_PRECOMPILER
3089 3183
3090 } // namespace dart 3184 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698