| OLD | NEW |
| 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 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 I->object_store()->set_async_star_move_next_helper(null_function); | 495 I->object_store()->set_async_star_move_next_helper(null_function); |
| 496 I->object_store()->set_complete_on_async_return(null_function); | 496 I->object_store()->set_complete_on_async_return(null_function); |
| 497 I->object_store()->set_async_star_stream_controller(null_class); | 497 I->object_store()->set_async_star_stream_controller(null_class); |
| 498 } | 498 } |
| 499 DropClasses(); | 499 DropClasses(); |
| 500 DropLibraries(); | 500 DropLibraries(); |
| 501 | 501 |
| 502 BindStaticCalls(); | 502 BindStaticCalls(); |
| 503 SwitchICCalls(); | 503 SwitchICCalls(); |
| 504 | 504 |
| 505 ShareMegamorphicBuckets(); | 505 ProgramVisitor::Dedup(); |
| 506 DedupStackMaps(); | |
| 507 DedupCodeSourceMaps(); | |
| 508 DedupLists(); | |
| 509 | |
| 510 if (FLAG_dedup_instructions) { | |
| 511 // Reduces binary size but obfuscates profiler results. | |
| 512 DedupInstructions(); | |
| 513 } | |
| 514 | 506 |
| 515 zone_ = NULL; | 507 zone_ = NULL; |
| 516 } | 508 } |
| 517 | 509 |
| 518 intptr_t symbols_before = -1; | 510 intptr_t symbols_before = -1; |
| 519 intptr_t symbols_after = -1; | 511 intptr_t symbols_after = -1; |
| 520 intptr_t capacity = -1; | 512 intptr_t capacity = -1; |
| 521 if (FLAG_trace_precompiler) { | 513 if (FLAG_trace_precompiler) { |
| 522 Symbols::GetStats(I, &symbols_before, &capacity); | 514 Symbols::GetStats(I, &symbols_before, &capacity); |
| 523 } | 515 } |
| (...skipping 1739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2263 UnlinkedCallSet canonical_unlinked_calls_; | 2255 UnlinkedCallSet canonical_unlinked_calls_; |
| 2264 }; | 2256 }; |
| 2265 | 2257 |
| 2266 ASSERT(!I->compilation_allowed()); | 2258 ASSERT(!I->compilation_allowed()); |
| 2267 SwitchICCallsVisitor visitor(Z); | 2259 SwitchICCallsVisitor visitor(Z); |
| 2268 ProgramVisitor::VisitFunctions(&visitor); | 2260 ProgramVisitor::VisitFunctions(&visitor); |
| 2269 #endif | 2261 #endif |
| 2270 } | 2262 } |
| 2271 | 2263 |
| 2272 | 2264 |
| 2273 void Precompiler::ShareMegamorphicBuckets() { | |
| 2274 const GrowableObjectArray& table = GrowableObjectArray::Handle( | |
| 2275 Z, I->object_store()->megamorphic_cache_table()); | |
| 2276 if (table.IsNull()) return; | |
| 2277 MegamorphicCache& cache = MegamorphicCache::Handle(Z); | |
| 2278 | |
| 2279 const intptr_t capacity = 1; | |
| 2280 const Array& buckets = Array::Handle( | |
| 2281 Z, Array::New(MegamorphicCache::kEntryLength * capacity, Heap::kOld)); | |
| 2282 const Function& handler = | |
| 2283 Function::Handle(Z, MegamorphicCacheTable::miss_handler(I)); | |
| 2284 MegamorphicCache::SetEntry(buckets, 0, MegamorphicCache::smi_illegal_cid(), | |
| 2285 handler); | |
| 2286 | |
| 2287 for (intptr_t i = 0; i < table.Length(); i++) { | |
| 2288 cache ^= table.At(i); | |
| 2289 cache.set_buckets(buckets); | |
| 2290 cache.set_mask(capacity - 1); | |
| 2291 cache.set_filled_entry_count(0); | |
| 2292 } | |
| 2293 } | |
| 2294 | |
| 2295 | |
| 2296 void Precompiler::DedupStackMaps() { | |
| 2297 class DedupStackMapsVisitor : public FunctionVisitor { | |
| 2298 public: | |
| 2299 explicit DedupStackMapsVisitor(Zone* zone) | |
| 2300 : zone_(zone), | |
| 2301 canonical_stackmaps_(), | |
| 2302 code_(Code::Handle(zone)), | |
| 2303 stackmaps_(Array::Handle(zone)), | |
| 2304 stackmap_(StackMap::Handle(zone)) {} | |
| 2305 | |
| 2306 void Visit(const Function& function) { | |
| 2307 if (!function.HasCode()) { | |
| 2308 return; | |
| 2309 } | |
| 2310 code_ = function.CurrentCode(); | |
| 2311 stackmaps_ = code_.stackmaps(); | |
| 2312 if (stackmaps_.IsNull()) return; | |
| 2313 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { | |
| 2314 stackmap_ ^= stackmaps_.At(i); | |
| 2315 stackmap_ = DedupStackMap(stackmap_); | |
| 2316 stackmaps_.SetAt(i, stackmap_); | |
| 2317 } | |
| 2318 } | |
| 2319 | |
| 2320 RawStackMap* DedupStackMap(const StackMap& stackmap) { | |
| 2321 const StackMap* canonical_stackmap = | |
| 2322 canonical_stackmaps_.LookupValue(&stackmap); | |
| 2323 if (canonical_stackmap == NULL) { | |
| 2324 canonical_stackmaps_.Insert( | |
| 2325 &StackMap::ZoneHandle(zone_, stackmap.raw())); | |
| 2326 return stackmap.raw(); | |
| 2327 } else { | |
| 2328 return canonical_stackmap->raw(); | |
| 2329 } | |
| 2330 } | |
| 2331 | |
| 2332 private: | |
| 2333 Zone* zone_; | |
| 2334 StackMapSet canonical_stackmaps_; | |
| 2335 Code& code_; | |
| 2336 Array& stackmaps_; | |
| 2337 StackMap& stackmap_; | |
| 2338 }; | |
| 2339 | |
| 2340 DedupStackMapsVisitor visitor(Z); | |
| 2341 ProgramVisitor::VisitFunctions(&visitor); | |
| 2342 } | |
| 2343 | |
| 2344 | |
| 2345 void Precompiler::DedupCodeSourceMaps() { | |
| 2346 class DedupCodeSourceMapsVisitor : public FunctionVisitor { | |
| 2347 public: | |
| 2348 explicit DedupCodeSourceMapsVisitor(Zone* zone) | |
| 2349 : zone_(zone), | |
| 2350 canonical_code_source_maps_(), | |
| 2351 code_(Code::Handle(zone)), | |
| 2352 code_source_map_(CodeSourceMap::Handle(zone)) {} | |
| 2353 | |
| 2354 void Visit(const Function& function) { | |
| 2355 if (!function.HasCode()) { | |
| 2356 return; | |
| 2357 } | |
| 2358 code_ = function.CurrentCode(); | |
| 2359 code_source_map_ = code_.code_source_map(); | |
| 2360 ASSERT(!code_source_map_.IsNull()); | |
| 2361 code_source_map_ = DedupCodeSourceMap(code_source_map_); | |
| 2362 code_.set_code_source_map(code_source_map_); | |
| 2363 } | |
| 2364 | |
| 2365 RawCodeSourceMap* DedupCodeSourceMap(const CodeSourceMap& code_source_map) { | |
| 2366 const CodeSourceMap* canonical_code_source_map = | |
| 2367 canonical_code_source_maps_.LookupValue(&code_source_map); | |
| 2368 if (canonical_code_source_map == NULL) { | |
| 2369 canonical_code_source_maps_.Insert( | |
| 2370 &CodeSourceMap::ZoneHandle(zone_, code_source_map.raw())); | |
| 2371 return code_source_map.raw(); | |
| 2372 } else { | |
| 2373 return canonical_code_source_map->raw(); | |
| 2374 } | |
| 2375 } | |
| 2376 | |
| 2377 private: | |
| 2378 Zone* zone_; | |
| 2379 CodeSourceMapSet canonical_code_source_maps_; | |
| 2380 Code& code_; | |
| 2381 CodeSourceMap& code_source_map_; | |
| 2382 }; | |
| 2383 | |
| 2384 DedupCodeSourceMapsVisitor visitor(Z); | |
| 2385 ProgramVisitor::VisitFunctions(&visitor); | |
| 2386 } | |
| 2387 | |
| 2388 | |
| 2389 void Precompiler::DedupLists() { | |
| 2390 class DedupListsVisitor : public FunctionVisitor { | |
| 2391 public: | |
| 2392 explicit DedupListsVisitor(Zone* zone) | |
| 2393 : zone_(zone), | |
| 2394 canonical_lists_(), | |
| 2395 code_(Code::Handle(zone)), | |
| 2396 list_(Array::Handle(zone)) {} | |
| 2397 | |
| 2398 void Visit(const Function& function) { | |
| 2399 code_ = function.CurrentCode(); | |
| 2400 if (!code_.IsNull()) { | |
| 2401 list_ = code_.stackmaps(); | |
| 2402 if (!list_.IsNull()) { | |
| 2403 list_ = DedupList(list_); | |
| 2404 code_.set_stackmaps(list_); | |
| 2405 } | |
| 2406 list_ = code_.inlined_id_to_function(); | |
| 2407 if (!list_.IsNull()) { | |
| 2408 list_ = DedupList(list_); | |
| 2409 code_.set_inlined_id_to_function(list_); | |
| 2410 } | |
| 2411 } | |
| 2412 | |
| 2413 list_ = function.parameter_types(); | |
| 2414 if (!list_.IsNull()) { | |
| 2415 if (!function.IsSignatureFunction() && !function.IsClosureFunction() && | |
| 2416 (function.name() != Symbols::Call().raw()) && !list_.InVMHeap()) { | |
| 2417 // Parameter types not needed for function type tests. | |
| 2418 for (intptr_t i = 0; i < list_.Length(); i++) { | |
| 2419 list_.SetAt(i, Object::dynamic_type()); | |
| 2420 } | |
| 2421 } | |
| 2422 list_ = DedupList(list_); | |
| 2423 function.set_parameter_types(list_); | |
| 2424 } | |
| 2425 | |
| 2426 list_ = function.parameter_names(); | |
| 2427 if (!list_.IsNull()) { | |
| 2428 if (!function.HasOptionalNamedParameters() && !list_.InVMHeap()) { | |
| 2429 // Parameter names not needed for resolution. | |
| 2430 for (intptr_t i = 0; i < list_.Length(); i++) { | |
| 2431 list_.SetAt(i, Symbols::OptimizedOut()); | |
| 2432 } | |
| 2433 } | |
| 2434 list_ = DedupList(list_); | |
| 2435 function.set_parameter_names(list_); | |
| 2436 } | |
| 2437 } | |
| 2438 | |
| 2439 RawArray* DedupList(const Array& list) { | |
| 2440 const Array* canonical_list = canonical_lists_.LookupValue(&list); | |
| 2441 if (canonical_list == NULL) { | |
| 2442 canonical_lists_.Insert(&Array::ZoneHandle(zone_, list.raw())); | |
| 2443 return list.raw(); | |
| 2444 } else { | |
| 2445 return canonical_list->raw(); | |
| 2446 } | |
| 2447 } | |
| 2448 | |
| 2449 private: | |
| 2450 Zone* zone_; | |
| 2451 ArraySet canonical_lists_; | |
| 2452 Code& code_; | |
| 2453 Array& list_; | |
| 2454 }; | |
| 2455 | |
| 2456 DedupListsVisitor visitor(Z); | |
| 2457 ProgramVisitor::VisitFunctions(&visitor); | |
| 2458 } | |
| 2459 | |
| 2460 | |
| 2461 void Precompiler::DedupInstructions() { | |
| 2462 class DedupInstructionsVisitor : public FunctionVisitor { | |
| 2463 public: | |
| 2464 explicit DedupInstructionsVisitor(Zone* zone) | |
| 2465 : zone_(zone), | |
| 2466 canonical_instructions_set_(), | |
| 2467 code_(Code::Handle(zone)), | |
| 2468 instructions_(Instructions::Handle(zone)) {} | |
| 2469 | |
| 2470 void Visit(const Function& function) { | |
| 2471 if (!function.HasCode()) { | |
| 2472 ASSERT(function.HasImplicitClosureFunction()); | |
| 2473 return; | |
| 2474 } | |
| 2475 code_ = function.CurrentCode(); | |
| 2476 instructions_ = code_.instructions(); | |
| 2477 instructions_ = DedupOneInstructions(instructions_); | |
| 2478 code_.SetActiveInstructions(instructions_); | |
| 2479 code_.set_instructions(instructions_); | |
| 2480 function.SetInstructions(code_); // Update cached entry point. | |
| 2481 } | |
| 2482 | |
| 2483 RawInstructions* DedupOneInstructions(const Instructions& instructions) { | |
| 2484 const Instructions* canonical_instructions = | |
| 2485 canonical_instructions_set_.LookupValue(&instructions); | |
| 2486 if (canonical_instructions == NULL) { | |
| 2487 canonical_instructions_set_.Insert( | |
| 2488 &Instructions::ZoneHandle(zone_, instructions.raw())); | |
| 2489 return instructions.raw(); | |
| 2490 } else { | |
| 2491 return canonical_instructions->raw(); | |
| 2492 } | |
| 2493 } | |
| 2494 | |
| 2495 private: | |
| 2496 Zone* zone_; | |
| 2497 InstructionsSet canonical_instructions_set_; | |
| 2498 Code& code_; | |
| 2499 Instructions& instructions_; | |
| 2500 }; | |
| 2501 | |
| 2502 DedupInstructionsVisitor visitor(Z); | |
| 2503 ProgramVisitor::VisitFunctions(&visitor); | |
| 2504 } | |
| 2505 | |
| 2506 | |
| 2507 void Precompiler::FinalizeAllClasses() { | 2265 void Precompiler::FinalizeAllClasses() { |
| 2508 Library& lib = Library::Handle(Z); | 2266 Library& lib = Library::Handle(Z); |
| 2509 Class& cls = Class::Handle(Z); | 2267 Class& cls = Class::Handle(Z); |
| 2510 | 2268 |
| 2511 for (intptr_t i = 0; i < libraries_.Length(); i++) { | 2269 for (intptr_t i = 0; i < libraries_.Length(); i++) { |
| 2512 lib ^= libraries_.At(i); | 2270 lib ^= libraries_.At(i); |
| 2513 if (!lib.Loaded()) { | 2271 if (!lib.Loaded()) { |
| 2514 String& uri = String::Handle(Z, lib.url()); | 2272 String& uri = String::Handle(Z, lib.url()); |
| 2515 String& msg = String::Handle( | 2273 String& msg = String::Handle( |
| 2516 Z, | 2274 Z, |
| (...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3568 | 3326 |
| 3569 ASSERT(FLAG_precompiled_mode); | 3327 ASSERT(FLAG_precompiled_mode); |
| 3570 const bool optimized = function.IsOptimizable(); // False for natives. | 3328 const bool optimized = function.IsOptimizable(); // False for natives. |
| 3571 DartPrecompilationPipeline pipeline(zone, field_type_map); | 3329 DartPrecompilationPipeline pipeline(zone, field_type_map); |
| 3572 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); | 3330 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); |
| 3573 } | 3331 } |
| 3574 | 3332 |
| 3575 #endif // DART_PRECOMPILER | 3333 #endif // DART_PRECOMPILER |
| 3576 | 3334 |
| 3577 } // namespace dart | 3335 } // namespace dart |
| OLD | NEW |